diff options
author | J.J <thechairman@thechairman.info> | 2024-05-30 21:50:02 -0400 |
---|---|---|
committer | J.J <thechairman@thechairman.info> | 2024-05-30 21:50:02 -0400 |
commit | 612fd986ab1e00b6d34dc1937136250e08e89325 (patch) | |
tree | a3c93952040c6afdf348b5831619a45db7ba0a2e | |
parent | 231c2b688d1e6cf0846d46e883da30e042a9c6cf (diff) | |
download | gleam_aoc-612fd986ab1e00b6d34dc1937136250e08e89325.tar.gz gleam_aoc-612fd986ab1e00b6d34dc1937136250e08e89325.zip |
cleanup
1424 files changed, 148459 insertions, 0 deletions
diff --git a/aoc2023/aoc.toml b/aoc2023/aoc.toml new file mode 100644 index 0000000..fa43b17 --- /dev/null +++ b/aoc2023/aoc.toml @@ -0,0 +1,4 @@ +version = 2 +year = "2023" +session = "53616c7465645f5f807acd9ffb282e509c2b6c3708cfb893011552345aafd18d2b31c1ba607f059b89c6be6c8bafcf391024f8c16b915fd6573075bb4482fe03" +showtime = true diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cache Binary files differnew file mode 100644 index 0000000..f44ba7b --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cache_meta Binary files differnew file mode 100644 index 0000000..0af4a84 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.erl new file mode 100644 index 0000000..99741f8 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.erl @@ -0,0 +1,55 @@ +-module(adglent). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([inspect/1, get_input/1, get_test_folder/1, start_arguments/0, get_part/0]). +-export_type([example/1, problem/0, charlist/0]). + +-type example(NYX) :: {example, binary(), NYX}. + +-type problem() :: first | second. + +-type charlist() :: any(). + +-spec inspect(any()) -> binary(). +inspect(Value) -> + Inspected_value = gleam@string:inspect(Value), + case begin + _pipe = Inspected_value, + gleam@string:starts_with(_pipe, <<"\""/utf8>>) + end of + true -> + _pipe@1 = Inspected_value, + _pipe@2 = gleam@string:drop_left(_pipe@1, 1), + gleam@string:drop_right(_pipe@2, 1); + + false -> + Inspected_value + end. + +-spec get_input(binary()) -> {ok, binary()} | {error, simplifile:file_error()}. +get_input(Day) -> + simplifile:read( + <<<<"src/day"/utf8, Day/binary>>/binary, "/input.txt"/utf8>> + ). + +-spec get_test_folder(binary()) -> binary(). +get_test_folder(Day) -> + <<"test/day"/utf8, Day/binary>>. + +-spec start_arguments() -> list(binary()). +start_arguments() -> + _pipe = init:get_plain_arguments(), + gleam@list:map(_pipe, fun unicode:characters_to_binary/1). + +-spec get_part() -> {ok, problem()} | {error, nil}. +get_part() -> + case start_arguments() of + [<<"1"/utf8>>] -> + {ok, first}; + + [<<"2"/utf8>>] -> + {ok, second}; + + _ -> + {error, nil} + end. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.cache Binary files differnew file mode 100644 index 0000000..be237c1 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.cache_meta Binary files differnew file mode 100644 index 0000000..1637f81 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.erl new file mode 100644 index 0000000..68880ba --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.erl @@ -0,0 +1,278 @@ +-module(adglent@day). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([main/0]). + +-spec create_file_if_not_present(binary(), binary()) -> {ok, binary()} | + {error, binary()}. +create_file_if_not_present(Content, Path) -> + case simplifile:is_file(Path) of + true -> + {ok, <<Path/binary, " already exists - skipped"/utf8>>}; + + false -> + gleam@result:'try'( + begin + _pipe = simplifile:create_file(Path), + priv@errors:map_messages( + _pipe, + <<"Created "/utf8, Path/binary>>, + <<"Could not create "/utf8, Path/binary>> + ) + end, + fun(_) -> _pipe@1 = simplifile:write(Path, Content), + priv@errors:map_messages( + _pipe@1, + <<"Wrote "/utf8, Path/binary>>, + <<"Could not write to "/utf8, Path/binary>> + ) end + ) + end. + +-spec main() -> binary(). +main() -> + Day@1 = begin + _pipe = case adglent:start_arguments() of + [Day] -> + {ok, Day}; + + Args -> + {error, + <<"Expected day - found: "/utf8, + (gleam@string:join(Args, <<", "/utf8>>))/binary>>} + end, + _pipe@1 = priv@errors:map_error( + _pipe, + <<"Error when parsing command args"/utf8>> + ), + _pipe@2 = priv@errors:print_error(_pipe@1), + priv@errors:assert_ok(_pipe@2) + end, + Aoc_toml = begin + _pipe@3 = simplifile:read(<<"aoc.toml"/utf8>>), + _pipe@4 = priv@errors:map_error( + _pipe@3, + <<"Could not read aoc.toml"/utf8>> + ), + _pipe@5 = priv@errors:print_error(_pipe@4), + priv@errors:assert_ok(_pipe@5) + end, + Aoc_toml_version = priv@toml:get_int(Aoc_toml, [<<"version"/utf8>>]), + Year = begin + _pipe@6 = priv@toml:get_string(Aoc_toml, [<<"year"/utf8>>]), + _pipe@7 = priv@errors:map_error( + _pipe@6, + <<"Could not read \"year\" from aoc.toml"/utf8>> + ), + _pipe@8 = priv@errors:print_error(_pipe@7), + priv@errors:assert_ok(_pipe@8) + end, + Session = begin + _pipe@9 = priv@toml:get_string(Aoc_toml, [<<"session"/utf8>>]), + _pipe@10 = priv@errors:map_error( + _pipe@9, + <<"Could not read \"session\" from aoc.toml"/utf8>> + ), + _pipe@11 = priv@errors:print_error(_pipe@10), + priv@errors:assert_ok(_pipe@11) + end, + Showtime = case Aoc_toml_version of + {ok, 2} -> + _pipe@12 = priv@toml:get_bool(Aoc_toml, [<<"showtime"/utf8>>]), + _pipe@13 = priv@errors:map_error( + _pipe@12, + <<"Could not read \"showtime\" from aoc.toml"/utf8>> + ), + _pipe@14 = priv@errors:print_error(_pipe@13), + priv@errors:assert_ok(_pipe@14); + + _ -> + _pipe@15 = priv@toml:get_string(Aoc_toml, [<<"showtime"/utf8>>]), + _pipe@16 = gleam@result:map( + _pipe@15, + fun(Bool_string) -> case Bool_string of + <<"True"/utf8>> -> + true; + + _ -> + false + end end + ), + _pipe@17 = priv@errors:map_error( + _pipe@16, + <<"Could not read \"showtime\" from aoc.toml"/utf8>> + ), + _pipe@18 = priv@errors:print_error(_pipe@17), + priv@errors:assert_ok(_pipe@18) + end, + Test_folder = adglent:get_test_folder(Day@1), + Test_file = <<<<<<Test_folder/binary, "/day"/utf8>>/binary, Day@1/binary>>/binary, + "_test.gleam"/utf8>>, + _pipe@19 = simplifile:create_directory_all(Test_folder), + _pipe@20 = priv@errors:map_error( + _pipe@19, + <<<<"Could not create folder \""/utf8, Test_folder/binary>>/binary, + "\""/utf8>> + ), + _pipe@21 = priv@errors:print_error(_pipe@20), + priv@errors:assert_ok(_pipe@21), + Testfile_template = case Showtime of + true -> + <<" +import gleam/list +import showtime/tests/should +import adglent.{type Example, Example} +import day{{ day }}/solve + +type Problem1AnswerType = + String + +type Problem2AnswerType = + String + +/// Add examples for part 1 here: +/// ```gleam +///const part1_examples: List(Example(Problem1AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part1_examples: List(Example(Problem1AnswerType)) = [] + +/// Add examples for part 2 here: +/// ```gleam +///const part2_examples: List(Example(Problem2AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part2_examples: List(Example(Problem2AnswerType)) = [] + +pub fn part1_test() { + part1_examples + |> should.not_equal([]) + use example <- list.map(part1_examples) + solve.part1(example.input) + |> should.equal(example.answer) +} + +pub fn part2_test() { + part2_examples + |> should.not_equal([]) + use example <- list.map(part2_examples) + solve.part2(example.input) + |> should.equal(example.answer) +} + +"/utf8>>; + + false -> + <<" +import gleam/list +import gleeunit/should +import adglent.{type Example, Example} +import day{{ day }}/solve + +type Problem1AnswerType = + String + +type Problem2AnswerType = + String + +/// Add examples for part 1 here: +/// ```gleam +///const part1_examples: List(Example(Problem1AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part1_examples: List(Example(Problem1AnswerType)) = [] + +/// Add examples for part 2 here: +/// ```gleam +///const part2_examples: List(Example(Problem2AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part2_examples: List(Example(Problem2AnswerType)) = [] + +pub fn part1_test() { + part1_examples + |> should.not_equal([]) + use example <- list.map(part1_examples) + solve.part1(example.input) + |> should.equal(example.answer) +} + +pub fn part2_test() { + part2_examples + |> should.not_equal([]) + use example <- list.map(part2_examples) + solve.part2(example.input) + |> should.equal(example.answer) +} + +"/utf8>> + end, + _pipe@22 = priv@template:render( + Testfile_template, + [{<<"day"/utf8>>, Day@1}] + ), + _pipe@23 = create_file_if_not_present(_pipe@22, Test_file), + _pipe@24 = priv@errors:print_result(_pipe@23), + priv@errors:assert_ok(_pipe@24), + Solutions_folder = <<"src/day"/utf8, Day@1/binary>>, + Solution_file = <<Solutions_folder/binary, "/solve.gleam"/utf8>>, + _pipe@25 = simplifile:create_directory_all(Solutions_folder), + _pipe@26 = priv@errors:map_error( + _pipe@25, + <<<<"Could not create folder \""/utf8, Solutions_folder/binary>>/binary, + "\""/utf8>> + ), + _pipe@27 = priv@errors:print_error(_pipe@26), + priv@errors:assert_ok(_pipe@27), + _pipe@28 = priv@template:render( + <<" +import adglent.{First, Second} +import gleam/io + +pub fn part1(input: String) { + todo as \"Implement solution to part 1\" +} + +pub fn part2(input: String) { + todo as \"Implement solution to part 2\" +} + +pub fn main() { + let assert Ok(part) = adglent.get_part() + let assert Ok(input) = adglent.get_input(\"{{ day }}\") + case part { + First -> + part1(input) + |> adglent.inspect + |> io.println + Second -> + part2(input) + |> adglent.inspect + |> io.println + } +} +"/utf8>>, + [{<<"day"/utf8>>, Day@1}] + ), + _pipe@29 = create_file_if_not_present(_pipe@28, Solution_file), + _pipe@30 = priv@errors:print_result(_pipe@29), + priv@errors:assert_ok(_pipe@30), + _pipe@31 = create_file_if_not_present( + <<"input.txt"/utf8>>, + <<Solutions_folder/binary, "/.gitignore"/utf8>> + ), + _pipe@32 = priv@errors:print_result(_pipe@31), + priv@errors:assert_ok(_pipe@32), + Input = begin + _pipe@33 = priv@aoc_client:get_input(Year, Day@1, Session), + _pipe@34 = priv@errors:map_error( + _pipe@33, + <<"Error when fetching input"/utf8>> + ), + _pipe@35 = priv@errors:print_error(_pipe@34), + priv@errors:assert_ok(_pipe@35) + end, + _pipe@36 = Input, + _pipe@37 = gleam@string:trim(_pipe@36), + _pipe@38 = create_file_if_not_present( + _pipe@37, + <<Solutions_folder/binary, "/input.txt"/utf8>> + ), + _pipe@39 = priv@errors:print_result(_pipe@38), + priv@errors:assert_ok(_pipe@39). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.cache Binary files differnew file mode 100644 index 0000000..798878b --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.cache_meta Binary files differnew file mode 100644 index 0000000..2751b68 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.erl new file mode 100644 index 0000000..50d1242 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.erl @@ -0,0 +1,142 @@ +-module(adglent@init). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([main/0]). + +-spec main() -> {ok, binary()} | {error, binary()}. +main() -> + Year = priv@prompt:value(<<"Year"/utf8>>, <<"2023"/utf8>>, false), + Session = priv@prompt:value(<<"Session Cookie"/utf8>>, <<""/utf8>>, false), + Use_showtime = priv@prompt:confirm(<<"Use showtime"/utf8>>, false), + Aoc_toml_file = <<"aoc.toml"/utf8>>, + Overwrite = case simplifile:create_file(Aoc_toml_file) of + {ok, _} -> + true; + + {error, eexist} -> + priv@prompt:confirm(<<"aoc.toml exits - overwrite"/utf8>>, false); + + _ -> + erlang:error(#{gleam_error => panic, + message => <<"Could not create aoc.toml"/utf8>>, + module => <<"adglent/init"/utf8>>, + function => <<"main"/utf8>>, + line => 29}) + end, + _pipe@3 = case Overwrite of + true -> + _pipe@1 = priv@template:render( + <<" +version = {{ version }} +year = \"{{ year }}\" +session = \"{{ session }}\" +showtime = {{ showtime }} +"/utf8>>, + [{<<"version"/utf8>>, <<"2"/utf8>>}, + {<<"year"/utf8>>, Year}, + {<<"session"/utf8>>, Session}, + {<<"showtime"/utf8>>, + begin + _pipe = gleam@bool:to_string(Use_showtime), + gleam@string:lowercase(_pipe) + end}] + ), + _pipe@2 = simplifile:write(Aoc_toml_file, _pipe@1), + priv@errors:map_messages( + _pipe@2, + <<"aoc.toml - written"/utf8>>, + <<"Error when writing aoc.toml"/utf8>> + ); + + false -> + {ok, <<"aoc.toml - skipped"/utf8>>} + end, + priv@errors:print_result(_pipe@3), + Gleam_toml = begin + _pipe@4 = simplifile:read(<<"gleam.toml"/utf8>>), + _pipe@5 = priv@errors:map_error( + _pipe@4, + <<"Could not read gleam.toml"/utf8>> + ), + _pipe@6 = priv@errors:print_error(_pipe@5), + priv@errors:assert_ok(_pipe@6) + end, + Name = begin + _pipe@7 = priv@toml:get_string(Gleam_toml, [<<"name"/utf8>>]), + _pipe@8 = priv@errors:map_error( + _pipe@7, + <<"Could not read \"name\" from gleam.toml"/utf8>> + ), + _pipe@9 = priv@errors:print_error(_pipe@8), + priv@errors:assert_ok(_pipe@9) + end, + Test_main_file = <<<<"test/"/utf8, Name/binary>>/binary, + "_test.gleam"/utf8>>, + _pipe@12 = case Use_showtime of + true -> + _pipe@10 = priv@template:render( + <<" +import showtime + +pub fn main() { + showtime.main() +} +"/utf8>>, + [] + ), + _pipe@11 = simplifile:write(Test_main_file, _pipe@10), + priv@errors:map_messages( + _pipe@11, + <<"Wrote "/utf8, Test_main_file/binary>>, + <<"Could not write to "/utf8, Test_main_file/binary>> + ); + + false -> + {ok, <<"Using existing (gleeunit) "/utf8, Test_main_file/binary>>} + end, + _pipe@13 = priv@errors:print_result(_pipe@12), + priv@errors:assert_ok(_pipe@13), + _pipe@17 = case simplifile:is_file(<<".gitignore"/utf8>>) of + true -> + gleam@result:'try'( + begin + _pipe@14 = simplifile:read(<<".gitignore"/utf8>>), + gleam@result:map_error( + _pipe@14, + fun(Err) -> + <<"Could not read .gitignore: "/utf8, + (gleam@string:inspect(Err))/binary>> + end + ) + end, + fun(Gitignore) -> + Aoc_toml_ignored = begin + _pipe@15 = gleam@string:split(Gitignore, <<"\n"/utf8>>), + gleam@list:find( + _pipe@15, + fun(Line) -> Line =:= <<"aoc.toml"/utf8>> end + ) + end, + case Aoc_toml_ignored of + {error, _} -> + _pipe@16 = simplifile:append( + <<".gitignore"/utf8>>, + <<"\naoc.toml"/utf8>> + ), + priv@errors:map_messages( + _pipe@16, + <<".gitignore written"/utf8>>, + <<"Error when writing .gitignore"/utf8>> + ); + + {ok, _} -> + {ok, + <<".gitignore - skipped (already configured)"/utf8>>} + end + end + ); + + false -> + {error, <<"Could not find .gitignore"/utf8>>} + end, + priv@errors:print_result(_pipe@17). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent_ffi.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent_ffi.erl new file mode 100644 index 0000000..a6a92e6 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent_ffi.erl @@ -0,0 +1,12 @@ +-module(adglent_ffi). + +-export([get_line/1]). + +-spec get_line(io:prompt()) -> {ok, unicode:unicode_binary()} | {error, eof | no_data}. +get_line(Prompt) -> + case io:get_line(Prompt) of + eof -> {error, eof}; + {error, _} -> {error, no_data}; + Data when is_binary(Data) -> {ok, Data}; + Data when is_list(Data) -> {ok, unicode:characters_to_binary(Data)} + end. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.cache Binary files differnew file mode 100644 index 0000000..e87188f --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.cache_meta Binary files differnew file mode 100644 index 0000000..b6c1617 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.erl new file mode 100644 index 0000000..b30266b --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.erl @@ -0,0 +1,61 @@ +-module(priv@aoc_client). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([get_input/3]). + +-spec get_input(binary(), binary(), binary()) -> {ok, binary()} | + {error, binary()}. +get_input(Year, Day, Session) -> + Url = <<<<<<<<"https://adventofcode.com/"/utf8, Year/binary>>/binary, + "/day/"/utf8>>/binary, + Day/binary>>/binary, + "/input"/utf8>>, + gleam@result:'try'( + begin + _pipe = gleam@http@request:to(Url), + gleam@result:map_error( + _pipe, + fun(Error) -> + <<<<<<"Could not create request for \""/utf8, Url/binary>>/binary, + "\": "/utf8>>/binary, + (gleam@string:inspect(Error))/binary>> + end + ) + end, + fun(Request) -> + gleam@result:'try'( + begin + _pipe@1 = Request, + _pipe@2 = gleam@http@request:prepend_header( + _pipe@1, + <<"Accept"/utf8>>, + <<"application/json"/utf8>> + ), + _pipe@3 = gleam@http@request:prepend_header( + _pipe@2, + <<"Cookie"/utf8>>, + <<<<"session="/utf8, Session/binary>>/binary, ";"/utf8>> + ), + _pipe@4 = gleam@httpc:send(_pipe@3), + gleam@result:map_error( + _pipe@4, + fun(Error@1) -> + <<<<<<"Error when requesting \""/utf8, Url/binary>>/binary, + "\": "/utf8>>/binary, + (gleam@string:inspect(Error@1))/binary>> + end + ) + end, + fun(Response) -> case erlang:element(2, Response) of + Status when (Status >= 200) andalso (Status < 300) -> + {ok, erlang:element(4, Response)}; + + Status@1 -> + {error, + <<<<(gleam@int:to_string(Status@1))/binary, + " - "/utf8>>/binary, + (erlang:element(4, Response))/binary>>} + end end + ) + end + ). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.cache Binary files differnew file mode 100644 index 0000000..3ea27a4 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.cache_meta Binary files differnew file mode 100644 index 0000000..498e302 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.erl new file mode 100644 index 0000000..bd45efa --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.erl @@ -0,0 +1,74 @@ +-module(priv@errors). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([map_messages/3, map_error/2, print_result/1, print_error/1, assert_ok/1]). + +-spec map_messages({ok, any()} | {error, any()}, binary(), binary()) -> {ok, + binary()} | + {error, binary()}. +map_messages(Result, Success_message, Error_message) -> + _pipe = Result, + _pipe@1 = gleam@result:map_error( + _pipe, + fun(Error) -> + <<<<<<"Error - "/utf8, Error_message/binary>>/binary, ": "/utf8>>/binary, + (gleam@string:inspect(Error))/binary>> + end + ), + gleam@result:replace(_pipe@1, Success_message). + +-spec map_error({ok, PBO} | {error, any()}, binary()) -> {ok, PBO} | + {error, binary()}. +map_error(Result, Error_message) -> + _pipe = Result, + gleam@result:map_error( + _pipe, + fun(Error) -> + <<<<Error_message/binary, ": "/utf8>>/binary, + (gleam@string:inspect(Error))/binary>> + end + ). + +-spec print_result({ok, binary()} | {error, binary()}) -> {ok, binary()} | + {error, binary()}. +print_result(Result) -> + _pipe = Result, + _pipe@1 = gleam@result:unwrap_both(_pipe), + gleam@io:println(_pipe@1), + Result. + +-spec print_error({ok, PBX} | {error, binary()}) -> {ok, PBX} | + {error, binary()}. +print_error(Result) -> + _pipe = Result, + gleam@result:map_error( + _pipe, + fun(Err) -> + gleam@io:println(Err), + Err + end + ). + +-spec assert_ok({ok, PCB} | {error, binary()}) -> PCB. +assert_ok(Result) -> + _assert_subject = begin + _pipe = Result, + gleam@result:map_error( + _pipe, + fun(Err) -> + erlang:halt(1), + Err + end + ) + end, + {ok, Value} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"priv/errors"/utf8>>, + function => <<"assert_ok"/utf8>>, + line => 43}) + end, + Value. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.cache Binary files differnew file mode 100644 index 0000000..6d858d1 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.cache_meta Binary files differnew file mode 100644 index 0000000..b010daf --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.erl new file mode 100644 index 0000000..9be1713 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.erl @@ -0,0 +1,53 @@ +-module(priv@prompt). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([get_line/1, confirm/2, value/3]). +-export_type([get_line_error/0]). + +-type get_line_error() :: eof | no_data. + +-spec get_line(binary()) -> {ok, binary()} | {error, get_line_error()}. +get_line(Prompt) -> + adglent_ffi:get_line(Prompt). + +-spec confirm(binary(), boolean()) -> boolean(). +confirm(Message, Auto_accept) -> + Auto_accept orelse case begin + _pipe = adglent_ffi:get_line(<<Message/binary, "? (Y/N): "/utf8>>), + _pipe@1 = gleam@result:unwrap(_pipe, <<"n"/utf8>>), + gleam@string:trim(_pipe@1) + end of + <<"Y"/utf8>> -> + true; + + <<"y"/utf8>> -> + true; + + _ -> + false + end. + +-spec get_value_of_default(binary(), binary(), boolean()) -> binary(). +get_value_of_default(Message, Default, Auto_accept) -> + case Auto_accept of + true -> + Default; + + false -> + _pipe = adglent_ffi:get_line( + <<<<<<Message/binary, "? ("/utf8>>/binary, Default/binary>>/binary, + "): "/utf8>> + ), + _pipe@1 = gleam@result:unwrap(_pipe, <<""/utf8>>), + gleam@string:trim(_pipe@1) + end. + +-spec value(binary(), binary(), boolean()) -> binary(). +value(Message, Default, Auto_accept) -> + case get_value_of_default(Message, Default, Auto_accept) of + <<""/utf8>> -> + Default; + + Value -> + Value + end. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.cache Binary files differnew file mode 100644 index 0000000..1df1c9d --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.cache_meta Binary files differnew file mode 100644 index 0000000..5e1f919 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.erl new file mode 100644 index 0000000..dee331b --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.erl @@ -0,0 +1,25 @@ +-module(priv@template). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([render/2]). + +-spec render(binary(), list({binary(), binary()})) -> binary(). +render(Template, Substitutions) -> + <<(begin + _pipe = Substitutions, + _pipe@2 = gleam@list:fold( + _pipe, + Template, + fun(Template@1, Substitution) -> + {Name, Value} = Substitution, + _pipe@1 = Template@1, + gleam@string:replace( + _pipe@1, + <<<<"{{ "/utf8, Name/binary>>/binary, " }}"/utf8>>, + Value + ) + end + ), + gleam@string:trim(_pipe@2) + end)/binary, + "\n"/utf8>>. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.cache Binary files differnew file mode 100644 index 0000000..3f12af2 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.cache_meta Binary files differnew file mode 100644 index 0000000..3397840 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.erl new file mode 100644 index 0000000..7e36387 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.erl @@ -0,0 +1 @@ +-module(priv@templates@solution). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.cache Binary files differnew file mode 100644 index 0000000..3ca29d0 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.cache_meta Binary files differnew file mode 100644 index 0000000..17c867f --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.erl new file mode 100644 index 0000000..ca6b127 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.erl @@ -0,0 +1 @@ +-module(priv@templates@test_main). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.cache Binary files differnew file mode 100644 index 0000000..22f49a5 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.cache_meta Binary files differnew file mode 100644 index 0000000..c996833 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.erl new file mode 100644 index 0000000..2f5a41e --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.erl @@ -0,0 +1 @@ +-module(priv@templates@testfile_gleeunit). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.cache Binary files differnew file mode 100644 index 0000000..5dc9daa --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.cache_meta Binary files differnew file mode 100644 index 0000000..120c91f --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.erl new file mode 100644 index 0000000..bbbc8b2 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.erl @@ -0,0 +1 @@ +-module(priv@templates@testfile_showtime). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.cache Binary files differnew file mode 100644 index 0000000..0e5b549 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.cache_meta Binary files differnew file mode 100644 index 0000000..a423083 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.erl new file mode 100644 index 0000000..c53ca23 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.erl @@ -0,0 +1,83 @@ +-module(priv@toml). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([get_string/2, get_bool/2, get_int/2]). +-export_type([tom_error/0]). + +-type tom_error() :: {tom_parse_error, tom:parse_error()} | + {tom_get_error, tom:get_error()}. + +-spec get_string(binary(), list(binary())) -> {ok, binary()} | + {error, tom_error()}. +get_string(Toml_content, Key_path) -> + gleam@result:'try'( + begin + _pipe = tom:parse(<<Toml_content/binary, "\n"/utf8>>), + gleam@result:map_error( + _pipe, + fun(Field@0) -> {tom_parse_error, Field@0} end + ) + end, + fun(Toml) -> + gleam@result:'try'( + begin + _pipe@1 = tom:get_string(Toml, Key_path), + gleam@result:map_error( + _pipe@1, + fun(Field@0) -> {tom_get_error, Field@0} end + ) + end, + fun(Value) -> {ok, Value} end + ) + end + ). + +-spec get_bool(binary(), list(binary())) -> {ok, boolean()} | + {error, tom_error()}. +get_bool(Toml_content, Key_path) -> + gleam@result:'try'( + begin + _pipe = tom:parse(<<Toml_content/binary, "\n"/utf8>>), + gleam@result:map_error( + _pipe, + fun(Field@0) -> {tom_parse_error, Field@0} end + ) + end, + fun(Toml) -> + gleam@result:'try'( + begin + _pipe@1 = tom:get_bool(Toml, Key_path), + gleam@result:map_error( + _pipe@1, + fun(Field@0) -> {tom_get_error, Field@0} end + ) + end, + fun(Value) -> {ok, Value} end + ) + end + ). + +-spec get_int(binary(), list(binary())) -> {ok, integer()} | + {error, tom_error()}. +get_int(Toml_content, Key_path) -> + gleam@result:'try'( + begin + _pipe = tom:parse(<<Toml_content/binary, "\n"/utf8>>), + gleam@result:map_error( + _pipe, + fun(Field@0) -> {tom_parse_error, Field@0} end + ) + end, + fun(Toml) -> + gleam@result:'try'( + begin + _pipe@1 = tom:get_int(Toml, Key_path), + gleam@result:map_error( + _pipe@1, + fun(Field@0) -> {tom_get_error, Field@0} end + ) + end, + fun(Value) -> {ok, Value} end + ) + end + ). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cache Binary files differnew file mode 100644 index 0000000..a93f0d6 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cache_meta Binary files differnew file mode 100644 index 0000000..96a5705 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.erl new file mode 100644 index 0000000..1107421 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.erl @@ -0,0 +1,155 @@ +-module(showtime). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([main/0]). + +-spec mk_runner( + fun((gleam@option:option(list(binary())), list(binary()), showtime@internal@common@cli:capture()) -> PLX), + glint:command_input() +) -> PLX. +mk_runner(Func, Command) -> + _assert_subject = begin + _pipe = erlang:element(3, Command), + _pipe@1 = glint@flag:get_strings(_pipe, <<"modules"/utf8>>), + gleam@result:map(_pipe@1, fun(Modules) -> case Modules of + [] -> + none; + + Modules@1 -> + {some, Modules@1} + end end) + end, + {ok, Module_list} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime"/utf8>>, + function => <<"mk_runner"/utf8>>, + line => 91}) + end, + _assert_subject@1 = begin + _pipe@2 = erlang:element(3, Command), + glint@flag:get_strings(_pipe@2, <<"ignore"/utf8>>) + end, + {ok, Ignore_tags} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"showtime"/utf8>>, + function => <<"mk_runner"/utf8>>, + line => 100}) + end, + _assert_subject@2 = begin + _pipe@3 = erlang:element(3, Command), + _pipe@4 = glint@flag:get_string(_pipe@3, <<"capture"/utf8>>), + _pipe@5 = gleam@result:map( + _pipe@4, + fun(Arg) -> gleam@string:lowercase(Arg) end + ), + gleam@result:map(_pipe@5, fun(Arg@1) -> case Arg@1 of + <<"no"/utf8>> -> + no; + + <<"yes"/utf8>> -> + yes; + + <<"mixed"/utf8>> -> + mixed + end end) + end, + {ok, Capture_output} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"showtime"/utf8>>, + function => <<"mk_runner"/utf8>>, + line => 104}) + end, + Func(Module_list, Ignore_tags, Capture_output). + +-spec start_with_args( + list(binary()), + fun((gleam@option:option(list(binary())), list(binary()), showtime@internal@common@cli:capture()) -> any()) +) -> nil. +start_with_args(Args, Func) -> + Modules_flag = begin + _pipe = glint@flag:string_list(), + _pipe@1 = glint@flag:default(_pipe, []), + glint@flag:description( + _pipe@1, + <<"Run only tests in the modules in this list"/utf8>> + ) + end, + Ignore_flag = begin + _pipe@2 = glint@flag:string_list(), + _pipe@3 = glint@flag:default(_pipe@2, []), + glint@flag:description( + _pipe@3, + <<"Ignore tests that are have tags matching a tag in this list"/utf8>> + ) + end, + Capture_flag = begin + _pipe@4 = glint@flag:string(), + _pipe@5 = glint@flag:default(_pipe@4, <<"no"/utf8>>), + _pipe@6 = glint@flag:constraint( + _pipe@5, + glint@flag@constraint:one_of( + [<<"yes"/utf8>>, <<"no"/utf8>>, <<"mixed"/utf8>>] + ) + ), + glint@flag:description( + _pipe@6, + <<"Capture output: no (default) - output when tests are run, yes - output is captured and shown in report, mixed - output when run and in report"/utf8>> + ) + end, + _pipe@7 = glint:new(), + _pipe@12 = glint:add( + _pipe@7, + [], + begin + _pipe@8 = glint:command( + fun(_capture) -> mk_runner(Func, _capture) end + ), + _pipe@9 = glint:flag(_pipe@8, <<"modules"/utf8>>, Modules_flag), + _pipe@10 = glint:flag(_pipe@9, <<"ignore"/utf8>>, Ignore_flag), + _pipe@11 = glint:flag(_pipe@10, <<"capture"/utf8>>, Capture_flag), + glint:description(_pipe@11, <<"Runs test"/utf8>>) + end + ), + _pipe@13 = glint:with_pretty_help(_pipe@12, glint:default_pretty_help()), + glint:run(_pipe@13, Args). + +-spec main() -> nil. +main() -> + start_with_args( + gleam@erlang:start_arguments(), + fun(Module_list, Ignore_tags, Capture) -> + Test_event_handler = showtime@internal@erlang@event_handler:start(), + Test_module_handler = showtime@internal@erlang@module_handler:start( + Test_event_handler, + fun showtime@internal@erlang@discover:collect_test_functions/1, + fun showtime@internal@erlang@runner:run_test_suite/4, + Ignore_tags, + Capture + ), + Test_event_handler(start_test_run), + Modules = showtime@internal@erlang@discover:collect_modules( + Test_module_handler, + Module_list + ), + Test_event_handler( + {end_test_run, + begin + _pipe = Modules, + gleam@list:length(_pipe) + end} + ), + nil + end + ). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.cache Binary files differnew file mode 100644 index 0000000..2fd016f --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.cache_meta Binary files differnew file mode 100644 index 0000000..4c3ebd3 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.erl new file mode 100644 index 0000000..401b409 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.erl @@ -0,0 +1,8 @@ +-module(showtime@internal@common@cli). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export_type([capture/0]). + +-type capture() :: yes | no | mixed. + + diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.cache Binary files differnew file mode 100644 index 0000000..af5456d --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.cache_meta Binary files differnew file mode 100644 index 0000000..cea0c4b --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.erl new file mode 100644 index 0000000..9b9134c --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.erl @@ -0,0 +1,131 @@ +-module(showtime@internal@common@common_event_handler). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([handle_event/3]). +-export_type([test_state/0, handler_state/0]). + +-type test_state() :: not_started | running | {finished, integer()}. + +-type handler_state() :: {handler_state, + test_state(), + integer(), + gleam@dict:dict(binary(), gleam@dict:dict(binary(), showtime@internal@common@test_suite:test_run()))}. + +-spec handle_event( + showtime@internal@common@test_suite:test_event(), + fun(() -> integer()), + handler_state() +) -> handler_state(). +handle_event(Msg, System_time, State) -> + Test_state = erlang:element(2, State), + Num_done = erlang:element(3, State), + Events = erlang:element(4, State), + {Updated_test_state, Updated_num_done, Updated_events} = case Msg of + start_test_run -> + {running, Num_done, Events}; + + {start_test_suite, Module} -> + Maybe_module_events = gleam@map:get( + Events, + erlang:element(2, Module) + ), + New_events = case Maybe_module_events of + {ok, _} -> + Events; + + {error, _} -> + _pipe = Events, + gleam@map:insert( + _pipe, + erlang:element(2, Module), + gleam@map:new() + ) + end, + {Test_state, Num_done, New_events}; + + {start_test, Module@1, Test} -> + Current_time = System_time(), + Maybe_module_events@1 = gleam@map:get( + Events, + erlang:element(2, Module@1) + ), + New_events@1 = case Maybe_module_events@1 of + {ok, Module_events} -> + Maybe_test_event = gleam@map:get( + Module_events, + erlang:element(2, Test) + ), + case Maybe_test_event of + {error, _} -> + _pipe@1 = Events, + gleam@map:insert( + _pipe@1, + erlang:element(2, Module@1), + begin + _pipe@2 = Module_events, + gleam@map:insert( + _pipe@2, + erlang:element(2, Test), + {ongoing_test_run, Test, Current_time} + ) + end + ); + + {ok, _} -> + Events + end; + + {error, _} -> + Events + end, + {Test_state, Num_done, New_events@1}; + + {end_test, Module@2, Test@1, Result} -> + Current_time@1 = System_time(), + Maybe_module_events@2 = gleam@map:get( + Events, + erlang:element(2, Module@2) + ), + New_events@2 = case Maybe_module_events@2 of + {ok, Module_events@1} -> + Maybe_test_run = begin + _pipe@3 = Module_events@1, + gleam@map:get(_pipe@3, erlang:element(2, Test@1)) + end, + Updated_module_events = case Maybe_test_run of + {ok, {ongoing_test_run, Test_function, Started_at}} -> + _pipe@4 = Module_events@1, + gleam@map:insert( + _pipe@4, + erlang:element(2, Test@1), + {completed_test_run, + Test_function, + Current_time@1 - Started_at, + Result} + ); + + {error, _} -> + Module_events@1 + end, + _pipe@5 = Events, + gleam@map:insert( + _pipe@5, + erlang:element(2, Module@2), + Updated_module_events + ); + + {error, _} -> + Events + end, + {Test_state, Num_done, New_events@2}; + + {end_test_suite, _} -> + {Test_state, Num_done + 1, Events}; + + {end_test_run, Num_modules} -> + {{finished, Num_modules}, Num_done, Events}; + + _ -> + {running, Num_done, Events} + end, + {handler_state, Updated_test_state, Updated_num_done, Updated_events}. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.cache Binary files differnew file mode 100644 index 0000000..d460b8c --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.cache_meta Binary files differnew file mode 100644 index 0000000..ae0cd95 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.erl new file mode 100644 index 0000000..52b69ef --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.erl @@ -0,0 +1,54 @@ +-module(showtime@internal@common@test_result). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export_type([ignore_reason/0, test_return/0, exception/0, reason/0, reason_detail/0, gleam_error_detail/0, class/0, trace_list/0, trace/0, extra_info/0, arity_/0]). + +-type ignore_reason() :: ignore. + +-type test_return() :: {test_function_return, + gleam@dynamic:dynamic_(), + list(binary())} | + {ignored, ignore_reason()}. + +-type exception() :: {erlang_exception, + class(), + reason(), + trace_list(), + list(binary())}. + +-type reason() :: {assert_equal, list(reason_detail())} | + {assert_not_equal, list(reason_detail())} | + {assert_match, list(reason_detail())} | + {gleam_error, gleam_error_detail()} | + {gleam_assert, gleam@dynamic:dynamic_(), integer()} | + {generic_exception, gleam@dynamic:dynamic_()}. + +-type reason_detail() :: {module, binary()} | + {reason_line, integer()} | + {expression, binary()} | + {expected, gleam@dynamic:dynamic_()} | + {value, gleam@dynamic:dynamic_()} | + {pattern, binary()}. + +-type gleam_error_detail() :: {let_assert, + binary(), + binary(), + integer(), + binary(), + gleam@dynamic:dynamic_()}. + +-type class() :: erlang_error | exit | throw. + +-type trace_list() :: {trace_list, list(trace())}. + +-type trace() :: {trace, binary(), arity_(), list(extra_info())} | + {trace_module, binary(), binary(), arity_(), list(extra_info())}. + +-type extra_info() :: {error_info, + gleam@dict:dict(gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_())} | + {file, binary()} | + {line, integer()}. + +-type arity_() :: {num, integer()} | {arg_list, list(gleam@dynamic:dynamic_())}. + + diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.cache Binary files differnew file mode 100644 index 0000000..054b4d1 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.cache_meta Binary files differnew file mode 100644 index 0000000..b2139f9 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.erl new file mode 100644 index 0000000..ed41d72 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.erl @@ -0,0 +1,30 @@ +-module(showtime@internal@common@test_suite). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export_type([test_run/0, test_module/0, test_function/0, test_suite/0, test_event/0]). + +-type test_run() :: {ongoing_test_run, test_function(), integer()} | + {completed_test_run, + test_function(), + integer(), + {ok, showtime@internal@common@test_result:test_return()} | + {error, showtime@internal@common@test_result:exception()}}. + +-type test_module() :: {test_module, binary(), gleam@option:option(binary())}. + +-type test_function() :: {test_function, binary()}. + +-type test_suite() :: {test_suite, test_module(), list(test_function())}. + +-type test_event() :: start_test_run | + {start_test_suite, test_module()} | + {start_test, test_module(), test_function()} | + {end_test, + test_module(), + test_function(), + {ok, showtime@internal@common@test_result:test_return()} | + {error, showtime@internal@common@test_result:exception()}} | + {end_test_suite, test_module()} | + {end_test_run, integer()}. + + diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.cache Binary files differnew file mode 100644 index 0000000..5a8fdad --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.cache_meta Binary files differnew file mode 100644 index 0000000..236dd39 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.erl new file mode 100644 index 0000000..025c467 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.erl @@ -0,0 +1,230 @@ +-module(showtime@internal@erlang@discover). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([collect_modules/2, collect_test_functions/1]). + +-spec get_module_prefix(binary()) -> binary(). +get_module_prefix(Path) -> + Path_without_test = begin + _pipe = Path, + gleam@string:replace(_pipe, <<"./test"/utf8>>, <<""/utf8>>) + end, + Path_without_leading_slash = case gleam@string:starts_with( + Path_without_test, + <<"/"/utf8>> + ) of + true -> + gleam@string:drop_left(Path_without_test, 1); + + false -> + Path_without_test + end, + Module_prefix = begin + _pipe@1 = Path_without_leading_slash, + gleam@string:replace(_pipe@1, <<"/"/utf8>>, <<"@"/utf8>>) + end, + case gleam@string:length(Module_prefix) of + 0 -> + Module_prefix; + + _ -> + <<Module_prefix/binary, "@"/utf8>> + end. + +-spec collect_modules_in_folder( + binary(), + fun((showtime@internal@common@test_suite:test_module()) -> nil), + gleam@option:option(list(binary())) +) -> list(showtime@internal@common@test_suite:test_module()). +collect_modules_in_folder(Path, Test_module_handler, Only_modules) -> + Module_prefix = get_module_prefix(Path), + _assert_subject = simplifile:read_directory(Path), + {ok, Files} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/internal/erlang/discover"/utf8>>, + function => <<"collect_modules_in_folder"/utf8>>, + line => 40}) + end, + Test_modules_in_folder = begin + _pipe = Files, + _pipe@1 = gleam@list:filter( + _pipe, + fun(_capture) -> + gleam@string:ends_with(_capture, <<"_test.gleam"/utf8>>) + end + ), + gleam@list:filter_map( + _pipe@1, + fun(Test_module_file) -> + Module_name = <<Module_prefix/binary, + (begin + _pipe@2 = Test_module_file, + gleam@string:replace( + _pipe@2, + <<".gleam"/utf8>>, + <<""/utf8>> + ) + end)/binary>>, + case Only_modules of + {some, Only_modules_list} -> + Module_in_list = begin + _pipe@3 = Only_modules_list, + gleam@list:any( + _pipe@3, + fun(Only_module_name) -> + Only_module_name =:= begin + _pipe@4 = Module_name, + gleam@string:replace( + _pipe@4, + <<"@"/utf8>>, + <<"/"/utf8>> + ) + end + end + ) + end, + case Module_in_list of + true -> + Test_module = {test_module, + Module_name, + {some, Test_module_file}}, + Test_module_handler(Test_module), + {ok, Test_module}; + + false -> + {error, nil} + end; + + none -> + Test_module@1 = {test_module, + Module_name, + {some, Test_module_file}}, + Test_module_handler(Test_module@1), + {ok, Test_module@1} + end + end + ) + end, + Test_modules_in_subfolders = begin + _pipe@5 = Files, + _pipe@6 = gleam@list:map( + _pipe@5, + fun(Filename) -> + <<<<Path/binary, "/"/utf8>>/binary, Filename/binary>> + end + ), + _pipe@7 = gleam@list:filter( + _pipe@6, + fun(File) -> simplifile:is_directory(File) end + ), + gleam@list:fold( + _pipe@7, + [], + fun(Modules, Subfolder) -> _pipe@8 = Modules, + gleam@list:append( + _pipe@8, + collect_modules_in_folder( + Subfolder, + Test_module_handler, + Only_modules + ) + ) end + ) + end, + _pipe@9 = Test_modules_in_folder, + gleam@list:append(_pipe@9, Test_modules_in_subfolders). + +-spec collect_modules( + fun((showtime@internal@common@test_suite:test_module()) -> nil), + gleam@option:option(list(binary())) +) -> list(showtime@internal@common@test_suite:test_module()). +collect_modules(Test_module_handler, Only_modules) -> + collect_modules_in_folder( + <<"./test"/utf8>>, + Test_module_handler, + Only_modules + ). + +-spec collect_test_functions(showtime@internal@common@test_suite:test_module()) -> showtime@internal@common@test_suite:test_suite(). +collect_test_functions(Module) -> + Test_functions = begin + _pipe = erlang:apply( + erlang:binary_to_atom(erlang:element(2, Module)), + erlang:binary_to_atom(<<"module_info"/utf8>>), + [gleam@dynamic:from(erlang:binary_to_atom(<<"exports"/utf8>>))] + ), + gleam@dynamic:unsafe_coerce(_pipe) + end, + Test_functions_filtered = begin + _pipe@1 = Test_functions, + _pipe@3 = gleam@list:map( + _pipe@1, + fun(Entry) -> + {Name, Arity} = case Entry of + {_, _} -> Entry; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/internal/erlang/discover"/utf8>>, + function => <<"collect_test_functions"/utf8>>, + line => 131}) + end, + {begin + _pipe@2 = Name, + erlang:atom_to_binary(_pipe@2) + end, + Arity} + end + ), + _pipe@4 = gleam@list:filter_map( + _pipe@3, + fun(Entry@1) -> + {Name@1, Arity@1} = case Entry@1 of + {_, _} -> Entry@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"showtime/internal/erlang/discover"/utf8>>, + function => <<"collect_test_functions"/utf8>>, + line => 139}) + end, + case gleam@string:ends_with(Name@1, <<"_test"/utf8>>) of + true -> + case Arity@1 of + 0 -> + {ok, Name@1}; + + _ -> + gleam@io:println( + <<<<<<<<"WARNING: function \""/utf8, + Name@1/binary>>/binary, + "\" has arity: "/utf8>>/binary, + (gleam@int:to_string(Arity@1))/binary>>/binary, + " - cannot be used as test (needs to be 0)"/utf8>> + ), + {error, <<"Wrong arity"/utf8>>} + end; + + false -> + {error, <<"Non matching name"/utf8>>} + end + end + ), + _pipe@5 = gleam@list:filter( + _pipe@4, + fun(_capture) -> + gleam@string:ends_with(_capture, <<"_test"/utf8>>) + end + ), + gleam@list:map( + _pipe@5, + fun(Function_name) -> {test_function, Function_name} end + ) + end, + {test_suite, Module, Test_functions_filtered}. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.cache Binary files differnew file mode 100644 index 0000000..e21ee6b --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.cache_meta Binary files differnew file mode 100644 index 0000000..1223c48 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.erl new file mode 100644 index 0000000..d3bdf0f --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.erl @@ -0,0 +1,76 @@ +-module(showtime@internal@erlang@event_handler). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([start/0]). +-export_type([event_handler_message/0]). + +-type event_handler_message() :: {event_handler_message, + showtime@internal@common@test_suite:test_event(), + gleam@erlang@process:subject(integer())}. + +-spec system_time() -> integer(). +system_time() -> + os:system_time(millisecond). + +-spec start() -> fun((showtime@internal@common@test_suite:test_event()) -> nil). +start() -> + _assert_subject = gleam@otp@actor:start( + {not_started, 0, gleam@map:new()}, + fun(Msg, State) -> + {event_handler_message, Test_event, Reply_to} = Msg, + {Test_state, Num_done, Events} = State, + Updated_state = showtime@internal@common@common_event_handler:handle_event( + Test_event, + fun system_time/0, + {handler_state, Test_state, Num_done, Events} + ), + case Updated_state of + {handler_state, {finished, Num_modules}, Num_done@1, Events@1} when Num_done@1 =:= Num_modules -> + {Test_report, Num_failed} = showtime@internal@reports@formatter:create_test_report( + Events@1 + ), + gleam@io:println(Test_report), + gleam@erlang@process:send(Reply_to, Num_failed), + {stop, normal}; + + {handler_state, Test_state@1, Num_done@2, Events@2} -> + {continue, {Test_state@1, Num_done@2, Events@2}, none} + end + end + ), + {ok, Subject} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/internal/erlang/event_handler"/utf8>>, + function => <<"start"/utf8>>, + line => 32}) + end, + Parent_subject = gleam@erlang@process:new_subject(), + Selector = begin + _pipe = gleam_erlang_ffi:new_selector(), + gleam@erlang@process:selecting(_pipe, Parent_subject, fun(X) -> X end) + end, + fun(Test_event@1) -> case Test_event@1 of + {end_test_run, _} -> + gleam@erlang@process:send( + Subject, + {event_handler_message, Test_event@1, Parent_subject} + ), + Num_failed@1 = gleam_erlang_ffi:select(Selector), + case Num_failed@1 > 0 of + true -> + erlang:halt(1); + + false -> + erlang:halt(0) + end; + + _ -> + gleam@erlang@process:send( + Subject, + {event_handler_message, Test_event@1, Parent_subject} + ) + end end. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.cache Binary files differnew file mode 100644 index 0000000..39bc91c --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.cache_meta Binary files differnew file mode 100644 index 0000000..7cd0c75 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.erl new file mode 100644 index 0000000..9eaadcf --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.erl @@ -0,0 +1,53 @@ +-module(showtime@internal@erlang@module_handler). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([start/5]). + +-spec start( + fun((showtime@internal@common@test_suite:test_event()) -> nil), + fun((showtime@internal@common@test_suite:test_module()) -> showtime@internal@common@test_suite:test_suite()), + fun((showtime@internal@common@test_suite:test_suite(), fun((showtime@internal@common@test_suite:test_event()) -> nil), list(binary()), showtime@internal@common@cli:capture()) -> nil), + list(binary()), + showtime@internal@common@cli:capture() +) -> fun((showtime@internal@common@test_suite:test_module()) -> nil). +start( + Test_event_handler, + Test_function_collector, + Run_test_suite, + Ignore_tags, + Capture +) -> + _assert_subject = gleam@otp@actor:start( + nil, + fun(Module, State) -> + gleam@erlang@process:start( + fun() -> + Test_suite = Test_function_collector(Module), + Test_event_handler({start_test_suite, Module}), + Run_test_suite( + Test_suite, + Test_event_handler, + Ignore_tags, + Capture + ), + Test_event_handler({end_test_suite, Module}) + end, + false + ), + {continue, State, none} + end + ), + {ok, Subject} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/internal/erlang/module_handler"/utf8>>, + function => <<"start"/utf8>>, + line => 23}) + end, + fun(Test_module) -> + gleam@erlang@process:send(Subject, Test_module), + nil + end. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.cache Binary files differnew file mode 100644 index 0000000..8251097 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.cache_meta Binary files differnew file mode 100644 index 0000000..069c9cf --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.erl new file mode 100644 index 0000000..93fc592 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.erl @@ -0,0 +1,46 @@ +-module(showtime@internal@erlang@runner). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([run_test/4, run_test_suite/4]). + +-spec run_test( + binary(), + binary(), + list(binary()), + showtime@internal@common@cli:capture() +) -> {ok, showtime@internal@common@test_result:test_return()} | + {error, showtime@internal@common@test_result:exception()}. +run_test(Module_name, Test_name, Ignore_tags, Capture) -> + Result = showtime_ffi:run_test( + erlang:binary_to_atom(Module_name), + erlang:binary_to_atom(Test_name), + Ignore_tags, + Capture + ), + Result. + +-spec run_test_suite( + showtime@internal@common@test_suite:test_suite(), + fun((showtime@internal@common@test_suite:test_event()) -> nil), + list(binary()), + showtime@internal@common@cli:capture() +) -> nil. +run_test_suite(Test_suite, Test_event_handler, Ignore_tags, Capture) -> + _pipe = erlang:element(3, Test_suite), + gleam@list:each( + _pipe, + fun(Test) -> + Test_event_handler( + {start_test, erlang:element(2, Test_suite), Test} + ), + Result = run_test( + erlang:element(2, erlang:element(2, Test_suite)), + erlang:element(2, Test), + Ignore_tags, + Capture + ), + Test_event_handler( + {end_test, erlang:element(2, Test_suite), Test, Result} + ) + end + ). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.cache Binary files differnew file mode 100644 index 0000000..8fd4424 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.cache_meta Binary files differnew file mode 100644 index 0000000..be99189 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.erl new file mode 100644 index 0000000..64f94fa --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.erl @@ -0,0 +1,61 @@ +-module(showtime@internal@reports@compare). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([compare/2]). + +-spec compare(gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> {binary(), + binary()}. +compare(Expected, Got) -> + Expected_as_list = begin + _pipe = Expected, + (gleam@dynamic:list(fun gleam@dynamic:dynamic/1))(_pipe) + end, + Got_as_list = begin + _pipe@1 = Got, + (gleam@dynamic:list(fun gleam@dynamic:dynamic/1))(_pipe@1) + end, + Expected_as_string = begin + _pipe@2 = Expected, + gleam@dynamic:string(_pipe@2) + end, + Got_as_string = begin + _pipe@3 = Got, + gleam@dynamic:string(_pipe@3) + end, + case {Expected_as_list, Got_as_list, Expected_as_string, Got_as_string} of + {{ok, Expected_list}, {ok, Got_list}, _, _} -> + Comparison = begin + _pipe@4 = gap:compare_lists(Expected_list, Got_list), + _pipe@5 = gap@styling:from_comparison(_pipe@4), + _pipe@6 = gap@styling:highlight( + _pipe@5, + fun showtime@internal@reports@styles:expected_highlight/1, + fun showtime@internal@reports@styles:got_highlight/1, + fun(Item) -> Item end + ), + gap@styling:to_styled_comparison(_pipe@6) + end, + {erlang:element(2, Comparison), erlang:element(3, Comparison)}; + + {_, _, {ok, Expected_string}, {ok, Got_string}} -> + Comparison@1 = begin + _pipe@7 = gap:compare_strings(Expected_string, Got_string), + _pipe@8 = gap@styling:from_comparison(_pipe@7), + _pipe@9 = gap@styling:highlight( + _pipe@8, + fun showtime@internal@reports@styles:expected_highlight/1, + fun showtime@internal@reports@styles:got_highlight/1, + fun(Item@1) -> Item@1 end + ), + gap@styling:to_styled_comparison(_pipe@9) + end, + {erlang:element(2, Comparison@1), erlang:element(3, Comparison@1)}; + + {_, _, _, _} -> + {showtime@internal@reports@styles:expected_highlight( + gleam@string:inspect(Expected) + ), + showtime@internal@reports@styles:got_highlight( + gleam@string:inspect(Got) + )} + end. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.cache Binary files differnew file mode 100644 index 0000000..69a4738 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.cache_meta Binary files differnew file mode 100644 index 0000000..86e3c59 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.erl new file mode 100644 index 0000000..cef0b49 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.erl @@ -0,0 +1,749 @@ +-module(showtime@internal@reports@formatter). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([create_test_report/1]). +-export_type([glee_unit_assertion_type/0, module_and_test/0, unified_error/0]). + +-type glee_unit_assertion_type() :: {glee_unit_assert_equal, binary()} | + {glee_unit_assert_not_equal, binary()} | + {glee_unit_assert_match, binary()}. + +-type module_and_test() :: {module_and_test_run, + binary(), + showtime@internal@common@test_suite:test_run()}. + +-type unified_error() :: {unified_error, + gleam@option:option(showtime@tests@meta:meta()), + binary(), + binary(), + binary(), + binary(), + gleam@option:option(integer()), + list(showtime@internal@common@test_result:trace())}. + +-spec erlang_error_to_unified( + list(showtime@internal@common@test_result:reason_detail()), + glee_unit_assertion_type(), + list(showtime@internal@common@test_result:trace()) +) -> unified_error(). +erlang_error_to_unified(Error_details, Assertion_type, Stacktrace) -> + _pipe = Error_details, + gleam@list:fold( + _pipe, + {unified_error, + none, + <<"not_set"/utf8>>, + erlang:element(2, Assertion_type), + <<""/utf8>>, + <<""/utf8>>, + none, + Stacktrace}, + fun(Unified, Reason) -> case Reason of + {expression, Expression} -> + erlang:setelement(3, Unified, Expression); + + {expected, Value} -> + case Assertion_type of + {glee_unit_assert_equal, _} -> + erlang:setelement( + 5, + Unified, + showtime@internal@reports@styles:expected_highlight( + gleam@string:inspect(Value) + ) + ); + + _ -> + Unified + end; + + {value, Value@1} -> + case Assertion_type of + {glee_unit_assert_not_equal, _} -> + erlang:setelement( + 6, + erlang:setelement( + 5, + Unified, + <<(showtime@internal@reports@styles:not_style( + <<"not "/utf8>> + ))/binary, + (gleam@string:inspect(Value@1))/binary>> + ), + showtime@internal@reports@styles:got_highlight( + gleam@string:inspect(Value@1) + ) + ); + + _ -> + erlang:setelement( + 6, + Unified, + showtime@internal@reports@styles:got_highlight( + gleam@string:inspect(Value@1) + ) + ) + end; + + {pattern, Pattern} -> + case Pattern of + <<"{ ok , _ }"/utf8>> -> + erlang:setelement( + 5, + Unified, + showtime@internal@reports@styles:expected_highlight( + <<"Ok(_)"/utf8>> + ) + ); + + <<"{ error , _ }"/utf8>> -> + erlang:setelement( + 5, + Unified, + showtime@internal@reports@styles:expected_highlight( + <<"Error(_)"/utf8>> + ) + ); + + _ -> + Unified + end; + + _ -> + Unified + end end + ). + +-spec gleam_error_to_unified( + showtime@internal@common@test_result:gleam_error_detail(), + list(showtime@internal@common@test_result:trace()) +) -> unified_error(). +gleam_error_to_unified(Gleam_error, Stacktrace) -> + case Gleam_error of + {let_assert, _, _, _, _, Value} -> + Result = gleam@dynamic:unsafe_coerce(Value), + {error, Assertion} = case Result of + {error, _} -> Result; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/internal/reports/formatter"/utf8>>, + function => <<"gleam_error_to_unified"/utf8>>, + line => 293}) + end, + case Assertion of + {eq, Got, Expected, Meta} -> + {Expected@1, Got@1} = showtime@internal@reports@compare:compare( + Expected, + Got + ), + {unified_error, + Meta, + <<"assert"/utf8>>, + <<"Assert equal"/utf8>>, + Expected@1, + Got@1, + none, + Stacktrace}; + + {not_eq, Got@2, Expected@2, Meta@1} -> + {unified_error, + Meta@1, + <<"assert"/utf8>>, + <<"Assert not equal"/utf8>>, + <<(showtime@internal@reports@styles:not_style( + <<"not "/utf8>> + ))/binary, + (gleam@string:inspect(Expected@2))/binary>>, + gleam@string:inspect(Got@2), + none, + Stacktrace}; + + {is_ok, Got@3, Meta@2} -> + {unified_error, + Meta@2, + <<"assert"/utf8>>, + <<"Assert is Ok"/utf8>>, + showtime@internal@reports@styles:expected_highlight( + <<"Ok(_)"/utf8>> + ), + showtime@internal@reports@styles:got_highlight( + gleam@string:inspect(Got@3) + ), + none, + Stacktrace}; + + {is_error, Got@4, Meta@3} -> + {unified_error, + Meta@3, + <<"assert"/utf8>>, + <<"Assert is Ok"/utf8>>, + showtime@internal@reports@styles:expected_highlight( + <<"Error(_)"/utf8>> + ), + showtime@internal@reports@styles:got_highlight( + gleam@string:inspect(Got@4) + ), + none, + Stacktrace}; + + {fail, Meta@4} -> + {unified_error, + Meta@4, + <<"assert"/utf8>>, + <<"Assert is Ok"/utf8>>, + showtime@internal@reports@styles:got_highlight( + <<"should.fail()"/utf8>> + ), + showtime@internal@reports@styles:got_highlight( + <<"N/A - test always expected to fail"/utf8>> + ), + none, + Stacktrace} + end + end. + +-spec format_reason(unified_error(), binary(), binary(), list(binary())) -> list(list(showtime@internal@reports@table:col())). +format_reason(Error, Module, Function, Output_buffer) -> + Meta@1 = case erlang:element(2, Error) of + {some, Meta} -> + {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Description"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left, {content, erlang:element(2, Meta)}, 0}]}; + + none -> + none + end, + Stacktrace = begin + _pipe = erlang:element(8, Error), + gleam@list:map(_pipe, fun(Trace) -> case Trace of + {trace, Function@1, _, _} when Function@1 =:= <<""/utf8>> -> + <<"(anonymous)"/utf8>>; + + {trace_module, Module@1, Function@2, _, _} when Function@2 =:= <<""/utf8>> -> + <<<<Module@1/binary, "."/utf8>>/binary, + "(anonymous)"/utf8>>; + + {trace, Function@3, _, _} -> + Function@3; + + {trace_module, Module@2, Function@4, _, _} -> + <<<<Module@2/binary, "."/utf8>>/binary, + Function@4/binary>> + end end) + end, + Stacktrace_rows = case Stacktrace of + [] -> + []; + + [First | Rest] -> + First_row = {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Stacktrace"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left, + {styled_content, + showtime@internal@reports@styles:stacktrace_style( + First + )}, + 0}]}, + Rest_rows = begin + _pipe@1 = Rest, + gleam@list:map( + _pipe@1, + fun(Row) -> + {some, + [{align_right, {content, <<""/utf8>>}, 2}, + {separator, <<" "/utf8>>}, + {align_left, + {styled_content, + showtime@internal@reports@styles:stacktrace_style( + Row + )}, + 0}]} + end + ) + end, + [First_row | Rest_rows] + end, + Output_rows = case begin + _pipe@2 = Output_buffer, + _pipe@3 = gleam@list:reverse(_pipe@2), + gleam@list:map( + _pipe@3, + fun(Row@1) -> gleam@string:trim_right(Row@1) end + ) + end of + [] -> + []; + + [First@1 | Rest@1] -> + First_row@1 = {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Output"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left_overflow, + {styled_content, + showtime@internal@reports@styles:stacktrace_style( + First@1 + )}, + 0}]}, + Rest_rows@1 = begin + _pipe@4 = Rest@1, + gleam@list:map( + _pipe@4, + fun(Row@2) -> + {some, + [{align_right, {content, <<""/utf8>>}, 2}, + {separator, <<" "/utf8>>}, + {align_left_overflow, + {styled_content, + showtime@internal@reports@styles:stacktrace_style( + Row@2 + )}, + 0}]} + end + ) + end, + [First_row@1 | Rest_rows@1] + end, + Line@1 = begin + _pipe@5 = erlang:element(7, Error), + _pipe@6 = gleam@option:map( + _pipe@5, + fun(Line) -> <<":"/utf8, (gleam@int:to_string(Line))/binary>> end + ), + gleam@option:unwrap(_pipe@6, <<""/utf8>>) + end, + Arrow = <<(gleam@string:join( + gleam@list:repeat( + <<"-"/utf8>>, + (gleam@string:length(Module) + 1) + ((gleam@string:length( + Function + ) + + gleam@string:length(Line@1)) + div 2) + ), + <<""/utf8>> + ))/binary, + "⌄"/utf8>>, + Standard_table_rows = [{some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:error_style( + <<"Failed"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left, {content, Arrow}, 0}]}, + {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Test"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left, + {styled_content, + <<<<Module/binary, "."/utf8>>/binary, + (showtime@internal@reports@styles:function_style( + <<Function/binary, Line@1/binary>> + ))/binary>>}, + 0}]}, + Meta@1, + {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Expected"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left_overflow, + {styled_content, erlang:element(5, Error)}, + 0}]}, + {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Got"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left_overflow, + {styled_content, erlang:element(6, Error)}, + 0}]}], + _pipe@7 = Standard_table_rows, + _pipe@8 = gleam@list:append(_pipe@7, Stacktrace_rows), + _pipe@9 = gleam@list:append(_pipe@8, Output_rows), + _pipe@10 = gleam@list:append( + _pipe@9, + [{some, + [{align_right, {content, <<""/utf8>>}, 0}, + {align_right, {content, <<""/utf8>>}, 0}, + {align_right, {content, <<""/utf8>>}, 0}]}] + ), + gleam@list:filter_map( + _pipe@10, + fun(Row@3) -> gleam@option:to_result(Row@3, nil) end + ). + +-spec create_test_report( + gleam@dict:dict(binary(), gleam@dict:dict(binary(), showtime@internal@common@test_suite:test_run())) +) -> {binary(), integer()}. +create_test_report(Test_results) -> + All_test_runs = begin + _pipe = Test_results, + _pipe@1 = gleam@map:values(_pipe), + gleam@list:flat_map(_pipe@1, fun gleam@map:values/1) + end, + Failed_test_runs = begin + _pipe@2 = Test_results, + _pipe@3 = gleam@map:to_list(_pipe@2), + gleam@list:flat_map( + _pipe@3, + fun(Entry) -> + {Module_name, Test_module_results} = Entry, + _pipe@4 = Test_module_results, + _pipe@5 = gleam@map:values(_pipe@4), + gleam@list:filter_map(_pipe@5, fun(Test_run) -> case Test_run of + {completed_test_run, _, _, Result} -> + case Result of + {error, _} -> + {ok, + {module_and_test_run, + Module_name, + Test_run}}; + + {ok, {ignored, _}} -> + {error, nil}; + + {ok, _} -> + {error, nil} + end; + + _ -> + _pipe@6 = Test_run, + gleam@io:debug(_pipe@6), + {error, nil} + end end) + end + ) + end, + Ignored_test_runs = begin + _pipe@7 = Test_results, + _pipe@8 = gleam@map:to_list(_pipe@7), + gleam@list:flat_map( + _pipe@8, + fun(Entry@1) -> + {Module_name@1, Test_module_results@1} = Entry@1, + _pipe@9 = Test_module_results@1, + _pipe@10 = gleam@map:values(_pipe@9), + gleam@list:filter_map( + _pipe@10, + fun(Test_run@1) -> case Test_run@1 of + {completed_test_run, Test_function, _, Result@1} -> + case Result@1 of + {ok, {ignored, Reason}} -> + {ok, + {<<<<Module_name@1/binary, + "."/utf8>>/binary, + (erlang:element( + 2, + Test_function + ))/binary>>, + Reason}}; + + _ -> + {error, nil} + end; + + _ -> + {error, nil} + end end + ) + end + ) + end, + Failed_tests_report = begin + _pipe@11 = Failed_test_runs, + _pipe@12 = gleam@list:filter_map( + _pipe@11, + fun(Module_and_test_run) -> + case erlang:element(3, Module_and_test_run) of + {completed_test_run, Test_function@1, _, Result@2} -> + case Result@2 of + {error, Exception} -> + case erlang:element(3, Exception) of + {assert_equal, Reason_details} -> + {ok, + format_reason( + erlang_error_to_unified( + Reason_details, + {glee_unit_assert_equal, + <<"Assert equal"/utf8>>}, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + ) + ), + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + {assert_not_equal, Reason_details@1} -> + {ok, + format_reason( + erlang_error_to_unified( + Reason_details@1, + {glee_unit_assert_not_equal, + <<"Assert not equal"/utf8>>}, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + ) + ), + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + {assert_match, Reason_details@2} -> + {ok, + format_reason( + erlang_error_to_unified( + Reason_details@2, + {glee_unit_assert_match, + <<"Assert match"/utf8>>}, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + ) + ), + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + {gleam_error, Reason@1} -> + {ok, + format_reason( + gleam_error_to_unified( + Reason@1, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + ) + ), + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + {gleam_assert, Value, Line_no} -> + {ok, + format_reason( + {unified_error, + none, + <<"gleam assert"/utf8>>, + <<"Assert failed"/utf8>>, + <<"Patterns should match"/utf8>>, + showtime@internal@reports@styles:error_style( + gleam@string:inspect( + Value + ) + ), + {some, Line_no}, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + )}, + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + {generic_exception, Value@1} -> + {ok, + format_reason( + {unified_error, + none, + <<"generic exception"/utf8>>, + <<"Test function threw an exception"/utf8>>, + <<"Exception in test function"/utf8>>, + showtime@internal@reports@styles:error_style( + gleam@string:inspect( + Value@1 + ) + ), + none, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + )}, + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + Other -> + gleam@io:println( + <<"Other: "/utf8, + (gleam@string:inspect(Other))/binary>> + ), + erlang:error(#{gleam_error => panic, + message => <<"panic expression evaluated"/utf8>>, + module => <<"showtime/internal/reports/formatter"/utf8>>, + function => <<"create_test_report"/utf8>>, + line => 178}), + {error, nil} + end; + + _ -> + {error, nil} + end; + + _ -> + {error, nil} + end + end + ), + gleam@list:fold( + _pipe@12, + [], + fun(Rows, Test_rows) -> gleam@list:append(Rows, Test_rows) end + ) + end, + All_test_execution_time_reports = begin + _pipe@13 = All_test_runs, + gleam@list:filter_map(_pipe@13, fun(Test_run@2) -> case Test_run@2 of + {completed_test_run, Test_function@2, Total_time, _} -> + {ok, + <<<<<<(erlang:element(2, Test_function@2))/binary, + ": "/utf8>>/binary, + (gleam@int:to_string(Total_time))/binary>>/binary, + " ms"/utf8>>}; + + _ -> + {error, nil} + end end) + end, + _ = begin + _pipe@14 = All_test_execution_time_reports, + gleam@string:join(_pipe@14, <<"\n"/utf8>>) + end, + All_tests_count = begin + _pipe@15 = All_test_runs, + gleam@list:length(_pipe@15) + end, + Ignored_tests_count = begin + _pipe@16 = Ignored_test_runs, + gleam@list:length(_pipe@16) + end, + Failed_tests_count = begin + _pipe@17 = Failed_test_runs, + gleam@list:length(_pipe@17) + end, + Passed = showtime@internal@reports@styles:passed_style( + <<(gleam@int:to_string( + (All_tests_count - Failed_tests_count) - Ignored_tests_count + ))/binary, + " passed"/utf8>> + ), + Failed = showtime@internal@reports@styles:failed_style( + <<(gleam@int:to_string(Failed_tests_count))/binary, " failed"/utf8>> + ), + Ignored = case Ignored_tests_count of + 0 -> + <<""/utf8>>; + + _ -> + <<", "/utf8, + (showtime@internal@reports@styles:ignored_style( + <<(gleam@int:to_string(Ignored_tests_count))/binary, + " ignored"/utf8>> + ))/binary>> + end, + Failed_tests_table = begin + _pipe@18 = {table, none, Failed_tests_report}, + _pipe@19 = showtime@internal@reports@table:align_table(_pipe@18), + showtime@internal@reports@table:to_string(_pipe@19) + end, + Test_report = <<<<<<<<<<<<"\n"/utf8, Failed_tests_table/binary>>/binary, + "\n"/utf8>>/binary, + Passed/binary>>/binary, + ", "/utf8>>/binary, + Failed/binary>>/binary, + Ignored/binary>>, + {Test_report, Failed_tests_count}. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.cache Binary files differnew file mode 100644 index 0000000..f974100 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.cache_meta Binary files differnew file mode 100644 index 0000000..c0078b3 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.erl new file mode 100644 index 0000000..5243ae7 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.erl @@ -0,0 +1,93 @@ +-module(showtime@internal@reports@styles). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([not_style/1, module_style/1, heading_style/1, stacktrace_style/1, failed_style/1, error_style/1, got_highlight/1, passed_style/1, expected_highlight/1, ignored_style/1, function_style/1, strip_style/1]). + +-spec not_style(binary()) -> binary(). +not_style(Text) -> + gleam_community@ansi:bold(Text). + +-spec module_style(binary()) -> binary(). +module_style(Text) -> + gleam_community@ansi:cyan(Text). + +-spec heading_style(binary()) -> binary(). +heading_style(Text) -> + gleam_community@ansi:cyan(Text). + +-spec stacktrace_style(binary()) -> binary(). +stacktrace_style(Text) -> + Text. + +-spec bold_red(binary()) -> binary(). +bold_red(Text) -> + gleam_community@ansi:bold(gleam_community@ansi:red(Text)). + +-spec failed_style(binary()) -> binary(). +failed_style(Text) -> + bold_red(Text). + +-spec error_style(binary()) -> binary(). +error_style(Text) -> + bold_red(Text). + +-spec got_highlight(binary()) -> binary(). +got_highlight(Text) -> + bold_red(Text). + +-spec bold_green(binary()) -> binary(). +bold_green(Text) -> + gleam_community@ansi:bold(gleam_community@ansi:green(Text)). + +-spec passed_style(binary()) -> binary(). +passed_style(Text) -> + bold_green(Text). + +-spec expected_highlight(binary()) -> binary(). +expected_highlight(Text) -> + bold_green(Text). + +-spec bold_yellow(binary()) -> binary(). +bold_yellow(Text) -> + gleam_community@ansi:bold(gleam_community@ansi:yellow(Text)). + +-spec ignored_style(binary()) -> binary(). +ignored_style(Text) -> + bold_yellow(Text). + +-spec bold_cyan(binary()) -> binary(). +bold_cyan(Text) -> + gleam_community@ansi:bold(gleam_community@ansi:cyan(Text)). + +-spec function_style(binary()) -> binary(). +function_style(Text) -> + bold_cyan(Text). + +-spec strip_style(binary()) -> binary(). +strip_style(Text) -> + {New_text, _} = begin + _pipe = Text, + _pipe@1 = gleam@string:to_graphemes(_pipe), + gleam@list:fold( + _pipe@1, + {<<""/utf8>>, false}, + fun(Acc, Char) -> + {Str, Removing} = Acc, + Bit_char = gleam_stdlib:identity(Char), + case {Bit_char, Removing} of + {<<16#1b>>, _} -> + {Str, true}; + + {<<16#6d>>, true} -> + {Str, false}; + + {_, true} -> + {Str, true}; + + {_, false} -> + {<<Str/binary, Char/binary>>, false} + end + end + ) + end, + New_text. diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.cache Binary files differnew file mode 100644 index 0000000..86c39cb --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.cache_meta Binary files differnew file mode 100644 index 0000000..080524c --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.erl new file mode 100644 index 0000000..e0a5b40 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.erl @@ -0,0 +1,229 @@ +-module(showtime@internal@reports@table). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([to_string/1, align_table/1]). +-export_type([content/0, col/0, table/0]). + +-type content() :: {content, binary()} | {styled_content, binary()}. + +-type col() :: {align_right, content(), integer()} | + {align_left, content(), integer()} | + {align_right_overflow, content(), integer()} | + {align_left_overflow, content(), integer()} | + {separator, binary()} | + {aligned, binary()}. + +-type table() :: {table, gleam@option:option(binary()), list(list(col()))}. + +-spec to_string(table()) -> binary(). +to_string(Table) -> + Rows = begin + _pipe = erlang:element(3, Table), + _pipe@3 = gleam@list:map(_pipe, fun(Row) -> _pipe@1 = Row, + _pipe@2 = gleam@list:filter_map(_pipe@1, fun(Col) -> case Col of + {separator, Char} -> + {ok, Char}; + + {aligned, Content} -> + {ok, Content}; + + _ -> + {error, nil} + end end), + gleam@string:join(_pipe@2, <<""/utf8>>) end), + gleam@string:join(_pipe@3, <<"\n"/utf8>>) + end, + Header@1 = begin + _pipe@4 = erlang:element(2, Table), + _pipe@5 = gleam@option:map( + _pipe@4, + fun(Header) -> <<Header/binary, "\n"/utf8>> end + ), + gleam@option:unwrap(_pipe@5, <<""/utf8>>) + end, + <<Header@1/binary, Rows/binary>>. + +-spec pad_left(binary(), integer(), binary()) -> binary(). +pad_left(Str, Num, Char) -> + Padding = begin + _pipe = gleam@list:repeat(Char, Num), + gleam@string:join(_pipe, <<""/utf8>>) + end, + <<Padding/binary, Str/binary>>. + +-spec pad_right(binary(), integer(), binary()) -> binary(). +pad_right(Str, Num, Char) -> + Padding = begin + _pipe = gleam@list:repeat(Char, Num), + gleam@string:join(_pipe, <<""/utf8>>) + end, + <<Str/binary, Padding/binary>>. + +-spec align_table(table()) -> table(). +align_table(Table) -> + Cols = begin + _pipe = erlang:element(3, Table), + gleam@list:transpose(_pipe) + end, + Col_width = begin + _pipe@1 = Cols, + gleam@list:map(_pipe@1, fun(Col) -> _pipe@2 = Col, + _pipe@3 = gleam@list:map( + _pipe@2, + fun(Content) -> case Content of + {align_right, {content, Unstyled}, _} -> + Unstyled; + + {align_right, {styled_content, Styled}, _} -> + showtime@internal@reports@styles:strip_style( + Styled + ); + + {align_left, {content, Unstyled@1}, _} -> + Unstyled@1; + + {align_left, {styled_content, Styled@1}, _} -> + showtime@internal@reports@styles:strip_style( + Styled@1 + ); + + {align_left_overflow, _, _} -> + <<""/utf8>>; + + {align_right_overflow, _, _} -> + <<""/utf8>>; + + {separator, Char} -> + Char; + + {aligned, Content@1} -> + Content@1 + end end + ), + gleam@list:fold( + _pipe@3, + 0, + fun(Max, Str) -> + gleam@int:max(Max, gleam@string:length(Str)) + end + ) end) + end, + Aligned_col = begin + _pipe@4 = Cols, + _pipe@5 = gleam@list:zip(_pipe@4, Col_width), + gleam@list:map( + _pipe@5, + fun(Col_and_width) -> + {Col@1, Width} = Col_and_width, + _pipe@6 = Col@1, + gleam@list:map(_pipe@6, fun(Content@2) -> case Content@2 of + {align_right, {content, Unstyled@2}, Margin} -> + {aligned, + pad_left( + Unstyled@2, + (Width + Margin) - gleam@string:length( + Unstyled@2 + ), + <<" "/utf8>> + )}; + + {align_right, {styled_content, Styled@2}, Margin@1} -> + {aligned, + pad_left( + Styled@2, + (Width + Margin@1) - gleam@string:length( + showtime@internal@reports@styles:strip_style( + Styled@2 + ) + ), + <<" "/utf8>> + )}; + + {align_right_overflow, + {content, Unstyled@3}, + Margin@2} -> + {aligned, + pad_left( + Unstyled@3, + (Width + Margin@2) - gleam@string:length( + Unstyled@3 + ), + <<" "/utf8>> + )}; + + {align_right_overflow, + {styled_content, Styled@3}, + Margin@3} -> + {aligned, + pad_left( + Styled@3, + (Width + Margin@3) - gleam@string:length( + showtime@internal@reports@styles:strip_style( + Styled@3 + ) + ), + <<" "/utf8>> + )}; + + {align_left, {content, Unstyled@4}, Margin@4} -> + {aligned, + pad_right( + Unstyled@4, + (Width + Margin@4) - gleam@string:length( + Unstyled@4 + ), + <<" "/utf8>> + )}; + + {align_left, {styled_content, Styled@4}, Margin@5} -> + {aligned, + pad_right( + Styled@4, + (Width + Margin@5) - gleam@string:length( + showtime@internal@reports@styles:strip_style( + Styled@4 + ) + ), + <<" "/utf8>> + )}; + + {align_left_overflow, + {content, Unstyled@5}, + Margin@6} -> + {aligned, + pad_right( + Unstyled@5, + (Width + Margin@6) - gleam@string:length( + Unstyled@5 + ), + <<" "/utf8>> + )}; + + {align_left_overflow, + {styled_content, Styled@5}, + Margin@7} -> + {aligned, + pad_right( + Styled@5, + (Width + Margin@7) - gleam@string:length( + showtime@internal@reports@styles:strip_style( + Styled@5 + ) + ), + <<" "/utf8>> + )}; + + {separator, Char@1} -> + {separator, Char@1}; + + {aligned, Content@3} -> + {aligned, Content@3} + end end) + end + ) + end, + Aligned_rows = begin + _pipe@7 = Aligned_col, + gleam@list:transpose(_pipe@7) + end, + erlang:setelement(3, Table, Aligned_rows). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.cache Binary files differnew file mode 100644 index 0000000..d9b2000 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.cache_meta Binary files differnew file mode 100644 index 0000000..7f1bdda --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.erl new file mode 100644 index 0000000..904345a --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.erl @@ -0,0 +1,8 @@ +-module(showtime@tests@meta). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export_type([meta/0]). + +-type meta() :: {meta, binary(), list(binary())}. + + diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.cache Binary files differnew file mode 100644 index 0000000..1adcc9d --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.cache_meta Binary files differnew file mode 100644 index 0000000..fcc4e8a --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.erl new file mode 100644 index 0000000..88dafdd --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.erl @@ -0,0 +1,143 @@ +-module(showtime@tests@should). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([evaluate/1, equal/2, equal_meta/3, not_equal/2, not_equal_meta/3, be_ok/1, be_ok_meta/2, be_error/1, be_error_meta/2, fail/0, fail_meta/1, be_true/1, be_true_meta/2, be_false/1, be_false_meta/2]). +-export_type([assertion/2]). + +-type assertion(OEX, OEY) :: {eq, + OEX, + OEX, + gleam@option:option(showtime@tests@meta:meta())} | + {not_eq, OEX, OEX, gleam@option:option(showtime@tests@meta:meta())} | + {is_ok, + {ok, OEX} | {error, OEY}, + gleam@option:option(showtime@tests@meta:meta())} | + {is_error, + {ok, OEX} | {error, OEY}, + gleam@option:option(showtime@tests@meta:meta())} | + {fail, gleam@option:option(showtime@tests@meta:meta())}. + +-spec evaluate(assertion(any(), any())) -> nil. +evaluate(Assertion) -> + case Assertion of + {eq, A, B, _} -> + case A =:= B of + true -> + nil; + + false -> + showtime_ffi:gleam_error({error, Assertion}) + end; + + {not_eq, A@1, B@1, _} -> + case A@1 /= B@1 of + true -> + nil; + + false -> + showtime_ffi:gleam_error({error, Assertion}) + end; + + {is_ok, A@2, _} -> + case A@2 of + {ok, _} -> + nil; + + {error, _} -> + showtime_ffi:gleam_error({error, Assertion}) + end; + + {is_error, A@3, _} -> + case A@3 of + {error, _} -> + nil; + + {ok, _} -> + showtime_ffi:gleam_error({error, Assertion}) + end; + + {fail, _} -> + showtime_ffi:gleam_error({error, Assertion}) + end. + +-spec equal(OEZ, OEZ) -> nil. +equal(A, B) -> + evaluate({eq, A, B, none}). + +-spec equal_meta(OFB, OFB, showtime@tests@meta:meta()) -> nil. +equal_meta(A, B, Meta) -> + evaluate({eq, A, B, {some, Meta}}). + +-spec not_equal(OFD, OFD) -> nil. +not_equal(A, B) -> + evaluate({not_eq, A, B, none}). + +-spec not_equal_meta(OFF, OFF, showtime@tests@meta:meta()) -> nil. +not_equal_meta(A, B, Meta) -> + evaluate({not_eq, A, B, {some, Meta}}). + +-spec be_ok({ok, OFH} | {error, any()}) -> OFH. +be_ok(A) -> + evaluate({is_ok, A, none}), + {ok, Value} = case A of + {ok, _} -> A; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/tests/should"/utf8>>, + function => <<"be_ok"/utf8>>, + line => 30}) + end, + Value. + +-spec be_ok_meta({ok, any()} | {error, any()}, showtime@tests@meta:meta()) -> nil. +be_ok_meta(A, Meta) -> + evaluate({is_ok, A, {some, Meta}}). + +-spec be_error({ok, any()} | {error, OFS}) -> OFS. +be_error(A) -> + evaluate({is_error, A, none}), + {error, Value} = case A of + {error, _} -> A; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/tests/should"/utf8>>, + function => <<"be_error"/utf8>>, + line => 40}) + end, + Value. + +-spec be_error_meta({ok, any()} | {error, any()}, showtime@tests@meta:meta()) -> nil. +be_error_meta(A, Meta) -> + evaluate({is_error, A, {some, Meta}}). + +-spec fail() -> nil. +fail() -> + evaluate({fail, none}). + +-spec fail_meta(showtime@tests@meta:meta()) -> nil. +fail_meta(Meta) -> + evaluate({fail, {some, Meta}}). + +-spec be_true(boolean()) -> nil. +be_true(A) -> + _pipe = A, + equal(_pipe, true). + +-spec be_true_meta(boolean(), showtime@tests@meta:meta()) -> nil. +be_true_meta(A, Meta) -> + _pipe = A, + equal_meta(_pipe, true, Meta). + +-spec be_false(boolean()) -> nil. +be_false(A) -> + _pipe = A, + equal(_pipe, false). + +-spec be_false_meta(boolean(), showtime@tests@meta:meta()) -> nil. +be_false_meta(A, Meta) -> + _pipe = A, + equal_meta(_pipe, false, Meta). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.cache b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.cache Binary files differnew file mode 100644 index 0000000..06be22a --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.cache diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.cache_meta Binary files differnew file mode 100644 index 0000000..8354c6f --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.cache_meta diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.erl new file mode 100644 index 0000000..115dbb1 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.erl @@ -0,0 +1,57 @@ +-module(showtime@tests@test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([test/2, equal/3, not_equal/3, with_meta/2, be_ok/2, be_error/2, fail/1, be_true/2, be_false/2]). +-export_type([test/0, meta_should/1]). + +-type test() :: {test, showtime@tests@meta:meta(), fun(() -> nil)}. + +-type meta_should(PQU) :: {meta_should, + fun((PQU, PQU) -> nil), + fun((PQU, PQU) -> nil)}. + +-spec test(showtime@tests@meta:meta(), fun((showtime@tests@meta:meta()) -> nil)) -> test(). +test(Meta, Test_function) -> + {test, Meta, fun() -> Test_function(Meta) end}. + +-spec equal(PQZ, PQZ, showtime@tests@meta:meta()) -> nil. +equal(A, B, Meta) -> + gleam@io:debug(A), + gleam@io:debug(B), + showtime@tests@should:equal_meta(A, B, Meta). + +-spec not_equal(PRB, PRB, showtime@tests@meta:meta()) -> nil. +not_equal(A, B, Meta) -> + showtime@tests@should:equal_meta(A, B, Meta). + +-spec with_meta(showtime@tests@meta:meta(), fun((meta_should(any())) -> nil)) -> test(). +with_meta(Meta, Test_function) -> + {test, + Meta, + fun() -> + Test_function( + {meta_should, + fun(A, B) -> equal(A, B, Meta) end, + fun(A@1, B@1) -> not_equal(A@1, B@1, Meta) end} + ) + end}. + +-spec be_ok({ok, any()} | {error, any()}, showtime@tests@meta:meta()) -> nil. +be_ok(A, Meta) -> + showtime@tests@should:be_ok_meta(A, Meta). + +-spec be_error({ok, any()} | {error, any()}, showtime@tests@meta:meta()) -> nil. +be_error(A, Meta) -> + showtime@tests@should:be_error_meta(A, Meta). + +-spec fail(showtime@tests@meta:meta()) -> nil. +fail(Meta) -> + showtime@tests@should:fail_meta(Meta). + +-spec be_true(boolean(), showtime@tests@meta:meta()) -> nil. +be_true(A, Meta) -> + showtime@tests@should:be_true_meta(A, Meta). + +-spec be_false(boolean(), showtime@tests@meta:meta()) -> nil. +be_false(A, Meta) -> + showtime@tests@should:be_false_meta(A, Meta). diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime_ffi.erl b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime_ffi.erl new file mode 100644 index 0000000..3259623 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime_ffi.erl @@ -0,0 +1,187 @@ +-module(showtime_ffi). + +-export([run_test/4, functions/0, capture_output/1, gleam_error/1]). + +gleam_error(Value) -> + erlang:error(#{ + gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => Value, + module => <<"this/is/not/used"/utf8>>, + function => <<"gleam_error"/utf8>>, + % Not used + line => 0 + }). + +start_output_capture(Capture) -> + OldGroupLeader = group_leader(), + CapturePid = spawn(showtime_ffi, capture_output, [{[], {OldGroupLeader, Capture}}]), + group_leader(CapturePid, self()), + {CapturePid, OldGroupLeader}. + +stop_output_capture({CapturePid, OldGroupLeader}) -> + group_leader(OldGroupLeader, self()), + CapturePid ! {capture_done, self()}, + receive + Buffer -> + Buffer + end. + +capture_output({Buffer, {OldGroupLeader, Capture}}) -> + receive + {io_request, From, ReplyAs, {put_chars, unicode, BitString}} -> + case Capture of + yes -> + From ! {io_reply, ReplyAs, ok}, + capture_output({[BitString | Buffer], {OldGroupLeader, Capture}}); + mixed -> + OldGroupLeader ! {io_request, From, ReplyAs, {put_chars, unicode, BitString}}, + capture_output({[BitString | Buffer], {OldGroupLeader, Capture}}); + no -> + OldGroupLeader ! {io_request, From, ReplyAs, {put_chars, unicode, BitString}}, + capture_output({Buffer, {OldGroupLeader, Capture}}) + end; + {capture_done, SenderPid} -> + SenderPid ! Buffer; + OtherMessage -> + OldGroupLeader ! OtherMessage, + capture_output({Buffer, {OldGroupLeader, Capture}}) + end. + +run_test(Module, Function, IgnoreTags, Capture) -> + OutputCapture = start_output_capture(Capture), + try + Result = apply(Module, Function, []), + {ResultType, FinalResult} = + case Result of + {test, {meta, _Description, Tags}, TestFun} -> + case + lists:any( + fun(Tag) -> + lists:any(fun(IgnoreTag) -> IgnoreTag == Tag end, IgnoreTags) + end, + Tags + ) + of + true -> + {ignored, ignore}; + false -> + {test_function_return, TestFun()} + end; + DirectResult -> + {test_function_return, DirectResult} + end, + OutputCaptureBuffer = stop_output_capture(OutputCapture), + case ResultType of + ignored -> {ok, {ResultType, FinalResult}}; + _ -> {ok, {ResultType, FinalResult, OutputCaptureBuffer}} + end + catch + Class:Reason:Stacktrace -> + GleamReason = + case Reason of + {Assertion, ReasonList} -> + ErlangReasonList = + lists:map( + fun(ReasonDetail) -> + case ReasonDetail of + {line, LineNo} -> + {reason_line, LineNo}; + {expression, List} -> + {expression, list_to_binary(List)}; + {module, ModuleAtom} -> + {module, atom_to_binary(ModuleAtom)}; + {pattern, Pattern} -> + {pattern, list_to_binary(Pattern)}; + Other -> + Other + end + end, + ReasonList + ), + GleamAssertionType = + case Assertion of + assertEqual -> + assert_equal; + assertNotEqual -> + assert_not_equal; + assertMatch -> + assert_match; + OtherAssertionType -> + OtherAssertionType + end, + {GleamAssertionType, ErlangReasonList}; + #{ + function := GleamFunction, + gleam_error := GleamError, + line := Line, + message := Message, + module := GleamModule, + value := Value + } -> + case Value of + {error, {OkValue, _, _, _}} when OkValue == not_eq; OkValue == eq -> + {gleam_error, + {GleamError, GleamModule, GleamFunction, Line, Message, Value}}; + {error, {OkValue, _, _}} when OkValue == is_ok; OkValue == is_error -> + {gleam_error, + {GleamError, GleamModule, GleamFunction, Line, Message, Value}}; + {error, {OkValue, _}} when OkValue == fail -> + {gleam_error, + {GleamError, GleamModule, GleamFunction, Line, Message, Value}}; + _ -> + {gleam_assert, Value, Line} + end; + OtherReason -> + {generic_exception, OtherReason} + end, + GleamClass = + case Class of + error -> + erlang_error; + Other -> + Other + end, + GleamTraceList = + lists:map( + fun(Trace) -> + case Trace of + {ModuleName, FunctionName, Arity, ExtraInfoList} -> + {trace_module, atom_to_binary(ModuleName), + atom_to_binary(FunctionName), map_arity(Arity), + map_extra_info_list(ExtraInfoList)}; + {FunctionName, Arity, ExtraInfoList} -> + {trace, atom_to_binary(FunctionName), map_arity(Arity), + map_extra_info_list(ExtraInfoList)} + end + end, + Stacktrace + ), + OutputCaptureBufferCatch = stop_output_capture(OutputCapture), + {error, + {erlang_exception, GleamClass, GleamReason, {trace_list, GleamTraceList}, + OutputCaptureBufferCatch}} + end. + +map_extra_info_list(ExtraInfoList) -> + lists:map( + fun(ExtraInfo) -> + case ExtraInfo of + {file, FileNameList} -> {file, list_to_binary(FileNameList)}; + Other -> Other + end + end, + ExtraInfoList + ). + +map_arity(Arity) -> + if + is_list(Arity) -> + {arg_list, Arity}; + is_integer(Arity) -> + {num, Arity} + end. + +functions() -> + Funs = module_info(exports), + Funs. diff --git a/aoc2023/build/dev/erlang/adglent/ebin/adglent.app b/aoc2023/build/dev/erlang/adglent/ebin/adglent.app new file mode 100644 index 0000000..f8e1aa6 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/adglent.app @@ -0,0 +1,17 @@ +{application, adglent, [ + {vsn, "1.2.0"}, + {applications, [gap, + gleam_community_ansi, + gleam_erlang, + gleam_http, + gleam_httpc, + gleam_otp, + gleam_stdlib, + glint, + simplifile, + snag, + tom]}, + {description, "Advent of code helper - automating setup of tests, solution template and problem input"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/adglent/ebin/adglent.beam b/aoc2023/build/dev/erlang/adglent/ebin/adglent.beam Binary files differnew file mode 100644 index 0000000..aad1d26 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/adglent.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/adglent@day.beam b/aoc2023/build/dev/erlang/adglent/ebin/adglent@day.beam Binary files differnew file mode 100644 index 0000000..b7c03ed --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/adglent@day.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/adglent@init.beam b/aoc2023/build/dev/erlang/adglent/ebin/adglent@init.beam Binary files differnew file mode 100644 index 0000000..be1eae9 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/adglent@init.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/adglent_ffi.beam b/aoc2023/build/dev/erlang/adglent/ebin/adglent_ffi.beam Binary files differnew file mode 100644 index 0000000..1c75150 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/adglent_ffi.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@aoc_client.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@aoc_client.beam Binary files differnew file mode 100644 index 0000000..85aa9ae --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@aoc_client.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@errors.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@errors.beam Binary files differnew file mode 100644 index 0000000..c8778d1 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@errors.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@prompt.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@prompt.beam Binary files differnew file mode 100644 index 0000000..0228df2 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@prompt.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@template.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@template.beam Binary files differnew file mode 100644 index 0000000..4a3c938 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@template.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@solution.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@solution.beam Binary files differnew file mode 100644 index 0000000..aaf50f6 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@solution.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@test_main.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@test_main.beam Binary files differnew file mode 100644 index 0000000..d214095 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@test_main.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@testfile_gleeunit.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@testfile_gleeunit.beam Binary files differnew file mode 100644 index 0000000..7dc47b7 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@testfile_gleeunit.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@testfile_showtime.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@testfile_showtime.beam Binary files differnew file mode 100644 index 0000000..3667f53 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@testfile_showtime.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@toml.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@toml.beam Binary files differnew file mode 100644 index 0000000..ce828c9 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@toml.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime.beam Binary files differnew file mode 100644 index 0000000..c1d19b2 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@cli.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@cli.beam Binary files differnew file mode 100644 index 0000000..dec1bcc --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@cli.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@common_event_handler.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@common_event_handler.beam Binary files differnew file mode 100644 index 0000000..50fe885 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@common_event_handler.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@test_result.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@test_result.beam Binary files differnew file mode 100644 index 0000000..277fdd1 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@test_result.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@test_suite.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@test_suite.beam Binary files differnew file mode 100644 index 0000000..42dbbb9 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@test_suite.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@discover.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@discover.beam Binary files differnew file mode 100644 index 0000000..9f5d14e --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@discover.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@event_handler.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@event_handler.beam Binary files differnew file mode 100644 index 0000000..c9a64e1 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@event_handler.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@module_handler.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@module_handler.beam Binary files differnew file mode 100644 index 0000000..6b95d6c --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@module_handler.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@runner.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@runner.beam Binary files differnew file mode 100644 index 0000000..0681641 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@runner.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@compare.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@compare.beam Binary files differnew file mode 100644 index 0000000..cfe37b1 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@compare.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@formatter.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@formatter.beam Binary files differnew file mode 100644 index 0000000..46b885b --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@formatter.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@styles.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@styles.beam Binary files differnew file mode 100644 index 0000000..4fb83b7 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@styles.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@table.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@table.beam Binary files differnew file mode 100644 index 0000000..aaeb33c --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@table.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@meta.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@meta.beam Binary files differnew file mode 100644 index 0000000..ffaff22 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@meta.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@should.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@should.beam Binary files differnew file mode 100644 index 0000000..a87184d --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@should.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@test.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@test.beam Binary files differnew file mode 100644 index 0000000..65f2a87 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@test.beam diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime_ffi.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime_ffi.beam Binary files differnew file mode 100644 index 0000000..982e813 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime_ffi.beam diff --git a/aoc2023/build/dev/erlang/adglent/include/adglent_Example.hrl b/aoc2023/build/dev/erlang/adglent/include/adglent_Example.hrl new file mode 100644 index 0000000..615e473 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/adglent_Example.hrl @@ -0,0 +1 @@ +-record(example, {input :: binary(), answer :: any()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/priv@toml_TomGetError.hrl b/aoc2023/build/dev/erlang/adglent/include/priv@toml_TomGetError.hrl new file mode 100644 index 0000000..4cd5ddd --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/priv@toml_TomGetError.hrl @@ -0,0 +1 @@ +-record(tom_get_error, {error :: tom:get_error()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/priv@toml_TomParseError.hrl b/aoc2023/build/dev/erlang/adglent/include/priv@toml_TomParseError.hrl new file mode 100644 index 0000000..7306934 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/priv@toml_TomParseError.hrl @@ -0,0 +1 @@ +-record(tom_parse_error, {error :: tom:parse_error()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@common_event_handler_Finished.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@common_event_handler_Finished.hrl new file mode 100644 index 0000000..7d24e52 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@common_event_handler_Finished.hrl @@ -0,0 +1 @@ +-record(finished, {num_modules :: integer()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@common_event_handler_HandlerState.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@common_event_handler_HandlerState.hrl new file mode 100644 index 0000000..3efcd39 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@common_event_handler_HandlerState.hrl @@ -0,0 +1,5 @@ +-record(handler_state, { + test_state :: showtime@internal@common@common_event_handler:test_state(), + num_done :: integer(), + events :: gleam@dict:dict(binary(), gleam@dict:dict(binary(), showtime@internal@common@test_suite:test_run())) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ArgList.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ArgList.hrl new file mode 100644 index 0000000..79f34f8 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ArgList.hrl @@ -0,0 +1 @@ +-record(arg_list, {arg_list :: list(gleam@dynamic:dynamic_())}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertEqual.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertEqual.hrl new file mode 100644 index 0000000..c6458ba --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertEqual.hrl @@ -0,0 +1,3 @@ +-record(assert_equal, { + details :: list(showtime@internal@common@test_result:reason_detail()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertMatch.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertMatch.hrl new file mode 100644 index 0000000..4920304 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertMatch.hrl @@ -0,0 +1,3 @@ +-record(assert_match, { + details :: list(showtime@internal@common@test_result:reason_detail()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertNotEqual.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertNotEqual.hrl new file mode 100644 index 0000000..221c15f --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertNotEqual.hrl @@ -0,0 +1,3 @@ +-record(assert_not_equal, { + details :: list(showtime@internal@common@test_result:reason_detail()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ErlangException.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ErlangException.hrl new file mode 100644 index 0000000..9a31ba8 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ErlangException.hrl @@ -0,0 +1,6 @@ +-record(erlang_exception, { + class :: showtime@internal@common@test_result:class(), + reason :: showtime@internal@common@test_result:reason(), + stacktrace :: showtime@internal@common@test_result:trace_list(), + output_buffer :: list(binary()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ErrorInfo.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ErrorInfo.hrl new file mode 100644 index 0000000..4e0244d --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ErrorInfo.hrl @@ -0,0 +1,3 @@ +-record(error_info, { + error_info :: gleam@dict:dict(gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Expected.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Expected.hrl new file mode 100644 index 0000000..5e40ad3 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Expected.hrl @@ -0,0 +1 @@ +-record(expected, {value :: gleam@dynamic:dynamic_()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Expression.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Expression.hrl new file mode 100644 index 0000000..7aa0c35 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Expression.hrl @@ -0,0 +1 @@ +-record(expression, {expression :: binary()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_File.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_File.hrl new file mode 100644 index 0000000..1274b74 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_File.hrl @@ -0,0 +1 @@ +-record(file, {filename :: binary()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GenericException.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GenericException.hrl new file mode 100644 index 0000000..7c33d0d --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GenericException.hrl @@ -0,0 +1 @@ +-record(generic_exception, {value :: gleam@dynamic:dynamic_()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GleamAssert.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GleamAssert.hrl new file mode 100644 index 0000000..095748c --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GleamAssert.hrl @@ -0,0 +1 @@ +-record(gleam_assert, {value :: gleam@dynamic:dynamic_(), line_no :: integer()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GleamError.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GleamError.hrl new file mode 100644 index 0000000..68e6645 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GleamError.hrl @@ -0,0 +1,3 @@ +-record(gleam_error, { + details :: showtime@internal@common@test_result:gleam_error_detail() +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Ignored.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Ignored.hrl new file mode 100644 index 0000000..87b7e2f --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Ignored.hrl @@ -0,0 +1 @@ +-record(ignored, {reason :: showtime@internal@common@test_result:ignore_reason()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_LetAssert.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_LetAssert.hrl new file mode 100644 index 0000000..5f3f60d --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_LetAssert.hrl @@ -0,0 +1,7 @@ +-record(let_assert, { + module :: binary(), + function :: binary(), + line_no :: integer(), + message :: binary(), + value :: gleam@dynamic:dynamic_() +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Line.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Line.hrl new file mode 100644 index 0000000..9807df6 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Line.hrl @@ -0,0 +1 @@ +-record(line, {line_no :: integer()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Module.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Module.hrl new file mode 100644 index 0000000..8002c0c --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Module.hrl @@ -0,0 +1 @@ +-record(module, {name :: binary()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Num.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Num.hrl new file mode 100644 index 0000000..c36efa3 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Num.hrl @@ -0,0 +1 @@ +-record(num, {arity :: integer()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Pattern.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Pattern.hrl new file mode 100644 index 0000000..6aa9c84 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Pattern.hrl @@ -0,0 +1 @@ +-record(pattern, {pattern :: binary()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ReasonLine.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ReasonLine.hrl new file mode 100644 index 0000000..b7ad1ab --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ReasonLine.hrl @@ -0,0 +1 @@ +-record(reason_line, {line_no :: integer()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TestFunctionReturn.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TestFunctionReturn.hrl new file mode 100644 index 0000000..b0bc294 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TestFunctionReturn.hrl @@ -0,0 +1,4 @@ +-record(test_function_return, { + value :: gleam@dynamic:dynamic_(), + output_buffer :: list(binary()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Trace.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Trace.hrl new file mode 100644 index 0000000..4cb007c --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Trace.hrl @@ -0,0 +1,5 @@ +-record(trace, { + function :: binary(), + arity :: showtime@internal@common@test_result:arity_(), + extra_info :: list(showtime@internal@common@test_result:extra_info()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TraceList.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TraceList.hrl new file mode 100644 index 0000000..c1aa9c5 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TraceList.hrl @@ -0,0 +1,3 @@ +-record(trace_list, { + traces :: list(showtime@internal@common@test_result:trace()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TraceModule.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TraceModule.hrl new file mode 100644 index 0000000..595362f --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TraceModule.hrl @@ -0,0 +1,6 @@ +-record(trace_module, { + module :: binary(), + function :: binary(), + arity :: showtime@internal@common@test_result:arity_(), + extra_info :: list(showtime@internal@common@test_result:extra_info()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Value.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Value.hrl new file mode 100644 index 0000000..3a4b0dd --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Value.hrl @@ -0,0 +1 @@ +-record(value, {value :: gleam@dynamic:dynamic_()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_CompletedTestRun.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_CompletedTestRun.hrl new file mode 100644 index 0000000..927a0cf --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_CompletedTestRun.hrl @@ -0,0 +1,6 @@ +-record(completed_test_run, { + test_function :: showtime@internal@common@test_suite:test_function(), + total_time :: integer(), + result :: {ok, showtime@internal@common@test_result:test_return()} | + {error, showtime@internal@common@test_result:exception()} +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTest.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTest.hrl new file mode 100644 index 0000000..13df1bf --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTest.hrl @@ -0,0 +1,6 @@ +-record(end_test, { + test_module :: showtime@internal@common@test_suite:test_module(), + test_function :: showtime@internal@common@test_suite:test_function(), + result :: {ok, showtime@internal@common@test_result:test_return()} | + {error, showtime@internal@common@test_result:exception()} +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTestRun.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTestRun.hrl new file mode 100644 index 0000000..3f78991 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTestRun.hrl @@ -0,0 +1 @@ +-record(end_test_run, {num_modules :: integer()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTestSuite.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTestSuite.hrl new file mode 100644 index 0000000..a7f37b3 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTestSuite.hrl @@ -0,0 +1,3 @@ +-record(end_test_suite, { + test_module :: showtime@internal@common@test_suite:test_module() +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_OngoingTestRun.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_OngoingTestRun.hrl new file mode 100644 index 0000000..f52e5cc --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_OngoingTestRun.hrl @@ -0,0 +1,4 @@ +-record(ongoing_test_run, { + test_function :: showtime@internal@common@test_suite:test_function(), + started_at :: integer() +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_StartTest.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_StartTest.hrl new file mode 100644 index 0000000..d532609 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_StartTest.hrl @@ -0,0 +1,4 @@ +-record(start_test, { + test_module :: showtime@internal@common@test_suite:test_module(), + test_function :: showtime@internal@common@test_suite:test_function() +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_StartTestSuite.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_StartTestSuite.hrl new file mode 100644 index 0000000..d5a03d3 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_StartTestSuite.hrl @@ -0,0 +1,3 @@ +-record(start_test_suite, { + test_module :: showtime@internal@common@test_suite:test_module() +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestFunction.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestFunction.hrl new file mode 100644 index 0000000..a783ba4 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestFunction.hrl @@ -0,0 +1 @@ +-record(test_function, {name :: binary()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestModule.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestModule.hrl new file mode 100644 index 0000000..ee9baaf --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestModule.hrl @@ -0,0 +1 @@ +-record(test_module, {name :: binary(), path :: gleam@option:option(binary())}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestSuite.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestSuite.hrl new file mode 100644 index 0000000..253a946 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestSuite.hrl @@ -0,0 +1,4 @@ +-record(test_suite, { + module :: showtime@internal@common@test_suite:test_module(), + tests :: list(showtime@internal@common@test_suite:test_function()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignLeft.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignLeft.hrl new file mode 100644 index 0000000..ca52968 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignLeft.hrl @@ -0,0 +1,4 @@ +-record(align_left, { + content :: showtime@internal@reports@table:content(), + margin :: integer() +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignLeftOverflow.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignLeftOverflow.hrl new file mode 100644 index 0000000..8d5a673 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignLeftOverflow.hrl @@ -0,0 +1,4 @@ +-record(align_left_overflow, { + content :: showtime@internal@reports@table:content(), + margin :: integer() +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignRight.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignRight.hrl new file mode 100644 index 0000000..7f7a3f0 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignRight.hrl @@ -0,0 +1,4 @@ +-record(align_right, { + content :: showtime@internal@reports@table:content(), + margin :: integer() +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignRightOverflow.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignRightOverflow.hrl new file mode 100644 index 0000000..4fc4536 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignRightOverflow.hrl @@ -0,0 +1,4 @@ +-record(align_right_overflow, { + content :: showtime@internal@reports@table:content(), + margin :: integer() +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Aligned.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Aligned.hrl new file mode 100644 index 0000000..2343dfd --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Aligned.hrl @@ -0,0 +1 @@ +-record(aligned, {content :: binary()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Content.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Content.hrl new file mode 100644 index 0000000..044891b --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Content.hrl @@ -0,0 +1 @@ +-record(content, {unstyled_text :: binary()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Separator.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Separator.hrl new file mode 100644 index 0000000..db3f822 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Separator.hrl @@ -0,0 +1 @@ +-record(separator, {char :: binary()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_StyledContent.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_StyledContent.hrl new file mode 100644 index 0000000..ed500df --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_StyledContent.hrl @@ -0,0 +1 @@ +-record(styled_content, {styled_text :: binary()}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Table.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Table.hrl new file mode 100644 index 0000000..5b41bb1 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Table.hrl @@ -0,0 +1,4 @@ +-record(table, { + header :: gleam@option:option(binary()), + rows :: list(list(showtime@internal@reports@table:col())) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@tests@meta_Meta.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@meta_Meta.hrl new file mode 100644 index 0000000..14184fb --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@meta_Meta.hrl @@ -0,0 +1 @@ +-record(meta, {description :: binary(), tags :: list(binary())}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_Eq.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_Eq.hrl new file mode 100644 index 0000000..6ebea34 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_Eq.hrl @@ -0,0 +1,5 @@ +-record(eq, { + a :: any(), + b :: any(), + meta :: gleam@option:option(showtime@tests@meta:meta()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_Fail.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_Fail.hrl new file mode 100644 index 0000000..cf06a3c --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_Fail.hrl @@ -0,0 +1 @@ +-record(fail, {meta :: gleam@option:option(showtime@tests@meta:meta())}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_IsError.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_IsError.hrl new file mode 100644 index 0000000..e9cabf3 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_IsError.hrl @@ -0,0 +1,4 @@ +-record(is_error, { + a :: {ok, any()} | {error, any()}, + meta :: gleam@option:option(showtime@tests@meta:meta()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_IsOk.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_IsOk.hrl new file mode 100644 index 0000000..37c24ca --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_IsOk.hrl @@ -0,0 +1,4 @@ +-record(is_ok, { + a :: {ok, any()} | {error, any()}, + meta :: gleam@option:option(showtime@tests@meta:meta()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_NotEq.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_NotEq.hrl new file mode 100644 index 0000000..2a6bf48 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_NotEq.hrl @@ -0,0 +1,5 @@ +-record(not_eq, { + a :: any(), + b :: any(), + meta :: gleam@option:option(showtime@tests@meta:meta()) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@tests@test_MetaShould.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@test_MetaShould.hrl new file mode 100644 index 0000000..a814a93 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@test_MetaShould.hrl @@ -0,0 +1,4 @@ +-record(meta_should, { + equal :: fun((any(), any()) -> nil), + not_equal :: fun((any(), any()) -> nil) +}). diff --git a/aoc2023/build/dev/erlang/adglent/include/showtime@tests@test_Test.hrl b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@test_Test.hrl new file mode 100644 index 0000000..e75a0b7 --- /dev/null +++ b/aoc2023/build/dev/erlang/adglent/include/showtime@tests@test_Test.hrl @@ -0,0 +1,4 @@ +-record(test, { + meta :: showtime@tests@meta:meta(), + test_function :: fun(() -> nil) +}). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cache Binary files differnew file mode 100644 index 0000000..de3d10c --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cache_meta Binary files differnew file mode 100644 index 0000000..29c7ca9 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.erl new file mode 100644 index 0000000..6ab21a2 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.erl @@ -0,0 +1,21 @@ +-module(aoc2023). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([main/0]). + +-spec main() -> bitstring(). +main() -> + Trim = 8, + _assert_subject = gleam_stdlib:identity(<<"abcdefgh +abcdefgh"/utf8>>), + <<_:Trim/binary, "\n"/utf8, Rest/binary>> = case _assert_subject of + <<_:Trim/binary, "\n"/utf8, _/binary>> -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"aoc2023"/utf8>>, + function => <<"main"/utf8>>, + line => 9}) + end, + gleam@io:debug(Rest). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023@@main.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023@@main.erl new file mode 100644 index 0000000..ad291f1 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023@@main.erl @@ -0,0 +1,35 @@ +-module('aoc2023@@main'). + +-export([run/1]). + +run(Module) -> + io:setopts(standard_io, [binary, {encoding, utf8}]), + io:setopts(standard_error, [{encoding, utf8}]), + try + {ok, _} = application:ensure_all_started('aoc2023'), + erlang:process_flag(trap_exit, false), + Module:main(), + erlang:halt(0) + catch + Class:Reason:StackTrace -> + print_error(Class, Reason, StackTrace), + erlang:halt(127, [{flush, true}]) + end. + +print_error(Class, Reason, StackTrace) -> + E = erl_error:format_exception( + 1, Class, Reason, StackTrace, fun stack_filter/3, + fun print_stack_frame/2, unicode + ), + io:put_chars(E). + +stack_filter(Module, _F, _A) -> + case Module of + ?MODULE -> true; + erl_eval -> true; + init -> true; + _ -> false + end. + +print_stack_frame(Term, I) -> + io_lib:format("~." ++ integer_to_list(I) ++ "tP", [Term, 50]).
\ No newline at end of file diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.cache Binary files differnew file mode 100644 index 0000000..105c4ea --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.cache_meta Binary files differnew file mode 100644 index 0000000..6612dba --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.erl new file mode 100644 index 0000000..3a2a263 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.erl @@ -0,0 +1,8 @@ +-module(aoc2023_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([main/0]). + +-spec main() -> nil. +main() -> + showtime:main(). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.cache Binary files differnew file mode 100644 index 0000000..72b188e --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.cache_meta Binary files differnew file mode 100644 index 0000000..eba5ba6 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.erl new file mode 100644 index 0000000..ece7e8d --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.erl @@ -0,0 +1,52 @@ +-module(day10@day10_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, <<"7-F7- +.FJ|7 +SJLL7 +|F--J +LJ.LJ"/utf8>>, <<"8"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, <<"7-F7- +.FJ|7 +SJLL7 +|F--J +LJ.LJ"/utf8>>, <<"8"/utf8>>}], + fun(Example) -> _pipe@1 = day10@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"........... +.S-------7. +.|F-----7|. +.||OOOOO||. +.||OOOOO||. +.|L-7OF-J|. +.|II|O|II|. +.L--JOL--J. +.....O....."/utf8>>, + <<"4"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"........... +.S-------7. +.|F-----7|. +.||OOOOO||. +.||OOOOO||. +.|L-7OF-J|. +.|II|O|II|. +.L--JOL--J. +.....O....."/utf8>>, + <<"4"/utf8>>}], + fun(Example) -> _pipe@1 = day10@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.cache Binary files differnew file mode 100644 index 0000000..633f740 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.cache_meta Binary files differnew file mode 100644 index 0000000..5c3181a --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.erl new file mode 100644 index 0000000..f6178a2 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.erl @@ -0,0 +1,340 @@ +-module(day10@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([posn/0]). + +-type posn() :: {posn, integer(), integer()}. + +-spec add_posns(posn(), posn()) -> posn(). +add_posns(P1, P2) -> + {posn, + erlang:element(2, P1) + erlang:element(2, P2), + erlang:element(3, P1) + erlang:element(3, P2)}. + +-spec make_grid(binary()) -> gleam@dict:dict(posn(), binary()). +make_grid(Input) -> + _pipe = (gleam@list:index_map( + gleam@string:split(Input, <<"\n"/utf8>>), + fun(R, Row) -> + gleam@list:index_map( + gleam@string:to_graphemes(Row), + fun(C, Col) -> {{posn, R, C}, Col} end + ) + end + )), + _pipe@1 = gleam@list:flatten(_pipe), + gleam@dict:from_list(_pipe@1). + +-spec count_crossings( + posn(), + gleam@set:set(posn()), + gleam@dict:dict(posn(), binary()), + integer(), + binary() +) -> integer(). +count_crossings(P, Loop, Grid, Acc, Corner) -> + Maybe_cell = gleam@dict:get(Grid, P), + gleam@bool:guard( + Maybe_cell =:= {error, nil}, + Acc, + fun() -> + {ok, Cell} = case Maybe_cell of + {ok, _} -> Maybe_cell; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day10/solve"/utf8>>, + function => <<"count_crossings"/utf8>>, + line => 125}) + end, + Next = add_posns(P, {posn, 0, 1}), + case gleam@set:contains(Loop, P) of + false -> + count_crossings(Next, Loop, Grid, Acc, Corner); + + true -> + case {Corner, Cell} of + {_, <<"|"/utf8>>} -> + count_crossings(Next, Loop, Grid, Acc + 1, Corner); + + {_, <<"F"/utf8>>} -> + count_crossings(Next, Loop, Grid, Acc, Cell); + + {_, <<"L"/utf8>>} -> + count_crossings(Next, Loop, Grid, Acc, Cell); + + {<<"F"/utf8>>, <<"J"/utf8>>} -> + count_crossings( + Next, + Loop, + Grid, + Acc + 1, + <<""/utf8>> + ); + + {<<"L"/utf8>>, <<"7"/utf8>>} -> + count_crossings( + Next, + Loop, + Grid, + Acc + 1, + <<""/utf8>> + ); + + {<<"F"/utf8>>, <<"7"/utf8>>} -> + count_crossings(Next, Loop, Grid, Acc, <<""/utf8>>); + + {<<"L"/utf8>>, <<"J"/utf8>>} -> + count_crossings(Next, Loop, Grid, Acc, <<""/utf8>>); + + {_, _} -> + count_crossings(Next, Loop, Grid, Acc, Corner) + end + end + end + ). + +-spec trace_ray( + posn(), + gleam@set:set(posn()), + gleam@dict:dict(posn(), binary()) +) -> boolean(). +trace_ray(P, Loop, Grid) -> + gleam@bool:guard( + gleam@set:contains(Loop, P), + false, + fun() -> + gleam@int:is_odd(count_crossings(P, Loop, Grid, 0, <<""/utf8>>)) + end + ). + +-spec pipe_neighbors(binary()) -> list(posn()). +pipe_neighbors(Pipe) -> + case Pipe of + <<"|"/utf8>> -> + [{posn, -1, 0}, {posn, 1, 0}]; + + <<"-"/utf8>> -> + [{posn, 0, 1}, {posn, 0, -1}]; + + <<"L"/utf8>> -> + [{posn, -1, 0}, {posn, 0, 1}]; + + <<"F"/utf8>> -> + [{posn, 1, 0}, {posn, 0, 1}]; + + <<"7"/utf8>> -> + [{posn, 1, 0}, {posn, 0, -1}]; + + <<"J"/utf8>> -> + [{posn, -1, 0}, {posn, 0, -1}]; + + _ -> + erlang:error(#{gleam_error => panic, + message => <<"bad pipe"/utf8>>, + module => <<"day10/solve"/utf8>>, + function => <<"pipe_neighbors"/utf8>>, + line => 44}) + end. + +-spec to_next_pipe(posn(), gleam@dict:dict(posn(), binary()), list(posn())) -> list(posn()). +to_next_pipe(Current, Grid, Acc) -> + [Prev | _] = case Acc of + [_ | _] -> Acc; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day10/solve"/utf8>>, + function => <<"to_next_pipe"/utf8>>, + line => 76}) + end, + _assert_subject = gleam@dict:get(Grid, Current), + {ok, Pipe} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day10/solve"/utf8>>, + function => <<"to_next_pipe"/utf8>>, + line => 77}) + end, + gleam@bool:guard( + Pipe =:= <<"S"/utf8>>, + [Current | Acc], + fun() -> + _assert_subject@1 = begin + _pipe = Pipe, + _pipe@1 = pipe_neighbors(_pipe), + gleam@list:filter_map( + _pipe@1, + fun(P) -> case add_posns(P, Current) of + Neighbor when Neighbor =:= Prev -> + {error, nil}; + + Neighbor@1 -> + {ok, Neighbor@1} + end end + ) + end, + [Next] = case _assert_subject@1 of + [_] -> _assert_subject@1; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"day10/solve"/utf8>>, + function => <<"to_next_pipe"/utf8>>, + line => 79}) + end, + to_next_pipe(Next, Grid, [Current | Acc]) + end + ). + +-spec valid_start_direction(gleam@dict:dict(posn(), binary()), posn()) -> posn(). +valid_start_direction(Grid, S) -> + _assert_subject = (gleam@list:filter_map( + [{{posn, -1, 0}, [<<"|"/utf8>>, <<"7"/utf8>>, <<"F"/utf8>>]}, + {{posn, 1, 0}, [<<"|"/utf8>>, <<"J"/utf8>>, <<"L"/utf8>>]}, + {{posn, 0, 1}, [<<"-"/utf8>>, <<"J"/utf8>>, <<"7"/utf8>>]}, + {{posn, 0, -1}, [<<"-"/utf8>>, <<"F"/utf8>>, <<"L"/utf8>>]}], + fun(D) -> + {Delta, Valids} = D, + Neighbor = add_posns(S, Delta), + case gleam@dict:get(Grid, Neighbor) of + {ok, Pipe} -> + case gleam@list:contains(Valids, Pipe) of + true -> + {ok, Neighbor}; + + false -> + {error, nil} + end; + + {error, _} -> + {error, nil} + end + end + )), + [Dir | _] = case _assert_subject of + [_ | _] -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day10/solve"/utf8>>, + function => <<"valid_start_direction"/utf8>>, + line => 59}) + end, + Dir. + +-spec part1(binary()) -> binary(). +part1(Input) -> + Grid = begin + _pipe = Input, + make_grid(_pipe) + end, + _assert_subject = begin + _pipe@1 = Grid, + _pipe@2 = gleam@dict:filter( + _pipe@1, + fun(_, V) -> V =:= <<"S"/utf8>> end + ), + _pipe@3 = gleam@dict:keys(_pipe@2), + gleam@list:first(_pipe@3) + end, + {ok, S} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day10/solve"/utf8>>, + function => <<"part1"/utf8>>, + line => 97}) + end, + _pipe@4 = Grid, + _pipe@5 = valid_start_direction(_pipe@4, S), + _pipe@6 = to_next_pipe(_pipe@5, Grid, [S]), + _pipe@7 = gleam@list:length(_pipe@6), + _pipe@8 = (fun(I) -> ((I - 1) div 2) end)(_pipe@7), + gleam@string:inspect(_pipe@8). + +-spec part2(binary()) -> binary(). +part2(Input) -> + Grid = begin + _pipe = Input, + make_grid(_pipe) + end, + _assert_subject = begin + _pipe@1 = Grid, + _pipe@2 = gleam@dict:filter( + _pipe@1, + fun(_, V) -> V =:= <<"S"/utf8>> end + ), + _pipe@3 = gleam@dict:keys(_pipe@2), + gleam@list:first(_pipe@3) + end, + {ok, S} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day10/solve"/utf8>>, + function => <<"part2"/utf8>>, + line => 145}) + end, + Loop_pipes = begin + _pipe@4 = Grid, + _pipe@5 = valid_start_direction(_pipe@4, S), + _pipe@6 = to_next_pipe(_pipe@5, Grid, [S]), + gleam@set:from_list(_pipe@6) + end, + _pipe@7 = Grid, + _pipe@8 = gleam@dict:keys(_pipe@7), + _pipe@9 = gleam@list:filter( + _pipe@8, + fun(_capture) -> trace_ray(_capture, Loop_pipes, Grid) end + ), + _pipe@10 = gleam@list:length(_pipe@9), + gleam@string:inspect(_pipe@10). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day10/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 165}) + end, + _assert_subject@1 = adglent:get_input(<<"10"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day10/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 166}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.cache Binary files differnew file mode 100644 index 0000000..508a46b --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.cache_meta Binary files differnew file mode 100644 index 0000000..e03372f --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.erl new file mode 100644 index 0000000..01b02bc --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.erl @@ -0,0 +1,68 @@ +-module(day11@day11_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"...#...... +.......#.. +#......... +.......... +......#... +.#........ +.........# +.......... +.......#.. +#...#....."/utf8>>, + <<"374"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"...#...... +.......#.. +#......... +.......... +......#... +.#........ +.........# +.......... +.......#.. +#...#....."/utf8>>, + <<"374"/utf8>>}], + fun(Example) -> _pipe@1 = day11@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"...#...... +.......#.. +#......... +.......... +......#... +.#........ +.........# +.......... +.......#.. +#...#....."/utf8>>, + <<"8410"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"...#...... +.......#.. +#......... +.......... +......#... +.#........ +.........# +.......... +.......#.. +#...#....."/utf8>>, + <<"8410"/utf8>>}], + fun(Example) -> _pipe@1 = day11@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.cache Binary files differnew file mode 100644 index 0000000..64f1e54 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.cache_meta Binary files differnew file mode 100644 index 0000000..0ff3073 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.erl new file mode 100644 index 0000000..344613f --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.erl @@ -0,0 +1,130 @@ +-module(day11@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([posn/0]). + +-type posn() :: {posn, integer(), integer()}. + +-spec find_empty(list(list(binary()))) -> list(integer()). +find_empty(Grid) -> + gleam@list:index_fold( + Grid, + [], + fun(Acc, Row, R) -> case gleam@list:unique(Row) of + [<<"."/utf8>>] -> + [R | Acc]; + + _ -> + Acc + end end + ). + +-spec count_prior_empty_ranks(integer(), list(integer())) -> integer(). +count_prior_empty_ranks(Rank, Empty_ranks) -> + _pipe = Empty_ranks, + _pipe@1 = gleam@list:drop_while(_pipe, fun(R_empty) -> R_empty > Rank end), + gleam@list:length(_pipe@1). + +-spec parse_with_expansion(binary(), integer()) -> list(posn()). +parse_with_expansion(Input, Expansion) -> + Add = Expansion - 1, + Grid = begin + _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), + gleam@list:map(_pipe@1, fun gleam@string:to_graphemes/1) + end, + Empty_row_list = find_empty(Grid), + Empty_col_list = find_empty(gleam@list:transpose(Grid)), + _pipe@2 = (gleam@list:index_map( + Grid, + fun(R, Row) -> + gleam@list:index_fold( + Row, + [], + fun(Acc, Cell, C) -> + P = {posn, R, C}, + Empty_r = count_prior_empty_ranks(R, Empty_row_list), + Empty_c = count_prior_empty_ranks(C, Empty_col_list), + case Cell of + <<"#"/utf8>> -> + [{posn, + erlang:element(2, P) + (Empty_r * Add), + erlang:element(3, P) + (Empty_c * Add)} | + Acc]; + + _ -> + Acc + end + end + ) + end + )), + gleam@list:flatten(_pipe@2). + +-spec all_distances(list(posn())) -> integer(). +all_distances(Stars) -> + gleam@list:fold( + gleam@list:combination_pairs(Stars), + 0, + fun(Acc, Pair) -> + {S1, S2} = Pair, + (Acc + gleam@int:absolute_value( + erlang:element(2, S1) - erlang:element(2, S2) + )) + + gleam@int:absolute_value( + erlang:element(3, S1) - erlang:element(3, S2) + ) + end + ). + +-spec find_distances(binary(), integer()) -> binary(). +find_distances(Input, Expand_by) -> + _pipe = Input, + _pipe@1 = parse_with_expansion(_pipe, Expand_by), + _pipe@2 = all_distances(_pipe@1), + gleam@string:inspect(_pipe@2). + +-spec part1(binary()) -> binary(). +part1(Input) -> + find_distances(Input, 2). + +-spec part2(binary()) -> binary(). +part2(Input) -> + find_distances(Input, 1000000). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day11/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 72}) + end, + _assert_subject@1 = adglent:get_input(<<"11"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day11/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 73}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.cache Binary files differnew file mode 100644 index 0000000..849fca3 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.cache_meta Binary files differnew file mode 100644 index 0000000..51c4010 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.erl new file mode 100644 index 0000000..d4daa75 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.erl @@ -0,0 +1,38 @@ +-module(day12@day12_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"???.### 1,1,3 +.??..??...?##. 1,1,3 +?#?#?#?#?#?#?#? 1,3,1,6 +????.#...#... 4,1,1 +????.######..#####. 1,6,5 +?###???????? 3,2,1"/utf8>>, + <<"21"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"???.### 1,1,3 +.??..??...?##. 1,1,3 +?#?#?#?#?#?#?#? 1,3,1,6 +????.#...#... 4,1,1 +????.######..#####. 1,6,5 +?###???????? 3,2,1"/utf8>>, + <<"21"/utf8>>}], + fun(Example) -> _pipe@1 = day12@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [], + fun(Example) -> _pipe@1 = day12@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.cache Binary files differnew file mode 100644 index 0000000..f0476d1 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.cache_meta Binary files differnew file mode 100644 index 0000000..d8f9228 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.erl new file mode 100644 index 0000000..1331abe --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.erl @@ -0,0 +1,145 @@ +-module(day12@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). + +-spec parse_folds(binary(), integer()) -> list({binary(), list(integer())}). +parse_folds(Input, Folds) -> + Records = gleam@string:split(Input, <<"\n"/utf8>>), + gleam@list:map( + Records, + fun(Record) -> + _assert_subject = gleam@string:split_once(Record, <<" "/utf8>>), + {ok, {Template, Sets_str}} = case _assert_subject of + {ok, {_, _}} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day12/solve"/utf8>>, + function => <<"parse_folds"/utf8>>, + line => 15}) + end, + Template@1 = begin + _pipe = Template, + _pipe@1 = gleam@list:repeat(_pipe, Folds), + _pipe@2 = gleam@list:intersperse(_pipe@1, <<"?"/utf8>>), + gleam@string:concat(_pipe@2) + end, + Sets = begin + _pipe@3 = Sets_str, + _pipe@4 = gleam@string:split(_pipe@3, <<","/utf8>>), + _pipe@5 = gleam@list:map(_pipe@4, fun gleam@int:parse/1), + _pipe@6 = gleam@result:values(_pipe@5), + _pipe@7 = gleam@list:repeat(_pipe@6, Folds), + gleam@list:flatten(_pipe@7) + end, + {Template@1, Sets} + end + ). + +-spec do_count( + binary(), + list(integer()), + integer(), + boolean(), + utilities@memo:cache({binary(), list(integer()), integer(), boolean()}, integer()) +) -> integer(). +do_count(Template, Groups, Left, Gap, Cache) -> + utilities@memo:memoize( + Cache, + {Template, Groups, Left, Gap}, + fun() -> case {Template, Groups, Left, Gap} of + {<<""/utf8>>, [], 0, _} -> + 1; + + {<<"?"/utf8, T_rest/binary>>, [G | G_rest], 0, false} -> + do_count(T_rest, G_rest, G - 1, G =:= 1, Cache) + do_count( + T_rest, + Groups, + 0, + false, + Cache + ); + + {<<"?"/utf8, T_rest@1/binary>>, [], 0, false} -> + do_count(T_rest@1, Groups, 0, false, Cache); + + {<<"?"/utf8, T_rest@1/binary>>, _, 0, true} -> + do_count(T_rest@1, Groups, 0, false, Cache); + + {<<"."/utf8, T_rest@1/binary>>, _, 0, _} -> + do_count(T_rest@1, Groups, 0, false, Cache); + + {<<"#"/utf8, T_rest@2/binary>>, [G@1 | G_rest@1], 0, false} -> + do_count(T_rest@2, G_rest@1, G@1 - 1, G@1 =:= 1, Cache); + + {<<"?"/utf8, T_rest@3/binary>>, Gs, L, false} -> + do_count(T_rest@3, Gs, L - 1, L =:= 1, Cache); + + {<<"#"/utf8, T_rest@3/binary>>, Gs, L, false} -> + do_count(T_rest@3, Gs, L - 1, L =:= 1, Cache); + + {_, _, _, _} -> + 0 + end end + ). + +-spec count_solutions(integer(), {binary(), list(integer())}) -> integer(). +count_solutions(Acc, Condition) -> + utilities@memo:create( + fun(Cache) -> + {Template, Groups} = Condition, + Acc + do_count(Template, Groups, 0, false, Cache) + end + ). + +-spec part1(binary()) -> binary(). +part1(Input) -> + _pipe = Input, + _pipe@1 = parse_folds(_pipe, 1), + _pipe@2 = gleam@list:fold(_pipe@1, 0, fun count_solutions/2), + gleam@string:inspect(_pipe@2). + +-spec part2(binary()) -> binary(). +part2(Input) -> + _pipe = Input, + _pipe@1 = parse_folds(_pipe, 5), + _pipe@2 = gleam@list:fold(_pipe@1, 0, fun count_solutions/2), + gleam@string:inspect(_pipe@2). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day12/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 78}) + end, + _assert_subject@1 = adglent:get_input(<<"12"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day12/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 79}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.cache Binary files differnew file mode 100644 index 0000000..5ea210b --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.cache_meta Binary files differnew file mode 100644 index 0000000..034e2de --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.erl new file mode 100644 index 0000000..08f1bec --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.erl @@ -0,0 +1,88 @@ +-module(day13@day13_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"#.##..##. +..#.##.#. +##......# +##......# +..#.##.#. +..##..##. +#.#.##.#. + +#...##..# +#....#..# +..##..### +#####.##. +#####.##. +..##..### +#....#..#"/utf8>>, + <<"405"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"#.##..##. +..#.##.#. +##......# +##......# +..#.##.#. +..##..##. +#.#.##.#. + +#...##..# +#....#..# +..##..### +#####.##. +#####.##. +..##..### +#....#..#"/utf8>>, + <<"405"/utf8>>}], + fun(Example) -> _pipe@1 = day13@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"#.##..##. +..#.##.#. +##......# +##......# +..#.##.#. +..##..##. +#.#.##.#. + +#...##..# +#....#..# +..##..### +#####.##. +#####.##. +..##..### +#....#..#"/utf8>>, + <<"400"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"#.##..##. +..#.##.#. +##......# +##......# +..#.##.#. +..##..##. +#.#.##.#. + +#...##..# +#....#..# +..##..### +#####.##. +#####.##. +..##..### +#....#..#"/utf8>>, + <<"400"/utf8>>}], + fun(Example) -> _pipe@1 = day13@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.cache Binary files differnew file mode 100644 index 0000000..0d31dbe --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.cache_meta Binary files differnew file mode 100644 index 0000000..ee31fa5 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.erl new file mode 100644 index 0000000..ffe8959 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.erl @@ -0,0 +1,149 @@ +-module(day13@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([symmetry_type/0]). + +-type symmetry_type() :: {horizontal, integer()} | {vertical, integer()}. + +-spec do_is_symmetric(list(list(BVU)), list(list(BVU)), integer()) -> {ok, + integer()} | + {error, nil}. +do_is_symmetric(Left, Right, Errors) -> + gleam@bool:guard( + gleam@list:is_empty(Right), + {error, nil}, + fun() -> + [H | T] = case Right of + [_ | _] -> Right; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day13/solve"/utf8>>, + function => <<"do_is_symmetric"/utf8>>, + line => 23}) + end, + Found_errors = begin + _pipe = gleam@list:zip( + gleam@list:flatten(Left), + gleam@list:flatten(Right) + ), + _pipe@1 = gleam@list:filter( + _pipe, + fun(Tup) -> + erlang:element(2, Tup) /= erlang:element(1, Tup) + end + ), + gleam@list:length(_pipe@1) + end, + case Found_errors =:= Errors of + true -> + {ok, gleam@list:length(Left)}; + + false -> + do_is_symmetric([H | Left], T, Errors) + end + end + ). + +-spec is_symmetric(list(list(any())), integer()) -> {ok, integer()} | + {error, nil}. +is_symmetric(Xss, Errs) -> + [Left | Right] = case Xss of + [_ | _] -> Xss; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day13/solve"/utf8>>, + function => <<"is_symmetric"/utf8>>, + line => 13}) + end, + do_is_symmetric([Left], Right, Errs). + +-spec get_symmetry_type(list(list(binary())), integer()) -> symmetry_type(). +get_symmetry_type(Xss, Errors) -> + case is_symmetric(Xss, Errors) of + {ok, N} -> + {horizontal, N}; + + _ -> + _assert_subject = is_symmetric(gleam@list:transpose(Xss), Errors), + {ok, N@1} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day13/solve"/utf8>>, + function => <<"get_symmetry_type"/utf8>>, + line => 38}) + end, + {vertical, N@1} + end. + +-spec summarize_notes(list(symmetry_type())) -> integer(). +summarize_notes(Symmetries) -> + gleam@list:fold(Symmetries, 0, fun(Acc, Note) -> Acc + case Note of + {horizontal, N} -> + 100 * N; + + {vertical, N@1} -> + N@1 + end end). + +-spec solve(binary(), integer()) -> binary(). +solve(Input, Errors) -> + _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<"\n\n"/utf8>>), + _pipe@5 = gleam@list:map(_pipe@1, fun(Strs) -> _pipe@2 = Strs, + _pipe@3 = gleam@string:split(_pipe@2, <<"\n"/utf8>>), + _pipe@4 = gleam@list:map(_pipe@3, fun gleam@string:to_graphemes/1), + get_symmetry_type(_pipe@4, Errors) end), + _pipe@6 = summarize_notes(_pipe@5), + gleam@string:inspect(_pipe@6). + +-spec part1(binary()) -> binary(). +part1(Input) -> + solve(Input, 0). + +-spec part2(binary()) -> binary(). +part2(Input) -> + solve(Input, 1). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day13/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 75}) + end, + _assert_subject@1 = adglent:get_input(<<"13"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day13/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 76}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.cache Binary files differnew file mode 100644 index 0000000..cb5c2df --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.cache_meta Binary files differnew file mode 100644 index 0000000..af65466 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.erl new file mode 100644 index 0000000..fd81f21 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.erl @@ -0,0 +1,68 @@ +-module(day14@day14_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"O....#.... +O.OO#....# +.....##... +OO.#O....O +.O.....O#. +O.#..O.#.# +..O..#O..O +.......O.. +#....###.. +#OO..#...."/utf8>>, + <<"136"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"O....#.... +O.OO#....# +.....##... +OO.#O....O +.O.....O#. +O.#..O.#.# +..O..#O..O +.......O.. +#....###.. +#OO..#...."/utf8>>, + <<"136"/utf8>>}], + fun(Example) -> _pipe@1 = day14@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"O....#.... +O.OO#....# +.....##... +OO.#O....O +.O.....O#. +O.#..O.#.# +..O..#O..O +.......O.. +#....###.. +#OO..#...."/utf8>>, + <<"64"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"O....#.... +O.OO#....# +.....##... +OO.#O....O +.O.....O#. +O.#..O.#.# +..O..#O..O +.......O.. +#....###.. +#OO..#...."/utf8>>, + <<"64"/utf8>>}], + fun(Example) -> _pipe@1 = day14@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.cache Binary files differnew file mode 100644 index 0000000..2bceb68 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.cache_meta Binary files differnew file mode 100644 index 0000000..f6a8981 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.erl new file mode 100644 index 0000000..11e3202 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.erl @@ -0,0 +1,149 @@ +-module(day14@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). + +-spec parse(binary()) -> list(list(binary())). +parse(Input) -> + _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), + _pipe@2 = gleam@list:map(_pipe@1, fun gleam@string:to_graphemes/1), + gleam@list:transpose(_pipe@2). + +-spec roll_boulders(list(binary())) -> list(binary()). +roll_boulders(Strs) -> + _pipe = (gleam@list:map( + gleam@list:chunk( + Strs, + fun(C) -> (C =:= <<"O"/utf8>>) orelse (C =:= <<"."/utf8>>) end + ), + fun(Chunks) -> + gleam@list:sort( + Chunks, + gleam@order:reverse(fun gleam@string:compare/2) + ) + end + )), + gleam@list:flatten(_pipe). + +-spec score(list(list(binary()))) -> integer(). +score(Matrix) -> + gleam@list:fold( + Matrix, + 0, + fun(Acc, Col) -> + Acc + (gleam@list:index_fold( + gleam@list:reverse(Col), + 0, + fun(Col_acc, Char, N) -> case Char of + <<"O"/utf8>> -> + (Col_acc + N) + 1; + + _ -> + Col_acc + end end + )) + end + ). + +-spec part1(binary()) -> binary(). +part1(Input) -> + _pipe = Input, + _pipe@1 = parse(_pipe), + _pipe@2 = gleam@list:map(_pipe@1, fun roll_boulders/1), + _pipe@3 = score(_pipe@2), + gleam@string:inspect(_pipe@3). + +-spec rotate(list(list(BEG))) -> list(list(BEG)). +rotate(Matrix) -> + _pipe = Matrix, + _pipe@1 = gleam@list:map(_pipe, fun gleam@list:reverse/1), + gleam@list:transpose(_pipe@1). + +-spec spin(list(list(binary()))) -> list(list(binary())). +spin(Matrix) -> + gleam@list:fold(gleam@list:range(1, 4), Matrix, fun(Acc, _) -> _pipe = Acc, + _pipe@1 = gleam@list:map(_pipe, fun roll_boulders/1), + rotate(_pipe@1) end). + +-spec check_if_seen( + list(list(binary())), + gleam@dict:dict(list(list(binary())), integer()), + integer() +) -> integer(). +check_if_seen(Matrix, Cache, Count) -> + case gleam@dict:get(Cache, Matrix) of + {error, nil} -> + check_if_seen( + spin(Matrix), + gleam@dict:insert(Cache, Matrix, Count), + Count - 1 + ); + + {ok, N} -> + _assert_subject = gleam@int:modulo(Count, N - Count), + {ok, Extra} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day14/solve"/utf8>>, + function => <<"check_if_seen"/utf8>>, + line => 67}) + end, + _pipe = gleam@list:fold( + gleam@list:range(1, Extra), + Matrix, + fun(Acc, _) -> spin(Acc) end + ), + score(_pipe) + end. + +-spec spin_cycle(list(list(binary()))) -> integer(). +spin_cycle(Matrix) -> + Cache = gleam@dict:new(), + check_if_seen(Matrix, Cache, 1000000000). + +-spec part2(binary()) -> binary(). +part2(Input) -> + _pipe = Input, + _pipe@1 = parse(_pipe), + _pipe@2 = spin_cycle(_pipe@1), + gleam@string:inspect(_pipe@2). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day14/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 82}) + end, + _assert_subject@1 = adglent:get_input(<<"14"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day14/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 83}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.cache Binary files differnew file mode 100644 index 0000000..ebef31b --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.cache_meta Binary files differnew file mode 100644 index 0000000..2b2eed1 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.erl new file mode 100644 index 0000000..ad6d957 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.erl @@ -0,0 +1,32 @@ +-module(day15@day15_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"/utf8>>, + <<"1320"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"/utf8>>, + <<"1320"/utf8>>}], + fun(Example) -> _pipe@1 = day15@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"/utf8>>, + <<"145"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"/utf8>>, + <<"145"/utf8>>}], + fun(Example) -> _pipe@1 = day15@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.cache Binary files differnew file mode 100644 index 0000000..5f19cbb --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.cache_meta Binary files differnew file mode 100644 index 0000000..9fc44a6 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.erl new file mode 100644 index 0000000..c817452 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.erl @@ -0,0 +1,177 @@ +-module(day15@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([instruction/0]). + +-type instruction() :: {remove, binary()} | {insert, binary(), integer()}. + +-spec split(binary()) -> list(binary()). +split(Input) -> + _pipe = Input, + gleam@string:split(_pipe, <<","/utf8>>). + +-spec hash_algorithm(binary()) -> integer(). +hash_algorithm(Str) -> + Codepoints = begin + _pipe = Str, + _pipe@1 = gleam@string:to_utf_codepoints(_pipe), + gleam@list:map(_pipe@1, fun gleam@string:utf_codepoint_to_int/1) + end, + gleam@list:fold( + Codepoints, + 0, + fun(Acc, C) -> + _assert_subject = gleam@int:modulo((Acc + C) * 17, 256), + {ok, Acc@1} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day15/solve"/utf8>>, + function => <<"hash_algorithm"/utf8>>, + line => 20}) + end, + Acc@1 + end + ). + +-spec part1(binary()) -> binary(). +part1(Input) -> + _pipe = Input, + _pipe@1 = split(_pipe), + _pipe@2 = gleam@list:fold( + _pipe@1, + 0, + fun(Acc, Str) -> Acc + hash_algorithm(Str) end + ), + gleam@string:inspect(_pipe@2). + +-spec read_instruction(binary()) -> instruction(). +read_instruction(Str) -> + case gleam@string:split(Str, <<"="/utf8>>) of + [Label, Focal_str] -> + _assert_subject = gleam@int:parse(Focal_str), + {ok, Focal} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day15/solve"/utf8>>, + function => <<"read_instruction"/utf8>>, + line => 39}) + end, + {insert, Label, Focal}; + + _ -> + {remove, gleam@string:drop_right(Str, 1)} + end. + +-spec remove_lens(gleam@dict:dict(integer(), list({binary(), RCB})), binary()) -> gleam@dict:dict(integer(), list({binary(), + RCB})). +remove_lens(Boxes, Label) -> + gleam@dict:update(Boxes, hash_algorithm(Label), fun(V) -> case V of + {some, Lenses} -> + case gleam@list:key_pop(Lenses, Label) of + {ok, {_, Updated}} -> + Updated; + + {error, nil} -> + Lenses + end; + + none -> + [] + end end). + +-spec insert_lens( + gleam@dict:dict(integer(), list({binary(), RAT})), + binary(), + RAT +) -> gleam@dict:dict(integer(), list({binary(), RAT})). +insert_lens(Boxes, Label, Focal) -> + gleam@dict:update(Boxes, hash_algorithm(Label), fun(V) -> case V of + {some, Lenses} -> + gleam@list:key_set(Lenses, Label, Focal); + + none -> + [{Label, Focal}] + end end). + +-spec parse_instructions(list(binary())) -> gleam@dict:dict(integer(), list({binary(), + integer()})). +parse_instructions(Insts) -> + gleam@list:fold( + Insts, + gleam@dict:new(), + fun(Acc, Inst) -> case read_instruction(Inst) of + {remove, Label} -> + remove_lens(Acc, Label); + + {insert, Label@1, Focal} -> + insert_lens(Acc, Label@1, Focal) + end end + ). + +-spec focusing_power(gleam@dict:dict(integer(), list({binary(), integer()}))) -> integer(). +focusing_power(Boxes) -> + gleam@dict:fold( + Boxes, + 0, + fun(Acc, K, V) -> + Box_acc = (gleam@list:index_fold( + V, + 0, + fun(Acc@1, Lens, I) -> + Acc@1 + (erlang:element(2, Lens) * (I + 1)) + end + )), + Acc + ((K + 1) * Box_acc) + end + ). + +-spec part2(binary()) -> binary(). +part2(Input) -> + _pipe = Input, + _pipe@1 = split(_pipe), + _pipe@2 = parse_instructions(_pipe@1), + _pipe@3 = focusing_power(_pipe@2), + gleam@string:inspect(_pipe@3). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day15/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 92}) + end, + _assert_subject@1 = adglent:get_input(<<"15"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day15/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 93}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.cache Binary files differnew file mode 100644 index 0000000..a8d21d6 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.cache_meta Binary files differnew file mode 100644 index 0000000..7defae5 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.erl new file mode 100644 index 0000000..71bb64d --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.erl @@ -0,0 +1,68 @@ +-module(day16@day16_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<".|...\\.... +|.-.\\..... +.....|-... +........|. +.......... +.........\\ +..../.\\\\.. +.-.-/..|.. +.|....-|.\\ +..//.|...."/utf8>>, + 46}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<".|...\\.... +|.-.\\..... +.....|-... +........|. +.......... +.........\\ +..../.\\\\.. +.-.-/..|.. +.|....-|.\\ +..//.|...."/utf8>>, + 46}], + fun(Example) -> _pipe@1 = day16@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<".|...\\.... +|.-.\\..... +.....|-... +........|. +.......... +.........\\ +..../.\\\\.. +.-.-/..|.. +.|....-|.\\ +..//.|...."/utf8>>, + 51}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<".|...\\.... +|.-.\\..... +.....|-... +........|. +.......... +.........\\ +..../.\\\\.. +.-.-/..|.. +.|....-|.\\ +..//.|...."/utf8>>, + 51}], + fun(Example) -> _pipe@1 = day16@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.cache Binary files differnew file mode 100644 index 0000000..35182e1 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.cache_meta Binary files differnew file mode 100644 index 0000000..70fdb71 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.erl new file mode 100644 index 0000000..9e8b9b2 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.erl @@ -0,0 +1,253 @@ +-module(day16@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([direction/0, light/0]). + +-type direction() :: up | right | down | left. + +-type light() :: {light, utilities@array2d:posn(), direction()}. + +-spec move(light()) -> light(). +move(L) -> + {light, P, Dir} = L, + case Dir of + up -> + erlang:setelement( + 2, + L, + erlang:setelement(2, P, erlang:element(2, P) - 1) + ); + + down -> + erlang:setelement( + 2, + L, + erlang:setelement(2, P, erlang:element(2, P) + 1) + ); + + left -> + erlang:setelement( + 2, + L, + erlang:setelement(3, P, erlang:element(3, P) - 1) + ); + + right -> + erlang:setelement( + 2, + L, + erlang:setelement(3, P, erlang:element(3, P) + 1) + ) + end. + +-spec transform(light(), {ok, binary()} | {error, nil}) -> list(light()). +transform(L, Cell) -> + gleam@bool:guard( + gleam@result:is_error(Cell), + [], + fun() -> + {ok, C} = case Cell of + {ok, _} -> Cell; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day16/solve"/utf8>>, + function => <<"transform"/utf8>>, + line => 33}) + end, + {light, P, Dir} = L, + case {Dir, C} of + {_, <<"."/utf8>>} -> + [L]; + + {up, <<"|"/utf8>>} -> + [L]; + + {down, <<"|"/utf8>>} -> + [L]; + + {left, <<"-"/utf8>>} -> + [L]; + + {right, <<"-"/utf8>>} -> + [L]; + + {left, <<"/"/utf8>>} -> + [{light, P, down}]; + + {down, <<"/"/utf8>>} -> + [{light, P, left}]; + + {right, <<"/"/utf8>>} -> + [{light, P, up}]; + + {up, <<"/"/utf8>>} -> + [{light, P, right}]; + + {left, <<"\\"/utf8>>} -> + [{light, P, up}]; + + {up, <<"\\"/utf8>>} -> + [{light, P, left}]; + + {right, <<"\\"/utf8>>} -> + [{light, P, down}]; + + {down, <<"\\"/utf8>>} -> + [{light, P, right}]; + + {left, <<"|"/utf8>>} -> + [{light, P, up}, {light, P, down}]; + + {right, <<"|"/utf8>>} -> + [{light, P, up}, {light, P, down}]; + + {up, <<"-"/utf8>>} -> + [{light, P, left}, {light, P, right}]; + + {down, <<"-"/utf8>>} -> + [{light, P, left}, {light, P, right}]; + + {_, _} -> + erlang:error(#{gleam_error => panic, + message => <<"unrecognized cell type"/utf8>>, + module => <<"day16/solve"/utf8>>, + function => <<"transform"/utf8>>, + line => 50}) + end + end + ). + +-spec energize( + list(light()), + gleam@set:set(light()), + gleam@dict:dict(utilities@array2d:posn(), binary()) +) -> integer(). +energize(Lights, Visited, Grid) -> + Next_positions = begin + _pipe = Lights, + _pipe@1 = gleam@list:flat_map( + _pipe, + fun(L) -> + Next = move(L), + transform(Next, gleam@dict:get(Grid, erlang:element(2, Next))) + end + ), + gleam@list:filter( + _pipe@1, + fun(L@1) -> not gleam@set:contains(Visited, L@1) end + ) + end, + All_visited = gleam@set:union(gleam@set:from_list(Next_positions), Visited), + case Visited =:= All_visited of + true -> + _pipe@2 = gleam@set:fold( + Visited, + gleam@set:new(), + fun(Acc, L@2) -> + gleam@set:insert(Acc, erlang:element(2, L@2)) + end + ), + _pipe@3 = gleam@set:to_list(_pipe@2), + gleam@list:length(_pipe@3); + + false -> + energize(Next_positions, All_visited, Grid) + end. + +-spec part1(binary()) -> integer(). +part1(Input) -> + Grid = utilities@array2d:parse_grid(Input), + _pipe = [{light, {posn, 0, -1}, right}], + energize(_pipe, gleam@set:new(), Grid). + +-spec part2(binary()) -> integer(). +part2(Input) -> + Grid = utilities@array2d:parse_grid(Input), + {posn, Rows, Cols} = (gleam@list:fold( + gleam@dict:keys(Grid), + {posn, 0, 0}, + fun(Acc, P) -> + case (erlang:element(2, Acc) + erlang:element(3, Acc)) > (erlang:element( + 2, + P + ) + + erlang:element(3, P)) of + true -> + Acc; + + false -> + P + end + end + )), + All_starts = gleam@list:concat( + [gleam@list:map( + gleam@list:range(0, Rows), + fun(R) -> {light, {posn, R, -1}, right} end + ), + gleam@list:map( + gleam@list:range(0, Rows), + fun(R@1) -> {light, {posn, R@1, Cols + 1}, left} end + ), + gleam@list:map( + gleam@list:range(0, Cols), + fun(C) -> {light, {posn, -1, C}, down} end + ), + gleam@list:map( + gleam@list:range(0, Cols), + fun(C@1) -> {light, {posn, Rows + 1, C@1}, up} end + )] + ), + gleam@list:fold( + All_starts, + 0, + fun(Acc@1, P@1) -> + Energized = energize([P@1], gleam@set:new(), Grid), + case Acc@1 > Energized of + true -> + Acc@1; + + false -> + Energized + end + end + ). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day16/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 107}) + end, + _assert_subject@1 = adglent:get_input(<<"16"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day16/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 108}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.cache Binary files differnew file mode 100644 index 0000000..923d0a6 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.cache_meta Binary files differnew file mode 100644 index 0000000..1c9c12b --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.erl new file mode 100644 index 0000000..052b6cc --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.erl @@ -0,0 +1,42 @@ +-module(day17@day17_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"2413432311323 +3215453535623 +3255245654254 +3446585845452 +4546657867536 +1438598798454 +4457876987766 +3637877979653 +4654967986887 +4564679986453 +1224686865563 +2546548887735 +4322674655533"/utf8>>, + <<"102"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"2413432311323 +3215453535623 +3255245654254 +3446585845452 +4546657867536 +1438598798454 +4457876987766 +3637877979653 +4654967986887 +4564679986453 +1224686865563 +2546548887735 +4322674655533"/utf8>>, + <<"102"/utf8>>}], + fun(Example) -> _pipe@1 = day17@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.cache Binary files differnew file mode 100644 index 0000000..b06fb02 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.cache_meta Binary files differnew file mode 100644 index 0000000..aad0cb3 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.erl new file mode 100644 index 0000000..206ab5f --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.erl @@ -0,0 +1,231 @@ +-module(day17@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part2/1, part1/1, main/0]). +-export_type([state/0]). + +-type state() :: {state, + utilities@array2d:posn(), + integer(), + utilities@array2d:posn(), + list(utilities@array2d:posn())}. + +-spec same_dir(state()) -> list(utilities@array2d:posn()). +same_dir(S) -> + case erlang:element(5, S) of + [] -> + []; + + [First | _] = Deltas -> + _pipe = gleam@list:take_while(Deltas, fun(D) -> D =:= First end), + gleam@list:take(_pipe, 10) + end. + +-spec make_key(state()) -> {utilities@array2d:posn(), + list(utilities@array2d:posn())}. +make_key(S) -> + {erlang:element(2, S), same_dir(S)}. + +-spec is_goal(state(), integer(), utilities@array2d:posn()) -> boolean(). +is_goal(S, Min_run, Goal) -> + (Goal =:= erlang:element(2, S)) andalso (gleam@list:length(same_dir(S)) >= Min_run). + +-spec eliminate_bad_neighbors( + utilities@array2d:posn(), + state(), + integer(), + integer(), + gleam@dict:dict(utilities@array2d:posn(), any()) +) -> boolean(). +eliminate_bad_neighbors(D, S, Max, Min, Grid) -> + Neighbor = utilities@array2d:add_posns(D, erlang:element(2, S)), + gleam@bool:guard( + (Neighbor =:= erlang:element(4, S)) orelse not gleam@dict:has_key( + Grid, + Neighbor + ), + false, + fun() -> case {same_dir(S), gleam@list:length(same_dir(S))} of + {[Prev | _], L} when L =:= Max -> + D /= Prev; + + {_, 0} -> + true; + + {[Prev@1 | _], L@1} when L@1 < Min -> + D =:= Prev@1; + + {_, _} -> + true + end end + ). + +-spec make_state( + utilities@array2d:posn(), + state(), + gleam@dict:dict(utilities@array2d:posn(), integer()) +) -> state(). +make_state(D, S, Grid) -> + Neighbor = utilities@array2d:add_posns(D, erlang:element(2, S)), + _assert_subject = gleam@dict:get(Grid, Neighbor), + {ok, Heat_lost} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day17/solve"/utf8>>, + function => <<"make_state"/utf8>>, + line => 58}) + end, + {state, + Neighbor, + erlang:element(3, S) + Heat_lost, + erlang:element(2, S), + [D | erlang:element(5, S)]}. + +-spec find_path( + gleam@dict:dict(utilities@array2d:posn(), integer()), + utilities@prioqueue:priority_queue(state()), + gleam@set:set({utilities@array2d:posn(), list(utilities@array2d:posn())}), + fun((state()) -> list(state())), + fun((state()) -> boolean()) +) -> integer(). +find_path(Grid, Queue, Seen, Get_neighbors, Is_goal) -> + _assert_subject = utilities@prioqueue:pop(Queue), + {ok, {State, Rest}} = case _assert_subject of + {ok, {_, _}} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day17/solve"/utf8>>, + function => <<"find_path"/utf8>>, + line => 74}) + end, + Key = make_key( + begin + _pipe = State, + gleam@io:debug(_pipe) + end + ), + case gleam@set:contains(Seen, Key) of + true -> + find_path(Grid, Rest, Seen, Get_neighbors, Is_goal); + + false -> + Now_seen = gleam@set:insert(Seen, Key), + Neighbors = Get_neighbors(State), + case gleam@list:find(Neighbors, Is_goal) of + {ok, Final} -> + erlang:element(3, Final); + + _ -> + Now_queue = gleam@list:fold( + Neighbors, + Rest, + fun(Acc, N) -> + utilities@prioqueue:insert( + Acc, + N, + erlang:element(3, N) + ) + end + ), + find_path(Grid, Now_queue, Now_seen, Get_neighbors, Is_goal) + end + end. + +-spec part2(binary()) -> binary(). +part2(Input) -> + _pipe = Input, + gleam@string:inspect(_pipe). + +-spec find_good_neighbors( + integer(), + integer(), + state(), + gleam@dict:dict(utilities@array2d:posn(), integer()) +) -> list(state()). +find_good_neighbors(Max, Min, S, Grid) -> + _pipe = [{posn, -1, 0}, {posn, 1, 0}, {posn, 0, -1}, {posn, 0, 1}], + _pipe@1 = gleam@list:filter( + _pipe, + fun(_capture) -> + eliminate_bad_neighbors(_capture, S, Max, Min, Grid) + end + ), + gleam@list:map( + _pipe@1, + fun(_capture@1) -> make_state(_capture@1, S, Grid) end + ). + +-spec part1(binary()) -> binary(). +part1(Input) -> + Raw_grid = begin + _pipe = Input, + utilities@array2d:to_list_of_lists(_pipe) + end, + Grid = utilities@array2d:to_2d_intarray(Raw_grid), + Rmax = gleam@list:length(Raw_grid), + _assert_subject = begin + _pipe@1 = Raw_grid, + _pipe@2 = gleam@list:first(_pipe@1), + gleam@result:map(_pipe@2, fun gleam@list:length/1) + end, + {ok, Cmax} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day17/solve"/utf8>>, + function => <<"part1"/utf8>>, + line => 107}) + end, + Start = {state, {posn, 0, 0}, 0, {posn, 0, 0}, []}, + Goal = {posn, Rmax, Cmax}, + _pipe@3 = find_path( + Grid, + utilities@prioqueue:insert(utilities@prioqueue:new(), Start, 0), + gleam@set:new(), + fun(_capture) -> find_good_neighbors(0, 3, _capture, Grid) end, + fun(_capture@1) -> is_goal(_capture@1, 1, Goal) end + ), + gleam@string:inspect(_pipe@3). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day17/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 131}) + end, + _assert_subject@1 = adglent:get_input(<<"17"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day17/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 132}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.cache Binary files differnew file mode 100644 index 0000000..33f80d2 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.cache_meta Binary files differnew file mode 100644 index 0000000..22ffeb7 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.erl new file mode 100644 index 0000000..76bea52 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.erl @@ -0,0 +1,84 @@ +-module(day18@day18_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"R 6 (#70c710) +D 5 (#0dc571) +L 2 (#5713f0) +D 2 (#d2c081) +R 2 (#59c680) +D 2 (#411b91) +L 5 (#8ceee2) +U 2 (#caa173) +L 1 (#1b58a2) +U 2 (#caa171) +R 2 (#7807d2) +U 3 (#a77fa3) +L 2 (#015232) +U 2 (#7a21e3)"/utf8>>, + <<"62"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"R 6 (#70c710) +D 5 (#0dc571) +L 2 (#5713f0) +D 2 (#d2c081) +R 2 (#59c680) +D 2 (#411b91) +L 5 (#8ceee2) +U 2 (#caa173) +L 1 (#1b58a2) +U 2 (#caa171) +R 2 (#7807d2) +U 3 (#a77fa3) +L 2 (#015232) +U 2 (#7a21e3)"/utf8>>, + <<"62"/utf8>>}], + fun(Example) -> _pipe@1 = day18@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"R 6 (#70c710) +D 5 (#0dc571) +L 2 (#5713f0) +D 2 (#d2c081) +R 2 (#59c680) +D 2 (#411b91) +L 5 (#8ceee2) +U 2 (#caa173) +L 1 (#1b58a2) +U 2 (#caa171) +R 2 (#7807d2) +U 3 (#a77fa3) +L 2 (#015232) +U 2 (#7a21e3)"/utf8>>, + <<"952408144115"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"R 6 (#70c710) +D 5 (#0dc571) +L 2 (#5713f0) +D 2 (#d2c081) +R 2 (#59c680) +D 2 (#411b91) +L 5 (#8ceee2) +U 2 (#caa173) +L 1 (#1b58a2) +U 2 (#caa171) +R 2 (#7807d2) +U 3 (#a77fa3) +L 2 (#015232) +U 2 (#7a21e3)"/utf8>>, + <<"952408144115"/utf8>>}], + fun(Example) -> _pipe@1 = day18@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.cache Binary files differnew file mode 100644 index 0000000..c557ff7 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.cache_meta Binary files differnew file mode 100644 index 0000000..a536e04 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.erl new file mode 100644 index 0000000..4e54297 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.erl @@ -0,0 +1,218 @@ +-module(day18@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([coord/0, direction/0, dig/0]). + +-type coord() :: {coord, integer(), integer()}. + +-type direction() :: up | right | down | left. + +-type dig() :: {dig, direction(), integer()}. + +-spec to_direction(binary()) -> direction(). +to_direction(C) -> + case C of + <<"R"/utf8>> -> + right; + + <<"0"/utf8>> -> + right; + + <<"D"/utf8>> -> + down; + + <<"1"/utf8>> -> + down; + + <<"L"/utf8>> -> + left; + + <<"2"/utf8>> -> + left; + + <<"U"/utf8>> -> + up; + + <<"3"/utf8>> -> + up; + + _ -> + erlang:error(#{gleam_error => panic, + message => <<"panic expression evaluated"/utf8>>, + module => <<"day18/solve"/utf8>>, + function => <<"to_direction"/utf8>>, + line => 30}) + end. + +-spec parse_front(binary()) -> dig(). +parse_front(Line) -> + _assert_subject = gleam@regex:from_string(<<"(.) (.*) \\(.*\\)"/utf8>>), + {ok, Re} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day18/solve"/utf8>>, + function => <<"parse_front"/utf8>>, + line => 35}) + end, + _assert_subject@1 = gleam@regex:scan(Re, Line), + [{match, _, [{some, Dir}, {some, Dist}]}] = case _assert_subject@1 of + [{match, _, [{some, _}, {some, _}]}] -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day18/solve"/utf8>>, + function => <<"parse_front"/utf8>>, + line => 36}) + end, + _assert_subject@2 = gleam@int:parse(Dist), + {ok, N} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"day18/solve"/utf8>>, + function => <<"parse_front"/utf8>>, + line => 38}) + end, + {dig, to_direction(Dir), N}. + +-spec parse_hex(binary()) -> dig(). +parse_hex(Line) -> + _assert_subject = gleam@regex:from_string(<<"\\(#(.....)(.)\\)"/utf8>>), + {ok, Re} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day18/solve"/utf8>>, + function => <<"parse_hex"/utf8>>, + line => 43}) + end, + _assert_subject@1 = gleam@regex:scan(Re, Line), + [{match, _, [{some, Dist}, {some, Dir}]}] = case _assert_subject@1 of + [{match, _, [{some, _}, {some, _}]}] -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day18/solve"/utf8>>, + function => <<"parse_hex"/utf8>>, + line => 44}) + end, + _assert_subject@2 = gleam@int:base_parse(Dist, 16), + {ok, N} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"day18/solve"/utf8>>, + function => <<"parse_hex"/utf8>>, + line => 46}) + end, + {dig, to_direction(Dir), N}. + +-spec go(coord(), dig()) -> coord(). +go(Current, Dig) -> + case Dig of + {dig, up, N} -> + {coord, erlang:element(2, Current), erlang:element(3, Current) + N}; + + {dig, right, N@1} -> + {coord, + erlang:element(2, Current) + N@1, + erlang:element(3, Current)}; + + {dig, down, N@2} -> + {coord, + erlang:element(2, Current), + erlang:element(3, Current) - N@2}; + + {dig, left, N@3} -> + {coord, + erlang:element(2, Current) - N@3, + erlang:element(3, Current)} + end. + +-spec double_triangle(coord(), coord()) -> integer(). +double_triangle(C1, C2) -> + (erlang:element(2, C1) * erlang:element(3, C2)) - (erlang:element(2, C2) * erlang:element( + 3, + C1 + )). + +-spec do_next_dig(list(dig()), coord(), integer(), integer()) -> integer(). +do_next_dig(Digs, Current, Area, Perimeter) -> + case Digs of + [] -> + ((gleam@int:absolute_value(Area) div 2) + (Perimeter div 2)) + 1; + + [Dig | Rest] -> + Next = go(Current, Dig), + Area@1 = Area + double_triangle(Current, Next), + Perimeter@1 = Perimeter + erlang:element(3, Dig), + do_next_dig(Rest, Next, Area@1, Perimeter@1) + end. + +-spec start_dig(list(dig())) -> integer(). +start_dig(Digs) -> + do_next_dig(Digs, {coord, 0, 0}, 0, 0). + +-spec solve_with(binary(), fun((binary()) -> dig())) -> binary(). +solve_with(Input, F) -> + _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), + _pipe@2 = gleam@list:map(_pipe@1, F), + _pipe@3 = start_dig(_pipe@2), + gleam@string:inspect(_pipe@3). + +-spec part1(binary()) -> binary(). +part1(Input) -> + solve_with(Input, fun parse_front/1). + +-spec part2(binary()) -> binary(). +part2(Input) -> + solve_with(Input, fun parse_hex/1). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day18/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 101}) + end, + _assert_subject@1 = adglent:get_input(<<"18"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day18/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 102}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.cache Binary files differnew file mode 100644 index 0000000..32c0bad --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.cache_meta Binary files differnew file mode 100644 index 0000000..56332b7 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.erl new file mode 100644 index 0000000..d9fea80 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.erl @@ -0,0 +1,96 @@ +-module(day19@day19_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"px{a<2006:qkq,m>2090:A,rfg} +pv{a>1716:R,A} +lnx{m>1548:A,A} +rfg{s<537:gd,x>2440:R,A} +qs{s>3448:A,lnx} +qkq{x<1416:A,crn} +crn{x>2662:A,R} +in{s<1351:px,qqz} +qqz{s>2770:qs,m<1801:hdj,R} +gd{a>3333:R,R} +hdj{m>838:A,pv} + +{x=787,m=2655,a=1222,s=2876} +{x=1679,m=44,a=2067,s=496} +{x=2036,m=264,a=79,s=2244} +{x=2461,m=1339,a=466,s=291} +{x=2127,m=1623,a=2188,s=1013}"/utf8>>, + <<"19114"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"px{a<2006:qkq,m>2090:A,rfg} +pv{a>1716:R,A} +lnx{m>1548:A,A} +rfg{s<537:gd,x>2440:R,A} +qs{s>3448:A,lnx} +qkq{x<1416:A,crn} +crn{x>2662:A,R} +in{s<1351:px,qqz} +qqz{s>2770:qs,m<1801:hdj,R} +gd{a>3333:R,R} +hdj{m>838:A,pv} + +{x=787,m=2655,a=1222,s=2876} +{x=1679,m=44,a=2067,s=496} +{x=2036,m=264,a=79,s=2244} +{x=2461,m=1339,a=466,s=291} +{x=2127,m=1623,a=2188,s=1013}"/utf8>>, + <<"19114"/utf8>>}], + fun(Example) -> _pipe@1 = day19@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"px{a<2006:qkq,m>2090:A,rfg} +pv{a>1716:R,A} +lnx{m>1548:A,A} +rfg{s<537:gd,x>2440:R,A} +qs{s>3448:A,lnx} +qkq{x<1416:A,crn} +crn{x>2662:A,R} +in{s<1351:px,qqz} +qqz{s>2770:qs,m<1801:hdj,R} +gd{a>3333:R,R} +hdj{m>838:A,pv} + +{x=787,m=2655,a=1222,s=2876} +{x=1679,m=44,a=2067,s=496} +{x=2036,m=264,a=79,s=2244} +{x=2461,m=1339,a=466,s=291} +{x=2127,m=1623,a=2188,s=1013}"/utf8>>, + <<"167409079868000"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"px{a<2006:qkq,m>2090:A,rfg} +pv{a>1716:R,A} +lnx{m>1548:A,A} +rfg{s<537:gd,x>2440:R,A} +qs{s>3448:A,lnx} +qkq{x<1416:A,crn} +crn{x>2662:A,R} +in{s<1351:px,qqz} +qqz{s>2770:qs,m<1801:hdj,R} +gd{a>3333:R,R} +hdj{m>838:A,pv} + +{x=787,m=2655,a=1222,s=2876} +{x=1679,m=44,a=2067,s=496} +{x=2036,m=264,a=79,s=2244} +{x=2461,m=1339,a=466,s=291} +{x=2127,m=1623,a=2188,s=1013}"/utf8>>, + <<"167409079868000"/utf8>>}], + fun(Example) -> _pipe@1 = day19@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.cache Binary files differnew file mode 100644 index 0000000..45dad16 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.cache_meta Binary files differnew file mode 100644 index 0000000..8e99d6a --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.erl new file mode 100644 index 0000000..2f49f41 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.erl @@ -0,0 +1,459 @@ +-module(day19@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([rating/0, part/0, action/0, rule/0, interval/0, part_range/0]). + +-type rating() :: xtremely_cool | musical | aerodynamic | shiny. + +-type part() :: {part, integer(), integer(), integer(), integer()}. + +-type action() :: accept | reject | {send_to, binary()}. + +-type rule() :: {'if', rating(), gleam@order:order(), integer(), action()} | + {just, action()}. + +-type interval() :: {interval, integer(), integer()}. + +-type part_range() :: {part_range, + interval(), + interval(), + interval(), + interval()}. + +-spec to_instruction(binary()) -> action(). +to_instruction(Rule) -> + case Rule of + <<"A"/utf8>> -> + accept; + + <<"R"/utf8>> -> + reject; + + Name -> + {send_to, Name} + end. + +-spec to_rating(binary()) -> rating(). +to_rating(Rating) -> + case Rating of + <<"x"/utf8>> -> + xtremely_cool; + + <<"m"/utf8>> -> + musical; + + <<"a"/utf8>> -> + aerodynamic; + + _ -> + shiny + end. + +-spec get_rating(part(), rating()) -> integer(). +get_rating(Part, Rating) -> + case Rating of + xtremely_cool -> + erlang:element(2, Part); + + musical -> + erlang:element(3, Part); + + aerodynamic -> + erlang:element(4, Part); + + shiny -> + erlang:element(5, Part) + end. + +-spec to_comp(binary()) -> gleam@order:order(). +to_comp(Comp) -> + case Comp of + <<"<"/utf8>> -> + lt; + + _ -> + gt + end. + +-spec to_val(binary()) -> integer(). +to_val(Val) -> + _assert_subject = gleam@int:parse(Val), + {ok, N} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day19/solve"/utf8>>, + function => <<"to_val"/utf8>>, + line => 100}) + end, + N. + +-spec parse_rules(list(binary())) -> list(rule()). +parse_rules(Rules) -> + _assert_subject = gleam@regex:from_string(<<"(.*)(>|<)(.*):(.*)"/utf8>>), + {ok, Re_rule} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day19/solve"/utf8>>, + function => <<"parse_rules"/utf8>>, + line => 57}) + end, + gleam@list:map(Rules, fun(Rule) -> case gleam@regex:scan(Re_rule, Rule) of + [{match, _, [{some, R}, {some, C}, {some, T}, {some, I}]}] -> + {'if', + to_rating(R), + to_comp(C), + to_val(T), + to_instruction(I)}; + + _ -> + {just, to_instruction(Rule)} + end end). + +-spec parse_workflow(binary()) -> gleam@dict:dict(binary(), list(rule())). +parse_workflow(Input) -> + _assert_subject = gleam@regex:from_string(<<"(.*){(.*)}"/utf8>>), + {ok, Re} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day19/solve"/utf8>>, + function => <<"parse_workflow"/utf8>>, + line => 45}) + end, + gleam@list:fold( + gleam@string:split(Input, <<"\n"/utf8>>), + gleam@dict:new(), + fun(Acc, Line) -> + _assert_subject@1 = gleam@regex:scan(Re, Line), + [{match, _, [{some, Name}, {some, All_rules}]}] = case _assert_subject@1 of + [{match, _, [{some, _}, {some, _}]}] -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day19/solve"/utf8>>, + function => <<"parse_workflow"/utf8>>, + line => 48}) + end, + Rules = begin + _pipe = gleam@string:split(All_rules, <<","/utf8>>), + parse_rules(_pipe) + end, + gleam@dict:insert(Acc, Name, Rules) + end + ). + +-spec parse_parts(binary()) -> list(part()). +parse_parts(Input) -> + _assert_subject = gleam@regex:from_string( + <<"{x=(.*),m=(.*),a=(.*),s=(.*)}"/utf8>> + ), + {ok, Re} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day19/solve"/utf8>>, + function => <<"parse_parts"/utf8>>, + line => 105}) + end, + gleam@list:map( + gleam@string:split(Input, <<"\n"/utf8>>), + fun(Part) -> + _assert_subject@1 = gleam@regex:scan(Re, Part), + [{match, _, [{some, X}, {some, M}, {some, A}, {some, S}]}] = case _assert_subject@1 of + [{match, _, [{some, _}, {some, _}, {some, _}, {some, _}]}] -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day19/solve"/utf8>>, + function => <<"parse_parts"/utf8>>, + line => 108}) + end, + {part, to_val(X), to_val(M), to_val(A), to_val(S)} + end + ). + +-spec evaluate_rules(part(), list(rule())) -> action(). +evaluate_rules(Part, Rules) -> + case Rules of + [] -> + erlang:error(#{gleam_error => panic, + message => <<"panic expression evaluated"/utf8>>, + module => <<"day19/solve"/utf8>>, + function => <<"evaluate_rules"/utf8>>, + line => 128}); + + [{just, Do} | _] -> + Do; + + [{'if', Rating, Comparison, Threshold, Do@1} | Rest] -> + case gleam@int:compare(get_rating(Part, Rating), Threshold) =:= Comparison of + true -> + Do@1; + + false -> + evaluate_rules(Part, Rest) + end + end. + +-spec evaluate_workflow( + part(), + binary(), + gleam@dict:dict(binary(), list(rule())) +) -> integer(). +evaluate_workflow(Part, Name, Workflow) -> + _assert_subject = gleam@dict:get(Workflow, Name), + {ok, Rules} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day19/solve"/utf8>>, + function => <<"evaluate_workflow"/utf8>>, + line => 118}) + end, + case evaluate_rules(Part, Rules) of + accept -> + ((erlang:element(2, Part) + erlang:element(3, Part)) + erlang:element( + 4, + Part + )) + + erlang:element(5, Part); + + reject -> + 0; + + {send_to, Name@1} -> + evaluate_workflow(Part, Name@1, Workflow) + end. + +-spec start_evaluating_workflow(part(), gleam@dict:dict(binary(), list(rule()))) -> integer(). +start_evaluating_workflow(Part, Workflow) -> + evaluate_workflow(Part, <<"in"/utf8>>, Workflow). + +-spec part1(binary()) -> binary(). +part1(Input) -> + _assert_subject = gleam@string:split_once(Input, <<"\n\n"/utf8>>), + {ok, {Workflows_str, Parts_str}} = case _assert_subject of + {ok, {_, _}} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day19/solve"/utf8>>, + function => <<"part1"/utf8>>, + line => 139}) + end, + Workflows = parse_workflow(Workflows_str), + Parts = parse_parts(Parts_str), + _pipe = gleam@list:map( + Parts, + fun(_capture) -> start_evaluating_workflow(_capture, Workflows) end + ), + _pipe@1 = gleam@int:sum(_pipe), + gleam@string:inspect(_pipe@1). + +-spec size(interval()) -> integer(). +size(Interval) -> + (erlang:element(3, Interval) - erlang:element(2, Interval)) + 1. + +-spec all_in_range(part_range()) -> integer(). +all_in_range(Pr) -> + ((size(erlang:element(2, Pr)) * size(erlang:element(3, Pr))) * size( + erlang:element(4, Pr) + )) + * size(erlang:element(5, Pr)). + +-spec get_partrange(part_range(), rating()) -> interval(). +get_partrange(Pr, Rating) -> + case Rating of + xtremely_cool -> + erlang:element(2, Pr); + + musical -> + erlang:element(3, Pr); + + aerodynamic -> + erlang:element(4, Pr); + + shiny -> + erlang:element(5, Pr) + end. + +-spec update_partrange(part_range(), rating(), interval()) -> part_range(). +update_partrange(Pr, Rating, I) -> + case Rating of + xtremely_cool -> + erlang:setelement(2, Pr, I); + + musical -> + erlang:setelement(3, Pr, I); + + aerodynamic -> + erlang:setelement(4, Pr, I); + + shiny -> + erlang:setelement(5, Pr, I) + end. + +-spec evaluate_rules_on_range( + part_range(), + list(rule()), + gleam@dict:dict(binary(), list(rule())) +) -> integer(). +evaluate_rules_on_range(Pr, Rules, Workflow) -> + case Rules of + [{just, accept} | _] -> + all_in_range(Pr); + + [{just, reject} | _] -> + 0; + + [{just, {send_to, Name}} | _] -> + evaluate_workflow_on_range(Pr, Name, Workflow); + + [{'if', Rating, Comparison, T, Action} | Rest] -> + Mod_i = get_partrange(Pr, Rating), + case Comparison of + lt -> + split_range( + update_partrange( + Pr, + Rating, + {interval, erlang:element(2, Mod_i), T - 1} + ), + Action, + update_partrange( + Pr, + Rating, + {interval, T, erlang:element(3, Mod_i)} + ), + Rest, + Workflow + ); + + _ -> + split_range( + update_partrange( + Pr, + Rating, + {interval, T + 1, erlang:element(3, Mod_i)} + ), + Action, + update_partrange( + Pr, + Rating, + {interval, erlang:element(2, Mod_i), T} + ), + Rest, + Workflow + ) + end; + + [] -> + erlang:error(#{gleam_error => panic, + message => <<"panic expression evaluated"/utf8>>, + module => <<"day19/solve"/utf8>>, + function => <<"evaluate_rules_on_range"/utf8>>, + line => 225}) + end. + +-spec evaluate_workflow_on_range( + part_range(), + binary(), + gleam@dict:dict(binary(), list(rule())) +) -> integer(). +evaluate_workflow_on_range(Pr, Name, Workflow) -> + _assert_subject = gleam@dict:get(Workflow, Name), + {ok, Rules} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day19/solve"/utf8>>, + function => <<"evaluate_workflow_on_range"/utf8>>, + line => 191}) + end, + evaluate_rules_on_range(Pr, Rules, Workflow). + +-spec part2(binary()) -> binary(). +part2(Input) -> + _assert_subject = gleam@string:split_once(Input, <<"\n\n"/utf8>>), + {ok, {Workflows_str, _}} = case _assert_subject of + {ok, {_, _}} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day19/solve"/utf8>>, + function => <<"part2"/utf8>>, + line => 176}) + end, + Workflow = parse_workflow(Workflows_str), + Start = {interval, 1, 4000}, + _pipe = {part_range, Start, Start, Start, Start}, + _pipe@1 = evaluate_workflow_on_range(_pipe, <<"in"/utf8>>, Workflow), + gleam@string:inspect(_pipe@1). + +-spec split_range( + part_range(), + action(), + part_range(), + list(rule()), + gleam@dict:dict(binary(), list(rule())) +) -> integer(). +split_range(Keep, Action, Pass, Rest, Workflow) -> + gleam@int:add( + evaluate_rules_on_range(Keep, [{just, Action}], Workflow), + evaluate_rules_on_range(Pass, Rest, Workflow) + ). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day19/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 243}) + end, + _assert_subject@1 = adglent:get_input(<<"19"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day19/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 244}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.cache Binary files differnew file mode 100644 index 0000000..77a1d03 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.cache_meta Binary files differnew file mode 100644 index 0000000..da0b837 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.erl new file mode 100644 index 0000000..22e3cdd --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.erl @@ -0,0 +1,50 @@ +-module(day1@day1_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"1abc2 +pqr3stu8vwx +a1b2c3d4e5f +treb7uchet"/utf8>>, + <<"142"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"1abc2 +pqr3stu8vwx +a1b2c3d4e5f +treb7uchet"/utf8>>, + <<"142"/utf8>>}], + fun(Example) -> _pipe@1 = day1@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"two1nine +eightwothree +abcone2threexyz +xtwone3four +4nineeightseven2 +zoneight234 +7pqrstsixteen"/utf8>>, + <<"281"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"two1nine +eightwothree +abcone2threexyz +xtwone3four +4nineeightseven2 +zoneight234 +7pqrstsixteen"/utf8>>, + <<"281"/utf8>>}], + fun(Example) -> _pipe@1 = day1@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.cache Binary files differnew file mode 100644 index 0000000..a1932c5 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.cache_meta Binary files differnew file mode 100644 index 0000000..b3e1773 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.erl new file mode 100644 index 0000000..0d89b63 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.erl @@ -0,0 +1,118 @@ +-module(day1@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). + +-spec part1(binary()) -> binary(). +part1(Input) -> + _assert_subject = gleam@regex:from_string(<<"[1-9]"/utf8>>), + {ok, Re} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day1/solve"/utf8>>, + function => <<"part1"/utf8>>, + line => 9}) + end, + _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), + _pipe@2 = gleam@list:fold( + _pipe@1, + 0, + fun(Acc, S) -> + Matches = gleam@regex:scan(Re, S), + _assert_subject@1 = gleam@list:first(Matches), + {ok, {match, First, _}} = case _assert_subject@1 of + {ok, {match, _, _}} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day1/solve"/utf8>>, + function => <<"part1"/utf8>>, + line => 16}) + end, + _assert_subject@2 = gleam@list:last(Matches), + {ok, {match, Last, _}} = case _assert_subject@2 of + {ok, {match, _, _}} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"day1/solve"/utf8>>, + function => <<"part1"/utf8>>, + line => 17}) + end, + _assert_subject@3 = gleam@int:parse(<<First/binary, Last/binary>>), + {ok, I} = case _assert_subject@3 of + {ok, _} -> _assert_subject@3; + _assert_fail@3 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@3, + module => <<"day1/solve"/utf8>>, + function => <<"part1"/utf8>>, + line => 18}) + end, + Acc + I + end + ), + gleam@string:inspect(_pipe@2). + +-spec part2(binary()) -> binary(). +part2(Input) -> + _pipe = gleam@list:fold( + [{<<"one"/utf8>>, <<"o1e"/utf8>>}, + {<<"two"/utf8>>, <<"t2o"/utf8>>}, + {<<"three"/utf8>>, <<"t3e"/utf8>>}, + {<<"four"/utf8>>, <<"4"/utf8>>}, + {<<"five"/utf8>>, <<"5e"/utf8>>}, + {<<"six"/utf8>>, <<"6"/utf8>>}, + {<<"seven"/utf8>>, <<"7n"/utf8>>}, + {<<"eight"/utf8>>, <<"e8t"/utf8>>}, + {<<"nine"/utf8>>, <<"n9e"/utf8>>}], + Input, + fun(Acc, Sub) -> + {From, To} = Sub, + gleam@string:replace(Acc, From, To) + end + ), + part1(_pipe). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day1/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 45}) + end, + _assert_subject@1 = adglent:get_input(<<"1"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day1/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 46}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.cache Binary files differnew file mode 100644 index 0000000..7571e58 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.cache_meta Binary files differnew file mode 100644 index 0000000..74efc1e --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.erl new file mode 100644 index 0000000..4ae59a9 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.erl @@ -0,0 +1,42 @@ +-module(day20@day20_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"broadcaster -> a, b, c +%a -> b +%b -> c +%c -> inv +&inv -> a"/utf8>>, + <<"32000000"/utf8>>}, + {example, + <<"broadcaster -> a +%a -> inv, con +&inv -> b +%b -> con +&con -> output +output -> "/utf8>>, + <<"11687500"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"broadcaster -> a, b, c +%a -> b +%b -> c +%c -> inv +&inv -> a"/utf8>>, + <<"32000000"/utf8>>}, + {example, + <<"broadcaster -> a +%a -> inv, con +&inv -> b +%b -> con +&con -> output +output -> "/utf8>>, + <<"11687500"/utf8>>}], + fun(Example) -> _pipe@1 = day20@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.cache Binary files differnew file mode 100644 index 0000000..a8d7071 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.cache_meta Binary files differnew file mode 100644 index 0000000..a6f2f83 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.erl new file mode 100644 index 0000000..a496b49 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.erl @@ -0,0 +1,460 @@ +-module(day20@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([node_/0, tone/0, power/0, tone_pitch/0, state/0]). + +-type node_() :: {broadcaster, list(binary())} | + {flipflop, list(binary()), power()} | + {conjunction, list(binary()), gleam@dict:dict(binary(), tone_pitch())} | + ground. + +-type tone() :: {tone, binary(), binary(), tone_pitch()}. + +-type power() :: on | off. + +-type tone_pitch() :: low | high. + +-type state() :: {state, + gleam@dict:dict(binary(), node_()), + integer(), + integer(), + integer(), + gleam@dict:dict(binary(), integer())}. + +-spec flip_power(power()) -> power(). +flip_power(P) -> + case P of + on -> + off; + + off -> + on + end. + +-spec flip_flop_pitch(power()) -> tone_pitch(). +flip_flop_pitch(P) -> + case P of + off -> + high; + + on -> + low + end. + +-spec combinator_pitch(gleam@dict:dict(any(), tone_pitch())) -> tone_pitch(). +combinator_pitch(State) -> + case gleam@list:unique(gleam@dict:values(State)) of + [high] -> + low; + + _ -> + high + end. + +-spec get_children(node_()) -> list(binary()). +get_children(Node) -> + case Node of + {flipflop, Cs, _} -> + Cs; + + {conjunction, Cs@1, _} -> + Cs@1; + + {broadcaster, Cs@2} -> + Cs@2; + + ground -> + [] + end. + +-spec parse_node(binary()) -> {binary(), node_()}. +parse_node(Input) -> + _assert_subject = gleam@string:split(Input, <<" -> "/utf8>>), + [Full_name, Children_str] = case _assert_subject of + [_, _] -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day20/solve"/utf8>>, + function => <<"parse_node"/utf8>>, + line => 73}) + end, + Children = gleam@string:split(Children_str, <<", "/utf8>>), + case Full_name of + <<"%"/utf8, Name/binary>> -> + {Name, {flipflop, Children, off}}; + + <<"&"/utf8, Name@1/binary>> -> + {Name@1, {conjunction, Children, gleam@dict:new()}}; + + <<"broadcaster"/utf8>> -> + {<<"broadcaster"/utf8>>, {broadcaster, Children}}; + + Name@2 -> + {Name@2, ground} + end. + +-spec to_initial_state(list({binary(), node_()})) -> gleam@dict:dict(binary(), node_()). +to_initial_state(Nodes) -> + Node_dict = gleam@dict:from_list(Nodes), + Node_names = gleam@dict:keys(Node_dict), + Node_dict@1 = begin + _pipe = Node_dict, + _pipe@1 = gleam@dict:values(_pipe), + _pipe@2 = gleam@list:map(_pipe@1, fun get_children/1), + _pipe@3 = gleam@list:concat(_pipe@2), + _pipe@4 = gleam@set:from_list(_pipe@3), + _pipe@5 = gleam@set:drop(_pipe@4, gleam@dict:keys(Node_dict)), + _pipe@6 = gleam@set:to_list(_pipe@5), + gleam@list:fold( + _pipe@6, + Node_dict, + fun(Acc, N) -> gleam@dict:insert(Acc, N, ground) end + ) + end, + gleam@dict:map_values(Node_dict@1, fun(Name, Node) -> case Node of + {conjunction, Chs, _} -> + _pipe@7 = Node_names, + _pipe@8 = gleam@list:filter( + _pipe@7, + fun(N@1) -> + _assert_subject = gleam@dict:get(Node_dict@1, N@1), + {ok, Node@1} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day20/solve"/utf8>>, + function => <<"to_initial_state"/utf8>>, + line => 103}) + end, + gleam@list:contains(get_children(Node@1), Name) + end + ), + _pipe@9 = gleam@list:map( + _pipe@8, + fun(N@2) -> {N@2, low} end + ), + _pipe@10 = gleam@dict:from_list(_pipe@9), + (fun(Dict) -> {conjunction, Chs, Dict} end)(_pipe@10); + + Other -> + Other + end end). + +-spec add_to_queue( + binary(), + list(binary()), + tone_pitch(), + gleam@queue:queue(tone()) +) -> gleam@queue:queue(tone()). +add_to_queue(From, Children, Pitch, Queue) -> + gleam@list:fold( + Children, + Queue, + fun(Acc, C) -> gleam@queue:push_back(Acc, {tone, From, C, Pitch}) end + ). + +-spec add_tones( + state(), + gleam@dict:dict(binary(), node_()), + tone_pitch(), + integer() +) -> state(). +add_tones(State, Nodes, Pitch, N) -> + case Pitch of + low -> + erlang:setelement( + 5, + erlang:setelement( + 3, + erlang:setelement(2, State, Nodes), + erlang:element(3, State) + N + ), + erlang:element(5, State) + 1 + ); + + high -> + erlang:setelement( + 5, + erlang:setelement( + 4, + erlang:setelement(2, State, Nodes), + erlang:element(4, State) + N + ), + erlang:element(5, State) + 1 + ) + end. + +-spec check_for_interesting_node(state(), binary(), tone_pitch()) -> state(). +check_for_interesting_node(State, Name, Pitch_out) -> + case {Name, Pitch_out} of + {<<"rk"/utf8>>, high} -> + erlang:setelement( + 6, + State, + gleam@dict:insert( + erlang:element(6, State), + Name, + erlang:element(5, State) + ) + ); + + {<<"cd"/utf8>>, high} -> + erlang:setelement( + 6, + State, + gleam@dict:insert( + erlang:element(6, State), + Name, + erlang:element(5, State) + ) + ); + + {<<"zf"/utf8>>, high} -> + erlang:setelement( + 6, + State, + gleam@dict:insert( + erlang:element(6, State), + Name, + erlang:element(5, State) + ) + ); + + {<<"qx"/utf8>>, high} -> + erlang:setelement( + 6, + State, + gleam@dict:insert( + erlang:element(6, State), + Name, + erlang:element(5, State) + ) + ); + + {_, _} -> + State + end. + +-spec press_button_once(state(), gleam@queue:queue(tone())) -> state(). +press_button_once(Initial, Queue) -> + {state, Nodes, _, _, _, _} = Initial, + gleam@bool:guard( + gleam@queue:is_empty(Queue), + Initial, + fun() -> + _assert_subject = gleam@queue:pop_front(Queue), + {ok, {{tone, From_name, To_name, Pitch}, Rest}} = case _assert_subject of + {ok, {{tone, _, _, _}, _}} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day20/solve"/utf8>>, + function => <<"press_button_once"/utf8>>, + line => 131}) + end, + _assert_subject@1 = gleam@dict:get(Nodes, To_name), + {ok, To_node} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day20/solve"/utf8>>, + function => <<"press_button_once"/utf8>>, + line => 134}) + end, + case To_node of + {broadcaster, Children} -> + New_state = add_tones( + Initial, + Nodes, + Pitch, + gleam@list:length(Children) + 1 + ), + New_queue = add_to_queue(To_name, Children, Pitch, Rest), + press_button_once(New_state, New_queue); + + {conjunction, Children@1, State} -> + New_state@1 = begin + _pipe = State, + gleam@dict:insert(_pipe, From_name, Pitch) + end, + Updated_nodes = begin + _pipe@1 = {conjunction, Children@1, New_state@1}, + gleam@dict:insert(Nodes, To_name, _pipe@1) + end, + Pitch_out = combinator_pitch(New_state@1), + New_state@2 = begin + _pipe@2 = add_tones( + Initial, + Updated_nodes, + Pitch_out, + gleam@list:length(Children@1) + ), + check_for_interesting_node( + _pipe@2, + From_name, + Pitch_out + ) + end, + _pipe@3 = add_to_queue(To_name, Children@1, Pitch_out, Rest), + press_button_once(New_state@2, _pipe@3); + + {flipflop, _, _} when Pitch =:= high -> + press_button_once( + erlang:setelement( + 5, + Initial, + erlang:element(5, Initial) + 1 + ), + Rest + ); + + {flipflop, Children@2, State@1} -> + Updated_nodes@1 = begin + _pipe@4 = {flipflop, Children@2, flip_power(State@1)}, + gleam@dict:insert(Nodes, To_name, _pipe@4) + end, + Pitch_out@1 = flip_flop_pitch(State@1), + New_state@3 = add_tones( + Initial, + Updated_nodes@1, + Pitch_out@1, + gleam@list:length(Children@2) + ), + _pipe@5 = add_to_queue( + To_name, + Children@2, + flip_flop_pitch(State@1), + Rest + ), + press_button_once(New_state@3, _pipe@5); + + ground -> + press_button_once( + erlang:setelement( + 5, + Initial, + erlang:element(5, Initial) + 1 + ), + Rest + ) + end + end + ). + +-spec part1(binary()) -> binary(). +part1(Input) -> + Initial_state = begin + _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), + _pipe@2 = gleam@list:map(_pipe@1, fun parse_node/1), + to_initial_state(_pipe@2) + end, + _pipe@3 = gleam@iterator:iterate( + {state, Initial_state, 0, 0, 1, gleam@dict:new()}, + fun(_capture) -> + press_button_once( + _capture, + gleam@queue:from_list( + [{tone, <<"button"/utf8>>, <<"broadcaster"/utf8>>, low}] + ) + ) + end + ), + _pipe@4 = gleam@iterator:at(_pipe@3, 1000), + _pipe@5 = (fun(S) -> + {ok, {state, _, Low, High, _, _}} = case S of + {ok, {state, _, _, _, _, _}} -> S; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day20/solve"/utf8>>, + function => <<"part1"/utf8>>, + line => 199}) + end, + High * Low + end)(_pipe@4), + gleam@string:inspect(_pipe@5). + +-spec part2(binary()) -> binary(). +part2(Input) -> + Initial_state = begin + _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), + _pipe@2 = gleam@list:map(_pipe@1, fun parse_node/1), + to_initial_state(_pipe@2) + end, + _pipe@3 = gleam@iterator:iterate( + {state, Initial_state, 0, 0, 1, gleam@dict:new()}, + fun(_capture) -> + press_button_once( + _capture, + gleam@queue:from_list( + [{tone, <<"button"/utf8>>, <<"broadcaster"/utf8>>, low}] + ) + ) + end + ), + _pipe@4 = gleam@iterator:drop_while( + _pipe@3, + fun(S) -> gleam@dict:size(erlang:element(6, S)) < 4 end + ), + _pipe@5 = gleam@iterator:step(_pipe@4), + _pipe@6 = (fun(S@1) -> + {next, Goal, _} = case S@1 of + {next, _, _} -> S@1; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day20/solve"/utf8>>, + function => <<"part2"/utf8>>, + line => 232}) + end, + erlang:element(6, Goal) + end)(_pipe@5), + gleam@string:inspect(_pipe@6). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day20/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 239}) + end, + _assert_subject@1 = adglent:get_input(<<"20"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day20/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 240}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.cache Binary files differnew file mode 100644 index 0000000..7eec8c7 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.cache_meta Binary files differnew file mode 100644 index 0000000..10d8749 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.erl new file mode 100644 index 0000000..f2b842c --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.erl @@ -0,0 +1,24 @@ +-module(day21@day21_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [], + fun(Example) -> _pipe@1 = day21@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [], + fun(Example) -> _pipe@1 = day21@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.cache Binary files differnew file mode 100644 index 0000000..eb2a3e9 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.cache_meta Binary files differnew file mode 100644 index 0000000..d810856 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.erl new file mode 100644 index 0000000..be4464d --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.erl @@ -0,0 +1,56 @@ +-module(day21@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). + +-spec part1(binary()) -> any(). +part1(Input) -> + erlang:error(#{gleam_error => todo, + message => <<"Implement solution to part 1"/utf8>>, + module => <<"day21/solve"/utf8>>, + function => <<"part1"/utf8>>, + line => 5}). + +-spec part2(binary()) -> any(). +part2(Input) -> + erlang:error(#{gleam_error => todo, + message => <<"Implement solution to part 2"/utf8>>, + module => <<"day21/solve"/utf8>>, + function => <<"part2"/utf8>>, + line => 9}). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day21/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 13}) + end, + _assert_subject@1 = adglent:get_input(<<"21"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day21/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 14}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.cache Binary files differnew file mode 100644 index 0000000..48b46ff --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.cache_meta Binary files differnew file mode 100644 index 0000000..c0c6c8a --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.erl new file mode 100644 index 0000000..e571215 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.erl @@ -0,0 +1,56 @@ +-module(day22@day22_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"1,0,1~1,2,1 +0,0,2~2,0,2 +0,2,3~2,2,3 +0,0,4~0,2,4 +2,0,5~2,2,5 +0,1,6~2,1,6 +1,1,8~1,1,9"/utf8>>, + 5}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"1,0,1~1,2,1 +0,0,2~2,0,2 +0,2,3~2,2,3 +0,0,4~0,2,4 +2,0,5~2,2,5 +0,1,6~2,1,6 +1,1,8~1,1,9"/utf8>>, + 5}], + fun(Example) -> _pipe@1 = day22@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"1,0,1~1,2,1 +0,0,2~2,0,2 +0,2,3~2,2,3 +0,0,4~0,2,4 +2,0,5~2,2,5 +0,1,6~2,1,6 +1,1,8~1,1,9"/utf8>>, + 7}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"1,0,1~1,2,1 +0,0,2~2,0,2 +0,2,3~2,2,3 +0,0,4~0,2,4 +2,0,5~2,2,5 +0,1,6~2,1,6 +1,1,8~1,1,9"/utf8>>, + 7}], + fun(Example) -> _pipe@1 = day22@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.cache Binary files differnew file mode 100644 index 0000000..6fb1a11 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.cache_meta Binary files differnew file mode 100644 index 0000000..2a4dc01 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.erl new file mode 100644 index 0000000..6d6b33c --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.erl @@ -0,0 +1,369 @@ +-module(day22@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([point/0, block/0]). + +-type point() :: {point, integer(), integer(), integer()}. + +-type block() :: {block, integer(), point(), point()}. + +-spec down_one(point()) -> point(). +down_one(P) -> + erlang:setelement(4, P, erlang:element(4, P) - 1). + +-spec compare_blocks(block(), block()) -> gleam@order:order(). +compare_blocks(B1, B2) -> + gleam@int:compare( + erlang:element(4, erlang:element(4, B1)), + erlang:element(4, erlang:element(4, B2)) + ). + +-spec parse_block(integer(), binary()) -> block(). +parse_block(Index, Input) -> + _assert_subject = gleam@regex:from_string( + <<"(.*),(.*),(.*)~(.*),(.*),(.*)"/utf8>> + ), + {ok, Re} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day22/solve"/utf8>>, + function => <<"parse_block"/utf8>>, + line => 39}) + end, + _assert_subject@1 = gleam@regex:scan(Re, Input), + [Scan] = case _assert_subject@1 of + [_] -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day22/solve"/utf8>>, + function => <<"parse_block"/utf8>>, + line => 41}) + end, + _assert_subject@2 = begin + _pipe = erlang:element(3, Scan), + _pipe@1 = gleam@option:all(_pipe), + _pipe@2 = gleam@option:unwrap(_pipe@1, []), + _pipe@3 = gleam@list:map(_pipe@2, fun gleam@int:parse/1), + gleam@result:values(_pipe@3) + end, + [X1, Y1, Z1, X2, Y2, Z2] = case _assert_subject@2 of + [_, _, _, _, _, _] -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"day22/solve"/utf8>>, + function => <<"parse_block"/utf8>>, + line => 43}) + end, + {block, Index, {point, X1, Y1, Z1}, {point, X2, Y2, Z2}}. + +-spec cross_section_at_level(block(), integer()) -> list(point()). +cross_section_at_level(B, Z) -> + gleam@list:flat_map( + gleam@list:range( + erlang:element(2, erlang:element(3, B)), + erlang:element(2, erlang:element(4, B)) + ), + fun(X) -> + gleam@list:map( + gleam@list:range( + erlang:element(3, erlang:element(3, B)), + erlang:element(3, erlang:element(4, B)) + ), + fun(Y) -> {point, X, Y, Z} end + ) + end + ). + +-spec place_block(gleam@dict:dict(point(), block()), block(), integer()) -> gleam@dict:dict(point(), block()). +place_block(Space, B, Z) -> + Now_occupied = (gleam@list:flat_map( + gleam@list:range( + erlang:element(2, erlang:element(3, B)), + erlang:element(2, erlang:element(4, B)) + ), + fun(X) -> + gleam@list:flat_map( + gleam@list:range( + erlang:element(3, erlang:element(3, B)), + erlang:element(3, erlang:element(4, B)) + ), + fun(Y) -> + gleam@list:map( + gleam@list:range( + Z, + (Z + erlang:element(4, erlang:element(4, B))) - erlang:element( + 4, + erlang:element(3, B) + ) + ), + fun(Z@1) -> {{point, X, Y, Z@1}, B} end + ) + end + ) + end + )), + gleam@dict:merge(Space, gleam@dict:from_list(Now_occupied)). + +-spec do_find_lowest(gleam@dict:dict(point(), block()), block(), integer()) -> gleam@dict:dict(point(), block()). +do_find_lowest(Space, B, Z) -> + Is_intersecting = gleam@list:any( + cross_section_at_level(B, Z), + fun(_capture) -> gleam@dict:has_key(Space, _capture) end + ), + case {Z, Is_intersecting} of + {0, _} -> + place_block(Space, B, 1); + + {_, true} -> + place_block(Space, B, Z + 1); + + {_, false} -> + do_find_lowest(Space, B, Z - 1) + end. + +-spec find_lowest_level(gleam@dict:dict(point(), block()), block()) -> gleam@dict:dict(point(), block()). +find_lowest_level(Space, B) -> + do_find_lowest(Space, B, erlang:element(4, erlang:element(3, B))). + +-spec to_block_positions(gleam@dict:dict(point(), block())) -> gleam@dict:dict(block(), list(point())). +to_block_positions(Space) -> + gleam@dict:fold( + Space, + gleam@dict:new(), + fun(Acc, Point, Index) -> + gleam@dict:update(Acc, Index, fun(Points) -> case Points of + {some, Ps} -> + [Point | Ps]; + + none -> + [Point] + end end) + end + ). + +-spec above_blocks(gleam@dict:dict(block(), list(point()))) -> gleam@dict:dict(integer(), gleam@set:set(integer())). +above_blocks(Blocks) -> + gleam@dict:fold( + Blocks, + gleam@dict:new(), + fun(Acc, Block, Points) -> + gleam@dict:update( + Acc, + erlang:element(2, Block), + fun(_) -> + _pipe = (gleam@dict:filter( + Blocks, + fun(Above_block, Above_points) -> + (erlang:element(2, Above_block) /= erlang:element( + 2, + Block + )) + andalso gleam@list:any( + Above_points, + fun(P) -> + gleam@list:contains(Points, down_one(P)) + end + ) + end + )), + _pipe@1 = gleam@dict:keys(_pipe), + _pipe@2 = gleam@list:map( + _pipe@1, + fun(B) -> erlang:element(2, B) end + ), + gleam@set:from_list(_pipe@2) + end + ) + end + ). + +-spec below_blocks(gleam@dict:dict(integer(), gleam@set:set(integer()))) -> gleam@dict:dict(integer(), gleam@set:set(integer())). +below_blocks(Blocktree) -> + gleam@dict:fold( + Blocktree, + gleam@dict:new(), + fun(Acc, Block, _) -> + gleam@dict:update( + Acc, + Block, + fun(_) -> + _pipe = (gleam@dict:filter( + Blocktree, + fun(_, Aboves) -> gleam@set:contains(Aboves, Block) end + )), + _pipe@1 = gleam@dict:keys(_pipe), + gleam@set:from_list(_pipe@1) + end + ) + end + ). + +-spec vulnerable_blocks(gleam@dict:dict(integer(), gleam@set:set(integer()))) -> list(integer()). +vulnerable_blocks(Below_tree) -> + gleam@list:filter( + gleam@dict:keys(Below_tree), + fun(Block) -> + gleam@list:any( + gleam@dict:values(Below_tree), + fun(Bs) -> + not (gleam@set:size(Bs) =:= 0) andalso (gleam@set:size( + gleam@set:delete(Bs, Block) + ) + =:= 0) + end + ) + end + ). + +-spec part1(binary()) -> integer(). +part1(Input) -> + Settled_blocks = begin + _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), + _pipe@2 = gleam@list:index_map(_pipe@1, fun parse_block/2), + _pipe@3 = gleam@list:sort(_pipe@2, fun compare_blocks/2), + gleam@list:fold(_pipe@3, gleam@dict:new(), fun find_lowest_level/2) + end, + Block_positions = to_block_positions(Settled_blocks), + Above_blocks = above_blocks(Block_positions), + Below_blocks = below_blocks(Above_blocks), + Vulnerable_blocks = vulnerable_blocks(Below_blocks), + gleam@list:length(gleam@dict:keys(Block_positions)) - gleam@list:length( + Vulnerable_blocks + ). + +-spec do_falling_blocks( + gleam@set:set(integer()), + gleam@set:set(integer()), + gleam@dict:dict(integer(), gleam@set:set(integer())), + gleam@dict:dict(integer(), gleam@set:set(integer())) +) -> integer(). +do_falling_blocks(Fallen, Blocks, Above, Below) -> + gleam@bool:guard( + gleam@set:size(Blocks) =:= 0, + gleam@set:size(Fallen) - 1, + fun() -> + Blocks_above = begin + _pipe = (gleam@list:flat_map( + gleam@set:to_list(Blocks), + fun(Block) -> + _assert_subject = gleam@dict:get(Above, Block), + {ok, Supports} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day22/solve"/utf8>>, + function => <<"do_falling_blocks"/utf8>>, + line => 156}) + end, + gleam@list:filter( + gleam@set:to_list(Supports), + fun(Support) -> + _assert_subject@1 = gleam@dict:get( + Below, + Support + ), + {ok, Supportings} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error( + #{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day22/solve"/utf8>>, + function => <<"do_falling_blocks"/utf8>>, + line => 158} + ) + end, + gleam@list:all( + gleam@set:to_list(Supportings), + fun(Supporting) -> + gleam@set:contains(Fallen, Supporting) + end + ) + end + ) + end + )), + gleam@set:from_list(_pipe) + end, + _pipe@1 = gleam@set:union(Fallen, Blocks_above), + do_falling_blocks(_pipe@1, Blocks_above, Above, Below) + end + ). + +-spec all_falling_blocks( + integer(), + gleam@dict:dict(integer(), gleam@set:set(integer())), + gleam@dict:dict(integer(), gleam@set:set(integer())) +) -> integer(). +all_falling_blocks(N, Above, Below) -> + Starting_set = gleam@set:insert(gleam@set:new(), N), + do_falling_blocks(Starting_set, Starting_set, Above, Below). + +-spec part2(binary()) -> integer(). +part2(Input) -> + Settled_blocks = begin + _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), + _pipe@2 = gleam@list:index_map(_pipe@1, fun parse_block/2), + _pipe@3 = gleam@list:sort(_pipe@2, fun compare_blocks/2), + gleam@list:fold(_pipe@3, gleam@dict:new(), fun find_lowest_level/2) + end, + Block_positions = to_block_positions(Settled_blocks), + Above_blocks = above_blocks(Block_positions), + Below_blocks = below_blocks(Above_blocks), + Vulnerable_blocks = vulnerable_blocks(Below_blocks), + gleam@list:fold( + Vulnerable_blocks, + 0, + fun(Acc, B) -> + Acc + all_falling_blocks(B, Above_blocks, Below_blocks) + end + ). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day22/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 187}) + end, + _assert_subject@1 = adglent:get_input(<<"22"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day22/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 188}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.cache Binary files differnew file mode 100644 index 0000000..3a1c3d1 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.cache_meta Binary files differnew file mode 100644 index 0000000..128bc18 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.erl new file mode 100644 index 0000000..fe9d666 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.erl @@ -0,0 +1,120 @@ +-module(day23@day23_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"#.##################### +#.......#########...### +#######.#########.#.### +###.....#.>.>.###.#.### +###v#####.#v#.###.#.### +###.>...#.#.#.....#...# +###v###.#.#.#########.# +###...#.#.#.......#...# +#####.#.#.#######.#.### +#.....#.#.#.......#...# +#.#####.#.#.#########v# +#.#...#...#...###...>.# +#.#.#v#######v###.###v# +#...#.>.#...>.>.#.###.# +#####v#.#.###v#.#.###.# +#.....#...#...#.#.#...# +#.#########.###.#.#.### +#...###...#...#...#.### +###.###.#.###v#####v### +#...#...#.#.>.>.#.>.### +#.###.###.#.###.#.#v### +#.....###...###...#...# +#####################.#"/utf8>>, + 94}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"#.##################### +#.......#########...### +#######.#########.#.### +###.....#.>.>.###.#.### +###v#####.#v#.###.#.### +###.>...#.#.#.....#...# +###v###.#.#.#########.# +###...#.#.#.......#...# +#####.#.#.#######.#.### +#.....#.#.#.......#...# +#.#####.#.#.#########v# +#.#...#...#...###...>.# +#.#.#v#######v###.###v# +#...#.>.#...>.>.#.###.# +#####v#.#.###v#.#.###.# +#.....#...#...#.#.#...# +#.#########.###.#.#.### +#...###...#...#...#.### +###.###.#.###v#####v### +#...#...#.#.>.>.#.>.### +#.###.###.#.###.#.#v### +#.....###...###...#...# +#####################.#"/utf8>>, + 94}], + fun(Example) -> _pipe@1 = day23@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"#.##################### +#.......#########...### +#######.#########.#.### +###.....#.>.>.###.#.### +###v#####.#v#.###.#.### +###.>...#.#.#.....#...# +###v###.#.#.#########.# +###...#.#.#.......#...# +#####.#.#.#######.#.### +#.....#.#.#.......#...# +#.#####.#.#.#########v# +#.#...#...#...###...>.# +#.#.#v#######v###.###v# +#...#.>.#...>.>.#.###.# +#####v#.#.###v#.#.###.# +#.....#...#...#.#.#...# +#.#########.###.#.#.### +#...###...#...#...#.### +###.###.#.###v#####v### +#...#...#.#.>.>.#.>.### +#.###.###.#.###.#.#v### +#.....###...###...#...# +#####################.#"/utf8>>, + 154}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"#.##################### +#.......#########...### +#######.#########.#.### +###.....#.>.>.###.#.### +###v#####.#v#.###.#.### +###.>...#.#.#.....#...# +###v###.#.#.#########.# +###...#.#.#.......#...# +#####.#.#.#######.#.### +#.....#.#.#.......#...# +#.#####.#.#.#########v# +#.#...#...#...###...>.# +#.#.#v#######v###.###v# +#...#.>.#...>.>.#.###.# +#####v#.#.###v#.#.###.# +#.....#...#...#.#.#...# +#.#########.###.#.#.### +#...###...#...#...#.### +###.###.#.###v#####v### +#...#...#.#.>.>.#.>.### +#.###.###.#.###.#.#v### +#.....###...###...#...# +#####################.#"/utf8>>, + 154}], + fun(Example) -> _pipe@1 = day23@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.cache Binary files differnew file mode 100644 index 0000000..55cbb25 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.cache_meta Binary files differnew file mode 100644 index 0000000..925bbea --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.erl new file mode 100644 index 0000000..8a57e88 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.erl @@ -0,0 +1,337 @@ +-module(day23@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([path/0, route/0]). + +-type path() :: unknown | straight | junction. + +-type route() :: {route, utilities@array2d:posn(), integer()}. + +-spec append_to_key(gleam@option:option(list(RTF)), RTF) -> list(RTF). +append_to_key(V, New) -> + case V of + none -> + [New]; + + {some, Xs} -> + [New | Xs] + end. + +-spec first_parse_path(binary()) -> {ok, path()} | {error, nil}. +first_parse_path(C) -> + case C of + <<"#"/utf8>> -> + {error, nil}; + + _ -> + {ok, unknown} + end. + +-spec junction_neighbors(utilities@array2d:posn()) -> list(utilities@array2d:posn()). +junction_neighbors(P) -> + [erlang:setelement(2, P, erlang:element(2, P) + 1), + erlang:setelement(3, P, erlang:element(3, P) + 1)]. + +-spec mark_junctions(gleam@dict:dict(utilities@array2d:posn(), path())) -> gleam@dict:dict(utilities@array2d:posn(), path()). +mark_junctions(Trails) -> + gleam@dict:map_values( + Trails, + fun(Trail, _) -> + Valid_neighbors = begin + _pipe = Trail, + _pipe@1 = utilities@array2d:ortho_neighbors(_pipe), + gleam@list:filter( + _pipe@1, + fun(_capture) -> gleam@dict:has_key(Trails, _capture) end + ) + end, + case gleam@list:length(Valid_neighbors) of + 2 -> + straight; + + _ -> + junction + end + end + ). + +-spec walk_to_next_junction( + utilities@array2d:posn(), + utilities@array2d:posn(), + integer(), + gleam@set:set(utilities@array2d:posn()), + gleam@dict:dict(utilities@array2d:posn(), path()) +) -> {utilities@array2d:posn(), route()}. +walk_to_next_junction(Start, Current, Length, Seen, Trails) -> + _assert_subject = begin + _pipe = Current, + _pipe@1 = utilities@array2d:ortho_neighbors(_pipe), + gleam@list:filter( + _pipe@1, + fun(N) -> + gleam@dict:has_key(Trails, N) andalso not gleam@set:contains( + Seen, + N + ) + end + ) + end, + [Next] = case _assert_subject of + [_] -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day23/solve"/utf8>>, + function => <<"walk_to_next_junction"/utf8>>, + line => 73}) + end, + case gleam@dict:get(Trails, Next) of + {ok, junction} -> + {Start, {route, Next, Length + 1}}; + + _ -> + Seen@1 = gleam@set:insert(Seen, Current), + walk_to_next_junction(Start, Next, (Length + 1), Seen@1, Trails) + end. + +-spec start_walking_to_next_junction( + utilities@array2d:posn(), + utilities@array2d:posn(), + gleam@dict:dict(utilities@array2d:posn(), path()) +) -> {utilities@array2d:posn(), route()}. +start_walking_to_next_junction(Start, Next, Trails) -> + Seen = begin + _pipe = gleam@set:new(), + _pipe@1 = gleam@set:insert(_pipe, Start), + gleam@set:insert(_pipe@1, Next) + end, + walk_to_next_junction(Start, Next, 1, Seen, Trails). + +-spec find_routes( + list(utilities@array2d:posn()), + gleam@dict:dict(utilities@array2d:posn(), path()) +) -> list({utilities@array2d:posn(), route()}). +find_routes(Junctions, Trails) -> + gleam@list:flat_map( + Junctions, + fun(Junction) -> + gleam@list:filter_map( + junction_neighbors(Junction), + fun(Neighbor) -> case gleam@dict:has_key(Trails, Neighbor) of + true -> + {ok, + start_walking_to_next_junction( + Junction, + Neighbor, + Trails + )}; + + false -> + {error, nil} + end end + ) + end + ). + +-spec generate_routes( + list(utilities@array2d:posn()), + gleam@dict:dict(utilities@array2d:posn(), path()) +) -> gleam@dict:dict(utilities@array2d:posn(), list(route())). +generate_routes(Junctions, Trails) -> + gleam@list:fold( + find_routes(Junctions, Trails), + gleam@dict:new(), + fun(Acc, _use1) -> + {From, Route} = _use1, + gleam@dict:update( + Acc, + From, + fun(_capture) -> append_to_key(_capture, Route) end + ) + end + ). + +-spec generate_2way_routes( + list(utilities@array2d:posn()), + gleam@dict:dict(utilities@array2d:posn(), path()) +) -> gleam@dict:dict(utilities@array2d:posn(), list(route())). +generate_2way_routes(Junctions, Trails) -> + gleam@list:fold( + find_routes(Junctions, Trails), + gleam@dict:new(), + fun(Acc, _use1) -> + {From, Route} = _use1, + _pipe = Acc, + _pipe@1 = gleam@dict:update( + _pipe, + From, + fun(_capture) -> append_to_key(_capture, Route) end + ), + gleam@dict:update( + _pipe@1, + erlang:element(2, Route), + fun(_capture@1) -> + append_to_key( + _capture@1, + {route, From, erlang:element(3, Route)} + ) + end + ) + end + ). + +-spec do_dfs( + gleam@dict:dict(utilities@array2d:posn(), list(route())), + utilities@array2d:posn(), + utilities@array2d:posn(), + integer(), + gleam@set:set(utilities@array2d:posn()) +) -> integer(). +do_dfs(Routes, From, To, Acc, Seen) -> + gleam@bool:guard( + To =:= From, + Acc, + fun() -> + _assert_subject = gleam@dict:get(Routes, From), + {ok, All_routes} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day23/solve"/utf8>>, + function => <<"do_dfs"/utf8>>, + line => 134}) + end, + Neighbors = gleam@list:filter( + All_routes, + fun(R) -> not gleam@set:contains(Seen, erlang:element(2, R)) end + ), + case Neighbors of + [] -> + 0; + + Neighbors@1 -> + gleam@list:fold( + Neighbors@1, + Acc, + fun(Inner_acc, N) -> + Score = do_dfs( + Routes, + erlang:element(2, N), + To, + Acc + erlang:element(3, N), + gleam@set:insert(Seen, erlang:element(2, N)) + ), + gleam@int:max(Score, Inner_acc) + end + ) + end + end + ). + +-spec dfs( + gleam@dict:dict(utilities@array2d:posn(), list(route())), + utilities@array2d:posn(), + utilities@array2d:posn() +) -> integer(). +dfs(Routes, From, To) -> + Seen = gleam@set:insert(gleam@set:new(), From), + do_dfs(Routes, From, To, 0, Seen). + +-spec solve_using( + binary(), + fun((list(utilities@array2d:posn()), gleam@dict:dict(utilities@array2d:posn(), path())) -> gleam@dict:dict(utilities@array2d:posn(), list(route()))) +) -> integer(). +solve_using(Input, Using) -> + Min_row = 0, + Max_row = gleam@list:length(gleam@string:split(Input, <<"\n"/utf8>>)) - 1, + Trails = begin + _pipe = Input, + _pipe@1 = utilities@array2d:parse_grid_using( + _pipe, + fun first_parse_path/1 + ), + mark_junctions(_pipe@1) + end, + Junctions = begin + _pipe@2 = Trails, + _pipe@3 = gleam@dict:filter(_pipe@2, fun(_, V) -> V =:= junction end), + gleam@dict:keys(_pipe@3) + end, + _assert_subject = gleam@list:find( + Junctions, + fun(J) -> erlang:element(2, J) =:= Min_row end + ), + {ok, Start} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day23/solve"/utf8>>, + function => <<"solve_using"/utf8>>, + line => 165}) + end, + _assert_subject@1 = gleam@list:find( + Junctions, + fun(J@1) -> erlang:element(2, J@1) =:= Max_row end + ), + {ok, End} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day23/solve"/utf8>>, + function => <<"solve_using"/utf8>>, + line => 166}) + end, + Routes = Using(Junctions, Trails), + dfs(Routes, Start, End). + +-spec part1(binary()) -> integer(). +part1(Input) -> + solve_using(Input, fun generate_routes/2). + +-spec part2(binary()) -> integer(). +part2(Input) -> + solve_using(Input, fun generate_2way_routes/2). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day23/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 182}) + end, + _assert_subject@1 = adglent:get_input(<<"23"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day23/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 183}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.cache Binary files differnew file mode 100644 index 0000000..60923b3 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.cache_meta Binary files differnew file mode 100644 index 0000000..6e09c6a --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.erl new file mode 100644 index 0000000..693c962 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.erl @@ -0,0 +1,54 @@ +-module(day2@day2_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"/utf8>>, + 8}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"/utf8>>, + 8}], + fun(Example) -> _pipe@1 = day2@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"/utf8>>, + 2286}, + {example, + <<"Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green"/utf8>>, + 48}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green"/utf8>>, + 2286}, + {example, + <<"Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green"/utf8>>, + 48}], + fun(Example) -> _pipe@1 = day2@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.cache Binary files differnew file mode 100644 index 0000000..f550ee3 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.cache_meta Binary files differnew file mode 100644 index 0000000..b39c267 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.erl new file mode 100644 index 0000000..e7e3e63 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.erl @@ -0,0 +1,166 @@ +-module(day2@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([game/0]). + +-type game() :: {game, integer(), integer(), integer()}. + +-spec parse(binary()) -> list(list(game())). +parse(Input) -> + gleam@list:map( + gleam@string:split(Input, <<"\n"/utf8>>), + fun(Line) -> + _assert_subject = gleam@string:split(Line, <<": "/utf8>>), + [_, Rounds] = case _assert_subject of + [_, _] -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day2/solve"/utf8>>, + function => <<"parse"/utf8>>, + line => 13}) + end, + gleam@list:map( + gleam@string:split(Rounds, <<"; "/utf8>>), + fun(Match) -> + gleam@list:fold( + gleam@string:split(Match, <<", "/utf8>>), + {game, 0, 0, 0}, + fun(Acc, Draw) -> + _assert_subject@1 = gleam@string:split_once( + Draw, + <<" "/utf8>> + ), + {ok, {N_str, Color}} = case _assert_subject@1 of + {ok, {_, _}} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day2/solve"/utf8>>, + function => <<"parse"/utf8>>, + line => 19}) + end, + _assert_subject@2 = gleam@int:parse(N_str), + {ok, N} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"day2/solve"/utf8>>, + function => <<"parse"/utf8>>, + line => 20}) + end, + case Color of + <<"red"/utf8>> -> + erlang:setelement(2, Acc, N); + + <<"blue"/utf8>> -> + erlang:setelement(3, Acc, N); + + <<"green"/utf8>> -> + erlang:setelement(4, Acc, N); + + _ -> + erlang:error(#{gleam_error => panic, + message => <<"unrecognized color"/utf8>>, + module => <<"day2/solve"/utf8>>, + function => <<"parse"/utf8>>, + line => 25}) + end + end + ) + end + ) + end + ). + +-spec part1(binary()) -> integer(). +part1(Input) -> + gleam@list:index_fold( + parse(Input), + 0, + fun(Acc, Game, I) -> + case gleam@list:any( + Game, + fun(M) -> + ((erlang:element(2, M) > 12) orelse (erlang:element(4, M) > 13)) + orelse (erlang:element(3, M) > 14) + end + ) of + false -> + (Acc + I) + 1; + + true -> + Acc + end + end + ). + +-spec part2(binary()) -> integer(). +part2(Input) -> + _pipe = (gleam@list:map( + parse(Input), + fun(Game) -> + gleam@list:fold( + Game, + {game, 0, 0, 0}, + fun(Acc, Match) -> + {game, Red, Blue, Green} = Match, + {game, + gleam@int:max(Red, erlang:element(2, Acc)), + gleam@int:max(Blue, erlang:element(3, Acc)), + gleam@int:max(Green, erlang:element(4, Acc))} + end + ) + end + )), + gleam@list:fold( + _pipe, + 0, + fun(Acc@1, G) -> + Acc@1 + ((erlang:element(2, G) * erlang:element(3, G)) * erlang:element( + 4, + G + )) + end + ). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day2/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 54}) + end, + _assert_subject@1 = adglent:get_input(<<"2"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day2/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 55}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.cache Binary files differnew file mode 100644 index 0000000..49b0c33 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.cache_meta Binary files differnew file mode 100644 index 0000000..a5246d6 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.erl new file mode 100644 index 0000000..33a8c22 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.erl @@ -0,0 +1,68 @@ +-module(day3@day3_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"467..114.. +...*...... +..35..633. +......#... +617*...... +.....+.58. +..592..... +......755. +...$.*.... +.664.598.."/utf8>>, + 4361}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"467..114.. +...*...... +..35..633. +......#... +617*...... +.....+.58. +..592..... +......755. +...$.*.... +.664.598.."/utf8>>, + 4361}], + fun(Example) -> _pipe@1 = day3@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"467..114.. +...*...... +..35..633. +......#... +617*...... +.....+.58. +..592..... +......755. +...$.*.... +.664.598.."/utf8>>, + 467835}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"467..114.. +...*...... +..35..633. +......#... +617*...... +.....+.58. +..592..... +......755. +...$.*.... +.664.598.."/utf8>>, + 467835}], + fun(Example) -> _pipe@1 = day3@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.cache Binary files differnew file mode 100644 index 0000000..7024510 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.cache_meta Binary files differnew file mode 100644 index 0000000..8b7792a --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.erl new file mode 100644 index 0000000..9082643 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.erl @@ -0,0 +1,254 @@ +-module(day3@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([coord/0, symbol_kind/0, symbol/0, cell/0, part/0]). + +-type coord() :: {coord, integer(), integer()}. + +-type symbol_kind() :: gear | something_else. + +-type symbol() :: {number, integer()} | {symbol, symbol_kind()} | empty. + +-type cell() :: {cell, coord(), symbol()}. + +-type part() :: {part, list(coord()), integer()}. + +-spec to_symbol(binary()) -> symbol(). +to_symbol(C) -> + case {gleam@int:parse(C), C} of + {{ok, N}, _} -> + {number, N}; + + {_, <<"."/utf8>>} -> + empty; + + {_, <<"*"/utf8>>} -> + {symbol, gear}; + + {_, _} -> + {symbol, something_else} + end. + +-spec to_board(binary()) -> gleam@dict:dict(coord(), symbol()). +to_board(Input) -> + _pipe = (gleam@list:index_map( + gleam@string:split(Input, <<"\n"/utf8>>), + fun(Y, R) -> + gleam@list:index_map( + gleam@string:to_graphemes(R), + fun(X, C) -> {{coord, X, Y}, to_symbol(C)} end + ) + end + )), + _pipe@1 = gleam@list:flatten(_pipe), + gleam@dict:from_list(_pipe@1). + +-spec cell_compare(cell(), cell()) -> gleam@order:order(). +cell_compare(A, B) -> + case gleam@int:compare( + erlang:element(3, erlang:element(2, A)), + erlang:element(3, erlang:element(2, B)) + ) of + eq -> + gleam@int:compare( + erlang:element(2, erlang:element(2, A)), + erlang:element(2, erlang:element(2, B)) + ); + + Other -> + Other + end. + +-spec find_all_part_digits(gleam@dict:dict(coord(), symbol())) -> list(cell()). +find_all_part_digits(B) -> + _pipe = B, + _pipe@1 = gleam@dict:filter(_pipe, fun(_, V) -> case V of + {number, _} -> + true; + + _ -> + false + end end), + _pipe@2 = gleam@dict:to_list(_pipe@1), + _pipe@3 = gleam@list:map( + _pipe@2, + fun(Tup) -> {cell, erlang:element(1, Tup), erlang:element(2, Tup)} end + ), + gleam@list:sort(_pipe@3, fun cell_compare/2). + +-spec do_parts(list(cell()), list(part())) -> list(part()). +do_parts(Cells, Parts) -> + case Cells of + [] -> + Parts; + + [{cell, Next, {number, N}} | T] -> + case Parts of + [] -> + do_parts(T, [{part, [Next], N} | Parts]); + + [{part, [Prev | _] = Coords, N0} | Rest_parts] -> + case {(erlang:element(2, Next) - erlang:element(2, Prev)), + (erlang:element(3, Next) - erlang:element(3, Prev))} of + {1, 0} -> + do_parts( + T, + [{part, [Next | Coords], (N0 * 10) + N} | + Rest_parts] + ); + + {_, _} -> + do_parts(T, [{part, [Next], N} | Parts]) + end; + + _ -> + erlang:error(#{gleam_error => panic, + message => <<"panic expression evaluated"/utf8>>, + module => <<"day3/solve"/utf8>>, + function => <<"do_parts"/utf8>>, + line => 90}) + end; + + _ -> + erlang:error(#{gleam_error => panic, + message => <<"panic expression evaluated"/utf8>>, + module => <<"day3/solve"/utf8>>, + function => <<"do_parts"/utf8>>, + line => 93}) + end. + +-spec to_parts(list(cell())) -> list(part()). +to_parts(Cells) -> + do_parts(Cells, []). + +-spec all_neighbors(coord()) -> list(coord()). +all_neighbors(C) -> + gleam@list:flat_map( + [-1, 0, 1], + fun(Dx) -> gleam@list:filter_map([-1, 0, 1], fun(Dy) -> case {Dx, Dy} of + {0, 0} -> + {error, nil}; + + {_, _} -> + {ok, + {coord, + erlang:element(2, C) + Dx, + erlang:element(3, C) + Dy}} + end end) end + ). + +-spec sum_valid_parts(integer(), part(), gleam@dict:dict(coord(), symbol())) -> integer(). +sum_valid_parts(Acc, Part, Board) -> + Neighbors = begin + _pipe = erlang:element(2, Part), + _pipe@1 = gleam@list:flat_map(_pipe, fun all_neighbors/1), + gleam@list:unique(_pipe@1) + end, + Sym = [{ok, {symbol, gear}}, {ok, {symbol, something_else}}], + case gleam@list:any( + Neighbors, + fun(C) -> gleam@list:contains(Sym, gleam@dict:get(Board, C)) end + ) of + true -> + Acc + erlang:element(3, Part); + + false -> + Acc + end. + +-spec part1(binary()) -> integer(). +part1(Input) -> + Board = to_board(Input), + _pipe = Board, + _pipe@1 = find_all_part_digits(_pipe), + _pipe@2 = to_parts(_pipe@1), + gleam@list:fold( + _pipe@2, + 0, + fun(Acc, P) -> sum_valid_parts(Acc, P, Board) end + ). + +-spec to_part_with_neighbors(part()) -> part(). +to_part_with_neighbors(Part) -> + _pipe = erlang:element(2, Part), + _pipe@1 = gleam@list:flat_map(_pipe, fun all_neighbors/1), + _pipe@2 = gleam@list:unique(_pipe@1), + {part, _pipe@2, erlang:element(3, Part)}. + +-spec find_part_numbers_near_gear(coord(), list(part())) -> list(integer()). +find_part_numbers_near_gear(Gear, Parts) -> + gleam@list:filter_map( + Parts, + fun(Part) -> case gleam@list:contains(erlang:element(2, Part), Gear) of + true -> + {ok, erlang:element(3, Part)}; + + false -> + {error, nil} + end end + ). + +-spec to_sum_of_gear_ratios(list(list(integer()))) -> integer(). +to_sum_of_gear_ratios(Adjacent_parts) -> + gleam@list:fold(Adjacent_parts, 0, fun(Acc, Ps) -> case Ps of + [P1, P2] -> + Acc + (P1 * P2); + + _ -> + Acc + end end). + +-spec part2(binary()) -> integer(). +part2(Input) -> + Board = to_board(Input), + Parts = begin + _pipe = Board, + _pipe@1 = find_all_part_digits(_pipe), + _pipe@2 = to_parts(_pipe@1), + gleam@list:map(_pipe@2, fun to_part_with_neighbors/1) + end, + _pipe@3 = Board, + _pipe@4 = gleam@dict:filter(_pipe@3, fun(_, V) -> V =:= {symbol, gear} end), + _pipe@5 = gleam@dict:keys(_pipe@4), + _pipe@6 = gleam@list:map( + _pipe@5, + fun(_capture) -> find_part_numbers_near_gear(_capture, Parts) end + ), + to_sum_of_gear_ratios(_pipe@6). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day3/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 168}) + end, + _assert_subject@1 = adglent:get_input(<<"3"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day3/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 169}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.cache Binary files differnew file mode 100644 index 0000000..4c2e06a --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.cache_meta Binary files differnew file mode 100644 index 0000000..98d2944 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.erl new file mode 100644 index 0000000..b739e61 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.erl @@ -0,0 +1,52 @@ +-module(day4@day4_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 +Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 +Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 +Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 +Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 +Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11"/utf8>>, + 13}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 +Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 +Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 +Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 +Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 +Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11"/utf8>>, + 13}], + fun(Example) -> _pipe@1 = day4@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 +Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 +Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 +Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 +Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 +Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11"/utf8>>, + 30}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 +Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 +Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 +Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 +Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 +Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11"/utf8>>, + 30}], + fun(Example) -> _pipe@1 = day4@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.cache Binary files differnew file mode 100644 index 0000000..af204ff --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.cache_meta Binary files differnew file mode 100644 index 0000000..1db4b46 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.erl new file mode 100644 index 0000000..7cc0186 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.erl @@ -0,0 +1,169 @@ +-module(day4@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([card/0]). + +-type card() :: {card, integer(), integer()}. + +-spec numbers_to_set(binary()) -> gleam@set:set(integer()). +numbers_to_set(Str) -> + _pipe = Str, + _pipe@1 = gleam@string:split(_pipe, <<" "/utf8>>), + _pipe@2 = gleam@list:map(_pipe@1, fun gleam@int:parse/1), + _pipe@3 = gleam@result:values(_pipe@2), + gleam@set:from_list(_pipe@3). + +-spec parse_card(binary()) -> card(). +parse_card(Card) -> + _assert_subject = gleam@string:split_once(Card, <<": "/utf8>>), + {ok, {<<"Card"/utf8, N_str/binary>>, Rest}} = case _assert_subject of + {ok, {<<"Card"/utf8, _/binary>>, _}} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day4/solve"/utf8>>, + function => <<"parse_card"/utf8>>, + line => 25}) + end, + _assert_subject@1 = gleam@string:split_once(Rest, <<" | "/utf8>>), + {ok, {Winning_str, Has_str}} = case _assert_subject@1 of + {ok, {_, _}} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day4/solve"/utf8>>, + function => <<"parse_card"/utf8>>, + line => 26}) + end, + _assert_subject@2 = gleam@int:parse(gleam@string:trim(N_str)), + {ok, N} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"day4/solve"/utf8>>, + function => <<"parse_card"/utf8>>, + line => 27}) + end, + Winning = numbers_to_set(Winning_str), + Has = numbers_to_set(Has_str), + Winners = gleam@set:size(gleam@set:intersection(Winning, Has)), + {card, N, Winners}. + +-spec win_points(integer()) -> integer(). +win_points(N) -> + gleam@bool:guard(N < 2, N, fun() -> 2 * win_points(N - 1) end). + +-spec part1(binary()) -> integer(). +part1(Input) -> + gleam@list:fold( + gleam@string:split(Input, <<"\n"/utf8>>), + 0, + fun(Acc, C) -> _pipe = C, + _pipe@1 = parse_card(_pipe), + _pipe@2 = (fun(C@1) -> win_points(erlang:element(3, C@1)) end)( + _pipe@1 + ), + gleam@int:add(_pipe@2, Acc) end + ). + +-spec update_counts(integer(), card(), gleam@dict:dict(integer(), integer())) -> gleam@dict:dict(integer(), integer()). +update_counts(N, Card, Count) -> + _assert_subject = gleam@dict:get(Count, erlang:element(2, Card)), + {ok, Bonus} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day4/solve"/utf8>>, + function => <<"update_counts"/utf8>>, + line => 65}) + end, + gleam@list:fold( + gleam@list:range( + erlang:element(2, Card) + 1, + erlang:element(2, Card) + N + ), + Count, + fun(Acc, N@1) -> gleam@dict:update(Acc, N@1, fun(C) -> case C of + {some, I} -> + I + Bonus; + + none -> + erlang:error(#{gleam_error => panic, + message => <<"won a card that doesn't exist in the card pile"/utf8>>, + module => <<"day4/solve"/utf8>>, + function => <<"update_counts"/utf8>>, + line => 70}) + end end) end + ). + +-spec win_more_cards(list(binary()), gleam@dict:dict(integer(), integer())) -> integer(). +win_more_cards(Cards, Count) -> + case Cards of + [] -> + _pipe = Count, + _pipe@1 = gleam@dict:values(_pipe), + gleam@int:sum(_pipe@1); + + [Raw_card | Rest] -> + Card = parse_card(Raw_card), + case erlang:element(3, Card) of + 0 -> + win_more_cards(Rest, Count); + + N -> + win_more_cards(Rest, update_counts(N, Card, Count)) + end + end. + +-spec part2(binary()) -> integer(). +part2(Input) -> + Cards = gleam@string:split(Input, <<"\n"/utf8>>), + Count = begin + _pipe = gleam@list:range(1, gleam@list:length(Cards)), + _pipe@1 = gleam@list:map(_pipe, fun(N) -> {N, 1} end), + gleam@dict:from_list(_pipe@1) + end, + win_more_cards(Cards, Count). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day4/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 86}) + end, + _assert_subject@1 = adglent:get_input(<<"4"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day4/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 87}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.cache Binary files differnew file mode 100644 index 0000000..07488c8 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.cache_meta Binary files differnew file mode 100644 index 0000000..0ca1b7d --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.erl new file mode 100644 index 0000000..170eddd --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.erl @@ -0,0 +1,160 @@ +-module(day5@day5_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"seeds: 79 14 55 13 + +seed-to-soil map: +50 98 2 +52 50 48 + +soil-to-fertilizer map: +0 15 37 +37 52 2 +39 0 15 + +fertilizer-to-water map: +49 53 8 +0 11 42 +42 0 7 +57 7 4 + +water-to-light map: +88 18 7 +18 25 70 + +light-to-temperature map: +45 77 23 +81 45 19 +68 64 13 + +temperature-to-humidity map: +0 69 1 +1 0 69 + +humidity-to-location map: +60 56 37 +56 93 4"/utf8>>, + <<"35"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"seeds: 79 14 55 13 + +seed-to-soil map: +50 98 2 +52 50 48 + +soil-to-fertilizer map: +0 15 37 +37 52 2 +39 0 15 + +fertilizer-to-water map: +49 53 8 +0 11 42 +42 0 7 +57 7 4 + +water-to-light map: +88 18 7 +18 25 70 + +light-to-temperature map: +45 77 23 +81 45 19 +68 64 13 + +temperature-to-humidity map: +0 69 1 +1 0 69 + +humidity-to-location map: +60 56 37 +56 93 4"/utf8>>, + <<"35"/utf8>>}], + fun(Example) -> _pipe@1 = day5@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"seeds: 79 14 55 13 + +seed-to-soil map: +50 98 2 +52 50 48 + +soil-to-fertilizer map: +0 15 37 +37 52 2 +39 0 15 + +fertilizer-to-water map: +49 53 8 +0 11 42 +42 0 7 +57 7 4 + +water-to-light map: +88 18 7 +18 25 70 + +light-to-temperature map: +45 77 23 +81 45 19 +68 64 13 + +temperature-to-humidity map: +0 69 1 +1 0 69 + +humidity-to-location map: +60 56 37 +56 93 4"/utf8>>, + <<"46"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"seeds: 79 14 55 13 + +seed-to-soil map: +50 98 2 +52 50 48 + +soil-to-fertilizer map: +0 15 37 +37 52 2 +39 0 15 + +fertilizer-to-water map: +49 53 8 +0 11 42 +42 0 7 +57 7 4 + +water-to-light map: +88 18 7 +18 25 70 + +light-to-temperature map: +45 77 23 +81 45 19 +68 64 13 + +temperature-to-humidity map: +0 69 1 +1 0 69 + +humidity-to-location map: +60 56 37 +56 93 4"/utf8>>, + <<"46"/utf8>>}], + fun(Example) -> _pipe@1 = day5@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.cache Binary files differnew file mode 100644 index 0000000..22ec6e4 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.cache_meta Binary files differnew file mode 100644 index 0000000..2e8355d --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.erl new file mode 100644 index 0000000..5bb23ee --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.erl @@ -0,0 +1,269 @@ +-module(day5@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([almanac/0, mapping_range/0, seed_range/0]). + +-type almanac() :: {almanac, list(integer()), list(list(mapping_range()))}. + +-type mapping_range() :: {m_range, integer(), integer(), integer()}. + +-type seed_range() :: {s_range, integer(), integer()}. + +-spec string_to_int_list(binary()) -> list(integer()). +string_to_int_list(Str) -> + _pipe = Str, + _pipe@1 = gleam@string:split(_pipe, <<" "/utf8>>), + _pipe@2 = gleam@list:map(_pipe@1, fun gleam@int:parse/1), + gleam@result:values(_pipe@2). + +-spec parse_mrange(binary()) -> mapping_range(). +parse_mrange(Str) -> + _assert_subject = string_to_int_list(Str), + [Destination, Source, Range_width] = case _assert_subject of + [_, _, _] -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day5/solve"/utf8>>, + function => <<"parse_mrange"/utf8>>, + line => 55}) + end, + {m_range, Source, (Source + Range_width) - 1, Destination - Source}. + +-spec parse_mapper(list(binary())) -> list(mapping_range()). +parse_mapper(Strs) -> + [_ | Raw_ranges] = case Strs of + [_ | _] -> Strs; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day5/solve"/utf8>>, + function => <<"parse_mapper"/utf8>>, + line => 49}) + end, + _pipe = gleam@list:map(Raw_ranges, fun parse_mrange/1), + gleam@list:sort( + _pipe, + fun(A, B) -> + gleam@int:compare(erlang:element(2, A), erlang:element(2, B)) + end + ). + +-spec parse_input(binary()) -> almanac(). +parse_input(Input) -> + _assert_subject = gleam@string:split(Input, <<"\n\n"/utf8>>), + [<<"seeds: "/utf8, Raw_seeds/binary>> | Raw_mappers] = case _assert_subject of + [<<"seeds: "/utf8, _/binary>> | _] -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day5/solve"/utf8>>, + function => <<"parse_input"/utf8>>, + line => 29}) + end, + Seeds = string_to_int_list(Raw_seeds), + Mappers = gleam@list:map( + Raw_mappers, + gleam@function:compose( + fun(_capture) -> gleam@string:split(_capture, <<"\n"/utf8>>) end, + fun parse_mapper/1 + ) + ), + {almanac, Seeds, Mappers}. + +-spec correspond(integer(), list(mapping_range())) -> integer(). +correspond(N, Mapper) -> + gleam@list:fold_until( + Mapper, + N, + fun(Acc, Mrange) -> + case (erlang:element(2, Mrange) =< Acc) andalso (Acc =< erlang:element( + 3, + Mrange + )) of + true -> + {stop, Acc + erlang:element(4, Mrange)}; + + false -> + {continue, Acc} + end + end + ). + +-spec part1(binary()) -> binary(). +part1(Input) -> + {almanac, Seeds, Mappers} = parse_input(Input), + _pipe = gleam@list:map( + Seeds, + fun(_capture) -> + gleam@list:fold(Mappers, _capture, fun correspond/2) + end + ), + _pipe@1 = gleam@list:reduce(_pipe, fun gleam@int:min/2), + _pipe@2 = gleam@result:unwrap(_pipe@1, 0), + gleam@string:inspect(_pipe@2). + +-spec transform_range(seed_range(), mapping_range()) -> seed_range(). +transform_range(R, Mapper) -> + {s_range, + erlang:element(2, R) + erlang:element(4, Mapper), + erlang:element(3, R) + erlang:element(4, Mapper)}. + +-spec do_remap_range(seed_range(), list(mapping_range()), list(seed_range())) -> list(seed_range()). +do_remap_range(R, Mapper, Acc) -> + case Mapper of + [] -> + [R | Acc]; + + [M | _] when erlang:element(3, R) < erlang:element(2, M) -> + [R | Acc]; + + [M@1 | Ms] when erlang:element(2, R) > erlang:element(3, M@1) -> + do_remap_range(R, Ms, Acc); + + [M@2 | _] when (erlang:element(2, R) >= erlang:element(2, M@2)) andalso (erlang:element( + 3, + R + ) =< erlang:element(3, M@2)) -> + [transform_range(R, M@2) | Acc]; + + [M@3 | _] when (erlang:element(2, R) < erlang:element(2, M@3)) andalso (erlang:element( + 3, + R + ) =< erlang:element(3, M@3)) -> + [{s_range, erlang:element(2, R), erlang:element(2, M@3) - 1}, + transform_range( + {s_range, erlang:element(2, M@3), erlang:element(3, R)}, + M@3 + ) | + Acc]; + + [M@4 | Ms@1] when (erlang:element(2, R) >= erlang:element(2, M@4)) andalso (erlang:element( + 3, + R + ) > erlang:element(3, M@4)) -> + do_remap_range( + {s_range, erlang:element(3, M@4) + 1, erlang:element(3, R)}, + Ms@1, + [transform_range( + {s_range, erlang:element(2, R), erlang:element(3, M@4)}, + M@4 + ) | + Acc] + ); + + [M@5 | Ms@2] -> + do_remap_range( + {s_range, erlang:element(3, M@5) + 1, erlang:element(3, R)}, + Ms@2, + [{s_range, erlang:element(2, R), erlang:element(2, M@5) - 1}, + transform_range( + {s_range, + erlang:element(2, M@5), + erlang:element(3, M@5)}, + M@5 + ) | + Acc] + ) + end. + +-spec remap_range(seed_range(), list(mapping_range())) -> list(seed_range()). +remap_range(R, Mapper) -> + do_remap_range(R, Mapper, []). + +-spec remap_all_seed_ranges(list(seed_range()), list(list(mapping_range()))) -> list(seed_range()). +remap_all_seed_ranges(Srs, Mappers) -> + case Mappers of + [] -> + Srs; + + [Mapper | Rest] -> + _pipe = gleam@list:flat_map( + Srs, + fun(_capture) -> remap_range(_capture, Mapper) end + ), + remap_all_seed_ranges(_pipe, Rest) + end. + +-spec part2(binary()) -> binary(). +part2(Input) -> + {almanac, Seeds, Mappers} = parse_input(Input), + _assert_subject = begin + _pipe = Seeds, + _pipe@1 = gleam@list:sized_chunk(_pipe, 2), + _pipe@3 = gleam@list:map( + _pipe@1, + fun(Chunk) -> + [Start, Length] = case Chunk of + [_, _] -> Chunk; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day5/solve"/utf8>>, + function => <<"part2"/utf8>>, + line => 87}) + end, + _pipe@2 = [{s_range, Start, (Start + Length) - 1}], + remap_all_seed_ranges(_pipe@2, Mappers) + end + ), + _pipe@4 = gleam@list:flatten(_pipe@3), + gleam@list:sort( + _pipe@4, + fun(A, B) -> + gleam@int:compare(erlang:element(2, A), erlang:element(2, B)) + end + ) + end, + [{s_range, Answer, _} | _] = case _assert_subject of + [{s_range, _, _} | _] -> _assert_subject; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day5/solve"/utf8>>, + function => <<"part2"/utf8>>, + line => 83}) + end, + gleam@string:inspect(Answer). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day5/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 150}) + end, + _assert_subject@1 = adglent:get_input(<<"5"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day5/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 151}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.cache Binary files differnew file mode 100644 index 0000000..1b29ca0 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.cache_meta Binary files differnew file mode 100644 index 0000000..6ae533d --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.erl new file mode 100644 index 0000000..9e02cea --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.erl @@ -0,0 +1,36 @@ +-module(day6@day6_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"Time: 7 15 30 +Distance: 9 40 200"/utf8>>, + <<"288"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"Time: 7 15 30 +Distance: 9 40 200"/utf8>>, + <<"288"/utf8>>}], + fun(Example) -> _pipe@1 = day6@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"Time: 7 15 30 +Distance: 9 40 200"/utf8>>, + <<"71503"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"Time: 7 15 30 +Distance: 9 40 200"/utf8>>, + <<"71503"/utf8>>}], + fun(Example) -> _pipe@1 = day6@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.cache Binary files differnew file mode 100644 index 0000000..2a735ee --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.cache_meta Binary files differnew file mode 100644 index 0000000..e1a7797 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.erl new file mode 100644 index 0000000..6f70ab5 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.erl @@ -0,0 +1,131 @@ +-module(day6@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([race/0]). + +-type race() :: {race, integer(), integer()}. + +-spec parse_with_bad_kerning(binary()) -> list(race()). +parse_with_bad_kerning(Input) -> + _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), + _pipe@5 = gleam@list:map(_pipe@1, fun(Str) -> _pipe@2 = Str, + _pipe@3 = gleam@string:split(_pipe@2, <<" "/utf8>>), + _pipe@4 = gleam@list:map(_pipe@3, fun gleam@int:parse/1), + gleam@result:values(_pipe@4) end), + _pipe@6 = gleam@list:transpose(_pipe@5), + gleam@list:map( + _pipe@6, + fun(Ns) -> + [T, D] = case Ns of + [_, _] -> Ns; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day6/solve"/utf8>>, + function => <<"parse_with_bad_kerning"/utf8>>, + line => 23}) + end, + {race, T, D} + end + ). + +-spec find_bound(race(), integer(), integer()) -> integer(). +find_bound(Race, Button_time, Step) -> + Travel_time = erlang:element(2, Race) - Button_time, + case (Button_time * Travel_time) > erlang:element(3, Race) of + true -> + Button_time; + + false -> + find_bound(Race, Button_time + Step, Step) + end. + +-spec lower_bound(race()) -> integer(). +lower_bound(Race) -> + find_bound(Race, 1, 1). + +-spec upper_bound(race()) -> integer(). +upper_bound(Race) -> + find_bound(Race, erlang:element(2, Race), -1). + +-spec part1(binary()) -> binary(). +part1(Input) -> + _pipe = (gleam@list:fold( + parse_with_bad_kerning(Input), + 1, + fun(Acc, Race) -> + Acc * ((upper_bound(Race) - lower_bound(Race)) + 1) + end + )), + gleam@string:inspect(_pipe). + +-spec parse_properly(binary()) -> list(integer()). +parse_properly(Input) -> + _pipe = Input, + _pipe@1 = gleam@string:replace(_pipe, <<" "/utf8>>, <<""/utf8>>), + _pipe@2 = gleam@string:split(_pipe@1, <<"\n"/utf8>>), + _pipe@3 = gleam@list:flat_map( + _pipe@2, + fun(_capture) -> gleam@string:split(_capture, <<":"/utf8>>) end + ), + _pipe@4 = gleam@list:map(_pipe@3, fun gleam@int:parse/1), + gleam@result:values(_pipe@4). + +-spec part2(binary()) -> binary(). +part2(Input) -> + _assert_subject = begin + _pipe = Input, + parse_properly(_pipe) + end, + [Time, Distance] = case _assert_subject of + [_, _] -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day6/solve"/utf8>>, + function => <<"part2"/utf8>>, + line => 62}) + end, + Race = {race, Time, Distance}, + _pipe@1 = (upper_bound(Race) - lower_bound(Race)) + 1, + gleam@string:inspect(_pipe@1). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day6/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 73}) + end, + _assert_subject@1 = adglent:get_input(<<"6"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day6/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 74}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.cache Binary files differnew file mode 100644 index 0000000..d4830bb --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.cache_meta Binary files differnew file mode 100644 index 0000000..f63dc34 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.erl new file mode 100644 index 0000000..57e4a29 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.erl @@ -0,0 +1,48 @@ +-module(day7@day7_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"32T3K 765 +T55J5 684 +KK677 28 +KTJJT 220 +QQQJA 483"/utf8>>, + <<"6440"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"32T3K 765 +T55J5 684 +KK677 28 +KTJJT 220 +QQQJA 483"/utf8>>, + <<"6440"/utf8>>}], + fun(Example) -> _pipe@1 = day7@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"32T3K 765 +T55J5 684 +KK677 28 +KTJJT 220 +QQQJA 483"/utf8>>, + <<"5905"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"32T3K 765 +T55J5 684 +KK677 28 +KTJJT 220 +QQQJA 483"/utf8>>, + <<"5905"/utf8>>}], + fun(Example) -> _pipe@1 = day7@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.cache Binary files differnew file mode 100644 index 0000000..9d72fb4 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.cache_meta Binary files differnew file mode 100644 index 0000000..ff45788 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.erl new file mode 100644 index 0000000..d6bf6aa --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.erl @@ -0,0 +1,242 @@ +-module(day7@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([hand/0]). + +-type hand() :: {hand, list(integer()), integer()}. + +-spec card_counts(hand()) -> list(integer()). +card_counts(Hand) -> + _pipe = erlang:element(2, Hand), + _pipe@1 = gleam@list:sort(_pipe, fun gleam@int:compare/2), + _pipe@2 = gleam@list:chunk(_pipe@1, fun gleam@function:identity/1), + _pipe@3 = gleam@list:map(_pipe@2, fun gleam@list:length/1), + gleam@list:sort(_pipe@3, fun gleam@int:compare/2). + +-spec classify_hand(hand()) -> integer(). +classify_hand(Hand) -> + case {gleam@list:length(gleam@list:unique(erlang:element(2, Hand))), + card_counts(Hand)} of + {1, _} -> + 8; + + {2, [1, 4]} -> + 7; + + {2, [2, 3]} -> + 6; + + {3, [1, 1, 3]} -> + 5; + + {3, [1, 2, 2]} -> + 4; + + {4, _} -> + 3; + + {5, _} -> + 2; + + {_, _} -> + 1 + end. + +-spec card_rank(binary()) -> integer(). +card_rank(Card) -> + case {gleam@int:parse(Card), Card} of + {{ok, N}, _} -> + N; + + {_, <<"A"/utf8>>} -> + 14; + + {_, <<"K"/utf8>>} -> + 13; + + {_, <<"Q"/utf8>>} -> + 12; + + {_, <<"J"/utf8>>} -> + 11; + + {_, <<"T"/utf8>>} -> + 10; + + {_, _} -> + 1 + end. + +-spec parse_hand(binary()) -> hand(). +parse_hand(Str) -> + _assert_subject = gleam@string:split(Str, <<" "/utf8>>), + [Cards, Wager] = case _assert_subject of + [_, _] -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day7/solve"/utf8>>, + function => <<"parse_hand"/utf8>>, + line => 19}) + end, + Cards@1 = begin + _pipe = gleam@string:to_graphemes(Cards), + gleam@list:map(_pipe, fun card_rank/1) + end, + _assert_subject@1 = gleam@int:parse(Wager), + {ok, Wager@1} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day7/solve"/utf8>>, + function => <<"parse_hand"/utf8>>, + line => 23}) + end, + {hand, Cards@1, Wager@1}. + +-spec compare_top_card(list(integer()), list(integer())) -> gleam@order:order(). +compare_top_card(Cards1, Cards2) -> + gleam@bool:guard( + (Cards1 =:= []) orelse (Cards2 =:= []), + eq, + fun() -> + [C1 | Rest1] = case Cards1 of + [_ | _] -> Cards1; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day7/solve"/utf8>>, + function => <<"compare_top_card"/utf8>>, + line => 70}) + end, + [C2 | Rest2] = case Cards2 of + [_ | _] -> Cards2; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day7/solve"/utf8>>, + function => <<"compare_top_card"/utf8>>, + line => 71}) + end, + case gleam@int:compare(C1, C2) of + eq -> + compare_top_card(Rest1, Rest2); + + Other -> + Other + end + end + ). + +-spec compare_hands(hand(), hand(), fun((hand()) -> integer())) -> gleam@order:order(). +compare_hands(Hand1, Hand2, Using) -> + case gleam@int:compare(Using(Hand1), Using(Hand2)) of + eq -> + compare_top_card(erlang:element(2, Hand1), erlang:element(2, Hand2)); + + Other -> + Other + end. + +-spec part(binary(), fun((hand(), hand()) -> gleam@order:order())) -> binary(). +part(Input, Comparator) -> + _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), + _pipe@2 = gleam@list:map(_pipe@1, fun parse_hand/1), + _pipe@3 = gleam@list:sort(_pipe@2, Comparator), + _pipe@4 = gleam@list:index_map( + _pipe@3, + fun(I, H) -> (I + 1) * erlang:element(3, H) end + ), + _pipe@5 = gleam@int:sum(_pipe@4), + gleam@string:inspect(_pipe@5). + +-spec compare_without_wilds(hand(), hand()) -> gleam@order:order(). +compare_without_wilds(Hand1, Hand2) -> + compare_hands(Hand1, Hand2, fun classify_hand/1). + +-spec part1(binary()) -> binary(). +part1(Input) -> + part(Input, fun compare_without_wilds/2). + +-spec find_best_joker_substitution(hand()) -> hand(). +find_best_joker_substitution(Hand) -> + gleam@list:fold( + gleam@list:range(2, 14), + {hand, [], 0}, + fun(Acc, Card) -> + Subbed_cards = (gleam@list:map( + erlang:element(2, Hand), + fun(C) -> case C of + 1 -> + Card; + + Other -> + Other + end end + )), + Subbed_hand = erlang:setelement(2, Hand, Subbed_cards), + case compare_hands(Acc, Subbed_hand, fun classify_hand/1) of + lt -> + Subbed_hand; + + _ -> + Acc + end + end + ). + +-spec compare_hands_considering_jokers(hand(), hand()) -> gleam@order:order(). +compare_hands_considering_jokers(Hand1, Hand2) -> + compare_hands(Hand1, Hand2, fun(Hand) -> _pipe = Hand, + _pipe@1 = find_best_joker_substitution(_pipe), + classify_hand(_pipe@1) end). + +-spec part2(binary()) -> binary(). +part2(Input) -> + part( + gleam@string:replace(Input, <<"J"/utf8>>, <<"*"/utf8>>), + fun compare_hands_considering_jokers/2 + ). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day7/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 128}) + end, + _assert_subject@1 = adglent:get_input(<<"7"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day7/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 129}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.cache Binary files differnew file mode 100644 index 0000000..3d89b8b --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.cache_meta Binary files differnew file mode 100644 index 0000000..4082d33 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.erl new file mode 100644 index 0000000..b3e591d --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.erl @@ -0,0 +1,58 @@ +-module(day8@day8_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"LLR + +AAA = (BBB, BBB) +BBB = (AAA, ZZZ) +ZZZ = (ZZZ, ZZZ)"/utf8>>, + 6}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"LLR + +AAA = (BBB, BBB) +BBB = (AAA, ZZZ) +ZZZ = (ZZZ, ZZZ)"/utf8>>, + 6}], + fun(Example) -> _pipe@1 = day8@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"LR + +11A = (11B, XXX) +11B = (XXX, 11Z) +11Z = (11B, XXX) +22A = (22B, XXX) +22B = (22C, 22C) +22C = (22Z, 22Z) +22Z = (22B, 22B) +XXX = (XXX, XXX)"/utf8>>, + 6}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"LR + +11A = (11B, XXX) +11B = (XXX, 11Z) +11Z = (11B, XXX) +22A = (22B, XXX) +22B = (22C, 22C) +22C = (22Z, 22Z) +22Z = (22B, 22B) +XXX = (XXX, XXX)"/utf8>>, + 6}], + fun(Example) -> _pipe@1 = day8@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.cache Binary files differnew file mode 100644 index 0000000..a03967b --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.cache_meta Binary files differnew file mode 100644 index 0000000..4389637 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.erl new file mode 100644 index 0000000..30c5133 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.erl @@ -0,0 +1,179 @@ +-module(day8@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). +-export_type([paths/0]). + +-type paths() :: {paths, binary(), binary()}. + +-spec parse(binary()) -> {gleam@iterator:iterator(binary()), + gleam@dict:dict(binary(), paths())}. +parse(Input) -> + _assert_subject = gleam@string:split(Input, <<"\n\n"/utf8>>), + [Directions_str, Maze_str] = case _assert_subject of + [_, _] -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day8/solve"/utf8>>, + function => <<"parse"/utf8>>, + line => 20}) + end, + Directions = begin + _pipe = Directions_str, + _pipe@1 = gleam@string:to_graphemes(_pipe), + _pipe@2 = gleam@iterator:from_list(_pipe@1), + gleam@iterator:cycle(_pipe@2) + end, + _assert_subject@1 = gleam@regex:from_string( + <<"(...) = \\((...), (...)\\)"/utf8>> + ), + {ok, Re} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day8/solve"/utf8>>, + function => <<"parse"/utf8>>, + line => 28}) + end, + Maze = begin + _pipe@3 = Maze_str, + _pipe@4 = gleam@string:split(_pipe@3, <<"\n"/utf8>>), + _pipe@5 = gleam@list:map( + _pipe@4, + fun(Str) -> + _assert_subject@2 = gleam@regex:scan(Re, Str), + [{match, _, [{some, Name}, {some, Left}, {some, Right}]}] = case _assert_subject@2 of + [{match, _, [{some, _}, {some, _}, {some, _}]}] -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"day8/solve"/utf8>>, + function => <<"parse"/utf8>>, + line => 33}) + end, + {Name, {paths, Left, Right}} + end + ), + gleam@dict:from_list(_pipe@5) + end, + {Directions, Maze}. + +-spec to_next_step( + binary(), + binary(), + integer(), + gleam@iterator:iterator(binary()), + gleam@dict:dict(binary(), paths()) +) -> integer(). +to_next_step(Current, Stop_at, Count, Directions, Maze) -> + gleam@bool:guard( + gleam@string:ends_with(Current, Stop_at), + Count, + fun() -> + _assert_subject = gleam@iterator:step(Directions), + {next, Next_direction, Rest_directions} = case _assert_subject of + {next, _, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day8/solve"/utf8>>, + function => <<"to_next_step"/utf8>>, + line => 50}) + end, + _assert_subject@1 = gleam@dict:get(Maze, Current), + {ok, Paths} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day8/solve"/utf8>>, + function => <<"to_next_step"/utf8>>, + line => 51}) + end, + _pipe = case Next_direction of + <<"L"/utf8>> -> + erlang:element(2, Paths); + + <<"R"/utf8>> -> + erlang:element(3, Paths); + + _ -> + erlang:error(#{gleam_error => panic, + message => <<"bad direction"/utf8>>, + module => <<"day8/solve"/utf8>>, + function => <<"to_next_step"/utf8>>, + line => 55}) + end, + to_next_step(_pipe, Stop_at, Count + 1, Rest_directions, Maze) + end + ). + +-spec part1(binary()) -> integer(). +part1(Input) -> + {Directions, Maze} = parse(Input), + to_next_step(<<"AAA"/utf8>>, <<"ZZZ"/utf8>>, 0, Directions, Maze). + +-spec part2(binary()) -> integer(). +part2(Input) -> + {Directions, Maze} = parse(Input), + gleam@list:fold( + gleam@dict:keys(Maze), + 1, + fun(Acc, Name) -> case gleam@string:ends_with(Name, <<"A"/utf8>>) of + false -> + Acc; + + true -> + _pipe = to_next_step( + Name, + <<"Z"/utf8>>, + 0, + Directions, + Maze + ), + gleam_community@maths@arithmetics:lcm(_pipe, Acc) + end end + ). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day8/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 79}) + end, + _assert_subject@1 = adglent:get_input(<<"8"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day8/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 80}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.cache Binary files differnew file mode 100644 index 0000000..32b4cd1 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.cache_meta Binary files differnew file mode 100644 index 0000000..6e5f636 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.erl new file mode 100644 index 0000000..9532be7 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.erl @@ -0,0 +1,40 @@ +-module(day9@day9_test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1_test/0, part2_test/0]). + +-spec part1_test() -> list(nil). +part1_test() -> + _pipe = [{example, + <<"0 3 6 9 12 15 +1 3 6 10 15 21 +10 13 16 21 30 45"/utf8>>, + <<"114"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"0 3 6 9 12 15 +1 3 6 10 15 21 +10 13 16 21 30 45"/utf8>>, + <<"114"/utf8>>}], + fun(Example) -> _pipe@1 = day9@solve:part1(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). + +-spec part2_test() -> list(nil). +part2_test() -> + _pipe = [{example, + <<"0 3 6 9 12 15 +1 3 6 10 15 21 +10 13 16 21 30 45"/utf8>>, + <<"2"/utf8>>}], + showtime@tests@should:not_equal(_pipe, []), + gleam@list:map( + [{example, + <<"0 3 6 9 12 15 +1 3 6 10 15 21 +10 13 16 21 30 45"/utf8>>, + <<"2"/utf8>>}], + fun(Example) -> _pipe@1 = day9@solve:part2(erlang:element(2, Example)), + showtime@tests@should:equal(_pipe@1, erlang:element(3, Example)) end + ). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.cache Binary files differnew file mode 100644 index 0000000..afd006e --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.cache_meta Binary files differnew file mode 100644 index 0000000..7875518 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.erl new file mode 100644 index 0000000..87cd9f7 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.erl @@ -0,0 +1,133 @@ +-module(day9@solve). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([part1/1, part2/1, main/0]). + +-spec maybe_backwards(list(SLN), boolean()) -> list(SLN). +maybe_backwards(Xs, Backwards) -> + case Backwards of + false -> + gleam@list:reverse(Xs); + + true -> + Xs + end. + +-spec parse(binary(), boolean()) -> list(list(integer())). +parse(Input, Backwards) -> + gleam@list:map( + gleam@string:split(Input, <<"\n"/utf8>>), + fun(Line) -> + gleam@list:map( + maybe_backwards( + gleam@string:split(Line, <<" "/utf8>>), + Backwards + ), + fun(N_str) -> + _assert_subject = gleam@int:parse(N_str), + {ok, N} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day9/solve"/utf8>>, + function => <<"parse"/utf8>>, + line => 10}) + end, + N + end + ) + end + ). + +-spec is_constant(list(integer())) -> boolean(). +is_constant(Ns) -> + case gleam@list:unique(Ns) of + [_] -> + true; + + _ -> + false + end. + +-spec take_derivative(list(integer())) -> list(integer()). +take_derivative(Ns) -> + _pipe = Ns, + _pipe@1 = gleam@list:window_by_2(_pipe), + gleam@list:map( + _pipe@1, + fun(Tup) -> erlang:element(1, Tup) - erlang:element(2, Tup) end + ). + +-spec extrapolate(list(integer())) -> integer(). +extrapolate(Ns) -> + case {is_constant(Ns), Ns} of + {true, [N | _]} -> + N; + + {false, [N@1 | _]} -> + N@1 + extrapolate(take_derivative(Ns)); + + {_, _} -> + erlang:error(#{gleam_error => panic, + message => <<"list empty when it shouldn't be"/utf8>>, + module => <<"day9/solve"/utf8>>, + function => <<"extrapolate"/utf8>>, + line => 38}) + end. + +-spec part(binary(), boolean()) -> binary(). +part(Input, Backwards) -> + _pipe = Input, + _pipe@1 = parse(_pipe, Backwards), + _pipe@2 = gleam@list:fold( + _pipe@1, + 0, + fun(Acc, Ns) -> extrapolate(Ns) + Acc end + ), + gleam@string:inspect(_pipe@2). + +-spec part1(binary()) -> binary(). +part1(Input) -> + part(Input, false). + +-spec part2(binary()) -> binary(). +part2(Input) -> + part(Input, true). + +-spec main() -> nil. +main() -> + _assert_subject = adglent:get_part(), + {ok, Part} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"day9/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 58}) + end, + _assert_subject@1 = adglent:get_input(<<"9"/utf8>>), + {ok, Input} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"day9/solve"/utf8>>, + function => <<"main"/utf8>>, + line => 59}) + end, + case Part of + first -> + _pipe = part1(Input), + _pipe@1 = adglent:inspect(_pipe), + gleam@io:println(_pipe@1); + + second -> + _pipe@2 = part2(Input), + _pipe@3 = adglent:inspect(_pipe@2), + gleam@io:println(_pipe@3) + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.cache Binary files differnew file mode 100644 index 0000000..44f142d --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.cache_meta Binary files differnew file mode 100644 index 0000000..cd522ba --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.erl new file mode 100644 index 0000000..8790dec --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.erl @@ -0,0 +1,82 @@ +-module(utilities@array2d). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([add_posns/2, ortho_neighbors/1, to_2d_array_using/2, to_2d_array/1, to_2d_intarray/1, to_list_of_lists/1, parse_grid_using/2, parse_grid/1]). +-export_type([posn/0]). + +-type posn() :: {posn, integer(), integer()}. + +-spec add_posns(posn(), posn()) -> posn(). +add_posns(P1, P2) -> + case {P1, P2} of + {{posn, R1, C1}, {posn, R2, C2}} -> + {posn, R1 + R2, C1 + C2} + end. + +-spec ortho_neighbors(posn()) -> list(posn()). +ortho_neighbors(P) -> + {posn, R, C} = P, + [{posn, R + 1, C}, {posn, R - 1, C}, {posn, R, C + 1}, {posn, R, C - 1}]. + +-spec to_2d_array_using(list(list(PSV)), fun((PSV) -> {ok, PSY} | {error, nil})) -> gleam@dict:dict(posn(), PSY). +to_2d_array_using(Xss, F) -> + _pipe = (gleam@list:index_map( + Xss, + fun(R, Row) -> gleam@list:index_map(Row, fun(C, Cell) -> case F(Cell) of + {ok, Contents} -> + {ok, {{posn, R, C}, Contents}}; + + {error, nil} -> + {error, nil} + end end) end + )), + _pipe@1 = gleam@list:flatten(_pipe), + _pipe@2 = gleam@result:values(_pipe@1), + gleam@dict:from_list(_pipe@2). + +-spec to_2d_array(list(list(PSR))) -> gleam@dict:dict(posn(), PSR). +to_2d_array(Xss) -> + to_2d_array_using(Xss, fun(X) -> {ok, X} end). + +-spec to_2d_intarray(list(list(binary()))) -> gleam@dict:dict(posn(), integer()). +to_2d_intarray(Xss) -> + _pipe = (gleam@list:index_map( + Xss, + fun(R, Row) -> + gleam@list:index_map( + Row, + fun(C, Cell) -> + _assert_subject = gleam@int:parse(Cell), + {ok, N} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"utilities/array2d"/utf8>>, + function => <<"to_2d_intarray"/utf8>>, + line => 50}) + end, + {{posn, R, C}, N} + end + ) + end + )), + _pipe@1 = gleam@list:flatten(_pipe), + gleam@dict:from_list(_pipe@1). + +-spec to_list_of_lists(binary()) -> list(list(binary())). +to_list_of_lists(Str) -> + _pipe = Str, + _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>), + gleam@list:map(_pipe@1, fun gleam@string:to_graphemes/1). + +-spec parse_grid_using(binary(), fun((binary()) -> {ok, PTI} | {error, nil})) -> gleam@dict:dict(posn(), PTI). +parse_grid_using(Str, F) -> + _pipe = Str, + _pipe@1 = to_list_of_lists(_pipe), + to_2d_array_using(_pipe@1, F). + +-spec parse_grid(binary()) -> gleam@dict:dict(posn(), binary()). +parse_grid(Str) -> + parse_grid_using(Str, fun(X) -> {ok, X} end). diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.cache Binary files differnew file mode 100644 index 0000000..204b330 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.cache_meta Binary files differnew file mode 100644 index 0000000..4253e7c --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.erl new file mode 100644 index 0000000..376369c --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.erl @@ -0,0 +1,70 @@ +-module(utilities@memo). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([create/1, set/3, get/2, memoize/3]). +-export_type([message/2, cache/2]). + +-type message(SNL, SNM) :: shutdown | + {get, SNL, gleam@erlang@process:subject({ok, SNM} | {error, nil})} | + {set, SNL, SNM}. + +-opaque cache(SNN, SNO) :: {cache, + gleam@erlang@process:subject(message(SNN, SNO))}. + +-spec handle_message(message(SNU, SNV), gleam@dict:dict(SNU, SNV)) -> gleam@otp@actor:next(message(SNU, SNV), gleam@dict:dict(SNU, SNV)). +handle_message(Message, Dict) -> + case Message of + shutdown -> + {stop, normal}; + + {get, Key, Client} -> + gleam@erlang@process:send(Client, gleam@dict:get(Dict, Key)), + {continue, Dict, none}; + + {set, Key@1, Value} -> + {continue, gleam@dict:insert(Dict, Key@1, Value), none} + end. + +-spec create(fun((cache(any(), any())) -> SOK)) -> SOK. +create(Fun) -> + _assert_subject = gleam@otp@actor:start( + gleam@dict:new(), + fun handle_message/2 + ), + {ok, Server} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"utilities/memo"/utf8>>, + function => <<"create"/utf8>>, + line => 36}) + end, + Result = Fun({cache, Server}), + gleam@erlang@process:send(Server, shutdown), + Result. + +-spec set(cache(SOL, SOM), SOL, SOM) -> nil. +set(Cache, Key, Value) -> + gleam@erlang@process:send(erlang:element(2, Cache), {set, Key, Value}). + +-spec get(cache(SOP, SOQ), SOP) -> {ok, SOQ} | {error, nil}. +get(Cache, Key) -> + gleam@erlang@process:call( + erlang:element(2, Cache), + fun(C) -> {get, Key, C} end, + 1000 + ). + +-spec memoize(cache(SOV, SOW), SOV, fun(() -> SOW)) -> SOW. +memoize(Cache, Key, Fun) -> + Result = case get(Cache, Key) of + {ok, Value} -> + Value; + + {error, nil} -> + Fun() + end, + set(Cache, Key, Result), + Result. diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.cache b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.cache Binary files differnew file mode 100644 index 0000000..f013f33 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.cache diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.cache_meta Binary files differnew file mode 100644 index 0000000..84048ca --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.cache_meta diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.erl b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.erl new file mode 100644 index 0000000..f3784b2 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.erl @@ -0,0 +1,60 @@ +-module(utilities@prioqueue). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([new/0, insert/3, pop/1]). +-export_type([ref/0, p_queue/1, priority_queue/1, out_result/1]). + +-type ref() :: any(). + +-type p_queue(BAU) :: any() | {gleam_phantom, BAU}. + +-opaque priority_queue(BAV) :: {priority_queue, + p_queue({BAV, ref()}), + gleam@dict:dict(BAV, ref())}. + +-type out_result(BAW) :: empty | {value, BAW, integer()}. + +-spec new() -> priority_queue(any()). +new() -> + {priority_queue, pqueue2:new(), gleam@dict:new()}. + +-spec insert(priority_queue(BBI), BBI, integer()) -> priority_queue(BBI). +insert(Queue, Value, Priority) -> + Ref = erlang:make_ref(), + Refs = begin + _pipe = erlang:element(3, Queue), + gleam@dict:insert(_pipe, Value, Ref) + end, + {priority_queue, + pqueue2:in({Value, Ref}, Priority, erlang:element(2, Queue)), + Refs}. + +-spec pop(priority_queue(BBL)) -> {ok, {BBL, priority_queue(BBL)}} | + {error, nil}. +pop(Queue) -> + case pqueue2:pout(erlang:element(2, Queue)) of + {{value, {Value, Ref}, _}, Pqueue} -> + _assert_subject = gleam@dict:get(erlang:element(3, Queue), Value), + {ok, Recently_enqueued_ref} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"utilities/prioqueue"/utf8>>, + function => <<"pop"/utf8>>, + line => 54}) + end, + case Recently_enqueued_ref =:= Ref of + true -> + {ok, + {Value, + {priority_queue, Pqueue, erlang:element(3, Queue)}}}; + + false -> + pop({priority_queue, Pqueue, erlang:element(3, Queue)}) + end; + + {empty, _} -> + {error, nil} + end. diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023.app b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023.app new file mode 100644 index 0000000..043f0b6 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023.app @@ -0,0 +1,14 @@ +{application, aoc2023, [ + {vsn, "0.1.0"}, + {applications, [adglent, + gleam_community_maths, + gleam_erlang, + gleam_otp, + gleam_stdlib, + pqueue, + simplifile]}, + {description, ""}, + {modules, [day14@day14_test, + day14@solve]}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023.beam Binary files differnew file mode 100644 index 0000000..7fe2a91 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023@@main.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023@@main.beam Binary files differnew file mode 100644 index 0000000..9e35237 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023@@main.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023_test.beam Binary files differnew file mode 100644 index 0000000..7fac74c --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day10@day10_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day10@day10_test.beam Binary files differnew file mode 100644 index 0000000..0fe1fd6 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day10@day10_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day10@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day10@solve.beam Binary files differnew file mode 100644 index 0000000..5028a72 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day10@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day11@day11_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day11@day11_test.beam Binary files differnew file mode 100644 index 0000000..3e5c47d --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day11@day11_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day11@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day11@solve.beam Binary files differnew file mode 100644 index 0000000..ac8563e --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day11@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day12@day12_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day12@day12_test.beam Binary files differnew file mode 100644 index 0000000..a98331a --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day12@day12_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day12@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day12@solve.beam Binary files differnew file mode 100644 index 0000000..87869e4 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day12@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day13@day13_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day13@day13_test.beam Binary files differnew file mode 100644 index 0000000..b194d26 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day13@day13_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day13@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day13@solve.beam Binary files differnew file mode 100644 index 0000000..38974ae --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day13@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day14@day14_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day14@day14_test.beam Binary files differnew file mode 100644 index 0000000..2b4629d --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day14@day14_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day14@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day14@solve.beam Binary files differnew file mode 100644 index 0000000..aa76b4f --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day14@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day15@day15_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day15@day15_test.beam Binary files differnew file mode 100644 index 0000000..29aba3b --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day15@day15_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day15@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day15@solve.beam Binary files differnew file mode 100644 index 0000000..d3a892e --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day15@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day16@day16_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day16@day16_test.beam Binary files differnew file mode 100644 index 0000000..785aee1 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day16@day16_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day16@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day16@solve.beam Binary files differnew file mode 100644 index 0000000..b85d427 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day16@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day17@day17_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day17@day17_test.beam Binary files differnew file mode 100644 index 0000000..973225d --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day17@day17_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day17@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day17@solve.beam Binary files differnew file mode 100644 index 0000000..770b87b --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day17@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day18@day18_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day18@day18_test.beam Binary files differnew file mode 100644 index 0000000..d4668d8 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day18@day18_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day18@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day18@solve.beam Binary files differnew file mode 100644 index 0000000..1559a28 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day18@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day19@day19_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day19@day19_test.beam Binary files differnew file mode 100644 index 0000000..b4b142b --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day19@day19_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day19@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day19@solve.beam Binary files differnew file mode 100644 index 0000000..429a9c3 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day19@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day1@day1_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day1@day1_test.beam Binary files differnew file mode 100644 index 0000000..cc5cc2e --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day1@day1_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day1@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day1@solve.beam Binary files differnew file mode 100644 index 0000000..21582eb --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day1@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day20@day20_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day20@day20_test.beam Binary files differnew file mode 100644 index 0000000..69c5a85 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day20@day20_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day20@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day20@solve.beam Binary files differnew file mode 100644 index 0000000..2d186df --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day20@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day21@day21_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day21@day21_test.beam Binary files differnew file mode 100644 index 0000000..dcd764a --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day21@day21_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day21@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day21@solve.beam Binary files differnew file mode 100644 index 0000000..34bfb6f --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day21@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day22@day22_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day22@day22_test.beam Binary files differnew file mode 100644 index 0000000..511b695 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day22@day22_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day22@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day22@solve.beam Binary files differnew file mode 100644 index 0000000..dd15c2a --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day22@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day23@day23_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day23@day23_test.beam Binary files differnew file mode 100644 index 0000000..fd46989 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day23@day23_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day23@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day23@solve.beam Binary files differnew file mode 100644 index 0000000..d1c426f --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day23@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day2@day2_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day2@day2_test.beam Binary files differnew file mode 100644 index 0000000..96a97fc --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day2@day2_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day2@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day2@solve.beam Binary files differnew file mode 100644 index 0000000..592a360 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day2@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day3@day3_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day3@day3_test.beam Binary files differnew file mode 100644 index 0000000..12d57d1 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day3@day3_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day3@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day3@solve.beam Binary files differnew file mode 100644 index 0000000..9fa2011 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day3@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day4@day4_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day4@day4_test.beam Binary files differnew file mode 100644 index 0000000..41d9854 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day4@day4_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day4@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day4@solve.beam Binary files differnew file mode 100644 index 0000000..a8d5973 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day4@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day5@day5_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day5@day5_test.beam Binary files differnew file mode 100644 index 0000000..a7e22e1 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day5@day5_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day5@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day5@solve.beam Binary files differnew file mode 100644 index 0000000..d248e2c --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day5@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day6@day6_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day6@day6_test.beam Binary files differnew file mode 100644 index 0000000..11a7360 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day6@day6_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day6@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day6@solve.beam Binary files differnew file mode 100644 index 0000000..ddb5777 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day6@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day7@day7_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day7@day7_test.beam Binary files differnew file mode 100644 index 0000000..c4586b8 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day7@day7_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day7@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day7@solve.beam Binary files differnew file mode 100644 index 0000000..4ae1796 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day7@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day8@day8_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day8@day8_test.beam Binary files differnew file mode 100644 index 0000000..68fa255 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day8@day8_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day8@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day8@solve.beam Binary files differnew file mode 100644 index 0000000..d2d7689 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day8@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day9@day9_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day9@day9_test.beam Binary files differnew file mode 100644 index 0000000..f12dde7 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day9@day9_test.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day9@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day9@solve.beam Binary files differnew file mode 100644 index 0000000..4920ea7 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day9@solve.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@array2d.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@array2d.beam Binary files differnew file mode 100644 index 0000000..f265230 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@array2d.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@memo.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@memo.beam Binary files differnew file mode 100644 index 0000000..09a3274 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@memo.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@prioqueue.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@prioqueue.beam Binary files differnew file mode 100644 index 0000000..b95d0dd --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@prioqueue.beam diff --git a/aoc2023/build/dev/erlang/aoc2023/include/day2@solve_Game.hrl b/aoc2023/build/dev/erlang/aoc2023/include/day2@solve_Game.hrl new file mode 100644 index 0000000..7babf61 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/include/day2@solve_Game.hrl @@ -0,0 +1 @@ +-record(game, {red :: integer(), blue :: integer(), green :: integer()}). diff --git a/aoc2023/build/dev/erlang/aoc2023/include/day5@solve_Almanac.hrl b/aoc2023/build/dev/erlang/aoc2023/include/day5@solve_Almanac.hrl new file mode 100644 index 0000000..5c3086c --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/include/day5@solve_Almanac.hrl @@ -0,0 +1,4 @@ +-record(almanac, { + seeds :: list(integer()), + mappers :: list(list(day5@solve:mapping_range())) +}). diff --git a/aoc2023/build/dev/erlang/aoc2023/include/day5@solve_MRange.hrl b/aoc2023/build/dev/erlang/aoc2023/include/day5@solve_MRange.hrl new file mode 100644 index 0000000..999313f --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/include/day5@solve_MRange.hrl @@ -0,0 +1 @@ +-record(m_range, {start :: integer(), 'end' :: integer(), offset :: integer()}). diff --git a/aoc2023/build/dev/erlang/aoc2023/include/day5@solve_SRange.hrl b/aoc2023/build/dev/erlang/aoc2023/include/day5@solve_SRange.hrl new file mode 100644 index 0000000..56c67cd --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/include/day5@solve_SRange.hrl @@ -0,0 +1 @@ +-record(s_range, {start :: integer(), 'end' :: integer()}). diff --git a/aoc2023/build/dev/erlang/aoc2023/include/utilities@array2d_Posn.hrl b/aoc2023/build/dev/erlang/aoc2023/include/utilities@array2d_Posn.hrl new file mode 100644 index 0000000..94da3d5 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/include/utilities@array2d_Posn.hrl @@ -0,0 +1 @@ +-record(posn, {r :: integer(), c :: integer()}). diff --git a/aoc2023/build/dev/erlang/aoc2023/include/utilities@memo_Cache.hrl b/aoc2023/build/dev/erlang/aoc2023/include/utilities@memo_Cache.hrl new file mode 100644 index 0000000..941b746 --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/include/utilities@memo_Cache.hrl @@ -0,0 +1,3 @@ +-record(cache, { + server :: gleam@erlang@process:subject(utilities@memo:message(any(), any())) +}). diff --git a/aoc2023/build/dev/erlang/aoc2023/include/utilities@prioqueue_PriorityQueue.hrl b/aoc2023/build/dev/erlang/aoc2023/include/utilities@prioqueue_PriorityQueue.hrl new file mode 100644 index 0000000..0e12dca --- /dev/null +++ b/aoc2023/build/dev/erlang/aoc2023/include/utilities@prioqueue_PriorityQueue.hrl @@ -0,0 +1,4 @@ +-record(priority_queue, { + queue :: utilities@prioqueue:p_queue({any(), utilities@prioqueue:ref()}), + refs :: gleam@dict:dict(any(), utilities@prioqueue:ref()) +}). diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cache b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cache Binary files differnew file mode 100644 index 0000000..772b42f --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cache diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cache_meta b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cache_meta Binary files differnew file mode 100644 index 0000000..3a247a0 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cache_meta diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.erl b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.erl new file mode 100644 index 0000000..91045ce --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.erl @@ -0,0 +1,538 @@ +-module(gap). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([to_styled/1, compare_strings_with_algorithm/3, compare_lists_with_algorithm/3, myers/2, compare_lists/2, compare_strings/2, lcs/2]). +-export_type([score/1]). + +-type score(NLN) :: {score, integer(), gleam@option:option(NLN)}. + +-spec to_styled(gap@comparison:comparison(any())) -> gap@styled_comparison:styled_comparison(). +to_styled(Comparison) -> + _pipe = Comparison, + _pipe@1 = gap@styling:from_comparison(_pipe), + _pipe@2 = gap@styling:highlight( + _pipe@1, + fun gap@styling:first_highlight_default/1, + fun gap@styling:second_highlight_default/1, + fun gap@styling:no_highlight/1 + ), + gap@styling:to_styled_comparison(_pipe@2). + +-spec compare_strings_with_algorithm( + binary(), + binary(), + fun((list(binary()), list(binary())) -> gap@comparison:comparison(binary())) +) -> gap@comparison:comparison(binary()). +compare_strings_with_algorithm(First, Second, Algorithm) -> + Comparison = Algorithm( + gleam@string:to_graphemes(First), + gleam@string:to_graphemes(Second) + ), + case Comparison of + {list_comparison, First@1, Second@1} -> + {string_comparison, First@1, Second@1}; + + {string_comparison, First@2, Second@2} -> + {string_comparison, First@2, Second@2} + end. + +-spec compare_lists_with_algorithm( + list(NMC), + list(NMC), + fun((list(NMC), list(NMC)) -> gap@comparison:comparison(NMC)) +) -> gap@comparison:comparison(NMC). +compare_lists_with_algorithm(First_sequence, Second_sequence, Algorithm) -> + Algorithm(First_sequence, Second_sequence). + +-spec myers(list(NMH), list(NMH)) -> gap@comparison:comparison(NMH). +myers(First_sequence, Second_sequence) -> + Edits = gap@myers:difference(First_sequence, Second_sequence), + _pipe = Edits, + _pipe@1 = gleam@list:reverse(_pipe), + gleam@list:fold( + _pipe@1, + {list_comparison, [], []}, + fun(Comparison, Edit) -> case Comparison of + {list_comparison, First, Second} -> + case Edit of + {eq, Segment} -> + {list_comparison, + [{match, Segment} | First], + [{match, Segment} | Second]}; + + {ins, Segment@1} -> + {list_comparison, + First, + [{no_match, Segment@1} | Second]}; + + {del, Segment@2} -> + {list_comparison, + [{no_match, Segment@2} | First], + Second} + end; + + {string_comparison, _, _} -> + Comparison + end end + ). + +-spec compare_lists(list(NLY), list(NLY)) -> gap@comparison:comparison(NLY). +compare_lists(First_sequence, Second_sequence) -> + myers(First_sequence, Second_sequence). + +-spec compare_strings(binary(), binary()) -> gap@comparison:comparison(binary()). +compare_strings(First, Second) -> + Comparison = compare_lists( + gleam@string:to_graphemes(First), + gleam@string:to_graphemes(Second) + ), + case Comparison of + {list_comparison, First@1, Second@1} -> + {string_comparison, First@1, Second@1}; + + {string_comparison, First@2, Second@2} -> + {string_comparison, First@2, Second@2} + end. + +-spec prepend_and_merge( + list(gap@comparison:match(list(NMP))), + gap@comparison:match(list(NMP)) +) -> list(gap@comparison:match(list(NMP))). +prepend_and_merge(Matches, Match) -> + case {Matches, Match} of + {[], _} -> + [Match]; + + {[{match, First_match} | Rest], {match, _}} -> + [{match, + begin + _pipe = erlang:element(2, Match), + gleam@list:append(_pipe, First_match) + end} | + Rest]; + + {[{no_match, First_match@1} | Rest@1], {no_match, _}} -> + [{no_match, + begin + _pipe@1 = erlang:element(2, Match), + gleam@list:append(_pipe@1, First_match@1) + end} | + Rest@1]; + + {Matches@1, Match@1} -> + [Match@1 | Matches@1] + end. + +-spec append_and_merge( + list(gap@comparison:match(list(NMY))), + gap@comparison:match(list(NMY)) +) -> list(gap@comparison:match(list(NMY))). +append_and_merge(Matches, Match) -> + _pipe@3 = case {begin + _pipe = Matches, + gleam@list:reverse(_pipe) + end, + Match} of + {[], _} -> + [Match]; + + {[{match, First_match} | Rest], {match, _}} -> + [{match, + begin + _pipe@1 = First_match, + gleam@list:append(_pipe@1, erlang:element(2, Match)) + end} | + Rest]; + + {[{no_match, First_match@1} | Rest@1], {no_match, _}} -> + [{no_match, + begin + _pipe@2 = First_match@1, + gleam@list:append(_pipe@2, erlang:element(2, Match)) + end} | + Rest@1]; + + {Matches@1, Match@1} -> + [Match@1 | Matches@1] + end, + gleam@list:reverse(_pipe@3). + +-spec collect_matches( + gleam@dict:dict(NQZ, any()), + list(NNI), + fun((NQZ) -> integer()) +) -> list(gap@comparison:match(list(NNI))). +collect_matches(Tracking, Str, Extract_fun) -> + Matching_indexes = begin + _pipe = gleam@map:keys(Tracking), + _pipe@1 = gleam@list:map(_pipe, Extract_fun), + gleam@set:from_list(_pipe@1) + end, + Matches = begin + _pipe@2 = Str, + gleam@list:index_map( + _pipe@2, + fun(Index, Item) -> + case gleam@set:contains(Matching_indexes, Index) of + true -> + {match, Item}; + + false -> + {no_match, Item} + end + end + ) + end, + _pipe@3 = Matches, + _pipe@4 = gleam@list:chunk(_pipe@3, fun(Match) -> case Match of + {match, _} -> + true; + + {no_match, _} -> + false + end end), + gleam@list:map(_pipe@4, fun(Match_list) -> case Match_list of + [{match, _} | _] -> + {match, + gleam@list:filter_map( + Match_list, + fun(Match@1) -> case Match@1 of + {match, Item@1} -> + {ok, Item@1}; + + {no_match, _} -> + {error, nil} + end end + )}; + + [{no_match, _} | _] -> + {no_match, + gleam@list:filter_map( + Match_list, + fun(Match@2) -> case Match@2 of + {no_match, Item@2} -> + {ok, Item@2}; + + {match, _} -> + {error, nil} + end end + )} + end end). + +-spec back_track( + gleam@dict:dict({integer(), integer()}, score(NNM)), + integer(), + integer(), + list({{integer(), integer()}, NNM}) +) -> list({{integer(), integer()}, NNM}). +back_track(Diff_map, First_index, Second_index, Stack) -> + case (First_index =:= 0) orelse (Second_index =:= 0) of + true -> + This_score = begin + _pipe = gleam@map:get(Diff_map, {First_index, Second_index}), + gleam@result:unwrap(_pipe, {score, 0, none}) + end, + case This_score of + {score, _, {some, Item}} -> + [{{First_index, Second_index}, Item} | Stack]; + + _ -> + case {First_index, Second_index} of + {0, A} when A > 0 -> + back_track( + Diff_map, + First_index, + Second_index - 1, + Stack + ); + + {A@1, 0} when A@1 > 0 -> + back_track( + Diff_map, + First_index - 1, + Second_index, + Stack + ); + + {0, 0} -> + Stack; + + {_, _} -> + back_track( + Diff_map, + First_index - 1, + Second_index, + Stack + ) + end + end; + + false -> + This_score@1 = begin + _pipe@1 = gleam@map:get(Diff_map, {First_index, Second_index}), + gleam@result:unwrap(_pipe@1, {score, 0, none}) + end, + case This_score@1 of + {score, _, {some, Item@1}} -> + back_track( + Diff_map, + First_index - 1, + Second_index - 1, + [{{First_index, Second_index}, Item@1} | Stack] + ); + + {score, _, none} -> + Up = begin + _pipe@2 = gleam@map:get( + Diff_map, + {First_index, Second_index - 1} + ), + gleam@result:unwrap(_pipe@2, {score, 0, none}) + end, + Back = begin + _pipe@3 = gleam@map:get( + Diff_map, + {First_index - 1, Second_index} + ), + gleam@result:unwrap(_pipe@3, {score, 0, none}) + end, + case gleam@int:compare( + erlang:element(2, Up), + erlang:element(2, Back) + ) of + gt -> + back_track( + Diff_map, + First_index, + Second_index - 1, + Stack + ); + + lt -> + back_track( + Diff_map, + First_index - 1, + Second_index, + Stack + ); + + eq -> + case {First_index, Second_index} of + {0, A@2} when A@2 > 0 -> + back_track( + Diff_map, + First_index, + Second_index - 1, + Stack + ); + + {A@3, 0} when A@3 > 0 -> + back_track( + Diff_map, + First_index - 1, + Second_index, + Stack + ); + + {0, 0} -> + Stack; + + {_, _} -> + back_track( + Diff_map, + First_index - 1, + Second_index, + Stack + ) + end + end + end + end. + +-spec build_diff_map( + NNS, + integer(), + NNS, + integer(), + gleam@dict:dict({integer(), integer()}, score(NNS)) +) -> gleam@dict:dict({integer(), integer()}, score(NNS)). +build_diff_map(First_item, First_index, Second_item, Second_index, Diff_map) -> + Prev_score = begin + _pipe = gleam@map:get(Diff_map, {First_index - 1, Second_index - 1}), + gleam@result:unwrap(_pipe, {score, 0, none}) + end, + Derived_score_up = begin + _pipe@1 = Diff_map, + _pipe@2 = gleam@map:get(_pipe@1, {First_index, Second_index - 1}), + gleam@result:unwrap(_pipe@2, {score, 0, none}) + end, + Derived_score_back = begin + _pipe@3 = Diff_map, + _pipe@4 = gleam@map:get(_pipe@3, {First_index - 1, Second_index}), + gleam@result:unwrap(_pipe@4, {score, 0, none}) + end, + Derived_score = gleam@int:max( + erlang:element(2, Derived_score_up), + erlang:element(2, Derived_score_back) + ), + This_score = case First_item =:= Second_item of + true -> + {score, erlang:element(2, Prev_score) + 1, {some, First_item}}; + + false -> + {score, Derived_score, none} + end, + _pipe@5 = Diff_map, + gleam@map:insert(_pipe@5, {First_index, Second_index}, This_score). + +-spec lcs(list(NML), list(NML)) -> gap@comparison:comparison(NML). +lcs(First_sequence, Second_sequence) -> + Leading_matches = begin + _pipe = gleam@list:zip(First_sequence, Second_sequence), + _pipe@1 = gleam@list:take_while( + _pipe, + fun(Pair) -> erlang:element(1, Pair) =:= erlang:element(2, Pair) end + ), + gleam@list:map(_pipe@1, fun gleam@pair:first/1) + end, + Num_leading_matches = gleam@list:length(Leading_matches), + Trailing_matches = begin + _pipe@2 = gleam@list:zip( + gleam@list:reverse(First_sequence), + gleam@list:reverse(Second_sequence) + ), + _pipe@3 = gleam@list:take_while( + _pipe@2, + fun(Pair@1) -> + erlang:element(1, Pair@1) =:= erlang:element(2, Pair@1) + end + ), + _pipe@4 = gleam@list:map(_pipe@3, fun gleam@pair:first/1), + gleam@list:reverse(_pipe@4) + end, + Num_trailing_matches = gleam@list:length(Trailing_matches), + First_sequence_to_diff = begin + _pipe@5 = First_sequence, + _pipe@6 = gleam@list:drop(_pipe@5, Num_leading_matches), + gleam@list:take( + _pipe@6, + (gleam@list:length(First_sequence) - Num_leading_matches) - Num_trailing_matches + ) + end, + Second_sequence_to_diff = begin + _pipe@7 = Second_sequence, + _pipe@8 = gleam@list:drop(_pipe@7, Num_leading_matches), + gleam@list:take( + _pipe@8, + (gleam@list:length(Second_sequence) - Num_leading_matches) - Num_trailing_matches + ) + end, + Diff_map@2 = begin + _pipe@9 = Second_sequence_to_diff, + gleam@list:index_fold( + _pipe@9, + gleam@map:new(), + fun(Diff_map, Item_second, Index_second) -> + _pipe@10 = First_sequence_to_diff, + gleam@list:index_fold( + _pipe@10, + Diff_map, + fun(Diff_map@1, Item_first, Index_first) -> + build_diff_map( + Item_first, + Index_first, + Item_second, + Index_second, + Diff_map@1 + ) + end + ) + end + ) + end, + {First_segments@1, Second_segments@1} = case {First_sequence_to_diff, + Second_sequence_to_diff} of + {[], []} -> + {[], []}; + + {First_matching, []} -> + {[{no_match, First_matching}], []}; + + {[], Second_matching} -> + {[], [{no_match, Second_matching}]}; + + {First_sequence_to_diff@1, Second_sequence_to_diff@1} -> + Tracking = begin + _pipe@11 = back_track( + Diff_map@2, + gleam@list:length(First_sequence_to_diff@1) - 1, + gleam@list:length(Second_sequence_to_diff@1) - 1, + [] + ), + gleam@map:from_list(_pipe@11) + end, + First_segments = collect_matches( + Tracking, + First_sequence_to_diff@1, + fun(Key) -> + {First, _} = Key, + First + end + ), + Second_segments = collect_matches( + Tracking, + Second_sequence_to_diff@1, + fun(Key@1) -> + {_, Second} = Key@1, + Second + end + ), + {First_segments, Second_segments} + end, + {First_segments_with_leading_trailing, + Second_segments_with_leading_trailing} = case {Leading_matches, + Trailing_matches} of + {[], []} -> + {First_segments@1, Second_segments@1}; + + {[], Trailing_matches@1} -> + {begin + _pipe@12 = First_segments@1, + append_and_merge(_pipe@12, {match, Trailing_matches@1}) + end, + begin + _pipe@13 = Second_segments@1, + append_and_merge(_pipe@13, {match, Trailing_matches@1}) + end}; + + {Leading_matches@1, []} -> + {begin + _pipe@14 = First_segments@1, + prepend_and_merge(_pipe@14, {match, Leading_matches@1}) + end, + begin + _pipe@15 = Second_segments@1, + prepend_and_merge(_pipe@15, {match, Leading_matches@1}) + end}; + + {Leading_matches@2, Trailing_matches@2} -> + {begin + _pipe@16 = First_segments@1, + _pipe@17 = prepend_and_merge( + _pipe@16, + {match, Leading_matches@2} + ), + append_and_merge(_pipe@17, {match, Trailing_matches@2}) + end, + begin + _pipe@18 = Second_segments@1, + _pipe@19 = prepend_and_merge( + _pipe@18, + {match, Leading_matches@2} + ), + append_and_merge(_pipe@19, {match, Trailing_matches@2}) + end} + end, + {list_comparison, + First_segments_with_leading_trailing, + Second_segments_with_leading_trailing}. diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.cache b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.cache Binary files differnew file mode 100644 index 0000000..90fe99a --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.cache diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.cache_meta b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.cache_meta Binary files differnew file mode 100644 index 0000000..e3f3599 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.cache_meta diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.erl b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.erl new file mode 100644 index 0000000..74f5db4 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.erl @@ -0,0 +1,15 @@ +-module(gap@comparison). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export_type([comparison/1, match/1]). + +-type comparison(NBT) :: {list_comparison, + list(match(list(NBT))), + list(match(list(NBT)))} | + {string_comparison, + list(match(list(binary()))), + list(match(list(binary())))}. + +-type match(NBU) :: {match, NBU} | {no_match, NBU}. + + diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.cache b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.cache Binary files differnew file mode 100644 index 0000000..1d21cfe --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.cache diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.cache_meta b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.cache_meta Binary files differnew file mode 100644 index 0000000..6d51dd1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.cache_meta diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.erl b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.erl new file mode 100644 index 0000000..1472fc0 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.erl @@ -0,0 +1,156 @@ +-module(gap@myers). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([difference/2]). +-export_type([edit/1, path/1, status/1]). + +-type edit(NFW) :: {eq, list(NFW)} | {del, list(NFW)} | {ins, list(NFW)}. + +-type path(NFX) :: {path, + integer(), + integer(), + list(NFX), + list(NFX), + list(edit(NFX))}. + +-type status(NFY) :: {done, list(edit(NFY))} | + {next, list(path(NFY))} | + {cont, path(NFY)}. + +-spec compact_reverse(list(edit(NGI)), list(edit(NGI))) -> list(edit(NGI)). +compact_reverse(Edits, Acc) -> + case {Edits, Acc} of + {[], Acc@1} -> + Acc@1; + + {[{eq, Elem} | Rest], [{eq, Result} | Acc_rest]} -> + compact_reverse( + Rest, + [{eq, gleam@list:flatten([Elem, Result])} | Acc_rest] + ); + + {[{del, Elem@1} | Rest@1], [{del, Result@1} | Acc_rest@1]} -> + compact_reverse( + Rest@1, + [{del, gleam@list:flatten([Elem@1, Result@1])} | Acc_rest@1] + ); + + {[{ins, Elem@2} | Rest@2], [{ins, Result@2} | Acc_rest@2]} -> + compact_reverse( + Rest@2, + [{ins, gleam@list:flatten([Elem@2, Result@2])} | Acc_rest@2] + ); + + {[{eq, Elem@3} | Rest@3], Acc@2} -> + compact_reverse(Rest@3, [{eq, Elem@3} | Acc@2]); + + {[{del, Elem@4} | Rest@4], Acc@3} -> + compact_reverse(Rest@4, [{del, Elem@4} | Acc@3]); + + {[{ins, Elem@5} | Rest@5], Acc@4} -> + compact_reverse(Rest@5, [{ins, Elem@5} | Acc@4]) + end. + +-spec move_right(path(NHB)) -> path(NHB). +move_right(Path) -> + case Path of + {path, X, Y, List1, [Elem | Rest], Edits} -> + {path, X + 1, Y, List1, Rest, [{ins, [Elem]} | Edits]}; + + {path, X@1, Y@1, List1@1, [], Edits@1} -> + {path, X@1 + 1, Y@1, List1@1, [], Edits@1} + end. + +-spec move_down(path(NHE)) -> path(NHE). +move_down(Path) -> + case Path of + {path, X, Y, [Elem | Rest], List2, Edits} -> + {path, X, Y + 1, Rest, List2, [{del, [Elem]} | Edits]}; + + {path, X@1, Y@1, [], List2@1, Edits@1} -> + {path, X@1, Y@1 + 1, [], List2@1, Edits@1} + end. + +-spec proceed_path(integer(), integer(), list(path(NGV))) -> {path(NGV), + list(path(NGV))}. +proceed_path(Diag, Limit, Paths) -> + Neg_limit = - Limit, + case {Diag, Limit, Paths} of + {0, 0, [Path]} -> + {Path, []}; + + {Diag@1, _, [Path@1 | _] = Paths@1} when Diag@1 =:= Neg_limit -> + {move_down(Path@1), Paths@1}; + + {Diag@2, Limit@1, [Path@2 | _] = Paths@2} when Diag@2 =:= Limit@1 -> + {move_right(Path@2), Paths@2}; + + {_, _, [Path1, Path2 | Rest]} -> + case erlang:element(3, Path1) > erlang:element(3, Path2) of + true -> + {move_right(Path1), [Path2 | Rest]}; + + false -> + {move_down(Path2), [Path2 | Rest]} + end + end. + +-spec follow_snake(path(NHH)) -> status(NHH). +follow_snake(Path) -> + case Path of + {path, X, Y, [Elem1 | Rest1], [Elem2 | Rest2], Edits} when Elem1 =:= Elem2 -> + follow_snake( + {path, X + 1, Y + 1, Rest1, Rest2, [{eq, [Elem1]} | Edits]} + ); + + {path, _, _, [], [], Edits@1} -> + {done, Edits@1}; + + _ -> + {cont, Path} + end. + +-spec each_diagonal(integer(), integer(), list(path(NGP)), list(path(NGP))) -> status(NGP). +each_diagonal(Diag, Limit, Paths, Next_paths) -> + case Diag > Limit of + true -> + {next, gleam@list:reverse(Next_paths)}; + + false -> + {Path, Rest} = proceed_path(Diag, Limit, Paths), + case follow_snake(Path) of + {cont, Path@1} -> + each_diagonal(Diag + 2, Limit, Rest, [Path@1 | Next_paths]); + + Other -> + Other + end + end. + +-spec find_script(integer(), integer(), list(path(NGE))) -> list(edit(NGE)). +find_script(Envelope, Max, Paths) -> + case Envelope > Max of + true -> + []; + + false -> + case each_diagonal(- Envelope, Envelope, Paths, []) of + {done, Edits} -> + compact_reverse(Edits, []); + + {next, Paths@1} -> + find_script(Envelope + 1, Max, Paths@1); + + _ -> + erlang:error(#{gleam_error => panic, + message => <<"Didn't expect a Cont here"/utf8>>, + module => <<"gap/myers"/utf8>>, + function => <<"find_script"/utf8>>, + line => 35}) + end + end. + +-spec difference(list(NFZ), list(NFZ)) -> list(edit(NFZ)). +difference(List1, List2) -> + Path = {path, 0, 0, List1, List2, []}, + find_script(0, gleam@list:length(List1) + gleam@list:length(List2), [Path]). diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.cache b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.cache Binary files differnew file mode 100644 index 0000000..d03c302 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.cache diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.cache_meta b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.cache_meta Binary files differnew file mode 100644 index 0000000..dc9ffd0 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.cache_meta diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.erl b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.erl new file mode 100644 index 0000000..9a04ad4 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.erl @@ -0,0 +1,8 @@ +-module(gap@styled_comparison). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export_type([styled_comparison/0]). + +-type styled_comparison() :: {styled_comparison, binary(), binary()}. + + diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.cache b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.cache Binary files differnew file mode 100644 index 0000000..6fdaed1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.cache diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.cache_meta b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.cache_meta Binary files differnew file mode 100644 index 0000000..f580983 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.cache_meta diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.erl b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.erl new file mode 100644 index 0000000..4a7d2e2 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.erl @@ -0,0 +1,202 @@ +-module(gap@styling). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([from_comparison/1, highlight/4, serialize/2, first_highlight_default/1, second_highlight_default/1, no_highlight/1, mk_generic_serializer/2, to_styled_comparison/1]). +-export_type([part/1, highlighters/0, styling/1]). + +-type part(NCF) :: {part, binary(), list(NCF), fun((binary()) -> binary())} | + {all, binary()}. + +-type highlighters() :: {highlighters, + fun((binary()) -> binary()), + fun((binary()) -> binary()), + fun((binary()) -> binary())}. + +-opaque styling(NCG) :: {styling, + gap@comparison:comparison(NCG), + gleam@option:option(fun((part(NCG)) -> binary())), + gleam@option:option(highlighters())}. + +-spec from_comparison(gap@comparison:comparison(NCJ)) -> styling(NCJ). +from_comparison(Comparison) -> + {styling, Comparison, none, none}. + +-spec highlight( + styling(NCM), + fun((binary()) -> binary()), + fun((binary()) -> binary()), + fun((binary()) -> binary()) +) -> styling(NCM). +highlight(Styling, First, Second, Matching) -> + erlang:setelement( + 4, + Styling, + {some, {highlighters, First, Second, Matching}} + ). + +-spec serialize(styling(NCP), fun((part(NCP)) -> binary())) -> styling(NCP). +serialize(Styling, Serializer) -> + erlang:setelement(3, Styling, {some, Serializer}). + +-spec first_highlight_default(binary()) -> binary(). +first_highlight_default(String) -> + case String of + <<" "/utf8>> -> + _pipe = String, + _pipe@1 = gleam_community@ansi:underline(_pipe), + _pipe@2 = gleam_community@ansi:bold(_pipe@1), + gleam_community@ansi:green(_pipe@2); + + _ -> + _pipe@3 = String, + _pipe@4 = gleam_community@ansi:green(_pipe@3), + gleam_community@ansi:bold(_pipe@4) + end. + +-spec second_highlight_default(binary()) -> binary(). +second_highlight_default(String) -> + case String of + <<" "/utf8>> -> + _pipe = String, + _pipe@1 = gleam_community@ansi:underline(_pipe), + _pipe@2 = gleam_community@ansi:bold(_pipe@1), + gleam_community@ansi:red(_pipe@2); + + _ -> + _pipe@3 = String, + _pipe@4 = gleam_community@ansi:red(_pipe@3), + gleam_community@ansi:bold(_pipe@4) + end. + +-spec no_highlight(binary()) -> binary(). +no_highlight(String) -> + String. + +-spec string_serializer(part(binary())) -> binary(). +string_serializer(Part) -> + case Part of + {part, Acc, Sequence, Highlight} -> + <<Acc/binary, + (begin + _pipe = Sequence, + _pipe@1 = gleam@list:map(_pipe, Highlight), + gleam@string:join(_pipe@1, <<""/utf8>>) + end)/binary>>; + + {all, String} -> + String + end. + +-spec mk_generic_serializer(binary(), fun((binary()) -> binary())) -> fun((part(any())) -> binary()). +mk_generic_serializer(Separator, Around) -> + fun(Part) -> case Part of + {part, Acc, Sequence, Highlight} -> + Segment_separator = case Acc of + <<""/utf8>> -> + <<""/utf8>>; + + _ -> + Separator + end, + <<<<Acc/binary, Segment_separator/binary>>/binary, + (begin + _pipe = Sequence, + _pipe@1 = gleam@list:map( + _pipe, + fun gleam@string:inspect/1 + ), + _pipe@2 = gleam@list:map(_pipe@1, Highlight), + gleam@string:join(_pipe@2, Separator) + end)/binary>>; + + {all, String} -> + Around(String) + end end. + +-spec generic_serializer(part(any())) -> binary(). +generic_serializer(Part) -> + (mk_generic_serializer( + <<", "/utf8>>, + fun(All) -> <<<<"["/utf8, All/binary>>/binary, "]"/utf8>> end + ))(Part). + +-spec to_strings( + list(gap@comparison:match(list(NCZ))), + list(gap@comparison:match(list(NCZ))), + fun((part(NCZ)) -> binary()), + fun((binary()) -> binary()), + fun((binary()) -> binary()), + fun((binary()) -> binary()) +) -> gap@styled_comparison:styled_comparison(). +to_strings( + First, + Second, + Serializer, + First_highlight, + Second_highlight, + No_highlight +) -> + First_styled = begin + _pipe = First, + gleam@list:fold(_pipe, <<""/utf8>>, fun(Str, Match) -> case Match of + {match, Item} -> + Serializer({part, Str, Item, No_highlight}); + + {no_match, Item@1} -> + Serializer({part, Str, Item@1, First_highlight}) + end end) + end, + Second_styled = begin + _pipe@1 = Second, + gleam@list:fold( + _pipe@1, + <<""/utf8>>, + fun(Str@1, Match@1) -> case Match@1 of + {match, Item@2} -> + Serializer({part, Str@1, Item@2, No_highlight}); + + {no_match, Item@3} -> + Serializer({part, Str@1, Item@3, Second_highlight}) + end end + ) + end, + {styled_comparison, + Serializer({all, First_styled}), + Serializer({all, Second_styled})}. + +-spec to_styled_comparison(styling(any())) -> gap@styled_comparison:styled_comparison(). +to_styled_comparison(Styling) -> + Highlight = begin + _pipe = erlang:element(4, Styling), + gleam@option:unwrap( + _pipe, + {highlighters, + fun first_highlight_default/1, + fun second_highlight_default/1, + fun no_highlight/1} + ) + end, + case erlang:element(2, Styling) of + {string_comparison, First, Second} -> + to_strings( + First, + Second, + fun string_serializer/1, + erlang:element(2, Highlight), + erlang:element(3, Highlight), + erlang:element(4, Highlight) + ); + + {list_comparison, First@1, Second@1} -> + to_strings( + First@1, + Second@1, + gleam@option:unwrap( + erlang:element(3, Styling), + fun generic_serializer/1 + ), + erlang:element(2, Highlight), + erlang:element(3, Highlight), + erlang:element(4, Highlight) + ) + end. diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap_ffi.mjs b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap_ffi.mjs new file mode 100644 index 0000000..235c80b --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap_ffi.mjs @@ -0,0 +1,431 @@ +import { + Error, + List, + Ok, + inspect, + toList, + makeError, + isEqual, +} from "./gleam.mjs"; +import * as $option from "../gleam_stdlib/gleam/option.mjs"; + +const HASHCODE_CACHE = new WeakMap(); +const Nil = undefined; + +class MutableMap { + static #hashcode_cache = new WeakMap(); + + static hash(value) { + let existing = this.#hashcode_cache.get(value); + if (existing) { + return existing; + } else if (value instanceof Object) { + let hashcode = inspect(value); + HASHCODE_CACHE.set(value, hashcode); + return hashcode; + } else { + return value.toString(); + } + } + + constructor() { + this.entries = new globalThis.Map(); + } + + get size() { + return this.entries.size; + } + + inspect() { + let entries = [...this.entries.values()] + .map((pair) => inspect(pair)) + .join(", "); + return `map.from_list([${entries}])`; + } + + toList() { + return List.fromArray([...this.entries.values()]); + } + + insert(k, v) { + this.entries.set(MutableMap.hash(k), [k, v]); + return this; + } + + delete(k) { + this.entries.delete(MutableMap.hash(k)); + return this; + } + + get(key) { + let code = MutableMap.hash(key); + if (this.entries.has(code)) { + return new Ok(this.entries.get(code)[1]); + } else { + return new Error(Nil); + } + } +} + +export function new_mutable_map() { + return new MutableMap(); +} + +export function mutable_map_size(map) { + return map.size; +} + +export function mutable_map_to_list(map) { + return map.toList(); +} + +export function mutable_map_remove(k, map) { + return map.delete(k); +} + +export function mutable_map_get(map, key) { + return map.get(key); +} + +export function mutable_map_insert(key, value, map) { + return map.insert(key, value); +} + +// From map.mjs + +export function size(map) { + return mutable_map_size(map); +} + +export function to_list(map) { + return mutable_map_to_list(map); +} + +export function new$() { + return new_mutable_map(); +} + +export function get(from, get) { + return mutable_map_get(from, get); +} + +function do_has_key(key, map) { + return !isEqual(get(map, key), new Error(undefined)); +} + +export function has_key(map, key) { + return do_has_key(key, map); +} + +export function insert(map, key, value) { + return mutable_map_insert(key, value, map); +} + +function insert_pair(map, pair) { + return insert(map, pair[0], pair[1]); +} + +export function update(map, key, fun) { + let _pipe = map; + let _pipe$1 = get(_pipe, key); + let _pipe$2 = $option.from_result(_pipe$1); + let _pipe$3 = fun(_pipe$2); + return ((_capture) => { + return insert(map, key, _capture); + })(_pipe$3); +} + +export function delete$(map, key) { + return mutable_map_remove(key, map); +} + +function fold_list_of_pair(loop$list, loop$initial) { + while (true) { + let list = loop$list; + let initial = loop$initial; + if (list.hasLength(0)) { + return initial; + } else if (list.atLeastLength(1)) { + let x = list.head; + let rest = list.tail; + loop$list = rest; + loop$initial = insert(initial, x[0], x[1]); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 98, + "fold_list_of_pair", + "No case clause matched", + { values: [list] } + ); + } + } +} + +function do_from_list(list) { + return fold_list_of_pair(list, new$()); +} + +export function from_list(list) { + return do_from_list(list); +} + +function do_fold(loop$list, loop$initial, loop$fun) { + while (true) { + let list = loop$list; + let initial = loop$initial; + let fun = loop$fun; + if (list.hasLength(0)) { + return initial; + } else if (list.atLeastLength(1)) { + let k = list.head[0]; + let v = list.head[1]; + let tail = list.tail; + loop$list = tail; + loop$initial = fun(initial, k, v); + loop$fun = fun; + } else { + throw makeError( + "case_no_match", + "gleam/map", + 558, + "do_fold", + "No case clause matched", + { values: [list] } + ); + } + } +} + +export function fold(map, initial, fun) { + let _pipe = map; + let _pipe$1 = to_list(_pipe); + return do_fold(_pipe$1, initial, fun); +} + +function do_map_values(f, map) { + let f$1 = (map, k, v) => { + return insert(map, k, f(k, v)); + }; + let _pipe = map; + return fold(_pipe, new$(), f$1); +} + +export function map_values(map, fun) { + return do_map_values(fun, map); +} + +function do_filter(f, map) { + let insert$1 = (map, k, v) => { + let $ = f(k, v); + if ($) { + return insert(map, k, v); + } else { + return map; + } + }; + let _pipe = map; + return fold(_pipe, new$(), insert$1); +} + +export function filter(map, property) { + return do_filter(property, map); +} + +function do_keys_acc(loop$list, loop$acc) { + while (true) { + let list = loop$list; + let acc = loop$acc; + if (list.hasLength(0)) { + return reverse_and_concat(acc, toList([])); + } else if (list.atLeastLength(1)) { + let x = list.head; + let xs = list.tail; + loop$list = xs; + loop$acc = toList([x[0]], acc); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 276, + "do_keys_acc", + "No case clause matched", + { values: [list] } + ); + } + } +} + +function do_keys(map) { + let list_of_pairs = (() => { + let _pipe = map; + return to_list(_pipe); + })(); + return do_keys_acc(list_of_pairs, toList([])); +} + +export function keys(map) { + return do_keys(map); +} + +function reverse_and_concat(loop$remaining, loop$accumulator) { + while (true) { + let remaining = loop$remaining; + let accumulator = loop$accumulator; + if (remaining.hasLength(0)) { + return accumulator; + } else if (remaining.atLeastLength(1)) { + let item = remaining.head; + let rest = remaining.tail; + loop$remaining = rest; + loop$accumulator = toList([item], accumulator); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 269, + "reverse_and_concat", + "No case clause matched", + { values: [remaining] } + ); + } + } +} + +function do_values_acc(loop$list, loop$acc) { + while (true) { + let list = loop$list; + let acc = loop$acc; + if (list.hasLength(0)) { + return reverse_and_concat(acc, toList([])); + } else if (list.atLeastLength(1)) { + let x = list.head; + let xs = list.tail; + loop$list = xs; + loop$acc = toList([x[1]], acc); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 314, + "do_values_acc", + "No case clause matched", + { values: [list] } + ); + } + } +} + +function do_values(map) { + let list_of_pairs = (() => { + let _pipe = map; + return to_list(_pipe); + })(); + return do_values_acc(list_of_pairs, toList([])); +} + +export function values(map) { + return do_values(map); +} + +function insert_taken(loop$map, loop$desired_keys, loop$acc) { + while (true) { + let map = loop$map; + let desired_keys = loop$desired_keys; + let acc = loop$acc; + let insert$1 = (taken, key) => { + let $ = get(map, key); + if ($.isOk()) { + let value = $[0]; + return insert(taken, key, value); + } else { + return taken; + } + }; + if (desired_keys.hasLength(0)) { + return acc; + } else if (desired_keys.atLeastLength(1)) { + let x = desired_keys.head; + let xs = desired_keys.tail; + loop$map = map; + loop$desired_keys = xs; + loop$acc = insert$1(acc, x); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 411, + "insert_taken", + "No case clause matched", + { values: [desired_keys] } + ); + } + } +} + +function do_take(desired_keys, map) { + return insert_taken(map, desired_keys, new$()); +} + +export function take(map, desired_keys) { + return do_take(desired_keys, map); +} + +function fold_inserts(loop$new_entries, loop$map) { + while (true) { + let new_entries = loop$new_entries; + let map = loop$map; + if (new_entries.hasLength(0)) { + return map; + } else if (new_entries.atLeastLength(1)) { + let x = new_entries.head; + let xs = new_entries.tail; + loop$new_entries = xs; + loop$map = insert_pair(map, x); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 451, + "fold_inserts", + "No case clause matched", + { values: [new_entries] } + ); + } + } +} + +function do_merge(map, new_entries) { + let _pipe = new_entries; + let _pipe$1 = to_list(_pipe); + return fold_inserts(_pipe$1, map); +} + +export function merge(map, new_entries) { + return do_merge(map, new_entries); +} + +export function drop(loop$map, loop$disallowed_keys) { + while (true) { + let map = loop$map; + let disallowed_keys = loop$disallowed_keys; + if (disallowed_keys.hasLength(0)) { + return map; + } else if (disallowed_keys.atLeastLength(1)) { + let x = disallowed_keys.head; + let xs = disallowed_keys.tail; + loop$map = delete$(map, x); + loop$disallowed_keys = xs; + } else { + throw makeError( + "case_no_match", + "gleam/map", + 514, + "drop", + "No case clause matched", + { values: [disallowed_keys] } + ); + } + } +} diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/gap/ebin/gap.app b/aoc2023/build/dev/erlang/gap/ebin/gap.app new file mode 100644 index 0000000..ae37254 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/ebin/gap.app @@ -0,0 +1,8 @@ +{application, gap, [ + {vsn, "1.0.1"}, + {applications, [gleam_community_ansi, + gleam_stdlib]}, + {description, "A Gleam library for comparing strings/lists and producing a textual (styled) representation of the differences."}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/gap/ebin/gap.beam b/aoc2023/build/dev/erlang/gap/ebin/gap.beam Binary files differnew file mode 100644 index 0000000..4eaf513 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/ebin/gap.beam diff --git a/aoc2023/build/dev/erlang/gap/ebin/gap@comparison.beam b/aoc2023/build/dev/erlang/gap/ebin/gap@comparison.beam Binary files differnew file mode 100644 index 0000000..44091a1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/ebin/gap@comparison.beam diff --git a/aoc2023/build/dev/erlang/gap/ebin/gap@myers.beam b/aoc2023/build/dev/erlang/gap/ebin/gap@myers.beam Binary files differnew file mode 100644 index 0000000..d118f3d --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/ebin/gap@myers.beam diff --git a/aoc2023/build/dev/erlang/gap/ebin/gap@styled_comparison.beam b/aoc2023/build/dev/erlang/gap/ebin/gap@styled_comparison.beam Binary files differnew file mode 100644 index 0000000..dfce198 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/ebin/gap@styled_comparison.beam diff --git a/aoc2023/build/dev/erlang/gap/ebin/gap@styling.beam b/aoc2023/build/dev/erlang/gap/ebin/gap@styling.beam Binary files differnew file mode 100644 index 0000000..cf975af --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/ebin/gap@styling.beam diff --git a/aoc2023/build/dev/erlang/gap/include/gap@comparison_ListComparison.hrl b/aoc2023/build/dev/erlang/gap/include/gap@comparison_ListComparison.hrl new file mode 100644 index 0000000..5e4b20d --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/include/gap@comparison_ListComparison.hrl @@ -0,0 +1,4 @@ +-record(list_comparison, { + first :: list(gap@comparison:match(list(any()))), + second :: list(gap@comparison:match(list(any()))) +}). diff --git a/aoc2023/build/dev/erlang/gap/include/gap@comparison_Match.hrl b/aoc2023/build/dev/erlang/gap/include/gap@comparison_Match.hrl new file mode 100644 index 0000000..f1225dd --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/include/gap@comparison_Match.hrl @@ -0,0 +1 @@ +-record(match, {item :: any()}). diff --git a/aoc2023/build/dev/erlang/gap/include/gap@comparison_NoMatch.hrl b/aoc2023/build/dev/erlang/gap/include/gap@comparison_NoMatch.hrl new file mode 100644 index 0000000..742783b --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/include/gap@comparison_NoMatch.hrl @@ -0,0 +1 @@ +-record(no_match, {item :: any()}). diff --git a/aoc2023/build/dev/erlang/gap/include/gap@comparison_StringComparison.hrl b/aoc2023/build/dev/erlang/gap/include/gap@comparison_StringComparison.hrl new file mode 100644 index 0000000..c0b1a75 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/include/gap@comparison_StringComparison.hrl @@ -0,0 +1,4 @@ +-record(string_comparison, { + first :: list(gap@comparison:match(list(binary()))), + second :: list(gap@comparison:match(list(binary()))) +}). diff --git a/aoc2023/build/dev/erlang/gap/include/gap@styled_comparison_StyledComparison.hrl b/aoc2023/build/dev/erlang/gap/include/gap@styled_comparison_StyledComparison.hrl new file mode 100644 index 0000000..0e7c64a --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/include/gap@styled_comparison_StyledComparison.hrl @@ -0,0 +1 @@ +-record(styled_comparison, {first :: binary(), second :: binary()}). diff --git a/aoc2023/build/dev/erlang/gap/include/gap@styling_All.hrl b/aoc2023/build/dev/erlang/gap/include/gap@styling_All.hrl new file mode 100644 index 0000000..c11a9a6 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/include/gap@styling_All.hrl @@ -0,0 +1 @@ +-record(all, {all :: binary()}). diff --git a/aoc2023/build/dev/erlang/gap/include/gap@styling_Highlighters.hrl b/aoc2023/build/dev/erlang/gap/include/gap@styling_Highlighters.hrl new file mode 100644 index 0000000..6e073b3 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/include/gap@styling_Highlighters.hrl @@ -0,0 +1,5 @@ +-record(highlighters, { + first :: fun((binary()) -> binary()), + second :: fun((binary()) -> binary()), + matching :: fun((binary()) -> binary()) +}). diff --git a/aoc2023/build/dev/erlang/gap/include/gap@styling_Part.hrl b/aoc2023/build/dev/erlang/gap/include/gap@styling_Part.hrl new file mode 100644 index 0000000..db45796 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/include/gap@styling_Part.hrl @@ -0,0 +1,5 @@ +-record(part, { + acc :: binary(), + part :: list(any()), + highlight :: fun((binary()) -> binary()) +}). diff --git a/aoc2023/build/dev/erlang/gap/include/gap@styling_Styling.hrl b/aoc2023/build/dev/erlang/gap/include/gap@styling_Styling.hrl new file mode 100644 index 0000000..a7341c6 --- /dev/null +++ b/aoc2023/build/dev/erlang/gap/include/gap@styling_Styling.hrl @@ -0,0 +1,5 @@ +-record(styling, { + comparison :: gap@comparison:comparison(any()), + serializer :: gleam@option:option(fun((gap@styling:part(any())) -> binary())), + highlight :: gleam@option:option(gap@styling:highlighters()) +}). diff --git a/aoc2023/build/dev/erlang/gleam.lock b/aoc2023/build/dev/erlang/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam.lock diff --git a/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache b/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache Binary files differnew file mode 100644 index 0000000..1f67bd7 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache_meta b/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache_meta Binary files differnew file mode 100644 index 0000000..a01f4e8 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.erl b/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.erl new file mode 100644 index 0000000..1698e1e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.erl @@ -0,0 +1,263 @@ +-module(gleam_community@ansi). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([reset/1, bold/1, dim/1, italic/1, underline/1, inverse/1, hidden/1, strikethrough/1, black/1, red/1, green/1, yellow/1, blue/1, magenta/1, cyan/1, white/1, bright_black/1, grey/1, gray/1, bright_red/1, bright_green/1, bright_yellow/1, bright_blue/1, bright_magenta/1, bright_cyan/1, bright_white/1, hex/2, pink/1, colour/2, color/2, bg_black/1, bg_red/1, bg_green/1, bg_yellow/1, bg_blue/1, bg_magenta/1, bg_cyan/1, bg_white/1, bg_bright_black/1, bg_bright_red/1, bg_bright_green/1, bg_bright_yellow/1, bg_bright_blue/1, bg_bright_magenta/1, bg_bright_cyan/1, bg_bright_white/1, bg_hex/2, bg_pink/1, bg_colour/2, bg_color/2]). +-export_type([code/0]). + +-type code() :: {code, binary(), binary(), binary()}. + +-spec run(binary(), code()) -> binary(). +run(Text, Code) -> + <<<<(erlang:element(2, Code))/binary, + (gleam@string:replace( + Text, + erlang:element(4, Code), + erlang:element(2, Code) + ))/binary>>/binary, + (erlang:element(3, Code))/binary>>. + +-spec code(list(integer()), integer()) -> code(). +code(Open, Close) -> + Close_str = gleam@int:to_string(Close), + Open_strs = gleam@list:map(Open, fun gleam@int:to_string/1), + {code, + <<<<<<""/utf8, "["/utf8>>/binary, + (gleam@string:join(Open_strs, <<";"/utf8>>))/binary>>/binary, + "m"/utf8>>, + <<<<<<""/utf8, "["/utf8>>/binary, Close_str/binary>>/binary, "m"/utf8>>, + <<<<<<""/utf8, "["/utf8>>/binary, Close_str/binary>>/binary, "m"/utf8>>}. + +-spec reset(binary()) -> binary(). +reset(Text) -> + run(Text, code([0], 0)). + +-spec bold(binary()) -> binary(). +bold(Text) -> + run(Text, code([1], 22)). + +-spec dim(binary()) -> binary(). +dim(Text) -> + run(Text, code([2], 22)). + +-spec italic(binary()) -> binary(). +italic(Text) -> + run(Text, code([3], 23)). + +-spec underline(binary()) -> binary(). +underline(Text) -> + run(Text, code([4], 24)). + +-spec inverse(binary()) -> binary(). +inverse(Text) -> + run(Text, code([7], 27)). + +-spec hidden(binary()) -> binary(). +hidden(Text) -> + run(Text, code([8], 28)). + +-spec strikethrough(binary()) -> binary(). +strikethrough(Text) -> + run(Text, code([9], 29)). + +-spec black(binary()) -> binary(). +black(Text) -> + run(Text, code([30], 39)). + +-spec red(binary()) -> binary(). +red(Text) -> + run(Text, code([31], 39)). + +-spec green(binary()) -> binary(). +green(Text) -> + run(Text, code([32], 39)). + +-spec yellow(binary()) -> binary(). +yellow(Text) -> + run(Text, code([33], 39)). + +-spec blue(binary()) -> binary(). +blue(Text) -> + run(Text, code([34], 39)). + +-spec magenta(binary()) -> binary(). +magenta(Text) -> + run(Text, code([35], 39)). + +-spec cyan(binary()) -> binary(). +cyan(Text) -> + run(Text, code([36], 39)). + +-spec white(binary()) -> binary(). +white(Text) -> + run(Text, code([37], 39)). + +-spec bright_black(binary()) -> binary(). +bright_black(Text) -> + run(Text, code([90], 39)). + +-spec grey(binary()) -> binary(). +grey(Text) -> + bright_black(Text). + +-spec gray(binary()) -> binary(). +gray(Text) -> + bright_black(Text). + +-spec bright_red(binary()) -> binary(). +bright_red(Text) -> + run(Text, code([91], 39)). + +-spec bright_green(binary()) -> binary(). +bright_green(Text) -> + run(Text, code([92], 39)). + +-spec bright_yellow(binary()) -> binary(). +bright_yellow(Text) -> + run(Text, code([93], 39)). + +-spec bright_blue(binary()) -> binary(). +bright_blue(Text) -> + run(Text, code([94], 39)). + +-spec bright_magenta(binary()) -> binary(). +bright_magenta(Text) -> + run(Text, code([95], 39)). + +-spec bright_cyan(binary()) -> binary(). +bright_cyan(Text) -> + run(Text, code([96], 39)). + +-spec bright_white(binary()) -> binary(). +bright_white(Text) -> + run(Text, code([97], 39)). + +-spec hex(binary(), integer()) -> binary(). +hex(Text, Colour) -> + Colour@1 = gleam@int:clamp(Colour, 16#0, 16#ffffff), + run( + Text, + code( + [38, + 2, + begin + _pipe = erlang:'bsr'(Colour@1, 16), + erlang:'band'(_pipe, 16#ff) + end, + begin + _pipe@1 = erlang:'bsr'(Colour@1, 8), + erlang:'band'(_pipe@1, 16#ff) + end, + erlang:'band'(Colour@1, 16#ff)], + 39 + ) + ). + +-spec pink(binary()) -> binary(). +pink(Text) -> + hex(Text, 16#ffaff3). + +-spec colour(binary(), gleam_community@colour:colour()) -> binary(). +colour(Text, Colour) -> + Hex_colour = gleam_community@colour:to_rgb_hex(Colour), + hex(Text, Hex_colour). + +-spec color(binary(), gleam_community@colour:colour()) -> binary(). +color(Text, Color) -> + colour(Text, Color). + +-spec bg_black(binary()) -> binary(). +bg_black(Text) -> + run(Text, code([40], 49)). + +-spec bg_red(binary()) -> binary(). +bg_red(Text) -> + run(Text, code([41], 49)). + +-spec bg_green(binary()) -> binary(). +bg_green(Text) -> + run(Text, code([42], 49)). + +-spec bg_yellow(binary()) -> binary(). +bg_yellow(Text) -> + run(Text, code([43], 49)). + +-spec bg_blue(binary()) -> binary(). +bg_blue(Text) -> + run(Text, code([44], 49)). + +-spec bg_magenta(binary()) -> binary(). +bg_magenta(Text) -> + run(Text, code([45], 49)). + +-spec bg_cyan(binary()) -> binary(). +bg_cyan(Text) -> + run(Text, code([46], 49)). + +-spec bg_white(binary()) -> binary(). +bg_white(Text) -> + run(Text, code([47], 49)). + +-spec bg_bright_black(binary()) -> binary(). +bg_bright_black(Text) -> + run(Text, code([100], 49)). + +-spec bg_bright_red(binary()) -> binary(). +bg_bright_red(Text) -> + run(Text, code([101], 49)). + +-spec bg_bright_green(binary()) -> binary(). +bg_bright_green(Text) -> + run(Text, code([102], 49)). + +-spec bg_bright_yellow(binary()) -> binary(). +bg_bright_yellow(Text) -> + run(Text, code([103], 49)). + +-spec bg_bright_blue(binary()) -> binary(). +bg_bright_blue(Text) -> + run(Text, code([104], 49)). + +-spec bg_bright_magenta(binary()) -> binary(). +bg_bright_magenta(Text) -> + run(Text, code([105], 49)). + +-spec bg_bright_cyan(binary()) -> binary(). +bg_bright_cyan(Text) -> + run(Text, code([106], 49)). + +-spec bg_bright_white(binary()) -> binary(). +bg_bright_white(Text) -> + run(Text, code([107], 49)). + +-spec bg_hex(binary(), integer()) -> binary(). +bg_hex(Text, Colour) -> + run( + Text, + code( + [48, + 2, + begin + _pipe = erlang:'bsr'(Colour, 16), + erlang:'band'(_pipe, 16#ff) + end, + begin + _pipe@1 = erlang:'bsr'(Colour, 8), + erlang:'band'(_pipe@1, 16#ff) + end, + erlang:'band'(Colour, 16#ff)], + 49 + ) + ). + +-spec bg_pink(binary()) -> binary(). +bg_pink(Text) -> + bg_hex(Text, 16#ffaff3). + +-spec bg_colour(binary(), gleam_community@colour:colour()) -> binary(). +bg_colour(Text, Colour) -> + Hex_colour = gleam_community@colour:to_rgb_hex(Colour), + bg_hex(Text, Hex_colour). + +-spec bg_color(binary(), gleam_community@colour:colour()) -> binary(). +bg_color(Text, Colour) -> + bg_colour(Text, Colour). diff --git a/aoc2023/build/dev/erlang/gleam_community_ansi/ebin/gleam_community@ansi.beam b/aoc2023/build/dev/erlang/gleam_community_ansi/ebin/gleam_community@ansi.beam Binary files differnew file mode 100644 index 0000000..e94b760 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_ansi/ebin/gleam_community@ansi.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_ansi/ebin/gleam_community_ansi.app b/aoc2023/build/dev/erlang/gleam_community_ansi/ebin/gleam_community_ansi.app new file mode 100644 index 0000000..90e4d4a --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_ansi/ebin/gleam_community_ansi.app @@ -0,0 +1,8 @@ +{application, gleam_community_ansi, [ + {vsn, "1.2.0"}, + {applications, [gleam_community_colour, + gleam_stdlib]}, + {description, "ANSI colours, formatting, and control codes"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache Binary files differnew file mode 100644 index 0000000..c12620f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_meta b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_meta Binary files differnew file mode 100644 index 0000000..3584f7e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.erl b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.erl new file mode 100644 index 0000000..2bb8422 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.erl @@ -0,0 +1,513 @@ +-module(gleam_community@colour). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([from_rgb255/3, from_rgb/3, from_rgba/4, from_hsla/4, from_hsl/3, from_rgb_hex/1, from_rgb_hex_string/1, from_rgba_hex/1, from_rgba_hex_string/1, to_rgba/1, to_hsla/1, to_css_rgba_string/1, to_rgba_hex/1, to_rgba_hex_string/1, to_rgb_hex/1, to_rgb_hex_string/1]). +-export_type([colour/0]). + +-opaque colour() :: {rgba, float(), float(), float(), float()} | + {hsla, float(), float(), float(), float()}. + +-spec valid_colour_value(float()) -> {ok, float()} | {error, nil}. +valid_colour_value(C) -> + case (C > 1.0) orelse (C < +0.0) of + true -> + {error, nil}; + + false -> + {ok, C} + end. + +-spec hue_to_rgb(float(), float(), float()) -> float(). +hue_to_rgb(Hue, M1, M2) -> + H = case Hue of + _ when Hue < +0.0 -> + Hue + 1.0; + + _ when Hue > 1.0 -> + Hue - 1.0; + + _ -> + Hue + end, + H_t_6 = H * 6.0, + H_t_2 = H * 2.0, + H_t_3 = H * 3.0, + case H of + _ when H_t_6 < 1.0 -> + M1 + (((M2 - M1) * H) * 6.0); + + _ when H_t_2 < 1.0 -> + M2; + + _ when H_t_3 < 2.0 -> + M1 + (((M2 - M1) * ((2.0 / 3.0) - H)) * 6.0); + + _ -> + M1 + end. + +-spec hex_string_to_int(binary()) -> {ok, integer()} | {error, nil}. +hex_string_to_int(Hex_string) -> + Hex = case Hex_string of + <<"#"/utf8, Hex_number/binary>> -> + Hex_number; + + <<"0x"/utf8, Hex_number@1/binary>> -> + Hex_number@1; + + _ -> + Hex_string + end, + _pipe = Hex, + _pipe@1 = gleam@string:lowercase(_pipe), + _pipe@2 = gleam@string:to_graphemes(_pipe@1), + _pipe@3 = gleam@list:reverse(_pipe@2), + gleam@list:index_fold( + _pipe@3, + {ok, 0}, + fun(Total, Char, Index) -> case Total of + {error, nil} -> + {error, nil}; + + {ok, V} -> + gleam@result:then(case Char of + <<"a"/utf8>> -> + {ok, 10}; + + <<"b"/utf8>> -> + {ok, 11}; + + <<"c"/utf8>> -> + {ok, 12}; + + <<"d"/utf8>> -> + {ok, 13}; + + <<"e"/utf8>> -> + {ok, 14}; + + <<"f"/utf8>> -> + {ok, 15}; + + _ -> + gleam@int:parse(Char) + end, fun(Num) -> + gleam@result:then( + gleam@int:power(16, gleam@int:to_float(Index)), + fun(Base) -> + {ok, + V + gleam@float:round( + gleam@int:to_float(Num) * Base + )} + end + ) + end) + end end + ). + +-spec hsla_to_rgba(float(), float(), float(), float()) -> {float(), + float(), + float(), + float()}. +hsla_to_rgba(H, S, L, A) -> + M2 = case L =< 0.5 of + true -> + L * (S + 1.0); + + false -> + (L + S) - (L * S) + end, + M1 = (L * 2.0) - M2, + R = hue_to_rgb(H + (1.0 / 3.0), M1, M2), + G = hue_to_rgb(H, M1, M2), + B = hue_to_rgb(H - (1.0 / 3.0), M1, M2), + {R, G, B, A}. + +-spec rgba_to_hsla(float(), float(), float(), float()) -> {float(), + float(), + float(), + float()}. +rgba_to_hsla(R, G, B, A) -> + Min_colour = gleam@float:min(R, gleam@float:min(G, B)), + Max_colour = gleam@float:max(R, gleam@float:max(G, B)), + H1 = case true of + _ when Max_colour =:= R -> + gleam@float:divide(G - B, Max_colour - Min_colour); + + _ when Max_colour =:= G -> + _pipe = gleam@float:divide(B - R, Max_colour - Min_colour), + gleam@result:then(_pipe, fun(D) -> {ok, 2.0 + D} end); + + _ -> + _pipe@1 = gleam@float:divide(R - G, Max_colour - Min_colour), + gleam@result:then(_pipe@1, fun(D@1) -> {ok, 4.0 + D@1} end) + end, + H2 = case H1 of + {ok, V} -> + {ok, V * (1.0 / 6.0)}; + + _ -> + H1 + end, + H3 = case H2 of + {ok, V@1} when V@1 < +0.0 -> + V@1 + 1.0; + + {ok, V@2} -> + V@2; + + _ -> + +0.0 + end, + L = (Min_colour + Max_colour) / 2.0, + S = case true of + _ when Min_colour =:= Max_colour -> + +0.0; + + _ when L < 0.5 -> + case (Max_colour + Min_colour) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> (Max_colour - Min_colour) / Gleam@denominator + end; + + _ -> + case ((2.0 - Max_colour) - Min_colour) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator@1 -> (Max_colour - Min_colour) / Gleam@denominator@1 + end + end, + {H3, S, L, A}. + +-spec from_rgb255(integer(), integer(), integer()) -> {ok, colour()} | + {error, nil}. +from_rgb255(Red, Green, Blue) -> + gleam@result:then( + begin + _pipe = Red, + _pipe@1 = gleam@int:to_float(_pipe), + _pipe@2 = gleam@float:divide(_pipe@1, 255.0), + gleam@result:then(_pipe@2, fun valid_colour_value/1) + end, + fun(R) -> + gleam@result:then( + begin + _pipe@3 = Green, + _pipe@4 = gleam@int:to_float(_pipe@3), + _pipe@5 = gleam@float:divide(_pipe@4, 255.0), + gleam@result:then(_pipe@5, fun valid_colour_value/1) + end, + fun(G) -> + gleam@result:then( + begin + _pipe@6 = Blue, + _pipe@7 = gleam@int:to_float(_pipe@6), + _pipe@8 = gleam@float:divide(_pipe@7, 255.0), + gleam@result:then(_pipe@8, fun valid_colour_value/1) + end, + fun(B) -> {ok, {rgba, R, G, B, 1.0}} end + ) + end + ) + end + ). + +-spec from_rgb(float(), float(), float()) -> {ok, colour()} | {error, nil}. +from_rgb(Red, Green, Blue) -> + gleam@result:then( + valid_colour_value(Red), + fun(R) -> + gleam@result:then( + valid_colour_value(Green), + fun(G) -> + gleam@result:then( + valid_colour_value(Blue), + fun(B) -> {ok, {rgba, R, G, B, 1.0}} end + ) + end + ) + end + ). + +-spec from_rgba(float(), float(), float(), float()) -> {ok, colour()} | + {error, nil}. +from_rgba(Red, Green, Blue, Alpha) -> + gleam@result:then( + valid_colour_value(Red), + fun(R) -> + gleam@result:then( + valid_colour_value(Green), + fun(G) -> + gleam@result:then( + valid_colour_value(Blue), + fun(B) -> + gleam@result:then( + valid_colour_value(Alpha), + fun(A) -> {ok, {rgba, R, G, B, A}} end + ) + end + ) + end + ) + end + ). + +-spec from_hsla(float(), float(), float(), float()) -> {ok, colour()} | + {error, nil}. +from_hsla(Hue, Saturation, Lightness, Alpha) -> + gleam@result:then( + valid_colour_value(Hue), + fun(H) -> + gleam@result:then( + valid_colour_value(Saturation), + fun(S) -> + gleam@result:then( + valid_colour_value(Lightness), + fun(L) -> + gleam@result:then( + valid_colour_value(Alpha), + fun(A) -> {ok, {hsla, H, S, L, A}} end + ) + end + ) + end + ) + end + ). + +-spec from_hsl(float(), float(), float()) -> {ok, colour()} | {error, nil}. +from_hsl(Hue, Saturation, Lightness) -> + from_hsla(Hue, Saturation, Lightness, 1.0). + +-spec from_rgb_hex(integer()) -> {ok, colour()} | {error, nil}. +from_rgb_hex(Hex) -> + case (Hex > 16#ffffff) orelse (Hex < 0) of + true -> + {error, nil}; + + false -> + R = begin + _pipe = erlang:'bsr'(Hex, 16), + erlang:'band'(_pipe, 16#ff) + end, + G = begin + _pipe@1 = erlang:'bsr'(Hex, 8), + erlang:'band'(_pipe@1, 16#ff) + end, + B = erlang:'band'(Hex, 16#ff), + from_rgb255(R, G, B) + end. + +-spec from_rgb_hex_string(binary()) -> {ok, colour()} | {error, nil}. +from_rgb_hex_string(Hex_string) -> + gleam@result:then( + hex_string_to_int(Hex_string), + fun(Hex_int) -> from_rgb_hex(Hex_int) end + ). + +-spec from_rgba_hex(integer()) -> {ok, colour()} | {error, nil}. +from_rgba_hex(Hex) -> + case (Hex > 16#ffffffff) orelse (Hex < 0) of + true -> + {error, nil}; + + false -> + _assert_subject = begin + _pipe = erlang:'bsr'(Hex, 24), + _pipe@1 = erlang:'band'(_pipe, 16#ff), + _pipe@2 = gleam@int:to_float(_pipe@1), + gleam@float:divide(_pipe@2, 255.0) + end, + {ok, R} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/colour"/utf8>>, + function => <<"from_rgba_hex"/utf8>>, + line => 588}) + end, + _assert_subject@1 = begin + _pipe@3 = erlang:'bsr'(Hex, 16), + _pipe@4 = erlang:'band'(_pipe@3, 16#ff), + _pipe@5 = gleam@int:to_float(_pipe@4), + gleam@float:divide(_pipe@5, 255.0) + end, + {ok, G} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/colour"/utf8>>, + function => <<"from_rgba_hex"/utf8>>, + line => 594}) + end, + _assert_subject@2 = begin + _pipe@6 = erlang:'bsr'(Hex, 8), + _pipe@7 = erlang:'band'(_pipe@6, 16#ff), + _pipe@8 = gleam@int:to_float(_pipe@7), + gleam@float:divide(_pipe@8, 255.0) + end, + {ok, B} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"gleam_community/colour"/utf8>>, + function => <<"from_rgba_hex"/utf8>>, + line => 600}) + end, + _assert_subject@3 = begin + _pipe@9 = erlang:'band'(Hex, 16#ff), + _pipe@10 = gleam@int:to_float(_pipe@9), + gleam@float:divide(_pipe@10, 255.0) + end, + {ok, A} = case _assert_subject@3 of + {ok, _} -> _assert_subject@3; + _assert_fail@3 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@3, + module => <<"gleam_community/colour"/utf8>>, + function => <<"from_rgba_hex"/utf8>>, + line => 606}) + end, + from_rgba(R, G, B, A) + end. + +-spec from_rgba_hex_string(binary()) -> {ok, colour()} | {error, nil}. +from_rgba_hex_string(Hex_string) -> + gleam@result:then( + hex_string_to_int(Hex_string), + fun(Hex_int) -> from_rgba_hex(Hex_int) end + ). + +-spec to_rgba(colour()) -> {float(), float(), float(), float()}. +to_rgba(Colour) -> + case Colour of + {rgba, R, G, B, A} -> + {R, G, B, A}; + + {hsla, H, S, L, A@1} -> + hsla_to_rgba(H, S, L, A@1) + end. + +-spec to_hsla(colour()) -> {float(), float(), float(), float()}. +to_hsla(Colour) -> + case Colour of + {hsla, H, S, L, A} -> + {H, S, L, A}; + + {rgba, R, G, B, A@1} -> + rgba_to_hsla(R, G, B, A@1) + end. + +-spec to_css_rgba_string(colour()) -> binary(). +to_css_rgba_string(Colour) -> + {R, G, B, A} = to_rgba(Colour), + Percent = fun(X) -> + _assert_subject = begin + _pipe = X, + _pipe@1 = gleam@float:multiply(_pipe, 10000.0), + _pipe@2 = gleam@float:round(_pipe@1), + _pipe@3 = gleam@int:to_float(_pipe@2), + gleam@float:divide(_pipe@3, 100.0) + end, + {ok, P} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/colour"/utf8>>, + function => <<"to_css_rgba_string"/utf8>>, + line => 704}) + end, + P + end, + Round_to = fun(X@1) -> + _assert_subject@1 = begin + _pipe@4 = X@1, + _pipe@5 = gleam@float:multiply(_pipe@4, 1000.0), + _pipe@6 = gleam@float:round(_pipe@5), + _pipe@7 = gleam@int:to_float(_pipe@6), + gleam@float:divide(_pipe@7, 1000.0) + end, + {ok, R@1} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/colour"/utf8>>, + function => <<"to_css_rgba_string"/utf8>>, + line => 716}) + end, + R@1 + end, + gleam@string:join( + [<<"rgba("/utf8>>, + <<(gleam@float:to_string(Percent(R)))/binary, "%,"/utf8>>, + <<(gleam@float:to_string(Percent(G)))/binary, "%,"/utf8>>, + <<(gleam@float:to_string(Percent(B)))/binary, "%,"/utf8>>, + gleam@float:to_string(Round_to(A)), + <<")"/utf8>>], + <<""/utf8>> + ). + +-spec to_rgba_hex(colour()) -> integer(). +to_rgba_hex(Colour) -> + {R, G, B, A} = to_rgba(Colour), + Red = begin + _pipe = R * 255.0, + _pipe@1 = gleam@float:round(_pipe), + erlang:'bsl'(_pipe@1, 24) + end, + Green = begin + _pipe@2 = G * 255.0, + _pipe@3 = gleam@float:round(_pipe@2), + erlang:'bsl'(_pipe@3, 16) + end, + Blue = begin + _pipe@4 = B * 255.0, + _pipe@5 = gleam@float:round(_pipe@4), + erlang:'bsl'(_pipe@5, 8) + end, + Alpha = begin + _pipe@6 = A * 255.0, + gleam@float:round(_pipe@6) + end, + ((Red + Green) + Blue) + Alpha. + +-spec to_rgba_hex_string(colour()) -> binary(). +to_rgba_hex_string(Colour) -> + _pipe = to_rgba_hex(Colour), + gleam@int:to_base16(_pipe). + +-spec to_rgb_hex(colour()) -> integer(). +to_rgb_hex(Colour) -> + {R, G, B, _} = to_rgba(Colour), + Red = begin + _pipe = R * 255.0, + _pipe@1 = gleam@float:round(_pipe), + erlang:'bsl'(_pipe@1, 16) + end, + Green = begin + _pipe@2 = G * 255.0, + _pipe@3 = gleam@float:round(_pipe@2), + erlang:'bsl'(_pipe@3, 8) + end, + Blue = begin + _pipe@4 = B * 255.0, + gleam@float:round(_pipe@4) + end, + (Red + Green) + Blue. + +-spec to_rgb_hex_string(colour()) -> binary(). +to_rgb_hex_string(Colour) -> + _pipe = to_rgb_hex(Colour), + gleam@int:to_base16(_pipe). diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache Binary files differnew file mode 100644 index 0000000..5c98611 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_meta b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_meta Binary files differnew file mode 100644 index 0000000..0c78df4 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.erl b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.erl new file mode 100644 index 0000000..4370842 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.erl @@ -0,0 +1,75 @@ +-module(gleam_community@colour@accessibility). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([luminance/1, contrast_ratio/2, maximum_contrast/2]). + +-spec intensity(float()) -> float(). +intensity(Colour_value) -> + case true of + _ when Colour_value =< 0.03928 -> + Colour_value / 12.92; + + _ -> + _assert_subject = gleam@float:power( + (Colour_value + 0.055) / 1.055, + 2.4 + ), + {ok, I} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/colour/accessibility"/utf8>>, + function => <<"intensity"/utf8>>, + line => 62}) + end, + I + end. + +-spec luminance(gleam_community@colour:colour()) -> float(). +luminance(Colour) -> + {R, G, B, _} = gleam_community@colour:to_rgba(Colour), + R_intensity = intensity(R), + G_intensity = intensity(G), + B_intensity = intensity(B), + ((0.2126 * R_intensity) + (0.7152 * G_intensity)) + (0.0722 * B_intensity). + +-spec contrast_ratio( + gleam_community@colour:colour(), + gleam_community@colour:colour() +) -> float(). +contrast_ratio(Colour_a, Colour_b) -> + Luminance_a = luminance(Colour_a) + 0.05, + Luminance_b = luminance(Colour_b) + 0.05, + case Luminance_a > Luminance_b of + true -> + case Luminance_b of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> Luminance_a / Gleam@denominator + end; + + false -> + case Luminance_a of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator@1 -> Luminance_b / Gleam@denominator@1 + end + end. + +-spec maximum_contrast( + gleam_community@colour:colour(), + list(gleam_community@colour:colour()) +) -> {ok, gleam_community@colour:colour()} | {error, nil}. +maximum_contrast(Base, Colours) -> + _pipe = Colours, + _pipe@1 = gleam@list:sort( + _pipe, + fun(Colour_a, Colour_b) -> + Contrast_a = contrast_ratio(Base, Colour_a), + Contrast_b = contrast_ratio(Base, Colour_b), + gleam@float:compare(Contrast_b, Contrast_a) + end + ), + gleam@list:first(_pipe@1). diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community@colour.beam b/aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community@colour.beam Binary files differnew file mode 100644 index 0000000..008c06a --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community@colour.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community@colour@accessibility.beam b/aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community@colour@accessibility.beam Binary files differnew file mode 100644 index 0000000..15e491b --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community@colour@accessibility.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community_colour.app b/aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community_colour.app new file mode 100644 index 0000000..51800d3 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community_colour.app @@ -0,0 +1,7 @@ +{application, gleam_community_colour, [ + {vsn, "1.2.0"}, + {applications, [gleam_stdlib]}, + {description, "Colour types, conversions, and other utilities"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/include/gleam_community@colour_Hsla.hrl b/aoc2023/build/dev/erlang/gleam_community_colour/include/gleam_community@colour_Hsla.hrl new file mode 100644 index 0000000..06116df --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/include/gleam_community@colour_Hsla.hrl @@ -0,0 +1 @@ +-record(hsla, {h :: float(), s :: float(), l :: float(), a :: float()}). diff --git a/aoc2023/build/dev/erlang/gleam_community_colour/include/gleam_community@colour_Rgba.hrl b/aoc2023/build/dev/erlang/gleam_community_colour/include/gleam_community@colour_Rgba.hrl new file mode 100644 index 0000000..fff139e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_colour/include/gleam_community@colour_Rgba.hrl @@ -0,0 +1 @@ +-record(rgba, {r :: float(), g :: float(), b :: float(), a :: float()}). diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.cache b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.cache Binary files differnew file mode 100644 index 0000000..b683c40 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.cache_meta b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.cache_meta Binary files differnew file mode 100644 index 0000000..23d4726 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.erl b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.erl new file mode 100644 index 0000000..b45f48e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.erl @@ -0,0 +1,172 @@ +-module(gleam_community@maths@arithmetics). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([gcd/2, lcm/2, divisors/1, proper_divisors/1, float_sum/1, int_sum/1, float_product/1, int_product/1, float_cumulative_sum/1, int_cumulative_sum/1, float_cumumlative_product/1, int_cumulative_product/1]). + +-spec do_gcd(integer(), integer()) -> integer(). +do_gcd(X, Y) -> + case X =:= 0 of + true -> + Y; + + false -> + _assert_subject = gleam@int:modulo(Y, X), + {ok, Z} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/arithmetics"/utf8>>, + function => <<"do_gcd"/utf8>>, + line => 93}) + end, + do_gcd(Z, X) + end. + +-spec gcd(integer(), integer()) -> integer(). +gcd(X, Y) -> + Absx = gleam_community@maths@piecewise:int_absolute_value(X), + Absy = gleam_community@maths@piecewise:int_absolute_value(Y), + do_gcd(Absx, Absy). + +-spec lcm(integer(), integer()) -> integer(). +lcm(X, Y) -> + Absx = gleam_community@maths@piecewise:int_absolute_value(X), + Absy = gleam_community@maths@piecewise:int_absolute_value(Y), + case do_gcd(Absx, Absy) of + 0 -> 0; + Gleam@denominator -> Absx * Absy div Gleam@denominator + end. + +-spec find_divisors(integer()) -> list(integer()). +find_divisors(N) -> + Nabs = gleam_community@maths@piecewise:float_absolute_value( + gleam_community@maths@conversion:int_to_float(N) + ), + _assert_subject = gleam_community@maths@elementary:square_root(Nabs), + {ok, Sqrt_result} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/arithmetics"/utf8>>, + function => <<"find_divisors"/utf8>>, + line => 176}) + end, + Max = gleam_community@maths@conversion:float_to_int(Sqrt_result) + 1, + _pipe = gleam@list:range(2, Max), + _pipe@1 = gleam@list:fold(_pipe, [1, N], fun(Acc, I) -> case (case I of + 0 -> 0; + Gleam@denominator -> N rem Gleam@denominator + end) =:= 0 of + true -> + [I, case I of + 0 -> 0; + Gleam@denominator@1 -> N div Gleam@denominator@1 + end | Acc]; + + false -> + Acc + end end), + _pipe@2 = gleam@list:unique(_pipe@1), + gleam@list:sort(_pipe@2, fun gleam@int:compare/2). + +-spec divisors(integer()) -> list(integer()). +divisors(N) -> + find_divisors(N). + +-spec proper_divisors(integer()) -> list(integer()). +proper_divisors(N) -> + Divisors = find_divisors(N), + _pipe = Divisors, + gleam@list:take(_pipe, gleam@list:length(Divisors) - 1). + +-spec float_sum(list(float())) -> float(). +float_sum(Arr) -> + case Arr of + [] -> + +0.0; + + _ -> + _pipe = Arr, + gleam@list:fold(_pipe, +0.0, fun(Acc, A) -> A + Acc end) + end. + +-spec int_sum(list(integer())) -> integer(). +int_sum(Arr) -> + case Arr of + [] -> + 0; + + _ -> + _pipe = Arr, + gleam@list:fold(_pipe, 0, fun(Acc, A) -> A + Acc end) + end. + +-spec float_product(list(float())) -> float(). +float_product(Arr) -> + case Arr of + [] -> + 1.0; + + _ -> + _pipe = Arr, + gleam@list:fold(_pipe, 1.0, fun(Acc, A) -> A * Acc end) + end. + +-spec int_product(list(integer())) -> integer(). +int_product(Arr) -> + case Arr of + [] -> + 1; + + _ -> + _pipe = Arr, + gleam@list:fold(_pipe, 1, fun(Acc, A) -> A * Acc end) + end. + +-spec float_cumulative_sum(list(float())) -> list(float()). +float_cumulative_sum(Arr) -> + case Arr of + [] -> + []; + + _ -> + _pipe = Arr, + gleam@list:scan(_pipe, +0.0, fun(Acc, A) -> A + Acc end) + end. + +-spec int_cumulative_sum(list(integer())) -> list(integer()). +int_cumulative_sum(Arr) -> + case Arr of + [] -> + []; + + _ -> + _pipe = Arr, + gleam@list:scan(_pipe, 0, fun(Acc, A) -> A + Acc end) + end. + +-spec float_cumumlative_product(list(float())) -> list(float()). +float_cumumlative_product(Arr) -> + case Arr of + [] -> + []; + + _ -> + _pipe = Arr, + gleam@list:scan(_pipe, 1.0, fun(Acc, A) -> A * Acc end) + end. + +-spec int_cumulative_product(list(integer())) -> list(integer()). +int_cumulative_product(Arr) -> + case Arr of + [] -> + []; + + _ -> + _pipe = Arr, + gleam@list:scan(_pipe, 1, fun(Acc, A) -> A * Acc end) + end. diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.cache b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.cache Binary files differnew file mode 100644 index 0000000..e95a3b0 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.cache_meta b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.cache_meta Binary files differnew file mode 100644 index 0000000..f8262ee --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.erl b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.erl new file mode 100644 index 0000000..00130c0 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.erl @@ -0,0 +1,218 @@ +-module(gleam_community@maths@combinatorics). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([combination/2, factorial/1, permutation/2, list_combination/2, list_permutation/1, cartesian_product/2]). + +-spec combination(integer(), integer()) -> {ok, integer()} | {error, binary()}. +combination(N, K) -> + case N < 0 of + true -> + _pipe = <<"Invalid input argument: n < 0. Valid input is n > 0."/utf8>>, + {error, _pipe}; + + false -> + case (K < 0) orelse (K > N) of + true -> + _pipe@1 = 0, + {ok, _pipe@1}; + + false -> + case (K =:= 0) orelse (K =:= N) of + true -> + _pipe@2 = 1, + {ok, _pipe@2}; + + false -> + Min = case K < (N - K) of + true -> + K; + + false -> + N - K + end, + _pipe@3 = gleam@list:range(1, Min), + _pipe@4 = gleam@list:fold( + _pipe@3, + 1, + fun(Acc, X) -> case X of + 0 -> 0; + Gleam@denominator -> Acc * ((N + 1) - X) + div Gleam@denominator + end end + ), + {ok, _pipe@4} + end + end + end. + +-spec factorial(integer()) -> {ok, integer()} | {error, binary()}. +factorial(N) -> + case N < 0 of + true -> + _pipe = <<"Invalid input argument: n < 0. Valid input is n > 0."/utf8>>, + {error, _pipe}; + + false -> + case N of + 0 -> + _pipe@1 = 1, + {ok, _pipe@1}; + + 1 -> + _pipe@2 = 1, + {ok, _pipe@2}; + + _ -> + _pipe@3 = gleam@list:range(1, N), + _pipe@4 = gleam@list:fold( + _pipe@3, + 1, + fun(Acc, X) -> Acc * X end + ), + {ok, _pipe@4} + end + end. + +-spec permutation(integer(), integer()) -> {ok, integer()} | {error, binary()}. +permutation(N, K) -> + case N < 0 of + true -> + _pipe = <<"Invalid input argument: n < 0. Valid input is n > 0."/utf8>>, + {error, _pipe}; + + false -> + case (K < 0) orelse (K > N) of + true -> + _pipe@1 = 0, + {ok, _pipe@1}; + + false -> + case K =:= N of + true -> + _pipe@2 = 1, + {ok, _pipe@2}; + + false -> + _assert_subject = factorial(N), + {ok, V1} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/combinatorics"/utf8>>, + function => <<"permutation"/utf8>>, + line => 241}) + end, + _assert_subject@1 = factorial(N - K), + {ok, V2} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/combinatorics"/utf8>>, + function => <<"permutation"/utf8>>, + line => 242}) + end, + _pipe@3 = case V2 of + 0 -> 0; + Gleam@denominator -> V1 div Gleam@denominator + end, + {ok, _pipe@3} + end + end + end. + +-spec do_list_combination(list(JGD), integer(), list(JGD)) -> list(list(JGD)). +do_list_combination(Arr, K, Prefix) -> + case K of + 0 -> + [gleam@list:reverse(Prefix)]; + + _ -> + case Arr of + [] -> + []; + + [X | Xs] -> + With_x = do_list_combination(Xs, K - 1, [X | Prefix]), + Without_x = do_list_combination(Xs, K, Prefix), + gleam@list:append(With_x, Without_x) + end + end. + +-spec list_combination(list(JFX), integer()) -> {ok, list(list(JFX))} | + {error, binary()}. +list_combination(Arr, K) -> + case K < 0 of + true -> + _pipe = <<"Invalid input argument: k < 0. Valid input is k > 0."/utf8>>, + {error, _pipe}; + + false -> + case K > gleam@list:length(Arr) of + true -> + _pipe@1 = <<"Invalid input argument: k > length(arr). Valid input is 0 < k <= length(arr)."/utf8>>, + {error, _pipe@1}; + + false -> + _pipe@2 = do_list_combination(Arr, K, []), + {ok, _pipe@2} + end + end. + +-spec list_permutation(list(JGI)) -> list(list(JGI)). +list_permutation(Arr) -> + case Arr of + [] -> + [[]]; + + _ -> + gleam@list:flat_map( + Arr, + fun(X) -> + _assert_subject = gleam@list:pop(Arr, fun(Y) -> X =:= Y end), + {ok, {_, Remaining}} = case _assert_subject of + {ok, {_, _}} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/combinatorics"/utf8>>, + function => <<"list_permutation"/utf8>>, + line => 373}) + end, + gleam@list:map( + list_permutation(Remaining), + fun(Perm) -> [X | Perm] end + ) + end + ) + end. + +-spec cartesian_product(list(JGM), list(JGM)) -> list({JGM, JGM}). +cartesian_product(Xarr, Yarr) -> + Xset = begin + _pipe = Xarr, + gleam@set:from_list(_pipe) + end, + Yset = begin + _pipe@1 = Yarr, + gleam@set:from_list(_pipe@1) + end, + _pipe@2 = Xset, + _pipe@3 = gleam@set:fold( + _pipe@2, + gleam@set:new(), + fun(Accumulator0, Member0) -> + gleam@set:fold( + Yset, + Accumulator0, + fun(Accumulator1, Member1) -> + gleam@set:insert(Accumulator1, {Member0, Member1}) + end + ) + end + ), + gleam@set:to_list(_pipe@3). diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.cache b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.cache Binary files differnew file mode 100644 index 0000000..6b3ed43 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.cache_meta b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.cache_meta Binary files differnew file mode 100644 index 0000000..374a6fb --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.erl b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.erl new file mode 100644 index 0000000..1e44006 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.erl @@ -0,0 +1,24 @@ +-module(gleam_community@maths@conversion). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([int_to_float/1, float_to_int/1, degrees_to_radians/1, radians_to_degrees/1]). + +-spec int_to_float(integer()) -> float(). +int_to_float(X) -> + gleam@int:to_float(X). + +-spec float_to_int(float()) -> integer(). +float_to_int(X) -> + erlang:trunc(X). + +-spec degrees_to_radians(float()) -> float(). +degrees_to_radians(X) -> + (X * math:pi()) / 180.0. + +-spec radians_to_degrees(float()) -> float(). +radians_to_degrees(X) -> + case math:pi() of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> X * 180.0 / Gleam@denominator + end. diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.cache b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.cache Binary files differnew file mode 100644 index 0000000..5dbff0c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.cache_meta b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.cache_meta Binary files differnew file mode 100644 index 0000000..8a3590f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.erl b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.erl new file mode 100644 index 0000000..422021e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.erl @@ -0,0 +1,286 @@ +-module(gleam_community@maths@elementary). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([acos/1, acosh/1, asin/1, asinh/1, atan/1, atan2/2, atanh/1, cos/1, cosh/1, sin/1, sinh/1, tan/1, tanh/1, exponential/1, natural_logarithm/1, logarithm_2/1, logarithm_10/1, logarithm/2, power/2, square_root/1, cube_root/1, nth_root/2, pi/0, tau/0, e/0]). + +-spec acos(float()) -> {ok, float()} | {error, binary()}. +acos(X) -> + case (X >= -1.0) andalso (X =< 1.0) of + true -> + _pipe = math:acos(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1."/utf8>>, + {error, _pipe@1} + end. + +-spec acosh(float()) -> {ok, float()} | {error, binary()}. +acosh(X) -> + case X >= 1.0 of + true -> + _pipe = math:acosh(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x < 1. Valid input is x >= 1."/utf8>>, + {error, _pipe@1} + end. + +-spec asin(float()) -> {ok, float()} | {error, binary()}. +asin(X) -> + case (X >= -1.0) andalso (X =< 1.0) of + true -> + _pipe = math:asin(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1."/utf8>>, + {error, _pipe@1} + end. + +-spec asinh(float()) -> float(). +asinh(X) -> + math:asinh(X). + +-spec atan(float()) -> float(). +atan(X) -> + math:atan(X). + +-spec atan2(float(), float()) -> float(). +atan2(Y, X) -> + math:atan2(Y, X). + +-spec atanh(float()) -> {ok, float()} | {error, binary()}. +atanh(X) -> + case (X > -1.0) andalso (X < 1.0) of + true -> + _pipe = math:atanh(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x > -1 or x < 1. Valid input is -1. < x < 1."/utf8>>, + {error, _pipe@1} + end. + +-spec cos(float()) -> float(). +cos(X) -> + math:cos(X). + +-spec cosh(float()) -> float(). +cosh(X) -> + math:cosh(X). + +-spec sin(float()) -> float(). +sin(X) -> + math:sin(X). + +-spec sinh(float()) -> float(). +sinh(X) -> + math:sinh(X). + +-spec tan(float()) -> float(). +tan(X) -> + math:tan(X). + +-spec tanh(float()) -> float(). +tanh(X) -> + math:tanh(X). + +-spec exponential(float()) -> float(). +exponential(X) -> + math:exp(X). + +-spec natural_logarithm(float()) -> {ok, float()} | {error, binary()}. +natural_logarithm(X) -> + case X > +0.0 of + true -> + _pipe = math:log(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x <= 0. Valid input is x > 0."/utf8>>, + {error, _pipe@1} + end. + +-spec logarithm_2(float()) -> {ok, float()} | {error, binary()}. +logarithm_2(X) -> + case X > +0.0 of + true -> + _pipe = math:log2(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x <= 0. Valid input is x > 0."/utf8>>, + {error, _pipe@1} + end. + +-spec logarithm_10(float()) -> {ok, float()} | {error, binary()}. +logarithm_10(X) -> + case X > +0.0 of + true -> + _pipe = math:log10(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x <= 0. Valid input is x > 0."/utf8>>, + {error, _pipe@1} + end. + +-spec logarithm(float(), gleam@option:option(float())) -> {ok, float()} | + {error, binary()}. +logarithm(X, Base) -> + case X > +0.0 of + true -> + case Base of + {some, A} -> + case (A > +0.0) andalso (A /= 1.0) of + true -> + _assert_subject = logarithm_10(X), + {ok, Numerator} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/elementary"/utf8>>, + function => <<"logarithm"/utf8>>, + line => 820}) + end, + _assert_subject@1 = logarithm_10(A), + {ok, Denominator} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/elementary"/utf8>>, + function => <<"logarithm"/utf8>>, + line => 821}) + end, + _pipe = case Denominator of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> Numerator / Gleam@denominator + end, + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: base <= 0 or base == 1. Valid input is base > 0 and base != 1."/utf8>>, + {error, _pipe@1} + end; + + _ -> + _pipe@2 = <<"Invalid input argument: base <= 0 or base == 1. Valid input is base > 0 and base != 1."/utf8>>, + {error, _pipe@2} + end; + + _ -> + _pipe@3 = <<"Invalid input argument: x <= 0. Valid input is x > 0."/utf8>>, + {error, _pipe@3} + end. + +-spec power(float(), float()) -> {ok, float()} | {error, binary()}. +power(X, Y) -> + Fractional = (math:ceil(Y) - Y) > +0.0, + case ((X < +0.0) andalso Fractional) orelse ((X =:= +0.0) andalso (Y < +0.0)) of + true -> + _pipe = <<"Invalid input argument: x < 0 and y is fractional or x = 0 and y < 0."/utf8>>, + {error, _pipe}; + + false -> + _pipe@1 = math:pow(X, Y), + {ok, _pipe@1} + end. + +-spec square_root(float()) -> {ok, float()} | {error, binary()}. +square_root(X) -> + case X < +0.0 of + true -> + _pipe = <<"Invalid input argument: x < 0."/utf8>>, + {error, _pipe}; + + false -> + _assert_subject = power(X, 1.0 / 2.0), + {ok, Result} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/elementary"/utf8>>, + function => <<"square_root"/utf8>>, + line => 1066}) + end, + _pipe@1 = Result, + {ok, _pipe@1} + end. + +-spec cube_root(float()) -> {ok, float()} | {error, binary()}. +cube_root(X) -> + case X < +0.0 of + true -> + _pipe = <<"Invalid input argument: x < 0."/utf8>>, + {error, _pipe}; + + false -> + _assert_subject = power(X, 1.0 / 3.0), + {ok, Result} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/elementary"/utf8>>, + function => <<"cube_root"/utf8>>, + line => 1118}) + end, + _pipe@1 = Result, + {ok, _pipe@1} + end. + +-spec nth_root(float(), integer()) -> {ok, float()} | {error, binary()}. +nth_root(X, N) -> + case X < +0.0 of + true -> + _pipe = <<"Invalid input argument: x < 0. Valid input is x > 0"/utf8>>, + {error, _pipe}; + + false -> + case N >= 1 of + true -> + _assert_subject = power(X, case gleam@int:to_float(N) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> 1.0 / Gleam@denominator + end), + {ok, Result} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/elementary"/utf8>>, + function => <<"nth_root"/utf8>>, + line => 1175}) + end, + _pipe@1 = Result, + {ok, _pipe@1}; + + false -> + _pipe@2 = <<"Invalid input argument: n < 1. Valid input is n >= 2."/utf8>>, + {error, _pipe@2} + end + end. + +-spec pi() -> float(). +pi() -> + math:pi(). + +-spec tau() -> float(). +tau() -> + 2.0 * pi(). + +-spec e() -> float(). +e() -> + exponential(1.0). diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.cache b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.cache Binary files differnew file mode 100644 index 0000000..6dc087d --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.cache_meta b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.cache_meta Binary files differnew file mode 100644 index 0000000..ad6a7f1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.erl b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.erl new file mode 100644 index 0000000..3483014 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.erl @@ -0,0 +1,281 @@ +-module(gleam_community@maths@metrics). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([norm/2, minkowski_distance/3, manhatten_distance/2, euclidean_distance/2, mean/1, median/1, variance/2, standard_deviation/2]). + +-spec norm(list(float()), float()) -> float(). +norm(Arr, P) -> + case Arr of + [] -> + +0.0; + + _ -> + Agg = begin + _pipe = Arr, + gleam@list:fold( + _pipe, + +0.0, + fun(Acc, A) -> + _assert_subject = gleam_community@maths@elementary:power( + gleam_community@maths@piecewise:float_absolute_value( + A + ), + P + ), + {ok, Result} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"norm"/utf8>>, + line => 101}) + end, + Result + Acc + end + ) + end, + _assert_subject@1 = gleam_community@maths@elementary:power( + Agg, + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> 1.0 / Gleam@denominator + end + ), + {ok, Result@1} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"norm"/utf8>>, + line => 106}) + end, + Result@1 + end. + +-spec minkowski_distance(list(float()), list(float()), float()) -> {ok, float()} | + {error, binary()}. +minkowski_distance(Xarr, Yarr, P) -> + Xlen = gleam@list:length(Xarr), + Ylen = gleam@list:length(Yarr), + case Xlen =:= Ylen of + false -> + _pipe = <<"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."/utf8>>, + {error, _pipe}; + + true -> + case P < 1.0 of + true -> + _pipe@1 = <<"Invalid input argument: p < 1. Valid input is p >= 1."/utf8>>, + {error, _pipe@1}; + + false -> + _pipe@2 = gleam@list:zip(Xarr, Yarr), + _pipe@3 = gleam@list:map( + _pipe@2, + fun(Tuple) -> + gleam@pair:first(Tuple) - gleam@pair:second(Tuple) + end + ), + _pipe@4 = norm(_pipe@3, P), + {ok, _pipe@4} + end + end. + +-spec manhatten_distance(list(float()), list(float())) -> {ok, float()} | + {error, binary()}. +manhatten_distance(Xarr, Yarr) -> + minkowski_distance(Xarr, Yarr, 1.0). + +-spec euclidean_distance(list(float()), list(float())) -> {ok, float()} | + {error, binary()}. +euclidean_distance(Xarr, Yarr) -> + minkowski_distance(Xarr, Yarr, 2.0). + +-spec mean(list(float())) -> {ok, float()} | {error, binary()}. +mean(Arr) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _pipe@1 = Arr, + _pipe@2 = gleam_community@maths@arithmetics:float_sum(_pipe@1), + _pipe@3 = (fun(A) -> + case gleam_community@maths@conversion:int_to_float( + gleam@list:length(Arr) + ) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> A / Gleam@denominator + end + end)(_pipe@2), + {ok, _pipe@3} + end. + +-spec median(list(float())) -> {ok, float()} | {error, binary()}. +median(Arr) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + Count = gleam@list:length(Arr), + Mid = gleam@list:length(Arr) div 2, + Sorted = gleam@list:sort(Arr, fun gleam@float:compare/2), + case gleam_community@maths@predicates:is_odd(Count) of + true -> + _assert_subject = gleam@list:at(Sorted, Mid), + {ok, Val0} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"median"/utf8>>, + line => 402}) + end, + _pipe@1 = Val0, + {ok, _pipe@1}; + + false -> + _assert_subject@1 = gleam@list:at(Sorted, Mid - 1), + {ok, Val0@1} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"median"/utf8>>, + line => 409}) + end, + _assert_subject@2 = gleam@list:at(Sorted, Mid), + {ok, Val1} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"median"/utf8>>, + line => 410}) + end, + _pipe@2 = [Val0@1, Val1], + mean(_pipe@2) + end + end. + +-spec variance(list(float()), integer()) -> {ok, float()} | {error, binary()}. +variance(Arr, Ddof) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + case Ddof < 0 of + true -> + _pipe@1 = <<"Invalid input argument: ddof < 0. Valid input is ddof >= 0."/utf8>>, + {error, _pipe@1}; + + false -> + _assert_subject = mean(Arr), + {ok, Mean} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"variance"/utf8>>, + line => 475}) + end, + _pipe@2 = Arr, + _pipe@3 = gleam@list:map( + _pipe@2, + fun(A) -> + _assert_subject@1 = gleam_community@maths@elementary:power( + A - Mean, + 2.0 + ), + {ok, Result} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"variance"/utf8>>, + line => 478}) + end, + Result + end + ), + _pipe@4 = gleam_community@maths@arithmetics:float_sum( + _pipe@3 + ), + _pipe@5 = (fun(A@1) -> + case (gleam_community@maths@conversion:int_to_float( + gleam@list:length(Arr) + ) + - gleam_community@maths@conversion:int_to_float(Ddof)) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> A@1 / Gleam@denominator + end + end)(_pipe@4), + {ok, _pipe@5} + end + end. + +-spec standard_deviation(list(float()), integer()) -> {ok, float()} | + {error, binary()}. +standard_deviation(Arr, Ddof) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + case Ddof < 0 of + true -> + _pipe@1 = <<"Invalid input argument: ddof < 0. Valid input is ddof >= 0."/utf8>>, + {error, _pipe@1}; + + false -> + _assert_subject = variance(Arr, Ddof), + {ok, Variance} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"standard_deviation"/utf8>>, + line => 551}) + end, + _assert_subject@1 = gleam_community@maths@elementary:square_root( + Variance + ), + {ok, Stdev} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"standard_deviation"/utf8>>, + line => 554}) + end, + _pipe@2 = Stdev, + {ok, _pipe@2} + end + end. diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.cache b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.cache Binary files differnew file mode 100644 index 0000000..d65054e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.cache_meta b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.cache_meta Binary files differnew file mode 100644 index 0000000..21c97d4 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.erl b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.erl new file mode 100644 index 0000000..c724271 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.erl @@ -0,0 +1,563 @@ +-module(gleam_community@maths@piecewise). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([float_absolute_value/1, int_absolute_value/1, float_absolute_difference/2, int_absolute_difference/2, float_sign/1, round/3, ceiling/2, floor/2, truncate/2, int_sign/1, float_flip_sign/1, float_copy_sign/2, int_flip_sign/1, int_copy_sign/2, minimum/3, maximum/3, minmax/3, list_minimum/2, list_maximum/2, arg_minimum/2, arg_maximum/2, extrema/2]). +-export_type([rounding_mode/0]). + +-type rounding_mode() :: round_nearest | + round_ties_away | + round_ties_up | + round_to_zero | + round_down | + round_up. + +-spec truncate_float(float()) -> float(). +truncate_float(X) -> + erlang:trunc(X). + +-spec round_to_zero(float(), float()) -> float(). +round_to_zero(P, X) -> + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> truncate_float(X * P) / Gleam@denominator + end. + +-spec round_down(float(), float()) -> float(). +round_down(P, X) -> + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> math:floor(X * P) / Gleam@denominator + end. + +-spec round_up(float(), float()) -> float(). +round_up(P, X) -> + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> math:ceil(X * P) / Gleam@denominator + end. + +-spec float_absolute_value(float()) -> float(). +float_absolute_value(X) -> + case X > +0.0 of + true -> + X; + + false -> + -1.0 * X + end. + +-spec int_absolute_value(integer()) -> integer(). +int_absolute_value(X) -> + case X > 0 of + true -> + X; + + false -> + -1 * X + end. + +-spec float_absolute_difference(float(), float()) -> float(). +float_absolute_difference(A, B) -> + _pipe = A - B, + float_absolute_value(_pipe). + +-spec int_absolute_difference(integer(), integer()) -> integer(). +int_absolute_difference(A, B) -> + _pipe = A - B, + int_absolute_value(_pipe). + +-spec do_float_sign(float()) -> float(). +do_float_sign(X) -> + case X < +0.0 of + true -> + -1.0; + + false -> + case X =:= +0.0 of + true -> + +0.0; + + false -> + 1.0 + end + end. + +-spec float_sign(float()) -> float(). +float_sign(X) -> + do_float_sign(X). + +-spec round_to_nearest(float(), float()) -> float(). +round_to_nearest(P, X) -> + Xabs = float_absolute_value(X) * P, + Xabs_truncated = truncate_float(Xabs), + Remainder = Xabs - Xabs_truncated, + case Remainder of + _ when Remainder > 0.5 -> + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> float_sign(X) * truncate_float(Xabs + 1.0) + / Gleam@denominator + end; + + _ when Remainder =:= 0.5 -> + _assert_subject = gleam@int:modulo( + gleam_community@maths@conversion:float_to_int(Xabs), + 2 + ), + {ok, Is_even} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"round_to_nearest"/utf8>>, + line => 423}) + end, + case Is_even =:= 0 of + true -> + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator@1 -> float_sign(X) * Xabs_truncated / Gleam@denominator@1 + end; + + false -> + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator@2 -> float_sign(X) * truncate_float( + Xabs + 1.0 + ) + / Gleam@denominator@2 + end + end; + + _ -> + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator@3 -> float_sign(X) * Xabs_truncated / Gleam@denominator@3 + end + end. + +-spec round_ties_away(float(), float()) -> float(). +round_ties_away(P, X) -> + Xabs = float_absolute_value(X) * P, + Remainder = Xabs - truncate_float(Xabs), + case Remainder of + _ when Remainder >= 0.5 -> + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> float_sign(X) * truncate_float(Xabs + 1.0) + / Gleam@denominator + end; + + _ -> + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator@1 -> float_sign(X) * truncate_float(Xabs) / Gleam@denominator@1 + end + end. + +-spec round_ties_up(float(), float()) -> float(). +round_ties_up(P, X) -> + Xabs = float_absolute_value(X) * P, + Xabs_truncated = truncate_float(Xabs), + Remainder = Xabs - Xabs_truncated, + case Remainder of + _ when (Remainder >= 0.5) andalso (X >= +0.0) -> + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> float_sign(X) * truncate_float(Xabs + 1.0) + / Gleam@denominator + end; + + _ -> + case P of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator@1 -> float_sign(X) * Xabs_truncated / Gleam@denominator@1 + end + end. + +-spec do_round(float(), float(), gleam@option:option(rounding_mode())) -> {ok, + float()} | + {error, binary()}. +do_round(P, X, Mode) -> + case Mode of + {some, round_nearest} -> + _pipe = round_to_nearest(P, X), + {ok, _pipe}; + + {some, round_ties_away} -> + _pipe@1 = round_ties_away(P, X), + {ok, _pipe@1}; + + {some, round_ties_up} -> + _pipe@2 = round_ties_up(P, X), + {ok, _pipe@2}; + + {some, round_to_zero} -> + _pipe@3 = round_to_zero(P, X), + {ok, _pipe@3}; + + {some, round_down} -> + _pipe@4 = round_down(P, X), + {ok, _pipe@4}; + + {some, round_up} -> + _pipe@5 = round_up(P, X), + {ok, _pipe@5}; + + none -> + _pipe@6 = round_to_nearest(P, X), + {ok, _pipe@6} + end. + +-spec round( + float(), + gleam@option:option(integer()), + gleam@option:option(rounding_mode()) +) -> {ok, float()} | {error, binary()}. +round(X, Digits, Mode) -> + case Digits of + {some, A} -> + _assert_subject = gleam_community@maths@elementary:power( + 10.0, + gleam_community@maths@conversion:int_to_float(A) + ), + {ok, P} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"round"/utf8>>, + line => 366}) + end, + do_round(P, X, Mode); + + none -> + do_round(1.0, X, Mode) + end. + +-spec ceiling(float(), gleam@option:option(integer())) -> {ok, float()} | + {error, binary()}. +ceiling(X, Digits) -> + round(X, Digits, {some, round_up}). + +-spec floor(float(), gleam@option:option(integer())) -> {ok, float()} | + {error, binary()}. +floor(X, Digits) -> + round(X, Digits, {some, round_down}). + +-spec truncate(float(), gleam@option:option(integer())) -> {ok, float()} | + {error, binary()}. +truncate(X, Digits) -> + round(X, Digits, {some, round_to_zero}). + +-spec do_int_sign(integer()) -> integer(). +do_int_sign(X) -> + case X < 0 of + true -> + -1; + + false -> + case X =:= 0 of + true -> + 0; + + false -> + 1 + end + end. + +-spec int_sign(integer()) -> integer(). +int_sign(X) -> + do_int_sign(X). + +-spec float_flip_sign(float()) -> float(). +float_flip_sign(X) -> + -1.0 * X. + +-spec float_copy_sign(float(), float()) -> float(). +float_copy_sign(X, Y) -> + case float_sign(X) =:= float_sign(Y) of + true -> + X; + + false -> + float_flip_sign(X) + end. + +-spec int_flip_sign(integer()) -> integer(). +int_flip_sign(X) -> + -1 * X. + +-spec int_copy_sign(integer(), integer()) -> integer(). +int_copy_sign(X, Y) -> + case int_sign(X) =:= int_sign(Y) of + true -> + X; + + false -> + int_flip_sign(X) + end. + +-spec minimum(IUU, IUU, fun((IUU, IUU) -> gleam@order:order())) -> IUU. +minimum(X, Y, Compare) -> + case Compare(X, Y) of + lt -> + X; + + eq -> + X; + + gt -> + Y + end. + +-spec maximum(IUV, IUV, fun((IUV, IUV) -> gleam@order:order())) -> IUV. +maximum(X, Y, Compare) -> + case Compare(X, Y) of + lt -> + Y; + + eq -> + Y; + + gt -> + X + end. + +-spec minmax(IUW, IUW, fun((IUW, IUW) -> gleam@order:order())) -> {IUW, IUW}. +minmax(X, Y, Compare) -> + {minimum(X, Y, Compare), maximum(X, Y, Compare)}. + +-spec list_minimum(list(IUX), fun((IUX, IUX) -> gleam@order:order())) -> {ok, + IUX} | + {error, binary()}. +list_minimum(Arr, Compare) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _assert_subject = gleam@list:at(Arr, 0), + {ok, Val0} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"list_minimum"/utf8>>, + line => 945}) + end, + _pipe@1 = Arr, + _pipe@2 = gleam@list:fold( + _pipe@1, + Val0, + fun(Acc, Element) -> case Compare(Element, Acc) of + lt -> + Element; + + _ -> + Acc + end end + ), + {ok, _pipe@2} + end. + +-spec list_maximum(list(IVB), fun((IVB, IVB) -> gleam@order:order())) -> {ok, + IVB} | + {error, binary()}. +list_maximum(Arr, Compare) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _assert_subject = gleam@list:at(Arr, 0), + {ok, Val0} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"list_maximum"/utf8>>, + line => 1004}) + end, + _pipe@1 = Arr, + _pipe@2 = gleam@list:fold( + _pipe@1, + Val0, + fun(Acc, Element) -> case Compare(Acc, Element) of + lt -> + Element; + + _ -> + Acc + end end + ), + {ok, _pipe@2} + end. + +-spec arg_minimum(list(IVF), fun((IVF, IVF) -> gleam@order:order())) -> {ok, + list(integer())} | + {error, binary()}. +arg_minimum(Arr, Compare) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _assert_subject = begin + _pipe@1 = Arr, + list_minimum(_pipe@1, Compare) + end, + {ok, Min} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"arg_minimum"/utf8>>, + line => 1069}) + end, + _pipe@2 = Arr, + _pipe@3 = gleam@list:index_map( + _pipe@2, + fun(Index, Element) -> case Compare(Element, Min) of + eq -> + Index; + + _ -> + -1 + end end + ), + _pipe@4 = gleam@list:filter(_pipe@3, fun(Index@1) -> case Index@1 of + -1 -> + false; + + _ -> + true + end end), + {ok, _pipe@4} + end. + +-spec arg_maximum(list(IVK), fun((IVK, IVK) -> gleam@order:order())) -> {ok, + list(integer())} | + {error, binary()}. +arg_maximum(Arr, Compare) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _assert_subject = begin + _pipe@1 = Arr, + list_maximum(_pipe@1, Compare) + end, + {ok, Max} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"arg_maximum"/utf8>>, + line => 1139}) + end, + _pipe@2 = Arr, + _pipe@3 = gleam@list:index_map( + _pipe@2, + fun(Index, Element) -> case Compare(Element, Max) of + eq -> + Index; + + _ -> + -1 + end end + ), + _pipe@4 = gleam@list:filter(_pipe@3, fun(Index@1) -> case Index@1 of + -1 -> + false; + + _ -> + true + end end), + {ok, _pipe@4} + end. + +-spec extrema(list(IVP), fun((IVP, IVP) -> gleam@order:order())) -> {ok, + {IVP, IVP}} | + {error, binary()}. +extrema(Arr, Compare) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _assert_subject = gleam@list:at(Arr, 0), + {ok, Val_max} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"extrema"/utf8>>, + line => 1209}) + end, + _assert_subject@1 = gleam@list:at(Arr, 0), + {ok, Val_min} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"extrema"/utf8>>, + line => 1210}) + end, + _pipe@1 = Arr, + _pipe@2 = gleam@list:fold( + _pipe@1, + {Val_min, Val_max}, + fun(Acc, Element) -> + First = gleam@pair:first(Acc), + Second = gleam@pair:second(Acc), + case {Compare(Element, First), Compare(Second, Element)} of + {lt, lt} -> + {Element, Element}; + + {lt, _} -> + {Element, Second}; + + {_, lt} -> + {First, Element}; + + {_, _} -> + {First, Second} + end + end + ), + {ok, _pipe@2} + end. diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.cache b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.cache Binary files differnew file mode 100644 index 0000000..0ef2e9b --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.cache_meta b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.cache_meta Binary files differnew file mode 100644 index 0000000..549041c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.erl b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.erl new file mode 100644 index 0000000..42484d5 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.erl @@ -0,0 +1,118 @@ +-module(gleam_community@maths@predicates). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([is_close/4, all_close/4, is_fractional/1, is_power/2, is_perfect/1, is_even/1, is_odd/1]). + +-spec float_absolute_value(float()) -> float(). +float_absolute_value(X) -> + case X > +0.0 of + true -> + X; + + false -> + -1.0 * X + end. + +-spec float_absolute_difference(float(), float()) -> float(). +float_absolute_difference(A, B) -> + _pipe = A - B, + float_absolute_value(_pipe). + +-spec is_close(float(), float(), float(), float()) -> boolean(). +is_close(A, B, Rtol, Atol) -> + X = float_absolute_difference(A, B), + Y = Atol + (Rtol * float_absolute_value(B)), + case X =< Y of + true -> + true; + + false -> + false + end. + +-spec all_close(list(float()), list(float()), float(), float()) -> {ok, + list(boolean())} | + {error, binary()}. +all_close(Xarr, Yarr, Rtol, Atol) -> + Xlen = gleam@list:length(Xarr), + Ylen = gleam@list:length(Yarr), + case Xlen =:= Ylen of + false -> + _pipe = <<"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."/utf8>>, + {error, _pipe}; + + true -> + _pipe@1 = gleam@list:zip(Xarr, Yarr), + _pipe@2 = gleam@list:map( + _pipe@1, + fun(Z) -> + is_close( + gleam@pair:first(Z), + gleam@pair:second(Z), + Rtol, + Atol + ) + end + ), + {ok, _pipe@2} + end. + +-spec is_fractional(float()) -> boolean(). +is_fractional(X) -> + (math:ceil(X) - X) > +0.0. + +-spec is_power(integer(), integer()) -> boolean(). +is_power(X, Y) -> + _assert_subject = gleam_community@maths@elementary:logarithm( + gleam@int:to_float(X), + {some, gleam@int:to_float(Y)} + ), + {ok, Value} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/predicates"/utf8>>, + function => <<"is_power"/utf8>>, + line => 241}) + end, + _assert_subject@1 = gleam_community@maths@piecewise:truncate( + Value, + {some, 0} + ), + {ok, Truncated} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/predicates"/utf8>>, + function => <<"is_power"/utf8>>, + line => 243}) + end, + Rem = Value - Truncated, + Rem =:= +0.0. + +-spec do_sum(list(integer())) -> integer(). +do_sum(Arr) -> + case Arr of + [] -> + 0; + + _ -> + _pipe = Arr, + gleam@list:fold(_pipe, 0, fun(Acc, A) -> A + Acc end) + end. + +-spec is_perfect(integer()) -> boolean(). +is_perfect(N) -> + do_sum(gleam_community@maths@arithmetics:proper_divisors(N)) =:= N. + +-spec is_even(integer()) -> boolean(). +is_even(X) -> + (X rem 2) =:= 0. + +-spec is_odd(integer()) -> boolean(). +is_odd(X) -> + (X rem 2) /= 0. diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.cache b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.cache Binary files differnew file mode 100644 index 0000000..e06c185 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.cache_meta b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.cache_meta Binary files differnew file mode 100644 index 0000000..3a025a2 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.erl b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.erl new file mode 100644 index 0000000..72de13c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.erl @@ -0,0 +1,202 @@ +-module(gleam_community@maths@sequences). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([arange/3, linear_space/4, logarithmic_space/5, geometric_space/4]). + +-spec arange(float(), float(), float()) -> list(float()). +arange(Start, Stop, Step) -> + case ((Start >= Stop) andalso (Step > +0.0)) orelse ((Start =< Stop) andalso (Step + < +0.0)) of + true -> + []; + + false -> + Direction = case Start =< Stop of + true -> + 1.0; + + false -> + -1.0 + end, + Step_abs = gleam_community@maths@piecewise:float_absolute_value( + Step + ), + Num = case Step_abs of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> gleam_community@maths@piecewise:float_absolute_value( + Start - Stop + ) + / Gleam@denominator + end, + _pipe = gleam@list:range( + 0, + gleam_community@maths@conversion:float_to_int(Num) - 1 + ), + gleam@list:map( + _pipe, + fun(I) -> + Start + ((gleam_community@maths@conversion:int_to_float(I) * Step_abs) + * Direction) + end + ) + end. + +-spec linear_space(float(), float(), integer(), boolean()) -> {ok, + list(float())} | + {error, binary()}. +linear_space(Start, Stop, Num, Endpoint) -> + Direction = case Start =< Stop of + true -> + 1.0; + + false -> + -1.0 + end, + case Num > 0 of + true -> + case Endpoint of + true -> + Increment = case gleam_community@maths@conversion:int_to_float( + Num - 1 + ) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> gleam_community@maths@piecewise:float_absolute_value( + Start - Stop + ) + / Gleam@denominator + end, + _pipe = gleam@list:range(0, Num - 1), + _pipe@1 = gleam@list:map( + _pipe, + fun(I) -> + Start + ((gleam_community@maths@conversion:int_to_float( + I + ) + * Increment) + * Direction) + end + ), + {ok, _pipe@1}; + + false -> + Increment@1 = case gleam_community@maths@conversion:int_to_float( + Num + ) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator@1 -> gleam_community@maths@piecewise:float_absolute_value( + Start - Stop + ) + / Gleam@denominator@1 + end, + _pipe@2 = gleam@list:range(0, Num - 1), + _pipe@3 = gleam@list:map( + _pipe@2, + fun(I@1) -> + Start + ((gleam_community@maths@conversion:int_to_float( + I@1 + ) + * Increment@1) + * Direction) + end + ), + {ok, _pipe@3} + end; + + false -> + _pipe@4 = <<"Invalid input: num < 0. Valid input is num > 0."/utf8>>, + {error, _pipe@4} + end. + +-spec logarithmic_space(float(), float(), integer(), boolean(), float()) -> {ok, + list(float())} | + {error, binary()}. +logarithmic_space(Start, Stop, Num, Endpoint, Base) -> + case Num > 0 of + true -> + _assert_subject = linear_space(Start, Stop, Num, Endpoint), + {ok, Linspace} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/sequences"/utf8>>, + function => <<"logarithmic_space"/utf8>>, + line => 221}) + end, + _pipe = Linspace, + _pipe@1 = gleam@list:map( + _pipe, + fun(I) -> + _assert_subject@1 = gleam_community@maths@elementary:power( + Base, + I + ), + {ok, Result} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/sequences"/utf8>>, + function => <<"logarithmic_space"/utf8>>, + line => 224}) + end, + Result + end + ), + {ok, _pipe@1}; + + false -> + _pipe@2 = <<"Invalid input: num < 0. Valid input is num > 0."/utf8>>, + {error, _pipe@2} + end. + +-spec geometric_space(float(), float(), integer(), boolean()) -> {ok, + list(float())} | + {error, binary()}. +geometric_space(Start, Stop, Num, Endpoint) -> + case (Start =:= +0.0) orelse (Stop =:= +0.0) of + true -> + _pipe = <<""/utf8>>, + {error, _pipe}; + + false -> + case Num > 0 of + true -> + _assert_subject = gleam_community@maths@elementary:logarithm_10( + Start + ), + {ok, Log_start} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/sequences"/utf8>>, + function => <<"geometric_space"/utf8>>, + line => 293}) + end, + _assert_subject@1 = gleam_community@maths@elementary:logarithm_10( + Stop + ), + {ok, Log_stop} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/sequences"/utf8>>, + function => <<"geometric_space"/utf8>>, + line => 294}) + end, + logarithmic_space(Log_start, Log_stop, Num, Endpoint, 10.0); + + false -> + _pipe@1 = <<"Invalid input: num < 0. Valid input is num > 0."/utf8>>, + {error, _pipe@1} + end + end. diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.cache b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.cache Binary files differnew file mode 100644 index 0000000..0fdbab2 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.cache diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.cache_meta b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.cache_meta Binary files differnew file mode 100644 index 0000000..3c21994 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.erl b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.erl new file mode 100644 index 0000000..b1e9214 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.erl @@ -0,0 +1,163 @@ +-module(gleam_community@maths@special). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([erf/1, incomplete_gamma/2, gamma/1, beta/2]). + +-spec erf(float()) -> float(). +erf(X) -> + _assert_subject = [0.254829592, + -0.284496736, + 1.421413741, + -1.453152027, + 1.061405429], + [A1, A2, A3, A4, A5] = case _assert_subject of + [_, _, _, _, _] -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/special"/utf8>>, + function => <<"erf"/utf8>>, + line => 79}) + end, + P = 0.3275911, + Sign = gleam_community@maths@piecewise:float_sign(X), + X@1 = gleam_community@maths@piecewise:float_absolute_value(X), + T = case (1.0 + (P * X@1)) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> 1.0 / Gleam@denominator + end, + Y = 1.0 - ((((((((((A5 * T) + A4) * T) + A3) * T) + A2) * T) + A1) * T) * gleam_community@maths@elementary:exponential( + (-1.0 * X@1) * X@1 + )), + Sign * Y. + +-spec incomplete_gamma_sum(float(), float(), float(), float(), float()) -> float(). +incomplete_gamma_sum(A, X, T, S, N) -> + case T of + +0.0 -> + S; + + _ -> + Ns = S + T, + Nt = T * (case (A + N) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> X / Gleam@denominator + end), + incomplete_gamma_sum(A, X, Nt, Ns, N + 1.0) + end. + +-spec incomplete_gamma(float(), float()) -> {ok, float()} | {error, binary()}. +incomplete_gamma(A, X) -> + case (A > +0.0) andalso (X >= +0.0) of + true -> + _assert_subject = gleam_community@maths@elementary:power(X, A), + {ok, V} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/special"/utf8>>, + function => <<"incomplete_gamma"/utf8>>, + line => 173}) + end, + _pipe = (V * gleam_community@maths@elementary:exponential(-1.0 * X)) + * incomplete_gamma_sum(A, X, case A of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> 1.0 / Gleam@denominator + end, +0.0, 1.0), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invlaid input argument: a <= 0 or x < 0. Valid input is a > 0 and x >= 0."/utf8>>, + {error, _pipe@1} + end. + +-spec gamma_lanczos(float()) -> float(). +gamma_lanczos(X) -> + case X < 0.5 of + true -> + case (gleam_community@maths@elementary:sin( + gleam_community@maths@elementary:pi() * X + ) + * gamma_lanczos(1.0 - X)) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> gleam_community@maths@elementary:pi() / Gleam@denominator + end; + + false -> + Z = X - 1.0, + X@1 = gleam@list:index_fold( + [0.99999999999980993, + 676.5203681218851, + -1259.1392167224028, + 771.32342877765313, + -176.61502916214059, + 12.507343278686905, + -0.13857109526572012, + 0.0000099843695780195716, + 0.00000015056327351493116], + +0.0, + fun(Acc, V, Index) -> case Index > 0 of + true -> + Acc + (case (Z + gleam_community@maths@conversion:int_to_float( + Index + )) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator@1 -> V / Gleam@denominator@1 + end); + + false -> + V + end end + ), + T = (Z + 7.0) + 0.5, + _assert_subject = gleam_community@maths@elementary:power( + 2.0 * gleam_community@maths@elementary:pi(), + 0.5 + ), + {ok, V1} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/special"/utf8>>, + function => <<"gamma_lanczos"/utf8>>, + line => 146}) + end, + _assert_subject@1 = gleam_community@maths@elementary:power( + T, + Z + 0.5 + ), + {ok, V2} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/special"/utf8>>, + function => <<"gamma_lanczos"/utf8>>, + line => 147}) + end, + ((V1 * V2) * gleam_community@maths@elementary:exponential(-1.0 * T)) + * X@1 + end. + +-spec gamma(float()) -> float(). +gamma(X) -> + gamma_lanczos(X). + +-spec beta(float(), float()) -> float(). +beta(X, Y) -> + case gamma(X + Y) of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> gamma(X) * gamma(Y) / Gleam@denominator + end. diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/maths.mjs b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/maths.mjs new file mode 100644 index 0000000..5c5ab31 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/maths.mjs @@ -0,0 +1,95 @@ +export function sin(float) { + return Math.sin(float) +} + +export function pi() { + return Math.PI +} + +export function acos(float) { + return Math.acos(float) +} + +export function acosh(float) { + return Math.acosh(float) +} + +export function asin(float) { + return Math.asin(float) +} + +export function asinh(float) { + return Math.asinh(float) +} + +export function atan(float) { + return Math.atan(float) +} + +export function tan(float) { + return Math.tan(float) +} + +export function atan2(floaty, floatx) { + return Math.atan2(floaty, floatx) +} + +export function atanh(float) { + return Math.atanh(float) +} + +export function cos(float) { + return Math.cos(float) +} + +export function cosh(float) { + return Math.cosh(float) +} + +export function exponential(float) { + return Math.exp(float) +} + +export function ceiling(float) { + return Math.ceil(float) +} + +export function floor(float) { + return Math.floor(float) +} + +export function power(base, exponent) { + return Math.pow(base, exponent) +} + +export function logarithm(float) { + return Math.log(float) +} + +export function logarithm_10(float) { + return Math.log10(float) +} + +export function logarithm_2(float) { + return Math.log2(float) +} + +export function sinh(float) { + return Math.sinh(float) +} + +export function tanh(float) { + return Math.tanh(float) +} + +export function sign(float) { + return Math.sign(float) +} + +export function truncate(float) { + return Math.trunc(float) +} + +export function to_int(float) { + return Math.trunc(float) +} diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@arithmetics.beam b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@arithmetics.beam Binary files differnew file mode 100644 index 0000000..7bdc600 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@arithmetics.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@combinatorics.beam b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@combinatorics.beam Binary files differnew file mode 100644 index 0000000..f9cdc85 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@combinatorics.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@conversion.beam b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@conversion.beam Binary files differnew file mode 100644 index 0000000..bc6d41e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@conversion.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@elementary.beam b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@elementary.beam Binary files differnew file mode 100644 index 0000000..9850c86 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@elementary.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@metrics.beam b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@metrics.beam Binary files differnew file mode 100644 index 0000000..513efde --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@metrics.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@piecewise.beam b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@piecewise.beam Binary files differnew file mode 100644 index 0000000..652b871 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@piecewise.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@predicates.beam b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@predicates.beam Binary files differnew file mode 100644 index 0000000..c6fa350 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@predicates.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@sequences.beam b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@sequences.beam Binary files differnew file mode 100644 index 0000000..1039c56 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@sequences.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@special.beam b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@special.beam Binary files differnew file mode 100644 index 0000000..21b9149 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@special.beam diff --git a/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community_maths.app b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community_maths.app new file mode 100644 index 0000000..b24eaf7 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community_maths.app @@ -0,0 +1,7 @@ +{application, gleam_community_maths, [ + {vsn, "1.0.1"}, + {applications, [gleam_stdlib]}, + {description, "A basic maths library"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.cache b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.cache Binary files differnew file mode 100644 index 0000000..a136f2b --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.cache diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.cache_meta b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.cache_meta Binary files differnew file mode 100644 index 0000000..12933b2 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.erl b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.erl new file mode 100644 index 0000000..c689364 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.erl @@ -0,0 +1,90 @@ +-module(gleam@erlang). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([format/1, term_to_binary/1, get_line/1, system_time/1, erlang_timestamp/0, rescue/1, binary_to_term/1, unsafe_binary_to_term/1, start_arguments/0, ensure_all_started/1, make_reference/0, priv_directory/1]). +-export_type([safe/0, get_line_error/0, time_unit/0, crash/0, ensure_all_started_error/0, reference_/0]). + +-type safe() :: safe. + +-type get_line_error() :: eof | no_data. + +-type time_unit() :: second | millisecond | microsecond | nanosecond. + +-type crash() :: {exited, gleam@dynamic:dynamic_()} | + {thrown, gleam@dynamic:dynamic_()} | + {errored, gleam@dynamic:dynamic_()}. + +-type ensure_all_started_error() :: {unknown_application, + gleam@erlang@atom:atom_()} | + {application_failed_to_start, + gleam@erlang@atom:atom_(), + gleam@dynamic:dynamic_()}. + +-type reference_() :: any(). + +-spec format(any()) -> binary(). +format(Term) -> + unicode:characters_to_binary(io_lib:format(<<"~p"/utf8>>, [Term])). + +-spec term_to_binary(any()) -> bitstring(). +term_to_binary(A) -> + erlang:term_to_binary(A). + +-spec get_line(binary()) -> {ok, binary()} | {error, get_line_error()}. +get_line(Prompt) -> + gleam_erlang_ffi:get_line(Prompt). + +-spec system_time(time_unit()) -> integer(). +system_time(A) -> + os:system_time(A). + +-spec erlang_timestamp() -> {integer(), integer(), integer()}. +erlang_timestamp() -> + os:timestamp(). + +-spec rescue(fun(() -> GWM)) -> {ok, GWM} | {error, crash()}. +rescue(A) -> + gleam_erlang_ffi:rescue(A). + +-spec binary_to_term(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | + {error, nil}. +binary_to_term(Binary) -> + case gleam_erlang_ffi:rescue( + fun() -> erlang:binary_to_term(Binary, [safe]) end + ) of + {ok, Term} -> + {ok, Term}; + + {error, _} -> + {error, nil} + end. + +-spec unsafe_binary_to_term(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | + {error, nil}. +unsafe_binary_to_term(Binary) -> + case gleam_erlang_ffi:rescue(fun() -> erlang:binary_to_term(Binary, []) end) of + {ok, Term} -> + {ok, Term}; + + {error, _} -> + {error, nil} + end. + +-spec start_arguments() -> list(binary()). +start_arguments() -> + _pipe = init:get_plain_arguments(), + gleam@list:map(_pipe, fun unicode:characters_to_binary/1). + +-spec ensure_all_started(gleam@erlang@atom:atom_()) -> {ok, + list(gleam@erlang@atom:atom_())} | + {error, ensure_all_started_error()}. +ensure_all_started(Application) -> + gleam_erlang_ffi:ensure_all_started(Application). + +-spec make_reference() -> reference_(). +make_reference() -> + erlang:make_ref(). + +-spec priv_directory(binary()) -> {ok, binary()} | {error, nil}. +priv_directory(Name) -> + gleam_erlang_ffi:priv_directory(Name). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache Binary files differnew file mode 100644 index 0000000..83a03cd --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache_meta b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache_meta Binary files differnew file mode 100644 index 0000000..be33011 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.erl b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.erl new file mode 100644 index 0000000..f35c631 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.erl @@ -0,0 +1,26 @@ +-module(gleam@erlang@atom). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([from_string/1, create_from_string/1, to_string/1, from_dynamic/1]). +-export_type([atom_/0, from_string_error/0]). + +-type atom_() :: any(). + +-type from_string_error() :: atom_not_loaded. + +-spec from_string(binary()) -> {ok, atom_()} | {error, from_string_error()}. +from_string(A) -> + gleam_erlang_ffi:atom_from_string(A). + +-spec create_from_string(binary()) -> atom_(). +create_from_string(A) -> + erlang:binary_to_atom(A). + +-spec to_string(atom_()) -> binary(). +to_string(A) -> + erlang:atom_to_binary(A). + +-spec from_dynamic(gleam@dynamic:dynamic_()) -> {ok, atom_()} | + {error, list(gleam@dynamic:decode_error())}. +from_dynamic(From) -> + gleam_erlang_ffi:atom_from_dynamic(From). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache Binary files differnew file mode 100644 index 0000000..b4053cc --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache_meta b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache_meta Binary files differnew file mode 100644 index 0000000..82cfdb5 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.erl b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.erl new file mode 100644 index 0000000..dc1670d --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.erl @@ -0,0 +1,15 @@ +-module(gleam@erlang@charlist). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([to_string/1, from_string/1]). +-export_type([charlist/0]). + +-type charlist() :: any(). + +-spec to_string(charlist()) -> binary(). +to_string(A) -> + unicode:characters_to_binary(A). + +-spec from_string(binary()) -> charlist(). +from_string(A) -> + unicode:characters_to_list(A). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.cache b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.cache Binary files differnew file mode 100644 index 0000000..b447be6 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.cache diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.cache_meta b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.cache_meta Binary files differnew file mode 100644 index 0000000..1cb342b --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.erl b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.erl new file mode 100644 index 0000000..396b31a --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.erl @@ -0,0 +1,190 @@ +-module(gleam@erlang@file). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([file_info/1, link_info/1, is_directory/1, is_regular/1, file_exists/1, link_exists/1, make_directory/1, list_directory/1, delete_directory/1, recursive_delete/1, read/1, read_bits/1, write/2, write_bits/2, append/2, append_bits/2, delete/1]). +-export_type([reason/0, file_type/0, access/0, file_info/0]). + +-type reason() :: eacces | + eagain | + ebadf | + ebadmsg | + ebusy | + edeadlk | + edeadlock | + edquot | + eexist | + efault | + efbig | + eftype | + eintr | + einval | + eio | + eisdir | + eloop | + emfile | + emlink | + emultihop | + enametoolong | + enfile | + enobufs | + enodev | + enolck | + enolink | + enoent | + enomem | + enospc | + enosr | + enostr | + enosys | + enotblk | + enotdir | + enotsup | + enxio | + eopnotsupp | + eoverflow | + eperm | + epipe | + erange | + erofs | + espipe | + esrch | + estale | + etxtbsy | + exdev | + not_utf8. + +-type file_type() :: device | directory | other | regular | symlink. + +-type access() :: no_access | read | read_write | write. + +-type file_info() :: {file_info, + integer(), + file_type(), + access(), + integer(), + integer(), + integer(), + integer(), + integer(), + integer(), + integer(), + integer(), + integer(), + integer()}. + +-spec file_info(binary()) -> {ok, file_info()} | {error, reason()}. +file_info(A) -> + gleam_erlang_ffi:file_info(A). + +-spec link_info(binary()) -> {ok, file_info()} | {error, reason()}. +link_info(A) -> + gleam_erlang_ffi:link_info(A). + +-spec is_directory(binary()) -> {ok, boolean()} | {error, reason()}. +is_directory(Path) -> + gleam@result:map( + gleam_erlang_ffi:file_info(Path), + fun(_use0) -> + {file_info, _, File_type, _, _, _, _, _, _, _, _, _, _, _} = _use0, + File_type =:= directory + end + ). + +-spec is_regular(binary()) -> {ok, boolean()} | {error, reason()}. +is_regular(Path) -> + gleam@result:map( + gleam_erlang_ffi:file_info(Path), + fun(_use0) -> + {file_info, _, File_type, _, _, _, _, _, _, _, _, _, _, _} = _use0, + File_type =:= regular + end + ). + +-spec file_exists(binary()) -> {ok, boolean()} | {error, reason()}. +file_exists(Path) -> + Result = begin + _pipe = Path, + _pipe@1 = gleam_erlang_ffi:file_info(_pipe), + gleam@result:replace(_pipe@1, true) + end, + case Result of + {error, enoent} -> + {ok, false}; + + _ -> + Result + end. + +-spec link_exists(binary()) -> {ok, boolean()} | {error, reason()}. +link_exists(Path) -> + Result = begin + _pipe = Path, + _pipe@1 = gleam_erlang_ffi:link_info(_pipe), + gleam@result:replace(_pipe@1, true) + end, + case Result of + {error, enoent} -> + {ok, false}; + + _ -> + Result + end. + +-spec make_directory(binary()) -> {ok, nil} | {error, reason()}. +make_directory(A) -> + gleam_erlang_ffi:make_directory(A). + +-spec list_directory(binary()) -> {ok, list(binary())} | {error, reason()}. +list_directory(A) -> + gleam_erlang_ffi:list_directory(A). + +-spec delete_directory(binary()) -> {ok, nil} | {error, reason()}. +delete_directory(A) -> + gleam_erlang_ffi:delete_directory(A). + +-spec recursive_delete(binary()) -> {ok, nil} | {error, reason()}. +recursive_delete(A) -> + gleam_erlang_ffi:recursive_delete(A). + +-spec read(binary()) -> {ok, binary()} | {error, reason()}. +read(Path) -> + _pipe = Path, + _pipe@1 = gleam_erlang_ffi:read_file(_pipe), + gleam@result:then( + _pipe@1, + fun(Content) -> case gleam@bit_array:to_string(Content) of + {ok, String} -> + {ok, String}; + + {error, nil} -> + {error, not_utf8} + end end + ). + +-spec read_bits(binary()) -> {ok, bitstring()} | {error, reason()}. +read_bits(Path) -> + gleam_erlang_ffi:read_file(Path). + +-spec write(binary(), binary()) -> {ok, nil} | {error, reason()}. +write(Contents, Path) -> + _pipe = Contents, + _pipe@1 = gleam_stdlib:identity(_pipe), + gleam_erlang_ffi:write_file(_pipe@1, Path). + +-spec write_bits(bitstring(), binary()) -> {ok, nil} | {error, reason()}. +write_bits(Contents, Path) -> + gleam_erlang_ffi:write_file(Contents, Path). + +-spec append(binary(), binary()) -> {ok, nil} | {error, reason()}. +append(Contents, Path) -> + _pipe = Contents, + _pipe@1 = gleam_stdlib:identity(_pipe), + gleam_erlang_ffi:append_file(_pipe@1, Path). + +-spec append_bits(bitstring(), binary()) -> {ok, nil} | {error, reason()}. +append_bits(Contents, Path) -> + gleam_erlang_ffi:append_file(Contents, Path). + +-spec delete(binary()) -> {ok, nil} | {error, reason()}. +delete(A) -> + gleam_erlang_ffi:delete_file(A). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache Binary files differnew file mode 100644 index 0000000..acd84e1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache_meta b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache_meta Binary files differnew file mode 100644 index 0000000..085886a --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.erl b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.erl new file mode 100644 index 0000000..e421e84 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.erl @@ -0,0 +1,33 @@ +-module(gleam@erlang@node). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([self/0, visible/0, connect/1, send/3, to_atom/1]). +-export_type([node_/0, do_not_leak/0, connect_error/0]). + +-type node_() :: any(). + +-type do_not_leak() :: any(). + +-type connect_error() :: failed_to_connect | local_node_is_not_alive. + +-spec self() -> node_(). +self() -> + erlang:node(). + +-spec visible() -> list(node_()). +visible() -> + erlang:nodes(). + +-spec connect(gleam@erlang@atom:atom_()) -> {ok, node_()} | + {error, connect_error()}. +connect(Node) -> + gleam_erlang_ffi:connect_node(Node). + +-spec send(node_(), gleam@erlang@atom:atom_(), any()) -> nil. +send(Node, Name, Message) -> + erlang:send({Name, Node}, Message), + nil. + +-spec to_atom(node_()) -> gleam@erlang@atom:atom_(). +to_atom(Node) -> + gleam_erlang_ffi:identity(Node). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.cache b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.cache Binary files differnew file mode 100644 index 0000000..c7698fa --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.cache diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.cache_meta b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.cache_meta Binary files differnew file mode 100644 index 0000000..1d5fa83 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.erl b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.erl new file mode 100644 index 0000000..27bc111 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.erl @@ -0,0 +1,27 @@ +-module(gleam@erlang@os). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([get_all_env/0, get_env/1, set_env/2, unset_env/1, family/0]). +-export_type([os_family/0]). + +-type os_family() :: windows_nt | linux | darwin | free_bsd | {other, binary()}. + +-spec get_all_env() -> gleam@dict:dict(binary(), binary()). +get_all_env() -> + gleam_erlang_ffi:get_all_env(). + +-spec get_env(binary()) -> {ok, binary()} | {error, nil}. +get_env(Name) -> + gleam_erlang_ffi:get_env(Name). + +-spec set_env(binary(), binary()) -> nil. +set_env(Name, Value) -> + gleam_erlang_ffi:set_env(Name, Value). + +-spec unset_env(binary()) -> nil. +unset_env(Name) -> + gleam_erlang_ffi:unset_env(Name). + +-spec family() -> os_family(). +family() -> + gleam_erlang_ffi:os_family(). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache Binary files differnew file mode 100644 index 0000000..bb95436 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache_meta b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache_meta Binary files differnew file mode 100644 index 0000000..ad9209c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.erl b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.erl new file mode 100644 index 0000000..f8562ef --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.erl @@ -0,0 +1,374 @@ +-module(gleam@erlang@process). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([self/0, start/2, new_subject/0, subject_owner/1, send/2, new_selector/0, select/2, select_forever/1, map_selector/2, merge_selector/2, flush_messages/0, selecting_trapped_exits/2, selecting/3, 'receive'/2, selecting_record2/3, selecting_record3/3, selecting_record4/3, selecting_record5/3, selecting_record6/3, selecting_record7/3, selecting_record8/3, selecting_anything/2, sleep/1, sleep_forever/0, is_alive/1, monitor_process/1, selecting_process_down/3, demonitor_process/1, try_call/3, call/3, link/1, unlink/1, send_after/3, cancel_timer/1, kill/1, send_exit/1, send_abnormal_exit/2, trap_exits/1, register/2, unregister/1, named/1]). +-export_type([pid_/0, subject/1, do_not_leak/0, selector/1, exit_message/0, exit_reason/0, anything_selector_tag/0, process_monitor_flag/0, process_monitor/0, process_down/0, call_error/1, timer/0, cancelled/0, kill_flag/0]). + +-type pid_() :: any(). + +-opaque subject(GYI) :: {subject, pid_(), gleam@erlang:reference_()} | + {gleam_phantom, GYI}. + +-type do_not_leak() :: any(). + +-type selector(GYJ) :: any() | {gleam_phantom, GYJ}. + +-type exit_message() :: {exit_message, pid_(), exit_reason()}. + +-type exit_reason() :: normal | killed | {abnormal, binary()}. + +-type anything_selector_tag() :: anything. + +-type process_monitor_flag() :: process. + +-opaque process_monitor() :: {process_monitor, gleam@erlang:reference_()}. + +-type process_down() :: {process_down, pid_(), gleam@dynamic:dynamic_()}. + +-type call_error(GYK) :: {callee_down, gleam@dynamic:dynamic_()} | + call_timeout | + {gleam_phantom, GYK}. + +-type timer() :: any(). + +-type cancelled() :: timer_not_found | {cancelled, integer()}. + +-type kill_flag() :: kill. + +-spec self() -> pid_(). +self() -> + erlang:self(). + +-spec start(fun(() -> any()), boolean()) -> pid_(). +start(Implementation, Link) -> + case Link of + true -> + erlang:spawn_link(Implementation); + + false -> + erlang:spawn(Implementation) + end. + +-spec new_subject() -> subject(any()). +new_subject() -> + {subject, erlang:self(), erlang:make_ref()}. + +-spec subject_owner(subject(any())) -> pid_(). +subject_owner(Subject) -> + erlang:element(2, Subject). + +-spec send(subject(GYT), GYT) -> nil. +send(Subject, Message) -> + erlang:send( + erlang:element(2, Subject), + {erlang:element(3, Subject), Message} + ), + nil. + +-spec new_selector() -> selector(any()). +new_selector() -> + gleam_erlang_ffi:new_selector(). + +-spec select(selector(GZB), integer()) -> {ok, GZB} | {error, nil}. +select(From, Within) -> + gleam_erlang_ffi:select(From, Within). + +-spec select_forever(selector(GZF)) -> GZF. +select_forever(From) -> + gleam_erlang_ffi:select(From). + +-spec map_selector(selector(GZH), fun((GZH) -> GZJ)) -> selector(GZJ). +map_selector(A, B) -> + gleam_erlang_ffi:map_selector(A, B). + +-spec merge_selector(selector(GZL), selector(GZL)) -> selector(GZL). +merge_selector(A, B) -> + gleam_erlang_ffi:merge_selector(A, B). + +-spec flush_messages() -> nil. +flush_messages() -> + gleam_erlang_ffi:flush_messages(). + +-spec selecting_trapped_exits(selector(GZP), fun((exit_message()) -> GZP)) -> selector(GZP). +selecting_trapped_exits(Selector, Handler) -> + Tag = erlang:binary_to_atom(<<"EXIT"/utf8>>), + Handler@1 = fun(Message) -> + Reason = erlang:element(3, Message), + Normal = gleam@dynamic:from(normal), + Killed = gleam@dynamic:from(killed), + Reason@2 = case gleam@dynamic:string(Reason) of + _ when Reason =:= Normal -> + normal; + + _ when Reason =:= Killed -> + killed; + + {ok, Reason@1} -> + {abnormal, Reason@1}; + + {error, _} -> + {abnormal, gleam@string:inspect(Reason)} + end, + Handler({exit_message, erlang:element(2, Message), Reason@2}) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 3}, Handler@1). + +-spec selecting(selector(GZS), subject(GZU), fun((GZU) -> GZS)) -> selector(GZS). +selecting(Selector, Subject, Transform) -> + Handler = fun(Message) -> Transform(erlang:element(2, Message)) end, + gleam_erlang_ffi:insert_selector_handler( + Selector, + {erlang:element(3, Subject), 2}, + Handler + ). + +-spec 'receive'(subject(GYV), integer()) -> {ok, GYV} | {error, nil}. +'receive'(Subject, Milliseconds) -> + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = selecting(_pipe, Subject, fun(X) -> X end), + gleam_erlang_ffi:select(_pipe@1, Milliseconds). + +-spec selecting_record2( + selector(GZX), + any(), + fun((gleam@dynamic:dynamic_()) -> GZX) +) -> selector(GZX). +selecting_record2(Selector, Tag, Transform) -> + Handler = fun(Message) -> Transform(erlang:element(2, Message)) end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 2}, Handler). + +-spec selecting_record3( + selector(HAB), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> HAB) +) -> selector(HAB). +selecting_record3(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform(erlang:element(2, Message), erlang:element(3, Message)) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 3}, Handler). + +-spec selecting_record4( + selector(HAF), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> HAF) +) -> selector(HAF). +selecting_record4(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform( + erlang:element(2, Message), + erlang:element(3, Message), + erlang:element(4, Message) + ) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 4}, Handler). + +-spec selecting_record5( + selector(HAJ), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> HAJ) +) -> selector(HAJ). +selecting_record5(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform( + erlang:element(2, Message), + erlang:element(3, Message), + erlang:element(4, Message), + erlang:element(5, Message) + ) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 5}, Handler). + +-spec selecting_record6( + selector(HAN), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> HAN) +) -> selector(HAN). +selecting_record6(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform( + erlang:element(2, Message), + erlang:element(3, Message), + erlang:element(4, Message), + erlang:element(5, Message), + erlang:element(6, Message) + ) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 6}, Handler). + +-spec selecting_record7( + selector(HAR), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> HAR) +) -> selector(HAR). +selecting_record7(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform( + erlang:element(2, Message), + erlang:element(3, Message), + erlang:element(4, Message), + erlang:element(5, Message), + erlang:element(6, Message), + erlang:element(7, Message) + ) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 7}, Handler). + +-spec selecting_record8( + selector(HAV), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> HAV) +) -> selector(HAV). +selecting_record8(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform( + erlang:element(2, Message), + erlang:element(3, Message), + erlang:element(4, Message), + erlang:element(5, Message), + erlang:element(6, Message), + erlang:element(7, Message), + erlang:element(8, Message) + ) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 8}, Handler). + +-spec selecting_anything(selector(HAZ), fun((gleam@dynamic:dynamic_()) -> HAZ)) -> selector(HAZ). +selecting_anything(Selector, Handler) -> + gleam_erlang_ffi:insert_selector_handler(Selector, anything, Handler). + +-spec sleep(integer()) -> nil. +sleep(A) -> + gleam_erlang_ffi:sleep(A). + +-spec sleep_forever() -> nil. +sleep_forever() -> + gleam_erlang_ffi:sleep_forever(). + +-spec is_alive(pid_()) -> boolean(). +is_alive(A) -> + erlang:is_process_alive(A). + +-spec monitor_process(pid_()) -> process_monitor(). +monitor_process(Pid) -> + _pipe = process, + _pipe@1 = erlang:monitor(_pipe, Pid), + {process_monitor, _pipe@1}. + +-spec selecting_process_down( + selector(HBH), + process_monitor(), + fun((process_down()) -> HBH) +) -> selector(HBH). +selecting_process_down(Selector, Monitor, Mapping) -> + gleam_erlang_ffi:insert_selector_handler( + Selector, + erlang:element(2, Monitor), + Mapping + ). + +-spec demonitor_process(process_monitor()) -> nil. +demonitor_process(Monitor) -> + gleam_erlang_ffi:demonitor(Monitor). + +-spec try_call(subject(HBK), fun((subject(HBM)) -> HBK), integer()) -> {ok, HBM} | + {error, call_error(HBM)}. +try_call(Subject, Make_request, Timeout) -> + Reply_subject = new_subject(), + Monitor = monitor_process(subject_owner(Subject)), + send(Subject, Make_request(Reply_subject)), + Result = begin + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = selecting( + _pipe, + Reply_subject, + fun(Field@0) -> {ok, Field@0} end + ), + _pipe@2 = selecting_process_down( + _pipe@1, + Monitor, + fun(Down) -> {error, {callee_down, erlang:element(3, Down)}} end + ), + gleam_erlang_ffi:select(_pipe@2, Timeout) + end, + gleam_erlang_ffi:demonitor(Monitor), + case Result of + {error, nil} -> + {error, call_timeout}; + + {ok, Res} -> + Res + end. + +-spec call(subject(HBR), fun((subject(HBT)) -> HBR), integer()) -> HBT. +call(Subject, Make_request, Timeout) -> + _assert_subject = try_call(Subject, Make_request, Timeout), + {ok, Resp} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam/erlang/process"/utf8>>, + function => <<"call"/utf8>>, + line => 593}) + end, + Resp. + +-spec link(pid_()) -> boolean(). +link(Pid) -> + gleam_erlang_ffi:link(Pid). + +-spec unlink(pid_()) -> nil. +unlink(Pid) -> + erlang:unlink(Pid), + nil. + +-spec send_after(subject(HBW), integer(), HBW) -> timer(). +send_after(Subject, Delay, Message) -> + erlang:send_after( + Delay, + erlang:element(2, Subject), + {erlang:element(3, Subject), Message} + ). + +-spec cancel_timer(timer()) -> cancelled(). +cancel_timer(Timer) -> + case gleam@dynamic:int(erlang:cancel_timer(Timer)) of + {ok, I} -> + {cancelled, I}; + + {error, _} -> + timer_not_found + end. + +-spec kill(pid_()) -> nil. +kill(Pid) -> + erlang:exit(Pid, kill), + nil. + +-spec send_exit(pid_()) -> nil. +send_exit(Pid) -> + erlang:exit(Pid, normal), + nil. + +-spec send_abnormal_exit(pid_(), binary()) -> nil. +send_abnormal_exit(Pid, Reason) -> + erlang:exit(Pid, {abnormal, Reason}), + nil. + +-spec trap_exits(boolean()) -> nil. +trap_exits(A) -> + gleam_erlang_ffi:trap_exits(A). + +-spec register(pid_(), gleam@erlang@atom:atom_()) -> {ok, nil} | {error, nil}. +register(Pid, Name) -> + gleam_erlang_ffi:register_process(Pid, Name). + +-spec unregister(gleam@erlang@atom:atom_()) -> {ok, nil} | {error, nil}. +unregister(Name) -> + gleam_erlang_ffi:unregister_process(Name). + +-spec named(gleam@erlang@atom:atom_()) -> {ok, pid_()} | {error, nil}. +named(Name) -> + gleam_erlang_ffi:process_named(Name). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam_erlang_ffi.erl b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam_erlang_ffi.erl new file mode 100644 index 0000000..872126f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam_erlang_ffi.erl @@ -0,0 +1,263 @@ +-module(gleam_erlang_ffi). +-export([ + atom_from_dynamic/1, rescue/1, atom_from_string/1, get_line/1, + ensure_all_started/1, sleep/1, os_family/0, sleep_forever/0, read_file/1, + append_file/2, write_file/2, delete_file/1, get_all_env/0, get_env/1, + set_env/2, unset_env/1, delete_directory/1, recursive_delete/1, + list_directory/1, demonitor/1, make_directory/1, new_selector/0, link/1, + insert_selector_handler/3, select/1, select/2, trap_exits/1, map_selector/2, + merge_selector/2, flush_messages/0, file_info/1, link_info/1, + priv_directory/1, connect_node/1, register_process/2, unregister_process/1, + process_named/1, identity/1 +]). + +-define(is_posix_error(Error), + Error =:= eacces orelse Error =:= eagain orelse Error =:= ebadf orelse + Error =:= ebadmsg orelse Error =:= ebusy orelse Error =:= edeadlk orelse + Error =:= edeadlock orelse Error =:= edquot orelse Error =:= eexist orelse + Error =:= efault orelse Error =:= efbig orelse Error =:= eftype orelse + Error =:= eintr orelse Error =:= einval orelse Error =:= eio orelse + Error =:= eisdir orelse Error =:= eloop orelse Error =:= emfile orelse + Error =:= emlink orelse Error =:= emultihop orelse Error =:= enametoolong orelse + Error =:= enfile orelse Error =:= enobufs orelse Error =:= enodev orelse + Error =:= enolck orelse Error =:= enolink orelse Error =:= enoent orelse + Error =:= enomem orelse Error =:= enospc orelse Error =:= enosr orelse + Error =:= enostr orelse Error =:= enosys orelse Error =:= enotblk orelse + Error =:= enotdir orelse Error =:= enotsup orelse Error =:= enxio orelse + Error =:= eopnotsupp orelse Error =:= eoverflow orelse Error =:= eperm orelse + Error =:= epipe orelse Error =:= erange orelse Error =:= erofs orelse + Error =:= espipe orelse Error =:= esrch orelse Error =:= estale orelse + Error =:= etxtbsy orelse Error =:= exdev +). + +-spec atom_from_string(binary()) -> {ok, atom()} | {error, atom_not_loaded}. +atom_from_string(S) -> + try {ok, binary_to_existing_atom(S)} + catch error:badarg -> {error, atom_not_loaded} + end. + +atom_from_dynamic(Data) when is_atom(Data) -> + {ok, Data}; +atom_from_dynamic(Data) -> + {error, [{decode_error, <<"Atom">>, gleam@dynamic:classify(Data), []}]}. + +-spec get_line(io:prompt()) -> {ok, unicode:unicode_binary()} | {error, eof | no_data}. +get_line(Prompt) -> + case io:get_line(Prompt) of + eof -> {error, eof}; + {error, _} -> {error, no_data}; + Data when is_binary(Data) -> {ok, Data}; + Data when is_list(Data) -> {ok, unicode:characters_to_binary(Data)} + end. + +rescue(F) -> + try {ok, F()} + catch + throw:X -> {error, {thrown, X}}; + error:X -> {error, {errored, X}}; + exit:X -> {error, {exited, X}} + end. + +ensure_all_started(Application) -> + case application:ensure_all_started(Application) of + {ok, _} = Ok -> Ok; + + {error, {ProblemApp, {"no such file or directory", _}}} -> + {error, {unknown_application, ProblemApp}} + end. + +sleep(Microseconds) -> + timer:sleep(Microseconds), + nil. + +sleep_forever() -> + timer:sleep(infinity), + nil. + +file_info_result(Result) -> + case Result of + {ok, {file_info, Size, Type, Access, Atime, Mtime, Ctime, Mode, Links, MajorDevice, MinorDevice, Inode, Uid, Gid}} when Access =:= none -> + {ok, {file_info, Size, Type, no_access, Atime, Mtime, Ctime, Mode, Links, MajorDevice, MinorDevice, Inode, Uid, Gid}}; + {ok, _} -> + Result; + {error, Reason} when ?is_posix_error(Reason) -> + Result + end. + +file_info(Filename) -> + file_info_result(file:read_file_info(Filename, [{time, posix}])). + +link_info(Filename) -> + file_info_result(file:read_link_info(Filename, [{time, posix}])). + +posix_result(Result) -> + case Result of + ok -> {ok, nil}; + {ok, Value} -> {ok, Value}; + {error, Reason} when ?is_posix_error(Reason) -> {error, Reason} + end. + +read_file(Filename) -> + posix_result(file:read_file(Filename)). + +write_file(Contents, Filename) -> + posix_result(file:write_file(Filename, Contents)). + +append_file(Contents, Filename) -> + posix_result(file:write_file(Filename, Contents, [append])). + +delete_file(Filename) -> + posix_result(file:delete(Filename)). + +make_directory(Dir) -> + posix_result(file:make_dir(Dir)). + +list_directory(Dir) -> + case file:list_dir(Dir) of + {ok, Filenames} -> + {ok, [list_to_binary(Filename) || Filename <- Filenames]}; + {error, Reason} when ?is_posix_error(Reason) -> + {error, Reason} + end. + +delete_directory(Dir) -> + posix_result(file:del_dir(Dir)). + +recursive_delete(Dir) -> + posix_result(file:del_dir_r(Dir)). + +get_all_env() -> + BinVars = lists:map(fun(VarString) -> + [VarName, VarVal] = string:split(VarString, "="), + {list_to_binary(VarName), list_to_binary(VarVal)} + end, os:getenv()), + maps:from_list(BinVars). + +get_env(Name) -> + case os:getenv(binary_to_list(Name)) of + false -> {error, nil}; + Value -> {ok, list_to_binary(Value)} + end. + +set_env(Name, Value) -> + os:putenv(binary_to_list(Name), binary_to_list(Value)), + nil. + +unset_env(Name) -> + os:unsetenv(binary_to_list(Name)), + nil. + +os_family() -> + case os:type() of + {win32, nt} -> + windows_nt; + {unix, linux} -> + linux; + {unix, darwin} -> + darwin; + {unix, freebsd} -> + free_bsd; + {_, Other} -> + {other, atom_to_binary(Other, utf8)} + end. + +new_selector() -> + {selector, #{}}. + +map_selector({selector, Handlers}, Fn) -> + MappedHandlers = maps:map(fun(_Tag, Handler) -> + fun(Message) -> Fn(Handler(Message)) end + end, Handlers), + {selector, MappedHandlers}. + +merge_selector({selector, HandlersA}, {selector, HandlersB}) -> + {selector, maps:merge(HandlersA, HandlersB)}. + +insert_selector_handler({selector, Handlers}, Tag, Fn) -> + {selector, Handlers#{Tag => Fn}}. + +select(Selector) -> + {ok, Message} = select(Selector, infinity), + Message. + +select({selector, Handlers}, Timeout) -> + AnythingHandler = maps:get(anything, Handlers, undefined), + receive + % Monitored process down messages. + % This is special cased so we can selectively receive based on the + % reference as well as the record tag. + {'DOWN', Ref, process, Pid, Reason} when is_map_key(Ref, Handlers) -> + Fn = maps:get(Ref, Handlers), + {ok, Fn({process_down, Pid, Reason})}; + + Msg when is_map_key({element(1, Msg), tuple_size(Msg)}, Handlers) -> + Fn = maps:get({element(1, Msg), tuple_size(Msg)}, Handlers), + {ok, Fn(Msg)}; + + Msg when AnythingHandler =/= undefined -> + {ok, AnythingHandler(Msg)} + after Timeout -> + {error, nil} + end. + +demonitor({_, Reference}) -> + erlang:demonitor(Reference, [flush]). + +link(Pid) -> + try + erlang:link(Pid) + catch + error:_ -> false + end. + +trap_exits(ShouldTrap) -> + erlang:process_flag(trap_exit, ShouldTrap), + nil. + +flush_messages() -> + receive _Message -> flush_messages() + after 0 -> nil + end. + +priv_directory(Name) -> + try erlang:binary_to_existing_atom(Name) of + Atom -> + case code:priv_dir(Atom) of + {error, _} -> {error, nil}; + Path -> {ok, unicode:characters_to_binary(Path)} + end + catch + error:badarg -> {error, nil} + end. + +connect_node(Node) -> + case net_kernel:connect_node(Node) of + true -> {ok, Node}; + false -> {error, failed_to_connect}; + ignored -> {error, local_node_is_not_alive} + end. + +register_process(Pid, Name) -> + try + true = erlang:register(Name, Pid), + {ok, nil} + catch + error:badarg -> {error, nil} + end. + +unregister_process(Name) -> + try + true = erlang:unregister(Name), + {ok, nil} + catch + error:badarg -> {error, nil} + end. + +process_named(Name) -> + case erlang:whereis(Name) of + Pid when is_pid(Pid) -> {ok, Pid}; + _ -> {error, nil} + end. + +identity(X) -> + X. diff --git a/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang.beam b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang.beam Binary files differnew file mode 100644 index 0000000..9f714eb --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang.beam diff --git a/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@atom.beam b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@atom.beam Binary files differnew file mode 100644 index 0000000..a85b4fa --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@atom.beam diff --git a/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@charlist.beam b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@charlist.beam Binary files differnew file mode 100644 index 0000000..6d78db3 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@charlist.beam diff --git a/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@file.beam b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@file.beam Binary files differnew file mode 100644 index 0000000..7990b72 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@file.beam diff --git a/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@node.beam b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@node.beam Binary files differnew file mode 100644 index 0000000..d8ebb84 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@node.beam diff --git a/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@os.beam b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@os.beam Binary files differnew file mode 100644 index 0000000..40d121a --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@os.beam diff --git a/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@process.beam b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@process.beam Binary files differnew file mode 100644 index 0000000..8a73d73 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@process.beam diff --git a/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam_erlang.app b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam_erlang.app new file mode 100644 index 0000000..79950ab --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam_erlang.app @@ -0,0 +1,7 @@ +{application, gleam_erlang, [ + {vsn, "0.23.1"}, + {applications, [gleam_stdlib]}, + {description, "A Gleam library for working with Erlang"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam_erlang_ffi.beam b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam_erlang_ffi.beam Binary files differnew file mode 100644 index 0000000..965c70b --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam_erlang_ffi.beam diff --git a/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@file_FileInfo.hrl b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@file_FileInfo.hrl new file mode 100644 index 0000000..b38d11e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@file_FileInfo.hrl @@ -0,0 +1,15 @@ +-record(file_info, { + size :: integer(), + file_type :: gleam@erlang@file:file_type(), + access :: gleam@erlang@file:access(), + atime :: integer(), + mtime :: integer(), + ctime :: integer(), + mode :: integer(), + links :: integer(), + major_device :: integer(), + minor_device :: integer(), + inode :: integer(), + user_id :: integer(), + group_id :: integer() +}). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Abnormal.hrl b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Abnormal.hrl new file mode 100644 index 0000000..4cd0452 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Abnormal.hrl @@ -0,0 +1 @@ +-record(abnormal, {reason :: binary()}). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_CalleeDown.hrl b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_CalleeDown.hrl new file mode 100644 index 0000000..5dd5047 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_CalleeDown.hrl @@ -0,0 +1 @@ +-record(callee_down, {reason :: gleam@dynamic:dynamic_()}). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Cancelled.hrl b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Cancelled.hrl new file mode 100644 index 0000000..b82b49f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Cancelled.hrl @@ -0,0 +1 @@ +-record(cancelled, {time_remaining :: integer()}). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ExitMessage.hrl b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ExitMessage.hrl new file mode 100644 index 0000000..c476308 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ExitMessage.hrl @@ -0,0 +1,4 @@ +-record(exit_message, { + pid :: gleam@erlang@process:pid_(), + reason :: gleam@erlang@process:exit_reason() +}). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ProcessDown.hrl b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ProcessDown.hrl new file mode 100644 index 0000000..df0b6b7 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ProcessDown.hrl @@ -0,0 +1,4 @@ +-record(process_down, { + pid :: gleam@erlang@process:pid_(), + reason :: gleam@dynamic:dynamic_() +}). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ProcessMonitor.hrl b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ProcessMonitor.hrl new file mode 100644 index 0000000..ce552e2 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ProcessMonitor.hrl @@ -0,0 +1 @@ +-record(process_monitor, {tag :: gleam@erlang:reference_()}). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Subject.hrl b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Subject.hrl new file mode 100644 index 0000000..abc46b2 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Subject.hrl @@ -0,0 +1,4 @@ +-record(subject, { + owner :: gleam@erlang@process:pid_(), + tag :: gleam@erlang:reference_() +}). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang_ApplicationFailedToStart.hrl b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang_ApplicationFailedToStart.hrl new file mode 100644 index 0000000..52c9896 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang_ApplicationFailedToStart.hrl @@ -0,0 +1,4 @@ +-record(application_failed_to_start, { + name :: gleam@erlang@atom:atom_(), + reason :: gleam@dynamic:dynamic_() +}). diff --git a/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang_UnknownApplication.hrl b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang_UnknownApplication.hrl new file mode 100644 index 0000000..fde3c61 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang_UnknownApplication.hrl @@ -0,0 +1 @@ +-record(unknown_application, {name :: gleam@erlang@atom:atom_()}). diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.cache b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.cache Binary files differnew file mode 100644 index 0000000..5bba9de --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.cache diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.cache_meta b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.cache_meta Binary files differnew file mode 100644 index 0000000..dc85da7 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.erl b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.erl new file mode 100644 index 0000000..ebc8768 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.erl @@ -0,0 +1,626 @@ +-module(gleam@http). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([parse_method/1, method_to_string/1, scheme_to_string/1, scheme_from_string/1, parse_content_disposition/1, parse_multipart_body/2, method_from_dynamic/1, parse_multipart_headers/2]). +-export_type([method/0, scheme/0, multipart_headers/0, multipart_body/0, content_disposition/0]). + +-type method() :: get | + post | + head | + put | + delete | + trace | + connect | + options | + patch | + {other, binary()}. + +-type scheme() :: http | https. + +-type multipart_headers() :: {multipart_headers, + list({binary(), binary()}), + bitstring()} | + {more_required_for_headers, + fun((bitstring()) -> {ok, multipart_headers()} | {error, nil})}. + +-type multipart_body() :: {multipart_body, bitstring(), boolean(), bitstring()} | + {more_required_for_body, + bitstring(), + fun((bitstring()) -> {ok, multipart_body()} | {error, nil})}. + +-type content_disposition() :: {content_disposition, + binary(), + list({binary(), binary()})}. + +-spec parse_method(binary()) -> {ok, method()} | {error, nil}. +parse_method(S) -> + case gleam@string:lowercase(S) of + <<"connect"/utf8>> -> + {ok, connect}; + + <<"delete"/utf8>> -> + {ok, delete}; + + <<"get"/utf8>> -> + {ok, get}; + + <<"head"/utf8>> -> + {ok, head}; + + <<"options"/utf8>> -> + {ok, options}; + + <<"patch"/utf8>> -> + {ok, patch}; + + <<"post"/utf8>> -> + {ok, post}; + + <<"put"/utf8>> -> + {ok, put}; + + <<"trace"/utf8>> -> + {ok, trace}; + + _ -> + {error, nil} + end. + +-spec method_to_string(method()) -> binary(). +method_to_string(Method) -> + case Method of + connect -> + <<"connect"/utf8>>; + + delete -> + <<"delete"/utf8>>; + + get -> + <<"get"/utf8>>; + + head -> + <<"head"/utf8>>; + + options -> + <<"options"/utf8>>; + + patch -> + <<"patch"/utf8>>; + + post -> + <<"post"/utf8>>; + + put -> + <<"put"/utf8>>; + + trace -> + <<"trace"/utf8>>; + + {other, S} -> + S + end. + +-spec scheme_to_string(scheme()) -> binary(). +scheme_to_string(Scheme) -> + case Scheme of + http -> + <<"http"/utf8>>; + + https -> + <<"https"/utf8>> + end. + +-spec scheme_from_string(binary()) -> {ok, scheme()} | {error, nil}. +scheme_from_string(Scheme) -> + case gleam@string:lowercase(Scheme) of + <<"http"/utf8>> -> + {ok, http}; + + <<"https"/utf8>> -> + {ok, https}; + + _ -> + {error, nil} + end. + +-spec skip_whitespace(bitstring()) -> bitstring(). +skip_whitespace(Data) -> + case Data of + <<32, Data@1/binary>> -> + skip_whitespace(Data@1); + + <<9, Data@1/binary>> -> + skip_whitespace(Data@1); + + _ -> + Data + end. + +-spec more_please_headers( + fun((bitstring()) -> {ok, multipart_headers()} | {error, nil}), + bitstring() +) -> {ok, multipart_headers()} | {error, nil}. +more_please_headers(Continuation, Existing) -> + {ok, + {more_required_for_headers, + fun(More) -> + gleam@bool:guard( + More =:= <<>>, + {error, nil}, + fun() -> + Continuation(<<Existing/bitstring, More/bitstring>>) + end + ) + end}}. + +-spec parse_rfc_2045_parameter_quoted_value(binary(), binary(), binary()) -> {ok, + {{binary(), binary()}, binary()}} | + {error, nil}. +parse_rfc_2045_parameter_quoted_value(Header, Name, Value) -> + case gleam@string:pop_grapheme(Header) of + {error, nil} -> + {error, nil}; + + {ok, {<<"\""/utf8>>, Rest}} -> + {ok, {{Name, Value}, Rest}}; + + {ok, {<<"\\"/utf8>>, Rest@1}} -> + gleam@result:'try'( + gleam@string:pop_grapheme(Rest@1), + fun(_use0) -> + {Grapheme, Rest@2} = _use0, + parse_rfc_2045_parameter_quoted_value( + Rest@2, + Name, + <<Value/binary, Grapheme/binary>> + ) + end + ); + + {ok, {Grapheme@1, Rest@3}} -> + parse_rfc_2045_parameter_quoted_value( + Rest@3, + Name, + <<Value/binary, Grapheme@1/binary>> + ) + end. + +-spec parse_rfc_2045_parameter_unquoted_value(binary(), binary(), binary()) -> {{binary(), + binary()}, + binary()}. +parse_rfc_2045_parameter_unquoted_value(Header, Name, Value) -> + case gleam@string:pop_grapheme(Header) of + {error, nil} -> + {{Name, Value}, Header}; + + {ok, {<<";"/utf8>>, Rest}} -> + {{Name, Value}, Rest}; + + {ok, {<<" "/utf8>>, Rest}} -> + {{Name, Value}, Rest}; + + {ok, {<<"\t"/utf8>>, Rest}} -> + {{Name, Value}, Rest}; + + {ok, {Grapheme, Rest@1}} -> + parse_rfc_2045_parameter_unquoted_value( + Rest@1, + Name, + <<Value/binary, Grapheme/binary>> + ) + end. + +-spec parse_rfc_2045_parameter_value(binary(), binary()) -> {ok, + {{binary(), binary()}, binary()}} | + {error, nil}. +parse_rfc_2045_parameter_value(Header, Name) -> + case gleam@string:pop_grapheme(Header) of + {error, nil} -> + {error, nil}; + + {ok, {<<"\""/utf8>>, Rest}} -> + parse_rfc_2045_parameter_quoted_value(Rest, Name, <<""/utf8>>); + + {ok, {Grapheme, Rest@1}} -> + {ok, + parse_rfc_2045_parameter_unquoted_value(Rest@1, Name, Grapheme)} + end. + +-spec parse_rfc_2045_parameter(binary(), binary()) -> {ok, + {{binary(), binary()}, binary()}} | + {error, nil}. +parse_rfc_2045_parameter(Header, Name) -> + gleam@result:'try'( + gleam@string:pop_grapheme(Header), + fun(_use0) -> + {Grapheme, Rest} = _use0, + case Grapheme of + <<"="/utf8>> -> + parse_rfc_2045_parameter_value(Rest, Name); + + _ -> + parse_rfc_2045_parameter( + Rest, + <<Name/binary, + (gleam@string:lowercase(Grapheme))/binary>> + ) + end + end + ). + +-spec parse_rfc_2045_parameters(binary(), list({binary(), binary()})) -> {ok, + list({binary(), binary()})} | + {error, nil}. +parse_rfc_2045_parameters(Header, Parameters) -> + case gleam@string:pop_grapheme(Header) of + {error, nil} -> + {ok, gleam@list:reverse(Parameters)}; + + {ok, {<<";"/utf8>>, Rest}} -> + parse_rfc_2045_parameters(Rest, Parameters); + + {ok, {<<" "/utf8>>, Rest}} -> + parse_rfc_2045_parameters(Rest, Parameters); + + {ok, {<<"\t"/utf8>>, Rest}} -> + parse_rfc_2045_parameters(Rest, Parameters); + + {ok, {Grapheme, Rest@1}} -> + Acc = gleam@string:lowercase(Grapheme), + gleam@result:'try'( + parse_rfc_2045_parameter(Rest@1, Acc), + fun(_use0) -> + {Parameter, Rest@2} = _use0, + parse_rfc_2045_parameters(Rest@2, [Parameter | Parameters]) + end + ) + end. + +-spec parse_content_disposition_type(binary(), binary()) -> {ok, + content_disposition()} | + {error, nil}. +parse_content_disposition_type(Header, Name) -> + case gleam@string:pop_grapheme(Header) of + {error, nil} -> + {ok, {content_disposition, Name, []}}; + + {ok, {<<" "/utf8>>, Rest}} -> + Result = parse_rfc_2045_parameters(Rest, []), + gleam@result:map( + Result, + fun(Parameters) -> {content_disposition, Name, Parameters} end + ); + + {ok, {<<"\t"/utf8>>, Rest}} -> + Result = parse_rfc_2045_parameters(Rest, []), + gleam@result:map( + Result, + fun(Parameters) -> {content_disposition, Name, Parameters} end + ); + + {ok, {<<";"/utf8>>, Rest}} -> + Result = parse_rfc_2045_parameters(Rest, []), + gleam@result:map( + Result, + fun(Parameters) -> {content_disposition, Name, Parameters} end + ); + + {ok, {Grapheme, Rest@1}} -> + parse_content_disposition_type( + Rest@1, + <<Name/binary, (gleam@string:lowercase(Grapheme))/binary>> + ) + end. + +-spec parse_content_disposition(binary()) -> {ok, content_disposition()} | + {error, nil}. +parse_content_disposition(Header) -> + parse_content_disposition_type(Header, <<""/utf8>>). + +-spec more_please_body( + fun((bitstring()) -> {ok, multipart_body()} | {error, nil}), + bitstring(), + bitstring() +) -> {ok, multipart_body()} | {error, nil}. +more_please_body(Continuation, Chunk, Existing) -> + _pipe = fun(More) -> + gleam@bool:guard( + More =:= <<>>, + {error, nil}, + fun() -> Continuation(<<Existing/bitstring, More/bitstring>>) end + ) + end, + _pipe@1 = {more_required_for_body, Chunk, _pipe}, + {ok, _pipe@1}. + +-spec parse_body_loop(bitstring(), bitstring(), bitstring()) -> {ok, + multipart_body()} | + {error, nil}. +parse_body_loop(Data, Boundary, Body) -> + Dsize = erlang:byte_size(Data), + Bsize = erlang:byte_size(Boundary), + Required = 6 + Bsize, + case Data of + _ when Dsize < Required -> + more_please_body( + fun(_capture) -> parse_body_loop(_capture, Boundary, <<>>) end, + Body, + Data + ); + + <<13, 10, Data@1/binary>> -> + Desired = <<45, 45, Boundary/bitstring>>, + Size = erlang:byte_size(Desired), + Dsize@1 = erlang:byte_size(Data@1), + Prefix = gleam_stdlib:bit_array_slice(Data@1, 0, Size), + Rest = gleam_stdlib:bit_array_slice(Data@1, Size, Dsize@1 - Size), + case {Prefix =:= {ok, Desired}, Rest} of + {true, {ok, <<13, 10, _/binary>>}} -> + {ok, {multipart_body, Body, false, Data@1}}; + + {true, {ok, <<45, 45, Data@2/binary>>}} -> + {ok, {multipart_body, Body, true, Data@2}}; + + {false, _} -> + parse_body_loop( + Data@1, + Boundary, + <<Body/bitstring, 13, 10>> + ); + + {_, _} -> + {error, nil} + end; + + <<Char, Data@3/binary>> -> + parse_body_loop(Data@3, Boundary, <<Body/bitstring, Char>>) + end. + +-spec parse_body_with_bit_array(bitstring(), bitstring()) -> {ok, + multipart_body()} | + {error, nil}. +parse_body_with_bit_array(Data, Boundary) -> + Bsize = erlang:byte_size(Boundary), + Prefix = gleam_stdlib:bit_array_slice(Data, 0, 2 + Bsize), + case Prefix =:= {ok, <<45, 45, Boundary/bitstring>>} of + true -> + {ok, {multipart_body, <<>>, false, Data}}; + + false -> + parse_body_loop(Data, Boundary, <<>>) + end. + +-spec parse_multipart_body(bitstring(), binary()) -> {ok, multipart_body()} | + {error, nil}. +parse_multipart_body(Data, Boundary) -> + _pipe = Boundary, + _pipe@1 = gleam_stdlib:identity(_pipe), + parse_body_with_bit_array(Data, _pipe@1). + +-spec method_from_dynamic(gleam@dynamic:dynamic_()) -> {ok, method()} | + {error, list(gleam@dynamic:decode_error())}. +method_from_dynamic(Value) -> + case gleam_http_native:decode_method(Value) of + {ok, Method} -> + {ok, Method}; + + {error, _} -> + {error, + [{decode_error, + <<"HTTP method"/utf8>>, + gleam@dynamic:classify(Value), + []}]} + end. + +-spec parse_header_value( + bitstring(), + list({binary(), binary()}), + bitstring(), + bitstring() +) -> {ok, multipart_headers()} | {error, nil}. +parse_header_value(Data, Headers, Name, Value) -> + Size = erlang:byte_size(Data), + case Data of + _ when Size < 4 -> + _pipe@2 = fun(Data@1) -> _pipe = Data@1, + _pipe@1 = skip_whitespace(_pipe), + parse_header_value(_pipe@1, Headers, Name, Value) end, + more_please_headers(_pipe@2, Data); + + <<13, 10, 13, 10, Data@2/binary>> -> + gleam@result:'try'( + gleam@bit_array:to_string(Name), + fun(Name@1) -> + gleam@result:map( + gleam@bit_array:to_string(Value), + fun(Value@1) -> + Headers@1 = gleam@list:reverse( + [{gleam@string:lowercase(Name@1), Value@1} | + Headers] + ), + {multipart_headers, Headers@1, Data@2} + end + ) + end + ); + + <<13, 10, 32, Data@3/binary>> -> + parse_header_value(Data@3, Headers, Name, Value); + + <<13, 10, 9, Data@3/binary>> -> + parse_header_value(Data@3, Headers, Name, Value); + + <<13, 10, Data@4/binary>> -> + gleam@result:'try'( + gleam@bit_array:to_string(Name), + fun(Name@2) -> + gleam@result:'try'( + gleam@bit_array:to_string(Value), + fun(Value@2) -> + Headers@2 = [{gleam@string:lowercase(Name@2), + Value@2} | + Headers], + parse_header_name(Data@4, Headers@2, <<>>) + end + ) + end + ); + + <<Char, Rest/binary>> -> + Value@3 = <<Value/bitstring, Char>>, + parse_header_value(Rest, Headers, Name, Value@3); + + _ -> + {error, nil} + end. + +-spec parse_header_name(bitstring(), list({binary(), binary()}), bitstring()) -> {ok, + multipart_headers()} | + {error, nil}. +parse_header_name(Data, Headers, Name) -> + case skip_whitespace(Data) of + <<58, Data@1/binary>> -> + _pipe = Data@1, + _pipe@1 = skip_whitespace(_pipe), + parse_header_value(_pipe@1, Headers, Name, <<>>); + + <<Char, Data@2/binary>> -> + parse_header_name(Data@2, Headers, <<Name/bitstring, Char>>); + + <<>> -> + more_please_headers( + fun(_capture) -> parse_header_name(_capture, Headers, Name) end, + Data + ) + end. + +-spec do_parse_headers(bitstring()) -> {ok, multipart_headers()} | {error, nil}. +do_parse_headers(Data) -> + case Data of + <<13, 10, 13, 10, Data@1/binary>> -> + {ok, {multipart_headers, [], Data@1}}; + + <<13, 10, Data@2/binary>> -> + parse_header_name(Data@2, [], <<>>); + + <<13>> -> + more_please_headers(fun do_parse_headers/1, Data); + + <<>> -> + more_please_headers(fun do_parse_headers/1, Data); + + _ -> + {error, nil} + end. + +-spec parse_headers_after_prelude(bitstring(), bitstring()) -> {ok, + multipart_headers()} | + {error, nil}. +parse_headers_after_prelude(Data, Boundary) -> + Dsize = erlang:byte_size(Data), + Bsize = erlang:byte_size(Boundary), + Required_size = Bsize + 4, + gleam@bool:guard( + Dsize < Required_size, + more_please_headers( + fun(_capture) -> parse_headers_after_prelude(_capture, Boundary) end, + Data + ), + fun() -> + gleam@result:'try'( + gleam_stdlib:bit_array_slice(Data, 0, Required_size - 2), + fun(Prefix) -> + gleam@result:'try'( + gleam_stdlib:bit_array_slice(Data, 2 + Bsize, 2), + fun(Second) -> + Desired = <<45, 45, Boundary/bitstring>>, + gleam@bool:guard( + Prefix /= Desired, + {error, nil}, + fun() -> case Second =:= <<45, 45>> of + true -> + Rest_size = Dsize - Required_size, + gleam@result:map( + gleam_stdlib:bit_array_slice( + Data, + Required_size, + Rest_size + ), + fun(Data@1) -> + {multipart_headers, + [], + Data@1} + end + ); + + false -> + Start = Required_size - 2, + Rest_size@1 = (Dsize - Required_size) + + 2, + gleam@result:'try'( + gleam_stdlib:bit_array_slice( + Data, + Start, + Rest_size@1 + ), + fun(Data@2) -> + do_parse_headers(Data@2) + end + ) + end end + ) + end + ) + end + ) + end + ). + +-spec skip_preamble(bitstring(), bitstring()) -> {ok, multipart_headers()} | + {error, nil}. +skip_preamble(Data, Boundary) -> + Data_size = erlang:byte_size(Data), + Boundary_size = erlang:byte_size(Boundary), + Required = Boundary_size + 4, + case Data of + _ when Data_size < Required -> + more_please_headers( + fun(_capture) -> skip_preamble(_capture, Boundary) end, + Data + ); + + <<13, 10, 45, 45, Data@1/binary>> -> + case gleam_stdlib:bit_array_slice(Data@1, 0, Boundary_size) of + {ok, Prefix} when Prefix =:= Boundary -> + Start = Boundary_size, + Length = erlang:byte_size(Data@1) - Boundary_size, + gleam@result:'try'( + gleam_stdlib:bit_array_slice(Data@1, Start, Length), + fun(Rest) -> do_parse_headers(Rest) end + ); + + {ok, _} -> + skip_preamble(Data@1, Boundary); + + {error, _} -> + {error, nil} + end; + + <<_, Data@2/binary>> -> + skip_preamble(Data@2, Boundary) + end. + +-spec parse_multipart_headers(bitstring(), binary()) -> {ok, + multipart_headers()} | + {error, nil}. +parse_multipart_headers(Data, Boundary) -> + Boundary@1 = gleam_stdlib:identity(Boundary), + Prefix = <<45, 45, Boundary@1/bitstring>>, + case gleam_stdlib:bit_array_slice(Data, 0, erlang:byte_size(Prefix)) =:= {ok, + Prefix} of + true -> + parse_headers_after_prelude(Data, Boundary@1); + + false -> + skip_preamble(Data, Boundary@1) + end. diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.cache b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.cache Binary files differnew file mode 100644 index 0000000..db0066c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.cache diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.cache_meta b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.cache_meta Binary files differnew file mode 100644 index 0000000..1f65dce --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.erl b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.erl new file mode 100644 index 0000000..46ee47f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.erl @@ -0,0 +1,153 @@ +-module(gleam@http@cookie). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([defaults/1, parse/1, set_header/3]). +-export_type([same_site_policy/0, attributes/0]). + +-type same_site_policy() :: lax | strict | none. + +-type attributes() :: {attributes, + gleam@option:option(integer()), + gleam@option:option(binary()), + gleam@option:option(binary()), + boolean(), + boolean(), + gleam@option:option(same_site_policy())}. + +-spec same_site_to_string(same_site_policy()) -> binary(). +same_site_to_string(Policy) -> + case Policy of + lax -> + <<"Lax"/utf8>>; + + strict -> + <<"Strict"/utf8>>; + + none -> + <<"None"/utf8>> + end. + +-spec defaults(gleam@http:scheme()) -> attributes(). +defaults(Scheme) -> + {attributes, + none, + none, + {some, <<"/"/utf8>>}, + Scheme =:= https, + true, + {some, lax}}. + +-spec check_token(binary()) -> {ok, nil} | {error, nil}. +check_token(Token) -> + case gleam@string:pop_grapheme(Token) of + {error, nil} -> + {ok, nil}; + + {ok, {<<" "/utf8>>, _}} -> + {error, nil}; + + {ok, {<<"\t"/utf8>>, _}} -> + {error, nil}; + + {ok, {<<"\r"/utf8>>, _}} -> + {error, nil}; + + {ok, {<<"\n"/utf8>>, _}} -> + {error, nil}; + + {ok, {<<"\f"/utf8>>, _}} -> + {error, nil}; + + {ok, {_, Rest}} -> + check_token(Rest) + end. + +-spec parse(binary()) -> list({binary(), binary()}). +parse(Cookie_string) -> + _assert_subject = gleam@regex:from_string(<<"[,;]"/utf8>>), + {ok, Re} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam/http/cookie"/utf8>>, + function => <<"parse"/utf8>>, + line => 101}) + end, + _pipe = gleam@regex:split(Re, Cookie_string), + gleam@list:filter_map( + _pipe, + fun(Pair) -> + case gleam@string:split_once(gleam@string:trim(Pair), <<"="/utf8>>) of + {ok, {<<""/utf8>>, _}} -> + {error, nil}; + + {ok, {Key, Value}} -> + Key@1 = gleam@string:trim(Key), + Value@1 = gleam@string:trim(Value), + gleam@result:then( + check_token(Key@1), + fun(_) -> + gleam@result:then( + check_token(Value@1), + fun(_) -> {ok, {Key@1, Value@1}} end + ) + end + ); + + {error, nil} -> + {error, nil} + end + end + ). + +-spec cookie_attributes_to_list(attributes()) -> list(list(binary())). +cookie_attributes_to_list(Attributes) -> + {attributes, Max_age, Domain, Path, Secure, Http_only, Same_site} = Attributes, + _pipe = [case Max_age of + {some, 0} -> + {some, [<<"Expires=Thu, 01 Jan 1970 00:00:00 GMT"/utf8>>]}; + + _ -> + none + end, gleam@option:map( + Max_age, + fun(Max_age@1) -> + [<<"Max-Age="/utf8>>, gleam@int:to_string(Max_age@1)] + end + ), gleam@option:map( + Domain, + fun(Domain@1) -> [<<"Domain="/utf8>>, Domain@1] end + ), gleam@option:map(Path, fun(Path@1) -> [<<"Path="/utf8>>, Path@1] end), case Secure of + true -> + {some, [<<"Secure"/utf8>>]}; + + false -> + none + end, case Http_only of + true -> + {some, [<<"HttpOnly"/utf8>>]}; + + false -> + none + end, gleam@option:map( + Same_site, + fun(Same_site@1) -> + [<<"SameSite="/utf8>>, same_site_to_string(Same_site@1)] + end + )], + gleam@list:filter_map( + _pipe, + fun(_capture) -> gleam@option:to_result(_capture, nil) end + ). + +-spec set_header(binary(), binary(), attributes()) -> binary(). +set_header(Name, Value, Attributes) -> + _pipe = [[Name, <<"="/utf8>>, Value] | + cookie_attributes_to_list(Attributes)], + _pipe@1 = gleam@list:map( + _pipe, + fun(_capture) -> gleam@string:join(_capture, <<""/utf8>>) end + ), + gleam@string:join(_pipe@1, <<"; "/utf8>>). diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.cache b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.cache Binary files differnew file mode 100644 index 0000000..ea0a2f6 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.cache diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.cache_meta b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.cache_meta Binary files differnew file mode 100644 index 0000000..2108b82 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.erl b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.erl new file mode 100644 index 0000000..50e6d31 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.erl @@ -0,0 +1,202 @@ +-module(gleam@http@request). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([to_uri/1, from_uri/1, get_header/2, set_header/3, prepend_header/3, set_body/2, map/2, path_segments/1, get_query/1, set_query/2, set_method/2, new/0, to/1, set_scheme/2, set_host/2, set_port/2, set_path/2, set_cookie/3, get_cookies/1]). +-export_type([request/1]). + +-type request(GHJ) :: {request, + gleam@http:method(), + list({binary(), binary()}), + GHJ, + gleam@http:scheme(), + binary(), + gleam@option:option(integer()), + binary(), + gleam@option:option(binary())}. + +-spec to_uri(request(any())) -> gleam@uri:uri(). +to_uri(Request) -> + {uri, + {some, gleam@http:scheme_to_string(erlang:element(5, Request))}, + none, + {some, erlang:element(6, Request)}, + erlang:element(7, Request), + erlang:element(8, Request), + erlang:element(9, Request), + none}. + +-spec from_uri(gleam@uri:uri()) -> {ok, request(binary())} | {error, nil}. +from_uri(Uri) -> + gleam@result:then( + begin + _pipe = erlang:element(2, Uri), + _pipe@1 = gleam@option:unwrap(_pipe, <<""/utf8>>), + gleam@http:scheme_from_string(_pipe@1) + end, + fun(Scheme) -> + gleam@result:then( + begin + _pipe@2 = erlang:element(4, Uri), + gleam@option:to_result(_pipe@2, nil) + end, + fun(Host) -> + Req = {request, + get, + [], + <<""/utf8>>, + Scheme, + Host, + erlang:element(5, Uri), + erlang:element(6, Uri), + erlang:element(7, Uri)}, + {ok, Req} + end + ) + end + ). + +-spec get_header(request(any()), binary()) -> {ok, binary()} | {error, nil}. +get_header(Request, Key) -> + gleam@list:key_find(erlang:element(3, Request), gleam@string:lowercase(Key)). + +-spec set_header(request(GHT), binary(), binary()) -> request(GHT). +set_header(Request, Key, Value) -> + Headers = gleam@list:key_set( + erlang:element(3, Request), + gleam@string:lowercase(Key), + Value + ), + erlang:setelement(3, Request, Headers). + +-spec prepend_header(request(GHW), binary(), binary()) -> request(GHW). +prepend_header(Request, Key, Value) -> + Headers = [{gleam@string:lowercase(Key), Value} | + erlang:element(3, Request)], + erlang:setelement(3, Request, Headers). + +-spec set_body(request(any()), GIB) -> request(GIB). +set_body(Req, Body) -> + {request, Method, Headers, _, Scheme, Host, Port, Path, Query} = Req, + {request, Method, Headers, Body, Scheme, Host, Port, Path, Query}. + +-spec map(request(GID), fun((GID) -> GIF)) -> request(GIF). +map(Request, Transform) -> + _pipe = erlang:element(4, Request), + _pipe@1 = Transform(_pipe), + set_body(Request, _pipe@1). + +-spec path_segments(request(any())) -> list(binary()). +path_segments(Request) -> + _pipe = erlang:element(8, Request), + gleam@uri:path_segments(_pipe). + +-spec get_query(request(any())) -> {ok, list({binary(), binary()})} | + {error, nil}. +get_query(Request) -> + case erlang:element(9, Request) of + {some, Query_string} -> + gleam@uri:parse_query(Query_string); + + none -> + {ok, []} + end. + +-spec set_query(request(GIP), list({binary(), binary()})) -> request(GIP). +set_query(Req, Query) -> + Pair = fun(T) -> + gleam@string_builder:from_strings( + [erlang:element(1, T), <<"="/utf8>>, erlang:element(2, T)] + ) + end, + Query@1 = begin + _pipe = Query, + _pipe@1 = gleam@list:map(_pipe, Pair), + _pipe@2 = gleam@list:intersperse( + _pipe@1, + gleam@string_builder:from_string(<<"&"/utf8>>) + ), + _pipe@3 = gleam@string_builder:concat(_pipe@2), + _pipe@4 = gleam@string_builder:to_string(_pipe@3), + {some, _pipe@4} + end, + erlang:setelement(9, Req, Query@1). + +-spec set_method(request(GIT), gleam@http:method()) -> request(GIT). +set_method(Req, Method) -> + erlang:setelement(2, Req, Method). + +-spec new() -> request(binary()). +new() -> + {request, + get, + [], + <<""/utf8>>, + https, + <<"localhost"/utf8>>, + none, + <<""/utf8>>, + none}. + +-spec to(binary()) -> {ok, request(binary())} | {error, nil}. +to(Url) -> + _pipe = Url, + _pipe@1 = gleam@uri:parse(_pipe), + gleam@result:then(_pipe@1, fun from_uri/1). + +-spec set_scheme(request(GJA), gleam@http:scheme()) -> request(GJA). +set_scheme(Req, Scheme) -> + erlang:setelement(5, Req, Scheme). + +-spec set_host(request(GJD), binary()) -> request(GJD). +set_host(Req, Host) -> + erlang:setelement(6, Req, Host). + +-spec set_port(request(GJG), integer()) -> request(GJG). +set_port(Req, Port) -> + erlang:setelement(7, Req, {some, Port}). + +-spec set_path(request(GJJ), binary()) -> request(GJJ). +set_path(Req, Path) -> + erlang:setelement(8, Req, Path). + +-spec set_cookie(request(GJM), binary(), binary()) -> request(GJM). +set_cookie(Req, Name, Value) -> + New_cookie_string = gleam@string:join([Name, Value], <<"="/utf8>>), + {Cookies_string@2, Headers@1} = case gleam@list:key_pop( + erlang:element(3, Req), + <<"cookie"/utf8>> + ) of + {ok, {Cookies_string, Headers}} -> + Cookies_string@1 = gleam@string:join( + [Cookies_string, New_cookie_string], + <<"; "/utf8>> + ), + {Cookies_string@1, Headers}; + + {error, nil} -> + {New_cookie_string, erlang:element(3, Req)} + end, + erlang:setelement( + 3, + Req, + [{<<"cookie"/utf8>>, Cookies_string@2} | Headers@1] + ). + +-spec get_cookies(request(any())) -> list({binary(), binary()}). +get_cookies(Req) -> + {request, _, Headers, _, _, _, _, _, _} = Req, + _pipe = Headers, + _pipe@1 = gleam@list:filter_map( + _pipe, + fun(Header) -> + {Name, Value} = Header, + case Name of + <<"cookie"/utf8>> -> + {ok, gleam@http@cookie:parse(Value)}; + + _ -> + {error, nil} + end + end + ), + gleam@list:flatten(_pipe@1). diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.cache b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.cache Binary files differnew file mode 100644 index 0000000..70474f1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.cache diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.cache_meta b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.cache_meta Binary files differnew file mode 100644 index 0000000..1f05041 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.erl b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.erl new file mode 100644 index 0000000..27849e7 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.erl @@ -0,0 +1,97 @@ +-module(gleam@http@response). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([new/1, get_header/2, set_header/3, prepend_header/3, set_body/2, try_map/2, map/2, redirect/1, get_cookies/1, set_cookie/4, expire_cookie/3]). +-export_type([response/1]). + +-type response(GON) :: {response, integer(), list({binary(), binary()}), GON}. + +-spec new(integer()) -> response(binary()). +new(Status) -> + {response, Status, [], <<""/utf8>>}. + +-spec get_header(response(any()), binary()) -> {ok, binary()} | {error, nil}. +get_header(Response, Key) -> + gleam@list:key_find( + erlang:element(3, Response), + gleam@string:lowercase(Key) + ). + +-spec set_header(response(GPC), binary(), binary()) -> response(GPC). +set_header(Response, Key, Value) -> + Headers = gleam@list:key_set( + erlang:element(3, Response), + gleam@string:lowercase(Key), + Value + ), + erlang:setelement(3, Response, Headers). + +-spec prepend_header(response(GPF), binary(), binary()) -> response(GPF). +prepend_header(Response, Key, Value) -> + Headers = [{gleam@string:lowercase(Key), Value} | + erlang:element(3, Response)], + erlang:setelement(3, Response, Headers). + +-spec set_body(response(any()), GPK) -> response(GPK). +set_body(Response, Body) -> + {response, Status, Headers, _} = Response, + {response, Status, Headers, Body}. + +-spec try_map(response(GOO), fun((GOO) -> {ok, GOQ} | {error, GOR})) -> {ok, + response(GOQ)} | + {error, GOR}. +try_map(Response, Transform) -> + gleam@result:then( + Transform(erlang:element(4, Response)), + fun(Body) -> {ok, set_body(Response, Body)} end + ). + +-spec map(response(GPM), fun((GPM) -> GPO)) -> response(GPO). +map(Response, Transform) -> + _pipe = erlang:element(4, Response), + _pipe@1 = Transform(_pipe), + set_body(Response, _pipe@1). + +-spec redirect(binary()) -> response(binary()). +redirect(Uri) -> + {response, + 303, + [{<<"location"/utf8>>, Uri}], + gleam@string:append(<<"You are being redirected to "/utf8>>, Uri)}. + +-spec get_cookies(response(any())) -> list({binary(), binary()}). +get_cookies(Resp) -> + {response, _, Headers, _} = Resp, + _pipe = Headers, + _pipe@1 = gleam@list:filter_map( + _pipe, + fun(Header) -> + {Name, Value} = Header, + case Name of + <<"set-cookie"/utf8>> -> + {ok, gleam@http@cookie:parse(Value)}; + + _ -> + {error, nil} + end + end + ), + gleam@list:flatten(_pipe@1). + +-spec set_cookie( + response(GPT), + binary(), + binary(), + gleam@http@cookie:attributes() +) -> response(GPT). +set_cookie(Response, Name, Value, Attributes) -> + prepend_header( + Response, + <<"set-cookie"/utf8>>, + gleam@http@cookie:set_header(Name, Value, Attributes) + ). + +-spec expire_cookie(response(GPW), binary(), gleam@http@cookie:attributes()) -> response(GPW). +expire_cookie(Response, Name, Attributes) -> + Attrs = erlang:setelement(2, Attributes, {some, 0}), + set_cookie(Response, Name, <<""/utf8>>, Attrs). diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.cache b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.cache Binary files differnew file mode 100644 index 0000000..3c1fcc1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.cache diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.cache_meta b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.cache_meta Binary files differnew file mode 100644 index 0000000..c0222d6 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.erl b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.erl new file mode 100644 index 0000000..3b4a425 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.erl @@ -0,0 +1,82 @@ +-module(gleam@http@service). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([map_response_body/2, prepend_response_header/3, method_override/1]). + +-spec map_response_body( + fun((gleam@http@request:request(GSL)) -> gleam@http@response:response(GSM)), + fun((GSM) -> GSP) +) -> fun((gleam@http@request:request(GSL)) -> gleam@http@response:response(GSP)). +map_response_body(Service, Mapper) -> + fun(Req) -> _pipe = Req, + _pipe@1 = Service(_pipe), + gleam@http@response:map(_pipe@1, Mapper) end. + +-spec prepend_response_header( + fun((gleam@http@request:request(GSS)) -> gleam@http@response:response(GST)), + binary(), + binary() +) -> fun((gleam@http@request:request(GSS)) -> gleam@http@response:response(GST)). +prepend_response_header(Service, Key, Value) -> + fun(Req) -> _pipe = Req, + _pipe@1 = Service(_pipe), + gleam@http@response:prepend_header(_pipe@1, Key, Value) end. + +-spec ensure_post(gleam@http@request:request(GSY)) -> {ok, + gleam@http@request:request(GSY)} | + {error, nil}. +ensure_post(Req) -> + case erlang:element(2, Req) of + post -> + {ok, Req}; + + _ -> + {error, nil} + end. + +-spec get_override_method(gleam@http@request:request(any())) -> {ok, + gleam@http:method()} | + {error, nil}. +get_override_method(Request) -> + gleam@result:then( + gleam@http@request:get_query(Request), + fun(Query_params) -> + gleam@result:then( + gleam@list:key_find(Query_params, <<"_method"/utf8>>), + fun(Method) -> + gleam@result:then( + gleam@http:parse_method(Method), + fun(Method@1) -> case Method@1 of + put -> + {ok, Method@1}; + + patch -> + {ok, Method@1}; + + delete -> + {ok, Method@1}; + + _ -> + {error, nil} + end end + ) + end + ) + end + ). + +-spec method_override( + fun((gleam@http@request:request(GTF)) -> gleam@http@response:response(GTG)) +) -> fun((gleam@http@request:request(GTF)) -> gleam@http@response:response(GTG)). +method_override(Service) -> + fun(Request) -> _pipe = Request, + _pipe@1 = ensure_post(_pipe), + _pipe@2 = gleam@result:then(_pipe@1, fun get_override_method/1), + _pipe@3 = gleam@result:map( + _pipe@2, + fun(_capture) -> + gleam@http@request:set_method(Request, _capture) + end + ), + _pipe@4 = gleam@result:unwrap(_pipe@3, Request), + Service(_pipe@4) end. diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam_http_native.erl b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam_http_native.erl new file mode 100644 index 0000000..bb499bb --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam_http_native.erl @@ -0,0 +1,88 @@ +-module(gleam_http_native). +-export([decode_method/1]). + +decode_method(Term) -> + case Term of + "connect" -> {ok, connect}; + "delete" -> {ok, delete}; + "get" -> {ok, get}; + "head" -> {ok, head}; + "options" -> {ok, options}; + "patch" -> {ok, patch}; + "post" -> {ok, post}; + "put" -> {ok, put}; + "trace" -> {ok, trace}; + "CONNECT" -> {ok, connect}; + "DELETE" -> {ok, delete}; + "GET" -> {ok, get}; + "HEAD" -> {ok, head}; + "OPTIONS" -> {ok, options}; + "PATCH" -> {ok, patch}; + "POST" -> {ok, post}; + "PUT" -> {ok, put}; + "TRACE" -> {ok, trace}; + "Connect" -> {ok, connect}; + "Delete" -> {ok, delete}; + "Get" -> {ok, get}; + "Head" -> {ok, head}; + "Options" -> {ok, options}; + "Patch" -> {ok, patch}; + "Post" -> {ok, post}; + "Put" -> {ok, put}; + "Trace" -> {ok, trace}; + 'connect' -> {ok, connect}; + 'delete' -> {ok, delete}; + 'get' -> {ok, get}; + 'head' -> {ok, head}; + 'options' -> {ok, options}; + 'patch' -> {ok, patch}; + 'post' -> {ok, post}; + 'put' -> {ok, put}; + 'trace' -> {ok, trace}; + 'CONNECT' -> {ok, connect}; + 'DELETE' -> {ok, delete}; + 'GET' -> {ok, get}; + 'HEAD' -> {ok, head}; + 'OPTIONS' -> {ok, options}; + 'PATCH' -> {ok, patch}; + 'POST' -> {ok, post}; + 'PUT' -> {ok, put}; + 'TRACE' -> {ok, trace}; + 'Connect' -> {ok, connect}; + 'Delete' -> {ok, delete}; + 'Get' -> {ok, get}; + 'Head' -> {ok, head}; + 'Options' -> {ok, options}; + 'Patch' -> {ok, patch}; + 'Post' -> {ok, post}; + 'Put' -> {ok, put}; + 'Trace' -> {ok, trace}; + <<"connect">> -> {ok, connect}; + <<"delete">> -> {ok, delete}; + <<"get">> -> {ok, get}; + <<"head">> -> {ok, head}; + <<"options">> -> {ok, options}; + <<"patch">> -> {ok, patch}; + <<"post">> -> {ok, post}; + <<"put">> -> {ok, put}; + <<"trace">> -> {ok, trace}; + <<"CONNECT">> -> {ok, connect}; + <<"DELETE">> -> {ok, delete}; + <<"GET">> -> {ok, get}; + <<"HEAD">> -> {ok, head}; + <<"OPTIONS">> -> {ok, options}; + <<"PATCH">> -> {ok, patch}; + <<"POST">> -> {ok, post}; + <<"PUT">> -> {ok, put}; + <<"TRACE">> -> {ok, trace}; + <<"Connect">> -> {ok, connect}; + <<"Delete">> -> {ok, delete}; + <<"Get">> -> {ok, get}; + <<"Head">> -> {ok, head}; + <<"Options">> -> {ok, options}; + <<"Patch">> -> {ok, patch}; + <<"Post">> -> {ok, post}; + <<"Put">> -> {ok, put}; + <<"Trace">> -> {ok, trace}; + _ -> {error, nil} + end. diff --git a/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam_http_native.mjs b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam_http_native.mjs new file mode 100644 index 0000000..c871a8b --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam_http_native.mjs @@ -0,0 +1,38 @@ +import { Ok, Error } from "./gleam.mjs"; +import { + Get, + Post, + Head, + Put, + Delete, + Trace, + Connect, + Options, + Patch, +} from "./gleam/http.mjs"; + +export function decode_method(value) { + try { + switch (value.toLowerCase()) { + case "get": + return new Ok(new Get()); + case "post": + return new Ok(new Post()); + case "head": + return new Ok(new Head()); + case "put": + return new Ok(new Put()); + case "delete": + return new Ok(new Delete()); + case "trace": + return new Ok(new Trace()); + case "connect": + return new Ok(new Connect()); + case "options": + return new Ok(new Options()); + case "patch": + return new Ok(new Patch()); + } + } catch {} + return new Error(undefined); +} diff --git a/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http.beam b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http.beam Binary files differnew file mode 100644 index 0000000..1d6dab6 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http.beam diff --git a/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@cookie.beam b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@cookie.beam Binary files differnew file mode 100644 index 0000000..0e9882c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@cookie.beam diff --git a/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@request.beam b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@request.beam Binary files differnew file mode 100644 index 0000000..ef3cd15 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@request.beam diff --git a/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@response.beam b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@response.beam Binary files differnew file mode 100644 index 0000000..a5a1f4c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@response.beam diff --git a/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@service.beam b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@service.beam Binary files differnew file mode 100644 index 0000000..09e3162 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@service.beam diff --git a/aoc2023/build/dev/erlang/gleam_http/ebin/gleam_http.app b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam_http.app new file mode 100644 index 0000000..5f55c6f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam_http.app @@ -0,0 +1,7 @@ +{application, gleam_http, [ + {vsn, "3.5.2"}, + {applications, [gleam_stdlib]}, + {description, "Types and functions for Gleam HTTP clients and servers"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/gleam_http/ebin/gleam_http_native.beam b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam_http_native.beam Binary files differnew file mode 100644 index 0000000..b69ece0 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam_http_native.beam diff --git a/aoc2023/build/dev/erlang/gleam_http/include/gleam@http@cookie_Attributes.hrl b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http@cookie_Attributes.hrl new file mode 100644 index 0000000..78a7d02 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http@cookie_Attributes.hrl @@ -0,0 +1,8 @@ +-record(attributes, { + max_age :: gleam@option:option(integer()), + domain :: gleam@option:option(binary()), + path :: gleam@option:option(binary()), + secure :: boolean(), + http_only :: boolean(), + same_site :: gleam@option:option(gleam@http@cookie:same_site_policy()) +}). diff --git a/aoc2023/build/dev/erlang/gleam_http/include/gleam@http@request_Request.hrl b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http@request_Request.hrl new file mode 100644 index 0000000..c8bbae6 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http@request_Request.hrl @@ -0,0 +1,10 @@ +-record(request, { + method :: gleam@http:method(), + headers :: list({binary(), binary()}), + body :: any(), + scheme :: gleam@http:scheme(), + host :: binary(), + port :: gleam@option:option(integer()), + path :: binary(), + 'query' :: gleam@option:option(binary()) +}). diff --git a/aoc2023/build/dev/erlang/gleam_http/include/gleam@http@response_Response.hrl b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http@response_Response.hrl new file mode 100644 index 0000000..ba6f077 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http@response_Response.hrl @@ -0,0 +1,5 @@ +-record(response, { + status :: integer(), + headers :: list({binary(), binary()}), + body :: any() +}). diff --git a/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MoreRequiredForBody.hrl b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MoreRequiredForBody.hrl new file mode 100644 index 0000000..abd56dd --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MoreRequiredForBody.hrl @@ -0,0 +1,5 @@ +-record(more_required_for_body, { + chunk :: bitstring(), + continuation :: fun((bitstring()) -> {ok, gleam@http:multipart_body()} | + {error, nil}) +}). diff --git a/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MoreRequiredForHeaders.hrl b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MoreRequiredForHeaders.hrl new file mode 100644 index 0000000..43729c1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MoreRequiredForHeaders.hrl @@ -0,0 +1,4 @@ +-record(more_required_for_headers, { + continuation :: fun((bitstring()) -> {ok, gleam@http:multipart_headers()} | + {error, nil}) +}). diff --git a/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MultipartBody.hrl b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MultipartBody.hrl new file mode 100644 index 0000000..4521591 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MultipartBody.hrl @@ -0,0 +1,5 @@ +-record(multipart_body, { + chunk :: bitstring(), + done :: boolean(), + remaining :: bitstring() +}). diff --git a/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MultipartHeaders.hrl b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MultipartHeaders.hrl new file mode 100644 index 0000000..d9fca5c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MultipartHeaders.hrl @@ -0,0 +1,4 @@ +-record(multipart_headers, { + headers :: list({binary(), binary()}), + remaining :: bitstring() +}). diff --git a/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.cache b/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.cache Binary files differnew file mode 100644 index 0000000..84e8417 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.cache diff --git a/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.cache_meta b/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.cache_meta Binary files differnew file mode 100644 index 0000000..a340156 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.erl b/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.erl new file mode 100644 index 0000000..4629ee6 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.erl @@ -0,0 +1,118 @@ +-module(gleam@httpc). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([send_bits/1, send/1]). +-export_type([charlist/0, erl_http_option/0, body_format/0, erl_option/0]). + +-type charlist() :: any(). + +-type erl_http_option() :: any(). + +-type body_format() :: binary. + +-type erl_option() :: {body_format, body_format()}. + +-spec charlist_header({binary(), binary()}) -> {charlist(), charlist()}. +charlist_header(Header) -> + {K, V} = Header, + {erlang:binary_to_list(K), erlang:binary_to_list(V)}. + +-spec string_header({charlist(), charlist()}) -> {binary(), binary()}. +string_header(Header) -> + {K, V} = Header, + {erlang:list_to_binary(K), erlang:list_to_binary(V)}. + +-spec send_bits(gleam@http@request:request(bitstring())) -> {ok, + gleam@http@response:response(bitstring())} | + {error, gleam@dynamic:dynamic_()}. +send_bits(Req) -> + Erl_url = begin + _pipe = Req, + _pipe@1 = gleam@http@request:to_uri(_pipe), + _pipe@2 = gleam@uri:to_string(_pipe@1), + erlang:binary_to_list(_pipe@2) + end, + Erl_headers = gleam@list:map(erlang:element(3, Req), fun charlist_header/1), + Erl_http_options = [], + Erl_options = [{body_format, binary}], + gleam@result:then(case erlang:element(2, Req) of + options -> + Erl_req = {Erl_url, Erl_headers}, + httpc:request( + erlang:element(2, Req), + Erl_req, + Erl_http_options, + Erl_options + ); + + head -> + Erl_req = {Erl_url, Erl_headers}, + httpc:request( + erlang:element(2, Req), + Erl_req, + Erl_http_options, + Erl_options + ); + + get -> + Erl_req = {Erl_url, Erl_headers}, + httpc:request( + erlang:element(2, Req), + Erl_req, + Erl_http_options, + Erl_options + ); + + _ -> + Erl_content_type = begin + _pipe@3 = Req, + _pipe@4 = gleam@http@request:get_header( + _pipe@3, + <<"content-type"/utf8>> + ), + _pipe@5 = gleam@result:unwrap( + _pipe@4, + <<"application/octet-stream"/utf8>> + ), + erlang:binary_to_list(_pipe@5) + end, + Erl_req@1 = {Erl_url, + Erl_headers, + Erl_content_type, + erlang:element(4, Req)}, + httpc:request( + erlang:element(2, Req), + Erl_req@1, + Erl_http_options, + Erl_options + ) + end, fun(Response) -> + {{_, Status, _}, Headers, Resp_body} = Response, + {ok, + {response, + Status, + gleam@list:map(Headers, fun string_header/1), + Resp_body}} + end). + +-spec send(gleam@http@request:request(binary())) -> {ok, + gleam@http@response:response(binary())} | + {error, gleam@dynamic:dynamic_()}. +send(Req) -> + gleam@result:then( + begin + _pipe = Req, + _pipe@1 = gleam@http@request:map(_pipe, fun gleam_stdlib:identity/1), + send_bits(_pipe@1) + end, + fun(Resp) -> case gleam@bit_array:to_string(erlang:element(4, Resp)) of + {ok, Body} -> + {ok, gleam@http@response:set_body(Resp, Body)}; + + {error, _} -> + {error, + gleam@dynamic:from( + <<"Response body was not valid UTF-8"/utf8>> + )} + end end + ). diff --git a/aoc2023/build/dev/erlang/gleam_httpc/ebin/gleam@httpc.beam b/aoc2023/build/dev/erlang/gleam_httpc/ebin/gleam@httpc.beam Binary files differnew file mode 100644 index 0000000..d4f3782 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_httpc/ebin/gleam@httpc.beam diff --git a/aoc2023/build/dev/erlang/gleam_httpc/ebin/gleam_httpc.app b/aoc2023/build/dev/erlang/gleam_httpc/ebin/gleam_httpc.app new file mode 100644 index 0000000..c99b5ea --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_httpc/ebin/gleam_httpc.app @@ -0,0 +1,10 @@ +{application, gleam_httpc, [ + {vsn, "2.1.1"}, + {applications, [gleam_http, + gleam_stdlib, + inets, + ssl]}, + {description, "Gleam bindings to Erlang's built in HTTP client, httpc"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.cache b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.cache Binary files differnew file mode 100644 index 0000000..df2a9bd --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.cache diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.cache_meta b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.cache_meta Binary files differnew file mode 100644 index 0000000..d5f2a3e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.erl b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.erl new file mode 100644 index 0000000..2002046 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.erl @@ -0,0 +1,273 @@ +-module(gleam@otp@actor). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([continue/1, with_selector/2, to_erlang_start_result/1, start_spec/1, start/2, send/2, call/3]). +-export_type([message/1, next/2, init_result/2, self/2, spec/2, start_error/0, start_init_message/1]). + +-type message(HLY) :: {message, HLY} | + {system, gleam@otp@system:system_message()} | + {unexpected, gleam@dynamic:dynamic_()}. + +-type next(HLZ, HMA) :: {continue, + HMA, + gleam@option:option(gleam@erlang@process:selector(HLZ))} | + {stop, gleam@erlang@process:exit_reason()}. + +-type init_result(HMB, HMC) :: {ready, HMB, gleam@erlang@process:selector(HMC)} | + {failed, binary()}. + +-type self(HMD, HME) :: {self, + gleam@otp@system:mode(), + gleam@erlang@process:pid_(), + HMD, + gleam@erlang@process:subject(HME), + gleam@erlang@process:selector(message(HME)), + gleam@otp@system:debug_state(), + fun((HME, HMD) -> next(HME, HMD))}. + +-type spec(HMF, HMG) :: {spec, + fun(() -> init_result(HMF, HMG)), + integer(), + fun((HMG, HMF) -> next(HMG, HMF))}. + +-type start_error() :: init_timeout | + {init_failed, gleam@erlang@process:exit_reason()} | + {init_crashed, gleam@dynamic:dynamic_()}. + +-type start_init_message(HMH) :: {ack, + {ok, gleam@erlang@process:subject(HMH)} | + {error, gleam@erlang@process:exit_reason()}} | + {mon, gleam@erlang@process:process_down()}. + +-spec continue(HMO) -> next(any(), HMO). +continue(State) -> + {continue, State, none}. + +-spec with_selector(next(HMS, HMT), gleam@erlang@process:selector(HMS)) -> next(HMS, HMT). +with_selector(Value, Selector) -> + case Value of + {continue, State, _} -> + {continue, State, {some, Selector}}; + + _ -> + Value + end. + +-spec exit_process(gleam@erlang@process:exit_reason()) -> gleam@erlang@process:exit_reason(). +exit_process(Reason) -> + Reason. + +-spec selecting_system_messages(gleam@erlang@process:selector(message(HNE))) -> gleam@erlang@process:selector(message(HNE)). +selecting_system_messages(Selector) -> + _pipe = Selector, + gleam@erlang@process:selecting_record3( + _pipe, + erlang:binary_to_atom(<<"system"/utf8>>), + fun gleam_otp_external:convert_system_message/2 + ). + +-spec receive_message(self(any(), HNA)) -> message(HNA). +receive_message(Self) -> + Selector = case erlang:element(2, Self) of + suspended -> + _pipe = gleam_erlang_ffi:new_selector(), + selecting_system_messages(_pipe); + + running -> + _pipe@1 = gleam_erlang_ffi:new_selector(), + _pipe@2 = gleam@erlang@process:selecting_anything( + _pipe@1, + fun(Field@0) -> {unexpected, Field@0} end + ), + _pipe@3 = gleam_erlang_ffi:merge_selector( + _pipe@2, + erlang:element(6, Self) + ), + selecting_system_messages(_pipe@3) + end, + gleam_erlang_ffi:select(Selector). + +-spec process_status_info(self(any(), any())) -> gleam@otp@system:status_info(). +process_status_info(Self) -> + {status_info, + erlang:binary_to_atom(<<"gleam@otp@actor"/utf8>>), + erlang:element(3, Self), + erlang:element(2, Self), + erlang:element(7, Self), + gleam@dynamic:from(erlang:element(4, Self))}. + +-spec init_selector( + gleam@erlang@process:subject(HRT), + gleam@erlang@process:selector(HRT) +) -> gleam@erlang@process:selector(message(HRT)). +init_selector(Subject, Selector) -> + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = gleam@erlang@process:selecting( + _pipe, + Subject, + fun(Field@0) -> {message, Field@0} end + ), + gleam_erlang_ffi:merge_selector( + _pipe@1, + gleam_erlang_ffi:map_selector( + Selector, + fun(Field@0) -> {message, Field@0} end + ) + ). + +-spec loop(self(any(), any())) -> gleam@erlang@process:exit_reason(). +loop(Self) -> + case receive_message(Self) of + {system, System} -> + case System of + {get_state, Callback} -> + Callback(gleam@dynamic:from(erlang:element(4, Self))), + loop(Self); + + {resume, Callback@1} -> + Callback@1(), + loop(erlang:setelement(2, Self, running)); + + {suspend, Callback@2} -> + Callback@2(), + loop(erlang:setelement(2, Self, suspended)); + + {get_status, Callback@3} -> + Callback@3(process_status_info(Self)), + loop(Self) + end; + + {unexpected, Message} -> + logger:warning( + unicode:characters_to_list( + <<"Actor discarding unexpected message: ~s"/utf8>> + ), + [unicode:characters_to_list(gleam@string:inspect(Message))] + ), + loop(Self); + + {message, Msg} -> + case (erlang:element(8, Self))(Msg, erlang:element(4, Self)) of + {stop, Reason} -> + exit_process(Reason); + + {continue, State, New_selector} -> + Selector = begin + _pipe = New_selector, + _pipe@1 = gleam@option:map( + _pipe, + fun(_capture) -> + init_selector(erlang:element(5, Self), _capture) + end + ), + gleam@option:unwrap(_pipe@1, erlang:element(6, Self)) + end, + loop( + erlang:setelement( + 6, + erlang:setelement(4, Self, State), + Selector + ) + ) + end + end. + +-spec initialise_actor( + spec(any(), HNV), + gleam@erlang@process:subject({ok, gleam@erlang@process:subject(HNV)} | + {error, gleam@erlang@process:exit_reason()}) +) -> gleam@erlang@process:exit_reason(). +initialise_actor(Spec, Ack) -> + Subject = gleam@erlang@process:new_subject(), + case (erlang:element(2, Spec))() of + {ready, State, Selector} -> + Selector@1 = init_selector(Subject, Selector), + gleam@erlang@process:send(Ack, {ok, Subject}), + Self = {self, + running, + gleam@erlang@process:subject_owner(Ack), + State, + Subject, + Selector@1, + sys:debug_options([]), + erlang:element(4, Spec)}, + loop(Self); + + {failed, Reason} -> + gleam@erlang@process:send(Ack, {error, {abnormal, Reason}}), + exit_process({abnormal, Reason}) + end. + +-spec to_erlang_start_result( + {ok, gleam@erlang@process:subject(any())} | {error, start_error()} +) -> {ok, gleam@erlang@process:pid_()} | {error, gleam@dynamic:dynamic_()}. +to_erlang_start_result(Res) -> + case Res of + {ok, X} -> + {ok, gleam@erlang@process:subject_owner(X)}; + + {error, X@1} -> + {error, gleam@dynamic:from(X@1)} + end. + +-spec start_spec(spec(any(), HOJ)) -> {ok, gleam@erlang@process:subject(HOJ)} | + {error, start_error()}. +start_spec(Spec) -> + Ack_subject = gleam@erlang@process:new_subject(), + Child = gleam@erlang@process:start( + fun() -> initialise_actor(Spec, Ack_subject) end, + true + ), + Monitor = gleam@erlang@process:monitor_process(Child), + Selector = begin + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = gleam@erlang@process:selecting( + _pipe, + Ack_subject, + fun(Field@0) -> {ack, Field@0} end + ), + gleam@erlang@process:selecting_process_down( + _pipe@1, + Monitor, + fun(Field@0) -> {mon, Field@0} end + ) + end, + Result = case gleam_erlang_ffi:select(Selector, erlang:element(3, Spec)) of + {ok, {ack, {ok, Channel}}} -> + {ok, Channel}; + + {ok, {ack, {error, Reason}}} -> + {error, {init_failed, Reason}}; + + {ok, {mon, Down}} -> + {error, {init_crashed, erlang:element(3, Down)}}; + + {error, nil} -> + gleam@erlang@process:kill(Child), + {error, init_timeout} + end, + gleam_erlang_ffi:demonitor(Monitor), + Result. + +-spec start(HOP, fun((HOQ, HOP) -> next(HOQ, HOP))) -> {ok, + gleam@erlang@process:subject(HOQ)} | + {error, start_error()}. +start(State, Loop) -> + start_spec( + {spec, + fun() -> {ready, State, gleam_erlang_ffi:new_selector()} end, + 5000, + Loop} + ). + +-spec send(gleam@erlang@process:subject(HOW), HOW) -> nil. +send(Subject, Msg) -> + gleam@erlang@process:send(Subject, Msg). + +-spec call( + gleam@erlang@process:subject(HOY), + fun((gleam@erlang@process:subject(HPA)) -> HOY), + integer() +) -> HPA. +call(Selector, Make_message, Timeout) -> + gleam@erlang@process:call(Selector, Make_message, Timeout). diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.cache b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.cache Binary files differnew file mode 100644 index 0000000..a2cc755 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.cache diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.cache_meta b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.cache_meta Binary files differnew file mode 100644 index 0000000..1997b5a --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.erl b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.erl new file mode 100644 index 0000000..716078f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.erl @@ -0,0 +1,53 @@ +-module(gleam@otp@intensity_tracker). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([new/2, trim_window/3, add_event/1]). +-export_type([intensity_tracker/0, too_intense/0]). + +-opaque intensity_tracker() :: {intensity_tracker, + integer(), + integer(), + list(integer())}. + +-type too_intense() :: too_intense. + +-spec new(integer(), integer()) -> intensity_tracker(). +new(Limit, Period) -> + {intensity_tracker, Limit, Period, []}. + +-spec now_seconds() -> integer(). +now_seconds() -> + erlang:monotonic_time(1). + +-spec trim_window(list(integer()), integer(), integer()) -> list(integer()). +trim_window(Events, Now, Period) -> + case Events of + [] -> + []; + + [Event | Events@1] -> + case Now >= (Event + Period) of + true -> + [Event | trim_window(Events@1, Now, Period)]; + + false -> + [] + end + end. + +-spec add_event(intensity_tracker()) -> {ok, intensity_tracker()} | + {error, too_intense()}. +add_event(Tracker) -> + Now = now_seconds(), + Events = trim_window( + [Now | erlang:element(4, Tracker)], + Now, + erlang:element(3, Tracker) + ), + case gleam@list:length(Events) >= erlang:element(2, Tracker) of + true -> + {error, too_intense}; + + false -> + {ok, erlang:setelement(4, Tracker, Events)} + end. diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.cache b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.cache Binary files differnew file mode 100644 index 0000000..a05f0e2 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.cache diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.cache_meta b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.cache_meta Binary files differnew file mode 100644 index 0000000..5f1cb59 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.erl b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.erl new file mode 100644 index 0000000..9bad092 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.erl @@ -0,0 +1,8 @@ +-module(gleam@otp@port). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export_type([port_/0]). + +-type port_() :: any(). + + diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.cache b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.cache Binary files differnew file mode 100644 index 0000000..2b4bef1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.cache diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.cache_meta b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.cache_meta Binary files differnew file mode 100644 index 0000000..f6f257e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.erl b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.erl new file mode 100644 index 0000000..bb07432 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.erl @@ -0,0 +1,322 @@ +-module(gleam@otp@supervisor). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([add/2, supervisor/1, worker/1, returning/2, start_spec/1, start/1, application_stopped/0, to_erlang_start_result/1]). +-export_type([spec/2, children/1, child_spec/3, child_start_error/0, message/0, instruction/0, state/1, starter/1, child/1, handle_exit_error/0, application_start_mode/0, application_stop/0]). + +-type spec(HXT, HXU) :: {spec, + HXT, + integer(), + integer(), + fun((children(HXT)) -> children(HXU))}. + +-opaque children(HXV) :: {ready, starter(HXV)} | {failed, child_start_error()}. + +-opaque child_spec(HXW, HXX, HXY) :: {child_spec, + fun((HXX) -> {ok, gleam@erlang@process:subject(HXW)} | + {error, gleam@otp@actor:start_error()}), + fun((HXX, gleam@erlang@process:subject(HXW)) -> HXY)}. + +-type child_start_error() :: {child_start_error, + gleam@option:option(gleam@erlang@process:pid_()), + gleam@otp@actor:start_error()}. + +-opaque message() :: {exit, gleam@erlang@process:exit_message()} | + {retry_restart, gleam@erlang@process:pid_()}. + +-type instruction() :: start_all | {start_from, gleam@erlang@process:pid_()}. + +-type state(HXZ) :: {state, + gleam@otp@intensity_tracker:intensity_tracker(), + starter(HXZ), + gleam@erlang@process:subject(gleam@erlang@process:pid_())}. + +-type starter(HYA) :: {starter, + HYA, + gleam@option:option(fun((instruction()) -> {ok, + {starter(HYA), instruction()}} | + {error, child_start_error()}))}. + +-type child(HYB) :: {child, gleam@erlang@process:pid_(), HYB}. + +-type handle_exit_error() :: {restart_failed, + gleam@erlang@process:pid_(), + gleam@otp@intensity_tracker:intensity_tracker()} | + too_many_restarts. + +-type application_start_mode() :: normal | + {takeover, gleam@erlang@node:node_()} | + {failover, gleam@erlang@node:node_()}. + +-type application_stop() :: any(). + +-spec start_child(child_spec(any(), HYF, HYG), HYF) -> {ok, child(HYG)} | + {error, child_start_error()}. +start_child(Child_spec, Argument) -> + gleam@result:then( + begin + _pipe = (erlang:element(2, Child_spec))(Argument), + gleam@result:map_error( + _pipe, + fun(_capture) -> {child_start_error, none, _capture} end + ) + end, + fun(Subject) -> + {ok, + {child, + gleam@erlang@process:subject_owner(Subject), + (erlang:element(3, Child_spec))(Argument, Subject)}} + end + ). + +-spec shutdown_child( + gleam@erlang@process:pid_(), + child_spec(any(), any(), any()) +) -> nil. +shutdown_child(Pid, _) -> + gleam@erlang@process:send_exit(Pid). + +-spec perform_instruction_for_child( + HYT, + instruction(), + child_spec(any(), HYT, HYV), + child(HYV) +) -> {ok, {child(HYV), instruction()}} | {error, child_start_error()}. +perform_instruction_for_child(Argument, Instruction, Child_spec, Child) -> + Current = erlang:element(2, Child), + case Instruction of + {start_from, Target} when Target =/= Current -> + {ok, {Child, Instruction}}; + + _ -> + shutdown_child(Current, Child_spec), + gleam@result:then( + start_child(Child_spec, Argument), + fun(Child@1) -> {ok, {Child@1, start_all}} end + ) + end. + +-spec add_child_to_starter( + starter(HZD), + child_spec(any(), HZD, HZG), + child(HZG) +) -> starter(HZG). +add_child_to_starter(Starter, Child_spec, Child) -> + Starter@3 = fun(Instruction) -> + gleam@result:then(case erlang:element(3, Starter) of + {some, Start} -> + Start(Instruction); + + none -> + {ok, {Starter, Instruction}} + end, fun(_use0) -> + {Starter@1, Instruction@1} = _use0, + gleam@result:then( + perform_instruction_for_child( + erlang:element(2, Starter@1), + Instruction@1, + Child_spec, + Child + ), + fun(_use0@1) -> + {Child@1, Instruction@2} = _use0@1, + Starter@2 = add_child_to_starter( + Starter@1, + Child_spec, + Child@1 + ), + {ok, {Starter@2, Instruction@2}} + end + ) + end) + end, + {starter, erlang:element(3, Child), {some, Starter@3}}. + +-spec start_and_add_child(starter(HZM), child_spec(any(), HZM, HZP)) -> children(HZP). +start_and_add_child(State, Child_spec) -> + case start_child(Child_spec, erlang:element(2, State)) of + {ok, Child} -> + {ready, add_child_to_starter(State, Child_spec, Child)}; + + {error, Reason} -> + {failed, Reason} + end. + +-spec add(children(HZU), child_spec(any(), HZU, HZX)) -> children(HZX). +add(Children, Child_spec) -> + case Children of + {failed, Fail} -> + {failed, Fail}; + + {ready, State} -> + start_and_add_child(State, Child_spec) + end. + +-spec supervisor( + fun((IAC) -> {ok, gleam@erlang@process:subject(IAD)} | + {error, gleam@otp@actor:start_error()}) +) -> child_spec(IAD, IAC, IAC). +supervisor(Start) -> + {child_spec, Start, fun(Argument, _) -> Argument end}. + +-spec worker( + fun((IAK) -> {ok, gleam@erlang@process:subject(IAL)} | + {error, gleam@otp@actor:start_error()}) +) -> child_spec(IAL, IAK, IAK). +worker(Start) -> + {child_spec, Start, fun(Argument, _) -> Argument end}. + +-spec returning( + child_spec(IAS, IAT, any()), + fun((IAT, gleam@erlang@process:subject(IAS)) -> IAZ) +) -> child_spec(IAS, IAT, IAZ). +returning(Child, Updater) -> + {child_spec, erlang:element(2, Child), Updater}. + +-spec init(spec(any(), IBE)) -> gleam@otp@actor:init_result(state(IBE), message()). +init(Spec) -> + Retry = gleam@erlang@process:new_subject(), + gleam_erlang_ffi:trap_exits(true), + Selector = begin + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = gleam@erlang@process:selecting( + _pipe, + Retry, + fun(Field@0) -> {retry_restart, Field@0} end + ), + gleam@erlang@process:selecting_trapped_exits( + _pipe@1, + fun(Field@0) -> {exit, Field@0} end + ) + end, + Result = begin + _pipe@2 = {starter, erlang:element(2, Spec), none}, + _pipe@3 = {ready, _pipe@2}, + (erlang:element(5, Spec))(_pipe@3) + end, + case Result of + {ready, Starter} -> + Restarts = gleam@otp@intensity_tracker:new( + erlang:element(3, Spec), + erlang:element(4, Spec) + ), + State = {state, Restarts, Starter, Retry}, + {ready, State, Selector}; + + {failed, Error} -> + {failed, case erlang:element(3, Error) of + init_timeout -> + <<"Child initialisation timed out"/utf8>>; + + {init_crashed, Reason} -> + gleam@string:append( + <<"Child crashed during initialisation: "/utf8>>, + gleam@string:inspect(Reason) + ); + + {init_failed, Reason@1} -> + gleam@string:append( + <<"Child failed to start during initialisation: "/utf8>>, + gleam@string:inspect(Reason@1) + ) + end} + end. + +-spec handle_exit(gleam@erlang@process:pid_(), state(IBK)) -> gleam@otp@actor:next(message(), state(IBK)). +handle_exit(Pid, State) -> + Outcome = begin + _assert_subject = erlang:element(3, erlang:element(3, State)), + {some, Start} = case _assert_subject of + {some, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam/otp/supervisor"/utf8>>, + function => <<"handle_exit"/utf8>>, + line => 293}) + end, + gleam@result:then( + begin + _pipe = erlang:element(2, State), + _pipe@1 = gleam@otp@intensity_tracker:add_event(_pipe), + gleam@result:map_error(_pipe@1, fun(_) -> too_many_restarts end) + end, + fun(Restarts) -> + gleam@result:then( + begin + _pipe@2 = Start({start_from, Pid}), + gleam@result:map_error( + _pipe@2, + fun(E) -> + {restart_failed, + gleam@option:unwrap( + erlang:element(2, E), + Pid + ), + Restarts} + end + ) + end, + fun(_use0) -> + {Starter, _} = _use0, + {ok, + erlang:setelement( + 2, + erlang:setelement(3, State, Starter), + Restarts + )} + end + ) + end + ) + end, + case Outcome of + {ok, State@1} -> + gleam@otp@actor:continue(State@1); + + {error, {restart_failed, Failed_child, Restarts@1}} -> + gleam@erlang@process:send(erlang:element(4, State), Failed_child), + State@2 = erlang:setelement(2, State, Restarts@1), + gleam@otp@actor:continue(State@2); + + {error, too_many_restarts} -> + {stop, + {abnormal, + <<"Child processes restarted too many times within allowed period"/utf8>>}} + end. + +-spec loop(message(), state(IBP)) -> gleam@otp@actor:next(message(), state(IBP)). +loop(Message, State) -> + case Message of + {exit, Exit_message} -> + handle_exit(erlang:element(2, Exit_message), State); + + {retry_restart, Pid} -> + handle_exit(Pid, State) + end. + +-spec start_spec(spec(any(), any())) -> {ok, + gleam@erlang@process:subject(message())} | + {error, gleam@otp@actor:start_error()}. +start_spec(Spec) -> + gleam@otp@actor:start_spec( + {spec, fun() -> init(Spec) end, 60000, fun loop/2} + ). + +-spec start(fun((children(nil)) -> children(any()))) -> {ok, + gleam@erlang@process:subject(message())} | + {error, gleam@otp@actor:start_error()}. +start(Init) -> + start_spec({spec, nil, 1, 5, Init}). + +-spec application_stopped() -> application_stop(). +application_stopped() -> + gleam_otp_external:application_stopped(). + +-spec to_erlang_start_result( + {ok, gleam@erlang@process:subject(any())} | + {error, gleam@otp@actor:start_error()} +) -> {ok, gleam@erlang@process:pid_()} | {error, gleam@dynamic:dynamic_()}. +to_erlang_start_result(Res) -> + gleam@otp@actor:to_erlang_start_result(Res). diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.cache b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.cache Binary files differnew file mode 100644 index 0000000..c489047 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.cache diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.cache_meta b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.cache_meta Binary files differnew file mode 100644 index 0000000..9f64041 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.erl b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.erl new file mode 100644 index 0000000..d6c6bfc --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.erl @@ -0,0 +1,43 @@ +-module(gleam@otp@system). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([debug_state/1, get_state/1, suspend/1, resume/1]). +-export_type([mode/0, debug_option/0, debug_state/0, status_info/0, system_message/0, do_not_leak/0]). + +-type mode() :: running | suspended. + +-type debug_option() :: no_debug. + +-type debug_state() :: any(). + +-type status_info() :: {status_info, + gleam@erlang@atom:atom_(), + gleam@erlang@process:pid_(), + mode(), + debug_state(), + gleam@dynamic:dynamic_()}. + +-type system_message() :: {resume, fun(() -> nil)} | + {suspend, fun(() -> nil)} | + {get_state, fun((gleam@dynamic:dynamic_()) -> nil)} | + {get_status, fun((status_info()) -> nil)}. + +-type do_not_leak() :: any(). + +-spec debug_state(list(debug_option())) -> debug_state(). +debug_state(A) -> + sys:debug_options(A). + +-spec get_state(gleam@erlang@process:pid_()) -> gleam@dynamic:dynamic_(). +get_state(From) -> + sys:get_state(From). + +-spec suspend(gleam@erlang@process:pid_()) -> nil. +suspend(Pid) -> + sys:suspend(Pid), + nil. + +-spec resume(gleam@erlang@process:pid_()) -> nil. +resume(Pid) -> + sys:resume(Pid), + nil. diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.cache b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.cache Binary files differnew file mode 100644 index 0000000..b71f5ea --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.cache diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.cache_meta b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.cache_meta Binary files differnew file mode 100644 index 0000000..e4f89cf --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.erl b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.erl new file mode 100644 index 0000000..7cb0540 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.erl @@ -0,0 +1,111 @@ +-module(gleam@otp@task). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([async/1, try_await/2, await/2, try_await_forever/1, await_forever/1]). +-export_type([task/1, await_error/0, message/1]). + +-opaque task(IKP) :: {task, + gleam@erlang@process:pid_(), + gleam@erlang@process:pid_(), + gleam@erlang@process:process_monitor(), + gleam@erlang@process:selector(message(IKP))}. + +-type await_error() :: timeout | {exit, gleam@dynamic:dynamic_()}. + +-type message(IKQ) :: {from_monitor, gleam@erlang@process:process_down()} | + {from_subject, IKQ}. + +-spec async(fun(() -> IKR)) -> task(IKR). +async(Work) -> + Owner = erlang:self(), + Subject = gleam@erlang@process:new_subject(), + Pid = gleam@erlang@process:start( + fun() -> gleam@erlang@process:send(Subject, Work()) end, + true + ), + Monitor = gleam@erlang@process:monitor_process(Pid), + Selector = begin + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = gleam@erlang@process:selecting_process_down( + _pipe, + Monitor, + fun(Field@0) -> {from_monitor, Field@0} end + ), + gleam@erlang@process:selecting( + _pipe@1, + Subject, + fun(Field@0) -> {from_subject, Field@0} end + ) + end, + {task, Owner, Pid, Monitor, Selector}. + +-spec assert_owner(task(any())) -> nil. +assert_owner(Task) -> + Self = erlang:self(), + case erlang:element(2, Task) =:= Self of + true -> + nil; + + false -> + gleam@erlang@process:send_abnormal_exit( + Self, + <<"awaited on a task that does not belong to this process"/utf8>> + ) + end. + +-spec try_await(task(IKV), integer()) -> {ok, IKV} | {error, await_error()}. +try_await(Task, Timeout) -> + assert_owner(Task), + case gleam_erlang_ffi:select(erlang:element(5, Task), Timeout) of + {ok, {from_subject, X}} -> + gleam_erlang_ffi:demonitor(erlang:element(4, Task)), + {ok, X}; + + {ok, {from_monitor, {process_down, _, Reason}}} -> + {error, {exit, Reason}}; + + {error, nil} -> + {error, timeout} + end. + +-spec await(task(IKZ), integer()) -> IKZ. +await(Task, Timeout) -> + _assert_subject = try_await(Task, Timeout), + {ok, Value} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam/otp/task"/utf8>>, + function => <<"await"/utf8>>, + line => 117}) + end, + Value. + +-spec try_await_forever(task(ILB)) -> {ok, ILB} | {error, await_error()}. +try_await_forever(Task) -> + assert_owner(Task), + case gleam_erlang_ffi:select(erlang:element(5, Task)) of + {from_subject, X} -> + gleam_erlang_ffi:demonitor(erlang:element(4, Task)), + {ok, X}; + + {from_monitor, {process_down, _, Reason}} -> + {error, {exit, Reason}} + end. + +-spec await_forever(task(ILF)) -> ILF. +await_forever(Task) -> + _assert_subject = try_await_forever(Task), + {ok, Value} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam/otp/task"/utf8>>, + function => <<"await_forever"/utf8>>, + line => 149}) + end, + Value. diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.cache b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.cache Binary files differnew file mode 100644 index 0000000..61dea2d --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.cache diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.cache_meta b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.cache_meta Binary files differnew file mode 100644 index 0000000..6b7a3a8 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.erl b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.erl new file mode 100644 index 0000000..03ae419 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.erl @@ -0,0 +1,28 @@ +-module(gleam_otp). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([main/0]). + +-spec spawn_task(integer()) -> gleam@otp@task:task(nil). +spawn_task(I) -> + gleam@otp@task:async(fun() -> case (I rem 500) =:= 0 of + true -> + gleam@io:println( + <<"Hello from "/utf8, (gleam@int:to_string(I))/binary>> + ); + + false -> + nil + end end). + +-spec main() -> integer(). +main() -> + gleam@io:debug( + gleam_otp_test_external:get_message_queue_length(erlang:self()) + ), + _pipe = gleam@list:range(0, 1000000), + _pipe@1 = gleam@list:map(_pipe, fun spawn_task/1), + gleam@list:each(_pipe@1, fun gleam@otp@task:await_forever/1), + gleam@io:debug( + gleam_otp_test_external:get_message_queue_length(erlang:self()) + ). diff --git a/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp_external.erl b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp_external.erl new file mode 100644 index 0000000..8910a67 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp_external.erl @@ -0,0 +1,43 @@ +-module(gleam_otp_external). + +-export([application_stopped/0, convert_system_message/2]). + +% TODO: support other system messages +% {replace_state, StateFn} +% {change_code, Mod, Vsn, Extra} +% {terminate, Reason} +% {debug, {log, Flag}} +% {debug, {trace, Flag}} +% {debug, {log_to_file, FileName}} +% {debug, {statistics, Flag}} +% {debug, no_debug} +% {debug, {install, {Func, FuncState}}} +% {debug, {install, {FuncId, Func, FuncState}}} +% {debug, {remove, FuncOrId}} +% GetStatus(Subject(StatusInfo)) +convert_system_message({From, Ref}, Request) when is_pid(From) -> + Reply = fun(Msg) -> + erlang:send(From, {Ref, Msg}), + nil + end, + System = fun(Callback) -> + {system, {Request, Callback}} + end, + case Request of + get_status -> System(fun(Status) -> Reply(process_status(Status)) end); + get_state -> System(Reply); + suspend -> System(fun() -> Reply(ok) end); + resume -> System(fun() -> Reply(ok) end); + Other -> {unexpeceted, Other} + end. + +process_status({status_info, Module, Parent, Mode, DebugState, State}) -> + Data = [ + get(), Mode, Parent, DebugState, + [{header, "Status for Gleam process " ++ pid_to_list(self())}, + {data, [{'Status', Mode}, {'Parent', Parent}, {'State', State}]}] + ], + {status, self(), {module, Module}, Data}. + +application_stopped() -> + ok. diff --git a/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@actor.beam b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@actor.beam Binary files differnew file mode 100644 index 0000000..7d3fd3e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@actor.beam diff --git a/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@intensity_tracker.beam b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@intensity_tracker.beam Binary files differnew file mode 100644 index 0000000..da2acd0 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@intensity_tracker.beam diff --git a/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@port.beam b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@port.beam Binary files differnew file mode 100644 index 0000000..a4a7340 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@port.beam diff --git a/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@supervisor.beam b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@supervisor.beam Binary files differnew file mode 100644 index 0000000..181508d --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@supervisor.beam diff --git a/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@system.beam b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@system.beam Binary files differnew file mode 100644 index 0000000..30d4309 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@system.beam diff --git a/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@task.beam b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@task.beam Binary files differnew file mode 100644 index 0000000..0f710a1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@task.beam diff --git a/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp.app b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp.app new file mode 100644 index 0000000..21dd444 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp.app @@ -0,0 +1,8 @@ +{application, gleam_otp, [ + {vsn, "0.8.0"}, + {applications, [gleam_erlang, + gleam_stdlib]}, + {description, "Fault tolerant multicore Gleam programs with OTP"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp.beam b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp.beam Binary files differnew file mode 100644 index 0000000..47eb31e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp.beam diff --git a/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp_external.beam b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp_external.beam Binary files differnew file mode 100644 index 0000000..5ffaafd --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp_external.beam diff --git a/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Continue.hrl b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Continue.hrl new file mode 100644 index 0000000..85677d1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Continue.hrl @@ -0,0 +1,4 @@ +-record(continue, { + state :: any(), + selector :: gleam@option:option(gleam@erlang@process:selector(any())) +}). diff --git a/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Ready.hrl b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Ready.hrl new file mode 100644 index 0000000..75faa95 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Ready.hrl @@ -0,0 +1 @@ +-record(ready, {state :: any(), selector :: gleam@erlang@process:selector(any())}). diff --git a/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Spec.hrl b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Spec.hrl new file mode 100644 index 0000000..5287439 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Spec.hrl @@ -0,0 +1,5 @@ +-record(spec, { + init :: fun(() -> gleam@otp@actor:init_result(any(), any())), + init_timeout :: integer(), + loop :: fun((any(), any()) -> gleam@otp@actor:next(any(), any())) +}). diff --git a/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@intensity_tracker_IntensityTracker.hrl b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@intensity_tracker_IntensityTracker.hrl new file mode 100644 index 0000000..3ed0b01 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@intensity_tracker_IntensityTracker.hrl @@ -0,0 +1,5 @@ +-record(intensity_tracker, { + limit :: integer(), + period :: integer(), + events :: list(integer()) +}). diff --git a/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@supervisor_ChildSpec.hrl b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@supervisor_ChildSpec.hrl new file mode 100644 index 0000000..7afd07f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@supervisor_ChildSpec.hrl @@ -0,0 +1,5 @@ +-record(child_spec, { + start :: fun((any()) -> {ok, gleam@erlang@process:subject(any())} | + {error, gleam@otp@actor:start_error()}), + returning :: fun((any(), gleam@erlang@process:subject(any())) -> any()) +}). diff --git a/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@supervisor_Spec.hrl b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@supervisor_Spec.hrl new file mode 100644 index 0000000..b10bd9f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@supervisor_Spec.hrl @@ -0,0 +1,6 @@ +-record(spec, { + argument :: any(), + max_frequency :: integer(), + frequency_period :: integer(), + init :: fun((gleam@otp@supervisor:children(any())) -> gleam@otp@supervisor:children(any())) +}). diff --git a/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@system_StatusInfo.hrl b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@system_StatusInfo.hrl new file mode 100644 index 0000000..99ab4cb --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@system_StatusInfo.hrl @@ -0,0 +1,7 @@ +-record(status_info, { + module :: gleam@erlang@atom:atom_(), + parent :: gleam@erlang@process:pid_(), + mode :: gleam@otp@system:mode(), + debug_state :: gleam@otp@system:debug_state(), + state :: gleam@dynamic:dynamic_() +}). diff --git a/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@task_Exit.hrl b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@task_Exit.hrl new file mode 100644 index 0000000..7c83874 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@task_Exit.hrl @@ -0,0 +1 @@ +-record(exit, {reason :: gleam@dynamic:dynamic_()}). diff --git a/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@task_Task.hrl b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@task_Task.hrl new file mode 100644 index 0000000..959bea8 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@task_Task.hrl @@ -0,0 +1,6 @@ +-record(task, { + owner :: gleam@erlang@process:pid_(), + pid :: gleam@erlang@process:pid_(), + monitor :: gleam@erlang@process:process_monitor(), + selector :: gleam@erlang@process:selector(gleam@otp@task:message(any())) +}). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/dict.mjs b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/dict.mjs new file mode 100644 index 0000000..a8309e0 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/dict.mjs @@ -0,0 +1,957 @@ +/** + * This file uses jsdoc to annotate types. + * These types can be checked using the typescript compiler with "checkjs" option. + */ + +import { isEqual } from "./gleam.mjs"; + +const referenceMap = new WeakMap(); +const tempDataView = new DataView(new ArrayBuffer(8)); +let referenceUID = 0; +/** + * hash the object by reference using a weak map and incrementing uid + * @param {any} o + * @returns {number} + */ +function hashByReference(o) { + const known = referenceMap.get(o); + if (known !== undefined) { + return known; + } + const hash = referenceUID++; + if (referenceUID === 0x7fffffff) { + referenceUID = 0; + } + referenceMap.set(o, hash); + return hash; +} +/** + * merge two hashes in an order sensitive way + * @param {number} a + * @param {number} b + * @returns {number} + */ +function hashMerge(a, b) { + return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; +} +/** + * standard string hash popularised by java + * @param {string} s + * @returns {number} + */ +function hashString(s) { + let hash = 0; + const len = s.length; + for (let i = 0; i < len; i++) { + hash = (Math.imul(31, hash) + s.charCodeAt(i)) | 0; + } + return hash; +} +/** + * hash a number by converting to two integers and do some jumbling + * @param {number} n + * @returns {number} + */ +function hashNumber(n) { + tempDataView.setFloat64(0, n); + const i = tempDataView.getInt32(0); + const j = tempDataView.getInt32(4); + return Math.imul(0x45d9f3b, (i >> 16) ^ i) ^ j; +} +/** + * hash a BigInt by converting it to a string and hashing that + * @param {BigInt} n + * @returns {number} + */ +function hashBigInt(n) { + return hashString(n.toString()); +} +/** + * hash any js object + * @param {any} o + * @returns {number} + */ +function hashObject(o) { + const proto = Object.getPrototypeOf(o); + if (proto !== null && typeof proto.hashCode === "function") { + try { + const code = o.hashCode(o); + if (typeof code === "number") { + return code; + } + } catch {} + } + if (o instanceof Promise || o instanceof WeakSet || o instanceof WeakMap) { + return hashByReference(o); + } + if (o instanceof Date) { + return hashNumber(o.getTime()); + } + let h = 0; + if (o instanceof ArrayBuffer) { + o = new Uint8Array(o); + } + if (Array.isArray(o) || o instanceof Uint8Array) { + for (let i = 0; i < o.length; i++) { + h = (Math.imul(31, h) + getHash(o[i])) | 0; + } + } else if (o instanceof Set) { + o.forEach((v) => { + h = (h + getHash(v)) | 0; + }); + } else if (o instanceof Map) { + o.forEach((v, k) => { + h = (h + hashMerge(getHash(v), getHash(k))) | 0; + }); + } else { + const keys = Object.keys(o); + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; + const v = o[k]; + h = (h + hashMerge(getHash(v), hashString(k))) | 0; + } + } + return h; +} +/** + * hash any js value + * @param {any} u + * @returns {number} + */ +export function getHash(u) { + if (u === null) return 0x42108422; + if (u === undefined) return 0x42108423; + if (u === true) return 0x42108421; + if (u === false) return 0x42108420; + switch (typeof u) { + case "number": + return hashNumber(u); + case "string": + return hashString(u); + case "bigint": + return hashBigInt(u); + case "object": + return hashObject(u); + case "symbol": + return hashByReference(u); + case "function": + return hashByReference(u); + default: + return 0; // should be unreachable + } +} +/** + * @template K,V + * @typedef {ArrayNode<K,V> | IndexNode<K,V> | CollisionNode<K,V>} Node + */ +/** + * @template K,V + * @typedef {{ type: typeof ENTRY, k: K, v: V }} Entry + */ +/** + * @template K,V + * @typedef {{ type: typeof ARRAY_NODE, size: number, array: (undefined | Entry<K,V> | Node<K,V>)[] }} ArrayNode + */ +/** + * @template K,V + * @typedef {{ type: typeof INDEX_NODE, bitmap: number, array: (Entry<K,V> | Node<K,V>)[] }} IndexNode + */ +/** + * @template K,V + * @typedef {{ type: typeof COLLISION_NODE, hash: number, array: Entry<K, V>[] }} CollisionNode + */ +/** + * @typedef {{ val: boolean }} Flag + */ +const SHIFT = 5; // number of bits you need to shift by to get the next bucket +const BUCKET_SIZE = Math.pow(2, SHIFT); +const MASK = BUCKET_SIZE - 1; // used to zero out all bits not in the bucket +const MAX_INDEX_NODE = BUCKET_SIZE / 2; // when does index node grow into array node +const MIN_ARRAY_NODE = BUCKET_SIZE / 4; // when does array node shrink to index node +const ENTRY = 0; +const ARRAY_NODE = 1; +const INDEX_NODE = 2; +const COLLISION_NODE = 3; +/** @type {IndexNode<any,any>} */ +const EMPTY = { + type: INDEX_NODE, + bitmap: 0, + array: [], +}; +/** + * Mask the hash to get only the bucket corresponding to shift + * @param {number} hash + * @param {number} shift + * @returns {number} + */ +function mask(hash, shift) { + return (hash >>> shift) & MASK; +} +/** + * Set only the Nth bit where N is the masked hash + * @param {number} hash + * @param {number} shift + * @returns {number} + */ +function bitpos(hash, shift) { + return 1 << mask(hash, shift); +} +/** + * Count the number of 1 bits in a number + * @param {number} x + * @returns {number} + */ +function bitcount(x) { + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0f0f0f0f; + x += x >> 8; + x += x >> 16; + return x & 0x7f; +} +/** + * Calculate the array index of an item in a bitmap index node + * @param {number} bitmap + * @param {number} bit + * @returns {number} + */ +function index(bitmap, bit) { + return bitcount(bitmap & (bit - 1)); +} +/** + * Efficiently copy an array and set one value at an index + * @template T + * @param {T[]} arr + * @param {number} at + * @param {T} val + * @returns {T[]} + */ +function cloneAndSet(arr, at, val) { + const len = arr.length; + const out = new Array(len); + for (let i = 0; i < len; ++i) { + out[i] = arr[i]; + } + out[at] = val; + return out; +} +/** + * Efficiently copy an array and insert one value at an index + * @template T + * @param {T[]} arr + * @param {number} at + * @param {T} val + * @returns {T[]} + */ +function spliceIn(arr, at, val) { + const len = arr.length; + const out = new Array(len + 1); + let i = 0; + let g = 0; + while (i < at) { + out[g++] = arr[i++]; + } + out[g++] = val; + while (i < len) { + out[g++] = arr[i++]; + } + return out; +} +/** + * Efficiently copy an array and remove one value at an index + * @template T + * @param {T[]} arr + * @param {number} at + * @returns {T[]} + */ +function spliceOut(arr, at) { + const len = arr.length; + const out = new Array(len - 1); + let i = 0; + let g = 0; + while (i < at) { + out[g++] = arr[i++]; + } + ++i; + while (i < len) { + out[g++] = arr[i++]; + } + return out; +} +/** + * Create a new node containing two entries + * @template K,V + * @param {number} shift + * @param {K} key1 + * @param {V} val1 + * @param {number} key2hash + * @param {K} key2 + * @param {V} val2 + * @returns {Node<K,V>} + */ +function createNode(shift, key1, val1, key2hash, key2, val2) { + const key1hash = getHash(key1); + if (key1hash === key2hash) { + return { + type: COLLISION_NODE, + hash: key1hash, + array: [ + { type: ENTRY, k: key1, v: val1 }, + { type: ENTRY, k: key2, v: val2 }, + ], + }; + } + const addedLeaf = { val: false }; + return assoc( + assocIndex(EMPTY, shift, key1hash, key1, val1, addedLeaf), + shift, + key2hash, + key2, + val2, + addedLeaf + ); +} +/** + * @template T,K,V + * @callback AssocFunction + * @param {T} root + * @param {number} shift + * @param {number} hash + * @param {K} key + * @param {V} val + * @param {Flag} addedLeaf + * @returns {Node<K,V>} + */ +/** + * Associate a node with a new entry, creating a new node + * @template T,K,V + * @type {AssocFunction<Node<K,V>,K,V>} + */ +function assoc(root, shift, hash, key, val, addedLeaf) { + switch (root.type) { + case ARRAY_NODE: + return assocArray(root, shift, hash, key, val, addedLeaf); + case INDEX_NODE: + return assocIndex(root, shift, hash, key, val, addedLeaf); + case COLLISION_NODE: + return assocCollision(root, shift, hash, key, val, addedLeaf); + } +} +/** + * @template T,K,V + * @type {AssocFunction<ArrayNode<K,V>,K,V>} + */ +function assocArray(root, shift, hash, key, val, addedLeaf) { + const idx = mask(hash, shift); + const node = root.array[idx]; + // if the corresponding index is empty set the index to a newly created node + if (node === undefined) { + addedLeaf.val = true; + return { + type: ARRAY_NODE, + size: root.size + 1, + array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }), + }; + } + if (node.type === ENTRY) { + // if keys are equal replace the entry + if (isEqual(key, node.k)) { + if (val === node.v) { + return root; + } + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet(root.array, idx, { + type: ENTRY, + k: key, + v: val, + }), + }; + } + // otherwise upgrade the entry to a node and insert + addedLeaf.val = true; + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet( + root.array, + idx, + createNode(shift + SHIFT, node.k, node.v, hash, key, val) + ), + }; + } + // otherwise call assoc on the child node + const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); + // if the child node hasn't changed just return the old root + if (n === node) { + return root; + } + // otherwise set the index to the new node + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet(root.array, idx, n), + }; +} +/** + * @template T,K,V + * @type {AssocFunction<IndexNode<K,V>,K,V>} + */ +function assocIndex(root, shift, hash, key, val, addedLeaf) { + const bit = bitpos(hash, shift); + const idx = index(root.bitmap, bit); + // if there is already a item at this hash index.. + if ((root.bitmap & bit) !== 0) { + // if there is a node at the index (not an entry), call assoc on the child node + const node = root.array[idx]; + if (node.type !== ENTRY) { + const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); + if (n === node) { + return root; + } + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet(root.array, idx, n), + }; + } + // otherwise there is an entry at the index + // if the keys are equal replace the entry with the updated value + const nodeKey = node.k; + if (isEqual(key, nodeKey)) { + if (val === node.v) { + return root; + } + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet(root.array, idx, { + type: ENTRY, + k: key, + v: val, + }), + }; + } + // if the keys are not equal, replace the entry with a new child node + addedLeaf.val = true; + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet( + root.array, + idx, + createNode(shift + SHIFT, nodeKey, node.v, hash, key, val) + ), + }; + } else { + // else there is currently no item at the hash index + const n = root.array.length; + // if the number of nodes is at the maximum, expand this node into an array node + if (n >= MAX_INDEX_NODE) { + // create a 32 length array for the new array node (one for each bit in the hash) + const nodes = new Array(32); + // create and insert a node for the new entry + const jdx = mask(hash, shift); + nodes[jdx] = assocIndex(EMPTY, shift + SHIFT, hash, key, val, addedLeaf); + let j = 0; + let bitmap = root.bitmap; + // place each item in the index node into the correct spot in the array node + // loop through all 32 bits / array positions + for (let i = 0; i < 32; i++) { + if ((bitmap & 1) !== 0) { + const node = root.array[j++]; + nodes[i] = node; + } + // shift the bitmap to process the next bit + bitmap = bitmap >>> 1; + } + return { + type: ARRAY_NODE, + size: n + 1, + array: nodes, + }; + } else { + // else there is still space in this index node + // simply insert a new entry at the hash index + const newArray = spliceIn(root.array, idx, { + type: ENTRY, + k: key, + v: val, + }); + addedLeaf.val = true; + return { + type: INDEX_NODE, + bitmap: root.bitmap | bit, + array: newArray, + }; + } + } +} +/** + * @template T,K,V + * @type {AssocFunction<CollisionNode<K,V>,K,V>} + */ +function assocCollision(root, shift, hash, key, val, addedLeaf) { + // if there is a hash collision + if (hash === root.hash) { + const idx = collisionIndexOf(root, key); + // if this key already exists replace the entry with the new value + if (idx !== -1) { + const entry = root.array[idx]; + if (entry.v === val) { + return root; + } + return { + type: COLLISION_NODE, + hash: hash, + array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }), + }; + } + // otherwise insert the entry at the end of the array + const size = root.array.length; + addedLeaf.val = true; + return { + type: COLLISION_NODE, + hash: hash, + array: cloneAndSet(root.array, size, { type: ENTRY, k: key, v: val }), + }; + } + // if there is no hash collision, upgrade to an index node + return assoc( + { + type: INDEX_NODE, + bitmap: bitpos(root.hash, shift), + array: [root], + }, + shift, + hash, + key, + val, + addedLeaf + ); +} +/** + * Find the index of a key in the collision node's array + * @template K,V + * @param {CollisionNode<K,V>} root + * @param {K} key + * @returns {number} + */ +function collisionIndexOf(root, key) { + const size = root.array.length; + for (let i = 0; i < size; i++) { + if (isEqual(key, root.array[i].k)) { + return i; + } + } + return -1; +} +/** + * @template T,K,V + * @callback FindFunction + * @param {T} root + * @param {number} shift + * @param {number} hash + * @param {K} key + * @returns {undefined | Entry<K,V>} + */ +/** + * Return the found entry or undefined if not present in the root + * @template K,V + * @type {FindFunction<Node<K,V>,K,V>} + */ +function find(root, shift, hash, key) { + switch (root.type) { + case ARRAY_NODE: + return findArray(root, shift, hash, key); + case INDEX_NODE: + return findIndex(root, shift, hash, key); + case COLLISION_NODE: + return findCollision(root, key); + } +} +/** + * @template K,V + * @type {FindFunction<ArrayNode<K,V>,K,V>} + */ +function findArray(root, shift, hash, key) { + const idx = mask(hash, shift); + const node = root.array[idx]; + if (node === undefined) { + return undefined; + } + if (node.type !== ENTRY) { + return find(node, shift + SHIFT, hash, key); + } + if (isEqual(key, node.k)) { + return node; + } + return undefined; +} +/** + * @template K,V + * @type {FindFunction<IndexNode<K,V>,K,V>} + */ +function findIndex(root, shift, hash, key) { + const bit = bitpos(hash, shift); + if ((root.bitmap & bit) === 0) { + return undefined; + } + const idx = index(root.bitmap, bit); + const node = root.array[idx]; + if (node.type !== ENTRY) { + return find(node, shift + SHIFT, hash, key); + } + if (isEqual(key, node.k)) { + return node; + } + return undefined; +} +/** + * @template K,V + * @param {CollisionNode<K,V>} root + * @param {K} key + * @returns {undefined | Entry<K,V>} + */ +function findCollision(root, key) { + const idx = collisionIndexOf(root, key); + if (idx < 0) { + return undefined; + } + return root.array[idx]; +} +/** + * @template T,K,V + * @callback WithoutFunction + * @param {T} root + * @param {number} shift + * @param {number} hash + * @param {K} key + * @returns {undefined | Node<K,V>} + */ +/** + * Remove an entry from the root, returning the updated root. + * Returns undefined if the node should be removed from the parent. + * @template K,V + * @type {WithoutFunction<Node<K,V>,K,V>} + * */ +function without(root, shift, hash, key) { + switch (root.type) { + case ARRAY_NODE: + return withoutArray(root, shift, hash, key); + case INDEX_NODE: + return withoutIndex(root, shift, hash, key); + case COLLISION_NODE: + return withoutCollision(root, key); + } +} +/** + * @template K,V + * @type {WithoutFunction<ArrayNode<K,V>,K,V>} + */ +function withoutArray(root, shift, hash, key) { + const idx = mask(hash, shift); + const node = root.array[idx]; + if (node === undefined) { + return root; // already empty + } + let n = undefined; + // if node is an entry and the keys are not equal there is nothing to remove + // if node is not an entry do a recursive call + if (node.type === ENTRY) { + if (!isEqual(node.k, key)) { + return root; // no changes + } + } else { + n = without(node, shift + SHIFT, hash, key); + if (n === node) { + return root; // no changes + } + } + // if the recursive call returned undefined the node should be removed + if (n === undefined) { + // if the number of child nodes is at the minimum, pack into an index node + if (root.size <= MIN_ARRAY_NODE) { + const arr = root.array; + const out = new Array(root.size - 1); + let i = 0; + let j = 0; + let bitmap = 0; + while (i < idx) { + const nv = arr[i]; + if (nv !== undefined) { + out[j] = nv; + bitmap |= 1 << i; + ++j; + } + ++i; + } + ++i; // skip copying the removed node + while (i < arr.length) { + const nv = arr[i]; + if (nv !== undefined) { + out[j] = nv; + bitmap |= 1 << i; + ++j; + } + ++i; + } + return { + type: INDEX_NODE, + bitmap: bitmap, + array: out, + }; + } + return { + type: ARRAY_NODE, + size: root.size - 1, + array: cloneAndSet(root.array, idx, n), + }; + } + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet(root.array, idx, n), + }; +} +/** + * @template K,V + * @type {WithoutFunction<IndexNode<K,V>,K,V>} + */ +function withoutIndex(root, shift, hash, key) { + const bit = bitpos(hash, shift); + if ((root.bitmap & bit) === 0) { + return root; // already empty + } + const idx = index(root.bitmap, bit); + const node = root.array[idx]; + // if the item is not an entry + if (node.type !== ENTRY) { + const n = without(node, shift + SHIFT, hash, key); + if (n === node) { + return root; // no changes + } + // if not undefined, the child node still has items, so update it + if (n !== undefined) { + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet(root.array, idx, n), + }; + } + // otherwise the child node should be removed + // if it was the only child node, remove this node from the parent + if (root.bitmap === bit) { + return undefined; + } + // otherwise just remove the child node + return { + type: INDEX_NODE, + bitmap: root.bitmap ^ bit, + array: spliceOut(root.array, idx), + }; + } + // otherwise the item is an entry, remove it if the key matches + if (isEqual(key, node.k)) { + if (root.bitmap === bit) { + return undefined; + } + return { + type: INDEX_NODE, + bitmap: root.bitmap ^ bit, + array: spliceOut(root.array, idx), + }; + } + return root; +} +/** + * @template K,V + * @param {CollisionNode<K,V>} root + * @param {K} key + * @returns {undefined | Node<K,V>} + */ +function withoutCollision(root, key) { + const idx = collisionIndexOf(root, key); + // if the key not found, no changes + if (idx < 0) { + return root; + } + // otherwise the entry was found, remove it + // if it was the only entry in this node, remove the whole node + if (root.array.length === 1) { + return undefined; + } + // otherwise just remove the entry + return { + type: COLLISION_NODE, + hash: root.hash, + array: spliceOut(root.array, idx), + }; +} +/** + * @template K,V + * @param {undefined | Node<K,V>} root + * @param {(value:V,key:K)=>void} fn + * @returns {void} + */ +function forEach(root, fn) { + if (root === undefined) { + return; + } + const items = root.array; + const size = items.length; + for (let i = 0; i < size; i++) { + const item = items[i]; + if (item === undefined) { + continue; + } + if (item.type === ENTRY) { + fn(item.v, item.k); + continue; + } + forEach(item, fn); + } +} +/** + * Extra wrapper to keep track of Dict size and clean up the API + * @template K,V + */ +export default class Dict { + /** + * @template V + * @param {Record<string,V>} o + * @returns {Dict<string,V>} + */ + static fromObject(o) { + const keys = Object.keys(o); + /** @type Dict<string,V> */ + let m = Dict.new(); + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; + m = m.set(k, o[k]); + } + return m; + } + /** + * @template K,V + * @param {Map<K,V>} o + * @returns {Dict<K,V>} + */ + static fromMap(o) { + /** @type Dict<K,V> */ + let m = Dict.new(); + o.forEach((v, k) => { + m = m.set(k, v); + }); + return m; + } + static new() { + return new Dict(undefined, 0); + } + /** + * @param {undefined | Node<K,V>} root + * @param {number} size + */ + constructor(root, size) { + this.root = root; + this.size = size; + } + /** + * @template NotFound + * @param {K} key + * @param {NotFound} notFound + * @returns {NotFound | V} + */ + get(key, notFound) { + if (this.root === undefined) { + return notFound; + } + const found = find(this.root, 0, getHash(key), key); + if (found === undefined) { + return notFound; + } + return found.v; + } + /** + * @param {K} key + * @param {V} val + * @returns {Dict<K,V>} + */ + set(key, val) { + const addedLeaf = { val: false }; + const root = this.root === undefined ? EMPTY : this.root; + const newRoot = assoc(root, 0, getHash(key), key, val, addedLeaf); + if (newRoot === this.root) { + return this; + } + return new Dict(newRoot, addedLeaf.val ? this.size + 1 : this.size); + } + /** + * @param {K} key + * @returns {Dict<K,V>} + */ + delete(key) { + if (this.root === undefined) { + return this; + } + const newRoot = without(this.root, 0, getHash(key), key); + if (newRoot === this.root) { + return this; + } + if (newRoot === undefined) { + return Dict.new(); + } + return new Dict(newRoot, this.size - 1); + } + /** + * @param {K} key + * @returns {boolean} + */ + has(key) { + if (this.root === undefined) { + return false; + } + return find(this.root, 0, getHash(key), key) !== undefined; + } + /** + * @returns {[K,V][]} + */ + entries() { + if (this.root === undefined) { + return []; + } + /** @type [K,V][] */ + const result = []; + this.forEach((v, k) => result.push([k, v])); + return result; + } + /** + * + * @param {(val:V,key:K)=>void} fn + */ + forEach(fn) { + forEach(this.root, fn); + } + hashCode() { + let h = 0; + this.forEach((v, k) => { + h = (h + hashMerge(getHash(v), getHash(k))) | 0; + }); + return h; + } + /** + * @param {unknown} o + * @returns {boolean} + */ + equals(o) { + if (!(o instanceof Dict) || this.size !== o.size) { + return false; + } + let equal = true; + this.forEach((v, k) => { + equal = equal && isEqual(o.get(k, !v), v); + }); + return equal; + } +} diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache Binary files differnew file mode 100644 index 0000000..ec2f726 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta Binary files differnew file mode 100644 index 0000000..a935fcc --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.erl new file mode 100644 index 0000000..d8d44c3 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.erl @@ -0,0 +1,20 @@ +-module(gleam@base). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([encode64/2, decode64/1, url_encode64/2, url_decode64/1]). + +-spec encode64(bitstring(), boolean()) -> binary(). +encode64(Input, Padding) -> + gleam@bit_array:base64_encode(Input, Padding). + +-spec decode64(binary()) -> {ok, bitstring()} | {error, nil}. +decode64(Encoded) -> + gleam@bit_array:base64_decode(Encoded). + +-spec url_encode64(bitstring(), boolean()) -> binary(). +url_encode64(Input, Padding) -> + gleam@bit_array:base64_url_encode(Input, Padding). + +-spec url_decode64(binary()) -> {ok, bitstring()} | {error, nil}. +url_decode64(Encoded) -> + gleam@bit_array:base64_url_decode(Encoded). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache Binary files differnew file mode 100644 index 0000000..1019a88 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta Binary files differnew file mode 100644 index 0000000..bfd3dd8 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.erl new file mode 100644 index 0000000..ae8e5ff --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.erl @@ -0,0 +1,102 @@ +-module(gleam@bit_array). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([from_string/1, byte_size/1, slice/3, is_utf8/1, to_string/1, concat/1, append/2, base64_encode/2, base64_decode/1, base64_url_encode/2, base64_url_decode/1, base16_encode/1, base16_decode/1]). + +-spec from_string(binary()) -> bitstring(). +from_string(X) -> + gleam_stdlib:identity(X). + +-spec byte_size(bitstring()) -> integer(). +byte_size(X) -> + erlang:byte_size(X). + +-spec slice(bitstring(), integer(), integer()) -> {ok, bitstring()} | + {error, nil}. +slice(String, Position, Length) -> + gleam_stdlib:bit_array_slice(String, Position, Length). + +-spec do_is_utf8(bitstring()) -> boolean(). +do_is_utf8(Bits) -> + case Bits of + <<>> -> + true; + + <<_/utf8, Rest/binary>> -> + do_is_utf8(Rest); + + _ -> + false + end. + +-spec is_utf8(bitstring()) -> boolean(). +is_utf8(Bits) -> + do_is_utf8(Bits). + +-spec do_to_string(bitstring()) -> {ok, binary()} | {error, nil}. +do_to_string(Bits) -> + case is_utf8(Bits) of + true -> + {ok, gleam_stdlib:identity(Bits)}; + + false -> + {error, nil} + end. + +-spec to_string(bitstring()) -> {ok, binary()} | {error, nil}. +to_string(Bits) -> + do_to_string(Bits). + +-spec concat(list(bitstring())) -> bitstring(). +concat(Bit_arrays) -> + gleam_stdlib:bit_array_concat(Bit_arrays). + +-spec append(bitstring(), bitstring()) -> bitstring(). +append(First, Second) -> + gleam_stdlib:bit_array_concat([First, Second]). + +-spec base64_encode(bitstring(), boolean()) -> binary(). +base64_encode(Input, Padding) -> + Encoded = base64:encode(Input), + case Padding of + true -> + Encoded; + + false -> + gleam@string:replace(Encoded, <<"="/utf8>>, <<""/utf8>>) + end. + +-spec base64_decode(binary()) -> {ok, bitstring()} | {error, nil}. +base64_decode(Encoded) -> + Padded = case erlang:byte_size(gleam_stdlib:identity(Encoded)) rem 4 of + 0 -> + Encoded; + + N -> + gleam@string:append( + Encoded, + gleam@string:repeat(<<"="/utf8>>, 4 - N) + ) + end, + gleam_stdlib:base_decode64(Padded). + +-spec base64_url_encode(bitstring(), boolean()) -> binary(). +base64_url_encode(Input, Padding) -> + _pipe = base64_encode(Input, Padding), + _pipe@1 = gleam@string:replace(_pipe, <<"+"/utf8>>, <<"-"/utf8>>), + gleam@string:replace(_pipe@1, <<"/"/utf8>>, <<"_"/utf8>>). + +-spec base64_url_decode(binary()) -> {ok, bitstring()} | {error, nil}. +base64_url_decode(Encoded) -> + _pipe = Encoded, + _pipe@1 = gleam@string:replace(_pipe, <<"-"/utf8>>, <<"+"/utf8>>), + _pipe@2 = gleam@string:replace(_pipe@1, <<"_"/utf8>>, <<"/"/utf8>>), + base64_decode(_pipe@2). + +-spec base16_encode(bitstring()) -> binary(). +base16_encode(Input) -> + binary:encode_hex(Input). + +-spec base16_decode(binary()) -> {ok, bitstring()} | {error, nil}. +base16_decode(Input) -> + gleam_stdlib:base16_decode(Input). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache Binary files differnew file mode 100644 index 0000000..98cc7fa --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_meta Binary files differnew file mode 100644 index 0000000..bc4a1a5 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.erl new file mode 100644 index 0000000..648605f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.erl @@ -0,0 +1,66 @@ +-module(gleam@bit_builder). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([new/0, prepend/2, append/2, prepend_builder/2, append_builder/2, prepend_string/2, append_string/2, concat/1, concat_bit_strings/1, from_string/1, from_string_builder/1, from_bit_string/1, to_bit_string/1, byte_size/1]). + +-spec new() -> gleam@bytes_builder:bytes_builder(). +new() -> + gleam@bytes_builder:new(). + +-spec prepend(gleam@bytes_builder:bytes_builder(), bitstring()) -> gleam@bytes_builder:bytes_builder(). +prepend(To, Prefix) -> + gleam@bytes_builder:prepend(To, Prefix). + +-spec append(gleam@bytes_builder:bytes_builder(), bitstring()) -> gleam@bytes_builder:bytes_builder(). +append(To, Suffix) -> + gleam@bytes_builder:append(To, Suffix). + +-spec prepend_builder( + gleam@bytes_builder:bytes_builder(), + gleam@bytes_builder:bytes_builder() +) -> gleam@bytes_builder:bytes_builder(). +prepend_builder(To, Prefix) -> + gleam@bytes_builder:prepend_builder(To, Prefix). + +-spec append_builder( + gleam@bytes_builder:bytes_builder(), + gleam@bytes_builder:bytes_builder() +) -> gleam@bytes_builder:bytes_builder(). +append_builder(First, Second) -> + gleam_stdlib:iodata_append(First, Second). + +-spec prepend_string(gleam@bytes_builder:bytes_builder(), binary()) -> gleam@bytes_builder:bytes_builder(). +prepend_string(To, Prefix) -> + gleam@bytes_builder:prepend_string(To, Prefix). + +-spec append_string(gleam@bytes_builder:bytes_builder(), binary()) -> gleam@bytes_builder:bytes_builder(). +append_string(To, Suffix) -> + gleam@bytes_builder:append_string(To, Suffix). + +-spec concat(list(gleam@bytes_builder:bytes_builder())) -> gleam@bytes_builder:bytes_builder(). +concat(Builders) -> + gleam_stdlib:identity(Builders). + +-spec concat_bit_strings(list(bitstring())) -> gleam@bytes_builder:bytes_builder(). +concat_bit_strings(Bits) -> + gleam_stdlib:identity(Bits). + +-spec from_string(binary()) -> gleam@bytes_builder:bytes_builder(). +from_string(String) -> + gleam_stdlib:wrap_list(String). + +-spec from_string_builder(gleam@string_builder:string_builder()) -> gleam@bytes_builder:bytes_builder(). +from_string_builder(Builder) -> + gleam_stdlib:wrap_list(Builder). + +-spec from_bit_string(bitstring()) -> gleam@bytes_builder:bytes_builder(). +from_bit_string(Bits) -> + gleam_stdlib:wrap_list(Bits). + +-spec to_bit_string(gleam@bytes_builder:bytes_builder()) -> bitstring(). +to_bit_string(Builder) -> + erlang:list_to_bitstring(Builder). + +-spec byte_size(gleam@bytes_builder:bytes_builder()) -> integer(). +byte_size(Builder) -> + erlang:iolist_size(Builder). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache Binary files differnew file mode 100644 index 0000000..04638ff --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_meta Binary files differnew file mode 100644 index 0000000..f9f229f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.erl new file mode 100644 index 0000000..d1eea04 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.erl @@ -0,0 +1,33 @@ +-module(gleam@bit_string). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([from_string/1, byte_size/1, append/2, slice/3, is_utf8/1, to_string/1, concat/1]). + +-spec from_string(binary()) -> bitstring(). +from_string(X) -> + gleam_stdlib:identity(X). + +-spec byte_size(bitstring()) -> integer(). +byte_size(X) -> + erlang:byte_size(X). + +-spec append(bitstring(), bitstring()) -> bitstring(). +append(First, Second) -> + gleam@bit_array:append(First, Second). + +-spec slice(bitstring(), integer(), integer()) -> {ok, bitstring()} | + {error, nil}. +slice(String, Position, Length) -> + gleam_stdlib:bit_array_slice(String, Position, Length). + +-spec is_utf8(bitstring()) -> boolean(). +is_utf8(Bits) -> + gleam@bit_array:is_utf8(Bits). + +-spec to_string(bitstring()) -> {ok, binary()} | {error, nil}. +to_string(Bits) -> + gleam@bit_array:to_string(Bits). + +-spec concat(list(bitstring())) -> bitstring(). +concat(Bit_strings) -> + gleam_stdlib:bit_array_concat(Bit_strings). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache Binary files differnew file mode 100644 index 0000000..7ff9604 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta Binary files differnew file mode 100644 index 0000000..33ef24c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.erl new file mode 100644 index 0000000..8f6abcc --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.erl @@ -0,0 +1,162 @@ +-module(gleam@bool). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export(['and'/2, 'or'/2, negate/1, nor/2, nand/2, exclusive_or/2, exclusive_nor/2, compare/2, max/2, min/2, to_int/1, to_string/1, guard/3, lazy_guard/3]). + +-spec 'and'(boolean(), boolean()) -> boolean(). +'and'(A, B) -> + A andalso B. + +-spec 'or'(boolean(), boolean()) -> boolean(). +'or'(A, B) -> + A orelse B. + +-spec negate(boolean()) -> boolean(). +negate(Bool) -> + case Bool of + true -> + false; + + false -> + true + end. + +-spec nor(boolean(), boolean()) -> boolean(). +nor(A, B) -> + case {A, B} of + {false, false} -> + true; + + {false, true} -> + false; + + {true, false} -> + false; + + {true, true} -> + false + end. + +-spec nand(boolean(), boolean()) -> boolean(). +nand(A, B) -> + case {A, B} of + {false, false} -> + true; + + {false, true} -> + true; + + {true, false} -> + true; + + {true, true} -> + false + end. + +-spec exclusive_or(boolean(), boolean()) -> boolean(). +exclusive_or(A, B) -> + case {A, B} of + {false, false} -> + false; + + {false, true} -> + true; + + {true, false} -> + true; + + {true, true} -> + false + end. + +-spec exclusive_nor(boolean(), boolean()) -> boolean(). +exclusive_nor(A, B) -> + case {A, B} of + {false, false} -> + true; + + {false, true} -> + false; + + {true, false} -> + false; + + {true, true} -> + true + end. + +-spec compare(boolean(), boolean()) -> gleam@order:order(). +compare(A, B) -> + case {A, B} of + {true, true} -> + eq; + + {true, false} -> + gt; + + {false, false} -> + eq; + + {false, true} -> + lt + end. + +-spec max(boolean(), boolean()) -> boolean(). +max(A, B) -> + case A of + true -> + true; + + false -> + B + end. + +-spec min(boolean(), boolean()) -> boolean(). +min(A, B) -> + case A of + false -> + false; + + true -> + B + end. + +-spec to_int(boolean()) -> integer(). +to_int(Bool) -> + case Bool of + false -> + 0; + + true -> + 1 + end. + +-spec to_string(boolean()) -> binary(). +to_string(Bool) -> + case Bool of + false -> + <<"False"/utf8>>; + + true -> + <<"True"/utf8>> + end. + +-spec guard(boolean(), CYG, fun(() -> CYG)) -> CYG. +guard(Requirement, Consequence, Alternative) -> + case Requirement of + true -> + Consequence; + + false -> + Alternative() + end. + +-spec lazy_guard(boolean(), fun(() -> CYH), fun(() -> CYH)) -> CYH. +lazy_guard(Requirement, Consequence, Alternative) -> + case Requirement of + true -> + Consequence(); + + false -> + Alternative() + end. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache Binary files differnew file mode 100644 index 0000000..2564637 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_meta Binary files differnew file mode 100644 index 0000000..7b614aa --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.erl new file mode 100644 index 0000000..61851fc --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.erl @@ -0,0 +1,87 @@ +-module(gleam@bytes_builder). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([append_builder/2, prepend_builder/2, concat/1, new/0, from_string/1, prepend_string/2, append_string/2, from_string_builder/1, from_bit_array/1, prepend/2, append/2, concat_bit_arrays/1, to_bit_array/1, byte_size/1]). +-export_type([bytes_builder/0]). + +-opaque bytes_builder() :: {bytes, bitstring()} | + {text, gleam@string_builder:string_builder()} | + {many, list(bytes_builder())}. + +-spec append_builder(bytes_builder(), bytes_builder()) -> bytes_builder(). +append_builder(First, Second) -> + gleam_stdlib:iodata_append(First, Second). + +-spec prepend_builder(bytes_builder(), bytes_builder()) -> bytes_builder(). +prepend_builder(Second, First) -> + gleam_stdlib:iodata_append(First, Second). + +-spec concat(list(bytes_builder())) -> bytes_builder(). +concat(Builders) -> + gleam_stdlib:identity(Builders). + +-spec new() -> bytes_builder(). +new() -> + gleam_stdlib:identity([]). + +-spec from_string(binary()) -> bytes_builder(). +from_string(String) -> + gleam_stdlib:wrap_list(String). + +-spec prepend_string(bytes_builder(), binary()) -> bytes_builder(). +prepend_string(Second, First) -> + gleam_stdlib:iodata_append(gleam_stdlib:wrap_list(First), Second). + +-spec append_string(bytes_builder(), binary()) -> bytes_builder(). +append_string(First, Second) -> + gleam_stdlib:iodata_append(First, gleam_stdlib:wrap_list(Second)). + +-spec from_string_builder(gleam@string_builder:string_builder()) -> bytes_builder(). +from_string_builder(Builder) -> + gleam_stdlib:wrap_list(Builder). + +-spec from_bit_array(bitstring()) -> bytes_builder(). +from_bit_array(Bits) -> + gleam_stdlib:wrap_list(Bits). + +-spec prepend(bytes_builder(), bitstring()) -> bytes_builder(). +prepend(Second, First) -> + gleam_stdlib:iodata_append(gleam_stdlib:wrap_list(First), Second). + +-spec append(bytes_builder(), bitstring()) -> bytes_builder(). +append(First, Second) -> + gleam_stdlib:iodata_append(First, gleam_stdlib:wrap_list(Second)). + +-spec concat_bit_arrays(list(bitstring())) -> bytes_builder(). +concat_bit_arrays(Bits) -> + gleam_stdlib:identity(Bits). + +-spec to_list(list(list(bytes_builder())), list(bitstring())) -> list(bitstring()). +to_list(Stack, Acc) -> + case Stack of + [] -> + Acc; + + [[] | Remaining_stack] -> + to_list(Remaining_stack, Acc); + + [[{bytes, Bits} | Rest] | Remaining_stack@1] -> + to_list([Rest | Remaining_stack@1], [Bits | Acc]); + + [[{text, Builder} | Rest@1] | Remaining_stack@2] -> + Bits@1 = gleam_stdlib:identity( + gleam@string_builder:to_string(Builder) + ), + to_list([Rest@1 | Remaining_stack@2], [Bits@1 | Acc]); + + [[{many, Builders} | Rest@2] | Remaining_stack@3] -> + to_list([Builders, Rest@2 | Remaining_stack@3], Acc) + end. + +-spec to_bit_array(bytes_builder()) -> bitstring(). +to_bit_array(Builder) -> + erlang:list_to_bitstring(Builder). + +-spec byte_size(bytes_builder()) -> integer(). +byte_size(Builder) -> + erlang:iolist_size(Builder). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache Binary files differnew file mode 100644 index 0000000..2aa2fe6 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta Binary files differnew file mode 100644 index 0000000..4410520 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.erl new file mode 100644 index 0000000..8dd79fd --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.erl @@ -0,0 +1,97 @@ +-module(gleam@dict). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([size/1, to_list/1, from_list/1, has_key/2, new/0, get/2, insert/3, map_values/2, keys/1, values/1, filter/2, take/2, merge/2, delete/2, drop/2, update/3, fold/3]). +-export_type([dict/2]). + +-type dict(KS, KT) :: any() | {gleam_phantom, KS, KT}. + +-spec size(dict(any(), any())) -> integer(). +size(Dict) -> + maps:size(Dict). + +-spec to_list(dict(LC, LD)) -> list({LC, LD}). +to_list(Dict) -> + maps:to_list(Dict). + +-spec from_list(list({LM, LN})) -> dict(LM, LN). +from_list(List) -> + maps:from_list(List). + +-spec has_key(dict(LW, any()), LW) -> boolean(). +has_key(Dict, Key) -> + maps:is_key(Key, Dict). + +-spec new() -> dict(any(), any()). +new() -> + maps:new(). + +-spec get(dict(MM, MN), MM) -> {ok, MN} | {error, nil}. +get(From, Get) -> + gleam_stdlib:map_get(From, Get). + +-spec insert(dict(MY, MZ), MY, MZ) -> dict(MY, MZ). +insert(Dict, Key, Value) -> + maps:put(Key, Value, Dict). + +-spec map_values(dict(NK, NL), fun((NK, NL) -> NO)) -> dict(NK, NO). +map_values(Dict, Fun) -> + maps:map(Fun, Dict). + +-spec keys(dict(NY, any())) -> list(NY). +keys(Dict) -> + maps:keys(Dict). + +-spec values(dict(any(), OJ)) -> list(OJ). +values(Dict) -> + maps:values(Dict). + +-spec filter(dict(OS, OT), fun((OS, OT) -> boolean())) -> dict(OS, OT). +filter(Dict, Predicate) -> + maps:filter(Predicate, Dict). + +-spec take(dict(PE, PF), list(PE)) -> dict(PE, PF). +take(Dict, Desired_keys) -> + maps:with(Desired_keys, Dict). + +-spec merge(dict(PS, PT), dict(PS, PT)) -> dict(PS, PT). +merge(Dict, New_entries) -> + maps:merge(Dict, New_entries). + +-spec delete(dict(QI, QJ), QI) -> dict(QI, QJ). +delete(Dict, Key) -> + maps:remove(Key, Dict). + +-spec drop(dict(QU, QV), list(QU)) -> dict(QU, QV). +drop(Dict, Disallowed_keys) -> + case Disallowed_keys of + [] -> + Dict; + + [X | Xs] -> + drop(delete(Dict, X), Xs) + end. + +-spec update(dict(RB, RC), RB, fun((gleam@option:option(RC)) -> RC)) -> dict(RB, RC). +update(Dict, Key, Fun) -> + _pipe = Dict, + _pipe@1 = get(_pipe, Key), + _pipe@2 = gleam@option:from_result(_pipe@1), + _pipe@3 = Fun(_pipe@2), + insert(Dict, Key, _pipe@3). + +-spec do_fold(list({RI, RJ}), RL, fun((RL, RI, RJ) -> RL)) -> RL. +do_fold(List, Initial, Fun) -> + case List of + [] -> + Initial; + + [{K, V} | Rest] -> + do_fold(Rest, Fun(Initial, K, V), Fun) + end. + +-spec fold(dict(RM, RN), RQ, fun((RQ, RM, RN) -> RQ)) -> RQ. +fold(Dict, Initial, Fun) -> + _pipe = Dict, + _pipe@1 = to_list(_pipe), + do_fold(_pipe@1, Initial, Fun). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache Binary files differnew file mode 100644 index 0000000..810ef80 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta Binary files differnew file mode 100644 index 0000000..9ae5074 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.erl new file mode 100644 index 0000000..8475e8c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.erl @@ -0,0 +1,808 @@ +-module(gleam@dynamic). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([from/1, unsafe_coerce/1, dynamic/1, bit_array/1, bit_string/1, classify/1, int/1, float/1, bool/1, shallow_list/1, optional/1, any/1, decode1/2, result/2, list/1, string/1, field/2, optional_field/2, element/2, tuple2/2, tuple3/3, tuple4/4, tuple5/5, tuple6/6, dict/2, map/2, decode2/3, decode3/4, decode4/5, decode5/6, decode6/7, decode7/8, decode8/9, decode9/10]). +-export_type([dynamic_/0, decode_error/0, unknown_tuple/0]). + +-type dynamic_() :: any(). + +-type decode_error() :: {decode_error, binary(), binary(), list(binary())}. + +-type unknown_tuple() :: any(). + +-spec from(any()) -> dynamic_(). +from(A) -> + gleam_stdlib:identity(A). + +-spec unsafe_coerce(dynamic_()) -> any(). +unsafe_coerce(A) -> + gleam_stdlib:identity(A). + +-spec dynamic(dynamic_()) -> {ok, dynamic_()} | {error, list(decode_error())}. +dynamic(Value) -> + {ok, Value}. + +-spec bit_array(dynamic_()) -> {ok, bitstring()} | {error, list(decode_error())}. +bit_array(Data) -> + gleam_stdlib:decode_bit_array(Data). + +-spec bit_string(dynamic_()) -> {ok, bitstring()} | + {error, list(decode_error())}. +bit_string(Data) -> + bit_array(Data). + +-spec put_expected(decode_error(), binary()) -> decode_error(). +put_expected(Error, Expected) -> + erlang:setelement(2, Error, Expected). + +-spec classify(dynamic_()) -> binary(). +classify(Data) -> + gleam_stdlib:classify_dynamic(Data). + +-spec int(dynamic_()) -> {ok, integer()} | {error, list(decode_error())}. +int(Data) -> + gleam_stdlib:decode_int(Data). + +-spec float(dynamic_()) -> {ok, float()} | {error, list(decode_error())}. +float(Data) -> + gleam_stdlib:decode_float(Data). + +-spec bool(dynamic_()) -> {ok, boolean()} | {error, list(decode_error())}. +bool(Data) -> + gleam_stdlib:decode_bool(Data). + +-spec shallow_list(dynamic_()) -> {ok, list(dynamic_())} | + {error, list(decode_error())}. +shallow_list(Value) -> + gleam_stdlib:decode_list(Value). + +-spec optional(fun((dynamic_()) -> {ok, DVA} | {error, list(decode_error())})) -> fun((dynamic_()) -> {ok, + gleam@option:option(DVA)} | + {error, list(decode_error())}). +optional(Decode) -> + fun(Value) -> gleam_stdlib:decode_option(Value, Decode) end. + +-spec at_least_decode_tuple_error(integer(), dynamic_()) -> {ok, any()} | + {error, list(decode_error())}. +at_least_decode_tuple_error(Size, Data) -> + S = case Size of + 1 -> + <<""/utf8>>; + + _ -> + <<"s"/utf8>> + end, + Error = begin + _pipe = [<<"Tuple of at least "/utf8>>, + gleam@int:to_string(Size), + <<" element"/utf8>>, + S], + _pipe@1 = gleam@string_builder:from_strings(_pipe), + _pipe@2 = gleam@string_builder:to_string(_pipe@1), + {decode_error, _pipe@2, classify(Data), []} + end, + {error, [Error]}. + +-spec any(list(fun((dynamic_()) -> {ok, DZH} | {error, list(decode_error())}))) -> fun((dynamic_()) -> {ok, + DZH} | + {error, list(decode_error())}). +any(Decoders) -> + fun(Data) -> case Decoders of + [] -> + {error, + [{decode_error, <<"another type"/utf8>>, classify(Data), []}]}; + + [Decoder | Decoders@1] -> + case Decoder(Data) of + {ok, Decoded} -> + {ok, Decoded}; + + {error, _} -> + (any(Decoders@1))(Data) + end + end end. + +-spec all_errors({ok, any()} | {error, list(decode_error())}) -> list(decode_error()). +all_errors(Result) -> + case Result of + {ok, _} -> + []; + + {error, Errors} -> + Errors + end. + +-spec decode1( + fun((DZL) -> DZM), + fun((dynamic_()) -> {ok, DZL} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DZM} | {error, list(decode_error())}). +decode1(Constructor, T1) -> + fun(Value) -> case T1(Value) of + {ok, A} -> + {ok, Constructor(A)}; + + A@1 -> + {error, all_errors(A@1)} + end end. + +-spec push_path(decode_error(), any()) -> decode_error(). +push_path(Error, Name) -> + Name@1 = from(Name), + Decoder = any( + [fun string/1, + fun(X) -> gleam@result:map(int(X), fun gleam@int:to_string/1) end] + ), + Name@3 = case Decoder(Name@1) of + {ok, Name@2} -> + Name@2; + + {error, _} -> + _pipe = [<<"<"/utf8>>, classify(Name@1), <<">"/utf8>>], + _pipe@1 = gleam@string_builder:from_strings(_pipe), + gleam@string_builder:to_string(_pipe@1) + end, + erlang:setelement(4, Error, [Name@3 | erlang:element(4, Error)]). + +-spec result( + fun((dynamic_()) -> {ok, DUO} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DUQ} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {ok, DUO} | {error, DUQ}} | + {error, list(decode_error())}). +result(Decode_ok, Decode_error) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_result(Value), + fun(Inner_result) -> case Inner_result of + {ok, Raw} -> + gleam@result:'try'( + begin + _pipe = Decode_ok(Raw), + map_errors( + _pipe, + fun(_capture) -> + push_path(_capture, <<"ok"/utf8>>) + end + ) + end, + fun(Value@1) -> {ok, {ok, Value@1}} end + ); + + {error, Raw@1} -> + gleam@result:'try'( + begin + _pipe@1 = Decode_error(Raw@1), + map_errors( + _pipe@1, + fun(_capture@1) -> + push_path(_capture@1, <<"error"/utf8>>) + end + ) + end, + fun(Value@2) -> {ok, {error, Value@2}} end + ) + end end + ) + end. + +-spec list(fun((dynamic_()) -> {ok, DUV} | {error, list(decode_error())})) -> fun((dynamic_()) -> {ok, + list(DUV)} | + {error, list(decode_error())}). +list(Decoder_type) -> + fun(Dynamic) -> + gleam@result:'try'(shallow_list(Dynamic), fun(List) -> _pipe = List, + _pipe@1 = gleam@list:try_map(_pipe, Decoder_type), + map_errors( + _pipe@1, + fun(_capture) -> push_path(_capture, <<"*"/utf8>>) end + ) end) + end. + +-spec map_errors( + {ok, DTJ} | {error, list(decode_error())}, + fun((decode_error()) -> decode_error()) +) -> {ok, DTJ} | {error, list(decode_error())}. +map_errors(Result, F) -> + gleam@result:map_error( + Result, + fun(_capture) -> gleam@list:map(_capture, F) end + ). + +-spec decode_string(dynamic_()) -> {ok, binary()} | + {error, list(decode_error())}. +decode_string(Data) -> + _pipe = bit_array(Data), + _pipe@1 = map_errors( + _pipe, + fun(_capture) -> put_expected(_capture, <<"String"/utf8>>) end + ), + gleam@result:'try'( + _pipe@1, + fun(Raw) -> case gleam@bit_array:to_string(Raw) of + {ok, String} -> + {ok, String}; + + {error, nil} -> + {error, + [{decode_error, + <<"String"/utf8>>, + <<"BitArray"/utf8>>, + []}]} + end end + ). + +-spec string(dynamic_()) -> {ok, binary()} | {error, list(decode_error())}. +string(Data) -> + decode_string(Data). + +-spec field( + any(), + fun((dynamic_()) -> {ok, DVK} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DVK} | {error, list(decode_error())}). +field(Name, Inner_type) -> + fun(Value) -> + Missing_field_error = {decode_error, + <<"field"/utf8>>, + <<"nothing"/utf8>>, + []}, + gleam@result:'try'( + gleam_stdlib:decode_field(Value, Name), + fun(Maybe_inner) -> _pipe = Maybe_inner, + _pipe@1 = gleam@option:to_result(_pipe, [Missing_field_error]), + _pipe@2 = gleam@result:'try'(_pipe@1, Inner_type), + map_errors( + _pipe@2, + fun(_capture) -> push_path(_capture, Name) end + ) end + ) + end. + +-spec optional_field( + any(), + fun((dynamic_()) -> {ok, DVO} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, gleam@option:option(DVO)} | + {error, list(decode_error())}). +optional_field(Name, Inner_type) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_field(Value, Name), + fun(Maybe_inner) -> case Maybe_inner of + none -> + {ok, none}; + + {some, Dynamic_inner} -> + _pipe = Dynamic_inner, + _pipe@1 = gleam_stdlib:decode_option(_pipe, Inner_type), + map_errors( + _pipe@1, + fun(_capture) -> push_path(_capture, Name) end + ) + end end + ) + end. + +-spec element( + integer(), + fun((dynamic_()) -> {ok, DVW} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DVW} | {error, list(decode_error())}). +element(Index, Inner_type) -> + fun(Data) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple(Data), + fun(Tuple) -> + Size = gleam_stdlib:size_of_tuple(Tuple), + gleam@result:'try'(case Index >= 0 of + true -> + case Index < Size of + true -> + gleam_stdlib:tuple_get(Tuple, Index); + + false -> + at_least_decode_tuple_error(Index + 1, Data) + end; + + false -> + case gleam@int:absolute_value(Index) =< Size of + true -> + gleam_stdlib:tuple_get(Tuple, Size + Index); + + false -> + at_least_decode_tuple_error( + gleam@int:absolute_value(Index), + Data + ) + end + end, fun(Data@1) -> _pipe = Inner_type(Data@1), + map_errors( + _pipe, + fun(_capture) -> push_path(_capture, Index) end + ) end) + end + ) + end. + +-spec tuple_errors({ok, any()} | {error, list(decode_error())}, binary()) -> list(decode_error()). +tuple_errors(Result, Name) -> + case Result of + {ok, _} -> + []; + + {error, Errors} -> + gleam@list:map( + Errors, + fun(_capture) -> push_path(_capture, Name) end + ) + end. + +-spec tuple2( + fun((dynamic_()) -> {ok, DWW} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DWY} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {DWW, DWY}} | {error, list(decode_error())}). +tuple2(Decode1, Decode2) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple2(Value), + fun(_use0) -> + {A, B} = _use0, + case {Decode1(A), Decode2(B)} of + {{ok, A@1}, {ok, B@1}} -> + {ok, {A@1, B@1}}; + + {A@2, B@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + {error, _pipe@1} + end + end + ) + end. + +-spec tuple3( + fun((dynamic_()) -> {ok, DXB} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXD} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXF} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {DXB, DXD, DXF}} | {error, list(decode_error())}). +tuple3(Decode1, Decode2, Decode3) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple3(Value), + fun(_use0) -> + {A, B, C} = _use0, + case {Decode1(A), Decode2(B), Decode3(C)} of + {{ok, A@1}, {ok, B@1}, {ok, C@1}} -> + {ok, {A@1, B@1, C@1}}; + + {A@2, B@2, C@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + {error, _pipe@2} + end + end + ) + end. + +-spec tuple4( + fun((dynamic_()) -> {ok, DXI} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXK} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXM} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXO} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {DXI, DXK, DXM, DXO}} | + {error, list(decode_error())}). +tuple4(Decode1, Decode2, Decode3, Decode4) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple4(Value), + fun(_use0) -> + {A, B, C, D} = _use0, + case {Decode1(A), Decode2(B), Decode3(C), Decode4(D)} of + {{ok, A@1}, {ok, B@1}, {ok, C@1}, {ok, D@1}} -> + {ok, {A@1, B@1, C@1, D@1}}; + + {A@2, B@2, C@2, D@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + _pipe@3 = gleam@list:append( + _pipe@2, + tuple_errors(D@2, <<"3"/utf8>>) + ), + {error, _pipe@3} + end + end + ) + end. + +-spec tuple5( + fun((dynamic_()) -> {ok, DXR} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXT} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXV} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXX} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXZ} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {DXR, DXT, DXV, DXX, DXZ}} | + {error, list(decode_error())}). +tuple5(Decode1, Decode2, Decode3, Decode4, Decode5) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple5(Value), + fun(_use0) -> + {A, B, C, D, E} = _use0, + case {Decode1(A), + Decode2(B), + Decode3(C), + Decode4(D), + Decode5(E)} of + {{ok, A@1}, {ok, B@1}, {ok, C@1}, {ok, D@1}, {ok, E@1}} -> + {ok, {A@1, B@1, C@1, D@1, E@1}}; + + {A@2, B@2, C@2, D@2, E@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + _pipe@3 = gleam@list:append( + _pipe@2, + tuple_errors(D@2, <<"3"/utf8>>) + ), + _pipe@4 = gleam@list:append( + _pipe@3, + tuple_errors(E@2, <<"4"/utf8>>) + ), + {error, _pipe@4} + end + end + ) + end. + +-spec tuple6( + fun((dynamic_()) -> {ok, DYC} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DYE} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DYG} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DYI} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DYK} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DYM} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {DYC, DYE, DYG, DYI, DYK, DYM}} | + {error, list(decode_error())}). +tuple6(Decode1, Decode2, Decode3, Decode4, Decode5, Decode6) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple6(Value), + fun(_use0) -> + {A, B, C, D, E, F} = _use0, + case {Decode1(A), + Decode2(B), + Decode3(C), + Decode4(D), + Decode5(E), + Decode6(F)} of + {{ok, A@1}, + {ok, B@1}, + {ok, C@1}, + {ok, D@1}, + {ok, E@1}, + {ok, F@1}} -> + {ok, {A@1, B@1, C@1, D@1, E@1, F@1}}; + + {A@2, B@2, C@2, D@2, E@2, F@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + _pipe@3 = gleam@list:append( + _pipe@2, + tuple_errors(D@2, <<"3"/utf8>>) + ), + _pipe@4 = gleam@list:append( + _pipe@3, + tuple_errors(E@2, <<"4"/utf8>>) + ), + _pipe@5 = gleam@list:append( + _pipe@4, + tuple_errors(F@2, <<"5"/utf8>>) + ), + {error, _pipe@5} + end + end + ) + end. + +-spec dict( + fun((dynamic_()) -> {ok, DYP} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DYR} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, gleam@dict:dict(DYP, DYR)} | + {error, list(decode_error())}). +dict(Key_type, Value_type) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_map(Value), + fun(Map) -> + gleam@result:'try'( + begin + _pipe = Map, + _pipe@1 = gleam@dict:to_list(_pipe), + gleam@list:try_map( + _pipe@1, + fun(Pair) -> + {K, V} = Pair, + gleam@result:'try'( + begin + _pipe@2 = Key_type(K), + map_errors( + _pipe@2, + fun(_capture) -> + push_path( + _capture, + <<"keys"/utf8>> + ) + end + ) + end, + fun(K@1) -> + gleam@result:'try'( + begin + _pipe@3 = Value_type(V), + map_errors( + _pipe@3, + fun(_capture@1) -> + push_path( + _capture@1, + <<"values"/utf8>> + ) + end + ) + end, + fun(V@1) -> {ok, {K@1, V@1}} end + ) + end + ) + end + ) + end, + fun(Pairs) -> {ok, gleam@dict:from_list(Pairs)} end + ) + end + ) + end. + +-spec map( + fun((dynamic_()) -> {ok, DYW} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DYY} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, gleam@dict:dict(DYW, DYY)} | + {error, list(decode_error())}). +map(Key_type, Value_type) -> + dict(Key_type, Value_type). + +-spec decode2( + fun((DZP, DZQ) -> DZR), + fun((dynamic_()) -> {ok, DZP} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DZQ} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DZR} | {error, list(decode_error())}). +decode2(Constructor, T1, T2) -> + fun(Value) -> case {T1(Value), T2(Value)} of + {{ok, A}, {ok, B}} -> + {ok, Constructor(A, B)}; + + {A@1, B@1} -> + {error, gleam@list:concat([all_errors(A@1), all_errors(B@1)])} + end end. + +-spec decode3( + fun((DZV, DZW, DZX) -> DZY), + fun((dynamic_()) -> {ok, DZV} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DZW} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DZX} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DZY} | {error, list(decode_error())}). +decode3(Constructor, T1, T2, T3) -> + fun(Value) -> case {T1(Value), T2(Value), T3(Value)} of + {{ok, A}, {ok, B}, {ok, C}} -> + {ok, Constructor(A, B, C)}; + + {A@1, B@1, C@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), all_errors(B@1), all_errors(C@1)] + )} + end end. + +-spec decode4( + fun((EAD, EAE, EAF, EAG) -> EAH), + fun((dynamic_()) -> {ok, EAD} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EAE} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EAF} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EAG} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EAH} | {error, list(decode_error())}). +decode4(Constructor, T1, T2, T3, T4) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}} -> + {ok, Constructor(A, B, C, D)}; + + {A@1, B@1, C@1, D@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1)] + )} + end end. + +-spec decode5( + fun((EAN, EAO, EAP, EAQ, EAR) -> EAS), + fun((dynamic_()) -> {ok, EAN} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EAO} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EAP} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EAQ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EAR} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EAS} | {error, list(decode_error())}). +decode5(Constructor, T1, T2, T3, T4, T5) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}, {ok, E}} -> + {ok, Constructor(A, B, C, D, E)}; + + {A@1, B@1, C@1, D@1, E@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1)] + )} + end end. + +-spec decode6( + fun((EAZ, EBA, EBB, EBC, EBD, EBE) -> EBF), + fun((dynamic_()) -> {ok, EAZ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBA} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBB} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBC} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBD} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBE} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EBF} | {error, list(decode_error())}). +decode6(Constructor, T1, T2, T3, T4, T5, T6) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}, {ok, E}, {ok, F}} -> + {ok, Constructor(A, B, C, D, E, F)}; + + {A@1, B@1, C@1, D@1, E@1, F@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1)] + )} + end end. + +-spec decode7( + fun((EBN, EBO, EBP, EBQ, EBR, EBS, EBT) -> EBU), + fun((dynamic_()) -> {ok, EBN} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBO} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBP} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBQ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBR} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBS} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBT} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EBU} | {error, list(decode_error())}). +decode7(Constructor, T1, T2, T3, T4, T5, T6, T7) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X), T7(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}, {ok, E}, {ok, F}, {ok, G}} -> + {ok, Constructor(A, B, C, D, E, F, G)}; + + {A@1, B@1, C@1, D@1, E@1, F@1, G@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1), + all_errors(G@1)] + )} + end end. + +-spec decode8( + fun((ECD, ECE, ECF, ECG, ECH, ECI, ECJ, ECK) -> ECL), + fun((dynamic_()) -> {ok, ECD} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECE} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECF} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECG} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECH} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECI} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECJ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECK} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, ECL} | {error, list(decode_error())}). +decode8(Constructor, T1, T2, T3, T4, T5, T6, T7, T8) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X), T7(X), T8(X)} of + {{ok, A}, + {ok, B}, + {ok, C}, + {ok, D}, + {ok, E}, + {ok, F}, + {ok, G}, + {ok, H}} -> + {ok, Constructor(A, B, C, D, E, F, G, H)}; + + {A@1, B@1, C@1, D@1, E@1, F@1, G@1, H@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1), + all_errors(G@1), + all_errors(H@1)] + )} + end end. + +-spec decode9( + fun((ECV, ECW, ECX, ECY, ECZ, EDA, EDB, EDC, EDD) -> EDE), + fun((dynamic_()) -> {ok, ECV} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECW} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECX} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECY} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECZ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EDA} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EDB} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EDC} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EDD} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EDE} | {error, list(decode_error())}). +decode9(Constructor, T1, T2, T3, T4, T5, T6, T7, T8, T9) -> + fun(X) -> + case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X), T7(X), T8(X), T9(X)} of + {{ok, A}, + {ok, B}, + {ok, C}, + {ok, D}, + {ok, E}, + {ok, F}, + {ok, G}, + {ok, H}, + {ok, I}} -> + {ok, Constructor(A, B, C, D, E, F, G, H, I)}; + + {A@1, B@1, C@1, D@1, E@1, F@1, G@1, H@1, I@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1), + all_errors(G@1), + all_errors(H@1), + all_errors(I@1)] + )} + end + end. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache Binary files differnew file mode 100644 index 0000000..94e0f92 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta Binary files differnew file mode 100644 index 0000000..f10b39f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.erl new file mode 100644 index 0000000..50e3ea3 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.erl @@ -0,0 +1,181 @@ +-module(gleam@float). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([parse/1, to_string/1, compare/2, min/2, max/2, clamp/3, ceiling/1, floor/1, round/1, truncate/1, absolute_value/1, loosely_compare/3, loosely_equals/3, power/2, square_root/1, negate/1, sum/1, product/1, random/2, divide/2, add/2, multiply/2, subtract/2]). + +-spec parse(binary()) -> {ok, float()} | {error, nil}. +parse(String) -> + gleam_stdlib:parse_float(String). + +-spec to_string(float()) -> binary(). +to_string(X) -> + gleam_stdlib:float_to_string(X). + +-spec compare(float(), float()) -> gleam@order:order(). +compare(A, B) -> + case A =:= B of + true -> + eq; + + false -> + case A < B of + true -> + lt; + + false -> + gt + end + end. + +-spec min(float(), float()) -> float(). +min(A, B) -> + case A < B of + true -> + A; + + false -> + B + end. + +-spec max(float(), float()) -> float(). +max(A, B) -> + case A > B of + true -> + A; + + false -> + B + end. + +-spec clamp(float(), float(), float()) -> float(). +clamp(X, Min_bound, Max_bound) -> + _pipe = X, + _pipe@1 = min(_pipe, Max_bound), + max(_pipe@1, Min_bound). + +-spec ceiling(float()) -> float(). +ceiling(X) -> + math:ceil(X). + +-spec floor(float()) -> float(). +floor(X) -> + math:floor(X). + +-spec round(float()) -> integer(). +round(X) -> + erlang:round(X). + +-spec truncate(float()) -> integer(). +truncate(X) -> + erlang:trunc(X). + +-spec absolute_value(float()) -> float(). +absolute_value(X) -> + case X >= +0.0 of + true -> + X; + + _ -> + +0.0 - X + end. + +-spec loosely_compare(float(), float(), float()) -> gleam@order:order(). +loosely_compare(A, B, Tolerance) -> + Difference = absolute_value(A - B), + case Difference =< Tolerance of + true -> + eq; + + false -> + compare(A, B) + end. + +-spec loosely_equals(float(), float(), float()) -> boolean(). +loosely_equals(A, B, Tolerance) -> + Difference = absolute_value(A - B), + Difference =< Tolerance. + +-spec power(float(), float()) -> {ok, float()} | {error, nil}. +power(Base, Exponent) -> + Fractional = (ceiling(Exponent) - Exponent) > +0.0, + case ((Base < +0.0) andalso Fractional) orelse ((Base =:= +0.0) andalso (Exponent + < +0.0)) of + true -> + {error, nil}; + + false -> + {ok, math:pow(Base, Exponent)} + end. + +-spec square_root(float()) -> {ok, float()} | {error, nil}. +square_root(X) -> + power(X, 0.5). + +-spec negate(float()) -> float(). +negate(X) -> + -1.0 * X. + +-spec do_sum(list(float()), float()) -> float(). +do_sum(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_sum(Rest, X + Initial) + end. + +-spec sum(list(float())) -> float(). +sum(Numbers) -> + _pipe = Numbers, + do_sum(_pipe, +0.0). + +-spec do_product(list(float()), float()) -> float(). +do_product(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_product(Rest, X * Initial) + end. + +-spec product(list(float())) -> float(). +product(Numbers) -> + case Numbers of + [] -> + 1.0; + + _ -> + do_product(Numbers, 1.0) + end. + +-spec random(float(), float()) -> float(). +random(Min, Max) -> + (rand:uniform() * (Max - Min)) + Min. + +-spec divide(float(), float()) -> {ok, float()} | {error, nil}. +divide(A, B) -> + case B of + +0.0 -> + {error, nil}; + + B@1 -> + {ok, case B@1 of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> A / Gleam@denominator + end} + end. + +-spec add(float(), float()) -> float(). +add(A, B) -> + A + B. + +-spec multiply(float(), float()) -> float(). +multiply(A, B) -> + A * B. + +-spec subtract(float(), float()) -> float(). +subtract(A, B) -> + A - B. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache Binary files differnew file mode 100644 index 0000000..f9fe0f4 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta Binary files differnew file mode 100644 index 0000000..ffb4624 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.erl new file mode 100644 index 0000000..524293a --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.erl @@ -0,0 +1,67 @@ +-module(gleam@function). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([compose/2, curry2/1, curry3/1, curry4/1, curry5/1, curry6/1, flip/1, identity/1, constant/1, tap/2, apply1/2, apply2/3, apply3/4]). + +-spec compose(fun((DFV) -> DFW), fun((DFW) -> DFX)) -> fun((DFV) -> DFX). +compose(Fun1, Fun2) -> + fun(A) -> Fun2(Fun1(A)) end. + +-spec curry2(fun((DFY, DFZ) -> DGA)) -> fun((DFY) -> fun((DFZ) -> DGA)). +curry2(Fun) -> + fun(A) -> fun(B) -> Fun(A, B) end end. + +-spec curry3(fun((DGC, DGD, DGE) -> DGF)) -> fun((DGC) -> fun((DGD) -> fun((DGE) -> DGF))). +curry3(Fun) -> + fun(A) -> fun(B) -> fun(C) -> Fun(A, B, C) end end end. + +-spec curry4(fun((DGH, DGI, DGJ, DGK) -> DGL)) -> fun((DGH) -> fun((DGI) -> fun((DGJ) -> fun((DGK) -> DGL)))). +curry4(Fun) -> + fun(A) -> fun(B) -> fun(C) -> fun(D) -> Fun(A, B, C, D) end end end end. + +-spec curry5(fun((DGN, DGO, DGP, DGQ, DGR) -> DGS)) -> fun((DGN) -> fun((DGO) -> fun((DGP) -> fun((DGQ) -> fun((DGR) -> DGS))))). +curry5(Fun) -> + fun(A) -> + fun(B) -> + fun(C) -> fun(D) -> fun(E) -> Fun(A, B, C, D, E) end end end + end + end. + +-spec curry6(fun((DGU, DGV, DGW, DGX, DGY, DGZ) -> DHA)) -> fun((DGU) -> fun((DGV) -> fun((DGW) -> fun((DGX) -> fun((DGY) -> fun((DGZ) -> DHA)))))). +curry6(Fun) -> + fun(A) -> + fun(B) -> + fun(C) -> + fun(D) -> fun(E) -> fun(F) -> Fun(A, B, C, D, E, F) end end end + end + end + end. + +-spec flip(fun((DHC, DHD) -> DHE)) -> fun((DHD, DHC) -> DHE). +flip(Fun) -> + fun(B, A) -> Fun(A, B) end. + +-spec identity(DHF) -> DHF. +identity(X) -> + X. + +-spec constant(DHG) -> fun((any()) -> DHG). +constant(Value) -> + fun(_) -> Value end. + +-spec tap(DHI, fun((DHI) -> any())) -> DHI. +tap(Arg, Effect) -> + Effect(Arg), + Arg. + +-spec apply1(fun((DHK) -> DHL), DHK) -> DHL. +apply1(Fun, Arg1) -> + Fun(Arg1). + +-spec apply2(fun((DHM, DHN) -> DHO), DHM, DHN) -> DHO. +apply2(Fun, Arg1, Arg2) -> + Fun(Arg1, Arg2). + +-spec apply3(fun((DHP, DHQ, DHR) -> DHS), DHP, DHQ, DHR) -> DHS. +apply3(Fun, Arg1, Arg2, Arg3) -> + Fun(Arg1, Arg2, Arg3). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache Binary files differnew file mode 100644 index 0000000..0afeaae --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta Binary files differnew file mode 100644 index 0000000..2d987e1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.erl new file mode 100644 index 0000000..b1960b7 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.erl @@ -0,0 +1,332 @@ +-module(gleam@int). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([absolute_value/1, parse/1, base_parse/2, to_string/1, to_base_string/2, to_base2/1, to_base8/1, to_base16/1, to_base36/1, to_float/1, power/2, square_root/1, compare/2, min/2, max/2, clamp/3, is_even/1, is_odd/1, negate/1, sum/1, product/1, digits/2, undigits/2, random/2, divide/2, remainder/2, modulo/2, floor_divide/2, add/2, multiply/2, subtract/2, bitwise_and/2, bitwise_not/1, bitwise_or/2, bitwise_exclusive_or/2, bitwise_shift_left/2, bitwise_shift_right/2]). +-export_type([invalid_base/0]). + +-type invalid_base() :: invalid_base. + +-spec absolute_value(integer()) -> integer(). +absolute_value(X) -> + case X >= 0 of + true -> + X; + + false -> + X * -1 + end. + +-spec parse(binary()) -> {ok, integer()} | {error, nil}. +parse(String) -> + gleam_stdlib:parse_int(String). + +-spec base_parse(binary(), integer()) -> {ok, integer()} | {error, nil}. +base_parse(String, Base) -> + case (Base >= 2) andalso (Base =< 36) of + true -> + gleam_stdlib:int_from_base_string(String, Base); + + false -> + {error, nil} + end. + +-spec to_string(integer()) -> binary(). +to_string(X) -> + erlang:integer_to_binary(X). + +-spec to_base_string(integer(), integer()) -> {ok, binary()} | + {error, invalid_base()}. +to_base_string(X, Base) -> + case (Base >= 2) andalso (Base =< 36) of + true -> + {ok, erlang:integer_to_binary(X, Base)}; + + false -> + {error, invalid_base} + end. + +-spec to_base2(integer()) -> binary(). +to_base2(X) -> + erlang:integer_to_binary(X, 2). + +-spec to_base8(integer()) -> binary(). +to_base8(X) -> + erlang:integer_to_binary(X, 8). + +-spec to_base16(integer()) -> binary(). +to_base16(X) -> + erlang:integer_to_binary(X, 16). + +-spec to_base36(integer()) -> binary(). +to_base36(X) -> + erlang:integer_to_binary(X, 36). + +-spec to_float(integer()) -> float(). +to_float(X) -> + erlang:float(X). + +-spec power(integer(), float()) -> {ok, float()} | {error, nil}. +power(Base, Exponent) -> + _pipe = Base, + _pipe@1 = to_float(_pipe), + gleam@float:power(_pipe@1, Exponent). + +-spec square_root(integer()) -> {ok, float()} | {error, nil}. +square_root(X) -> + _pipe = X, + _pipe@1 = to_float(_pipe), + gleam@float:square_root(_pipe@1). + +-spec compare(integer(), integer()) -> gleam@order:order(). +compare(A, B) -> + case A =:= B of + true -> + eq; + + false -> + case A < B of + true -> + lt; + + false -> + gt + end + end. + +-spec min(integer(), integer()) -> integer(). +min(A, B) -> + case A < B of + true -> + A; + + false -> + B + end. + +-spec max(integer(), integer()) -> integer(). +max(A, B) -> + case A > B of + true -> + A; + + false -> + B + end. + +-spec clamp(integer(), integer(), integer()) -> integer(). +clamp(X, Min_bound, Max_bound) -> + _pipe = X, + _pipe@1 = min(_pipe, Max_bound), + max(_pipe@1, Min_bound). + +-spec is_even(integer()) -> boolean(). +is_even(X) -> + (X rem 2) =:= 0. + +-spec is_odd(integer()) -> boolean(). +is_odd(X) -> + (X rem 2) /= 0. + +-spec negate(integer()) -> integer(). +negate(X) -> + -1 * X. + +-spec do_sum(list(integer()), integer()) -> integer(). +do_sum(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_sum(Rest, X + Initial) + end. + +-spec sum(list(integer())) -> integer(). +sum(Numbers) -> + _pipe = Numbers, + do_sum(_pipe, 0). + +-spec do_product(list(integer()), integer()) -> integer(). +do_product(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_product(Rest, X * Initial) + end. + +-spec product(list(integer())) -> integer(). +product(Numbers) -> + case Numbers of + [] -> + 1; + + _ -> + do_product(Numbers, 1) + end. + +-spec do_digits(integer(), integer(), list(integer())) -> list(integer()). +do_digits(X, Base, Acc) -> + case absolute_value(X) < Base of + true -> + [X | Acc]; + + false -> + do_digits(case Base of + 0 -> 0; + Gleam@denominator -> X div Gleam@denominator + end, Base, [case Base of + 0 -> 0; + Gleam@denominator@1 -> X rem Gleam@denominator@1 + end | Acc]) + end. + +-spec digits(integer(), integer()) -> {ok, list(integer())} | + {error, invalid_base()}. +digits(X, Base) -> + case Base < 2 of + true -> + {error, invalid_base}; + + false -> + {ok, do_digits(X, Base, [])} + end. + +-spec do_undigits(list(integer()), integer(), integer()) -> {ok, integer()} | + {error, invalid_base()}. +do_undigits(Numbers, Base, Acc) -> + case Numbers of + [] -> + {ok, Acc}; + + [Digit | _] when Digit >= Base -> + {error, invalid_base}; + + [Digit@1 | Rest] -> + do_undigits(Rest, Base, (Acc * Base) + Digit@1) + end. + +-spec undigits(list(integer()), integer()) -> {ok, integer()} | + {error, invalid_base()}. +undigits(Numbers, Base) -> + case Base < 2 of + true -> + {error, invalid_base}; + + false -> + do_undigits(Numbers, Base, 0) + end. + +-spec random(integer(), integer()) -> integer(). +random(Min, Max) -> + _pipe = gleam@float:random(to_float(Min), to_float(Max)), + _pipe@1 = gleam@float:floor(_pipe), + gleam@float:round(_pipe@1). + +-spec divide(integer(), integer()) -> {ok, integer()} | {error, nil}. +divide(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + Divisor@1 -> + {ok, case Divisor@1 of + 0 -> 0; + Gleam@denominator -> Dividend div Gleam@denominator + end} + end. + +-spec remainder(integer(), integer()) -> {ok, integer()} | {error, nil}. +remainder(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + Divisor@1 -> + {ok, case Divisor@1 of + 0 -> 0; + Gleam@denominator -> Dividend rem Gleam@denominator + end} + end. + +-spec modulo(integer(), integer()) -> {ok, integer()} | {error, nil}. +modulo(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + _ -> + Remainder = case Divisor of + 0 -> 0; + Gleam@denominator -> Dividend rem Gleam@denominator + end, + case (Remainder * Divisor) < 0 of + true -> + {ok, Remainder + Divisor}; + + false -> + {ok, Remainder} + end + end. + +-spec floor_divide(integer(), integer()) -> {ok, integer()} | {error, nil}. +floor_divide(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + Divisor@1 -> + case ((Dividend * Divisor@1) < 0) andalso ((case Divisor@1 of + 0 -> 0; + Gleam@denominator -> Dividend rem Gleam@denominator + end) /= 0) of + true -> + {ok, (case Divisor@1 of + 0 -> 0; + Gleam@denominator@1 -> Dividend div Gleam@denominator@1 + end) - 1}; + + false -> + {ok, case Divisor@1 of + 0 -> 0; + Gleam@denominator@2 -> Dividend div Gleam@denominator@2 + end} + end + end. + +-spec add(integer(), integer()) -> integer(). +add(A, B) -> + A + B. + +-spec multiply(integer(), integer()) -> integer(). +multiply(A, B) -> + A * B. + +-spec subtract(integer(), integer()) -> integer(). +subtract(A, B) -> + A - B. + +-spec bitwise_and(integer(), integer()) -> integer(). +bitwise_and(X, Y) -> + erlang:'band'(X, Y). + +-spec bitwise_not(integer()) -> integer(). +bitwise_not(X) -> + erlang:'bnot'(X). + +-spec bitwise_or(integer(), integer()) -> integer(). +bitwise_or(X, Y) -> + erlang:'bor'(X, Y). + +-spec bitwise_exclusive_or(integer(), integer()) -> integer(). +bitwise_exclusive_or(X, Y) -> + erlang:'bxor'(X, Y). + +-spec bitwise_shift_left(integer(), integer()) -> integer(). +bitwise_shift_left(X, Y) -> + erlang:'bsl'(X, Y). + +-spec bitwise_shift_right(integer(), integer()) -> integer(). +bitwise_shift_right(X, Y) -> + erlang:'bsr'(X, Y). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache Binary files differnew file mode 100644 index 0000000..3174256 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta Binary files differnew file mode 100644 index 0000000..06ce652 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.erl new file mode 100644 index 0000000..fbbe91f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.erl @@ -0,0 +1,27 @@ +-module(gleam@io). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([print/1, print_error/1, println/1, println_error/1, debug/1]). + +-spec print(binary()) -> nil. +print(String) -> + gleam_stdlib:print(String). + +-spec print_error(binary()) -> nil. +print_error(String) -> + gleam_stdlib:print_error(String). + +-spec println(binary()) -> nil. +println(String) -> + gleam_stdlib:println(String). + +-spec println_error(binary()) -> nil. +println_error(String) -> + gleam_stdlib:println_error(String). + +-spec debug(FBV) -> FBV. +debug(Term) -> + _pipe = Term, + _pipe@1 = gleam@string:inspect(_pipe), + gleam_stdlib:println_error(_pipe@1), + Term. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache Binary files differnew file mode 100644 index 0000000..afd5ec8 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta Binary files differnew file mode 100644 index 0000000..2dcb80d --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.erl new file mode 100644 index 0000000..d107b2c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.erl @@ -0,0 +1,744 @@ +-module(gleam@iterator). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([unfold/2, repeatedly/1, repeat/1, from_list/1, transform/3, fold/3, run/1, to_list/1, step/1, take/2, drop/2, map/2, map2/3, append/2, flatten/1, concat/1, flat_map/2, filter/2, cycle/1, find/2, index/1, iterate/2, take_while/2, drop_while/2, scan/3, zip/2, chunk/2, sized_chunk/2, intersperse/2, any/2, all/2, group/2, reduce/2, last/1, empty/0, once/1, range/2, single/1, interleave/2, fold_until/3, try_fold/3, first/1, at/2, length/1, each/2, yield/2]). +-export_type([action/1, iterator/1, step/2, chunk/2, sized_chunk/1]). + +-type action(BPF) :: stop | {continue, BPF, fun(() -> action(BPF))}. + +-opaque iterator(BPG) :: {iterator, fun(() -> action(BPG))}. + +-type step(BPH, BPI) :: {next, BPH, BPI} | done. + +-type chunk(BPJ, BPK) :: {another_by, + list(BPJ), + BPK, + BPJ, + fun(() -> action(BPJ))} | + {last_by, list(BPJ)}. + +-type sized_chunk(BPL) :: {another, list(BPL), fun(() -> action(BPL))} | + {last, list(BPL)} | + no_more. + +-spec stop() -> action(any()). +stop() -> + stop. + +-spec do_unfold(BPO, fun((BPO) -> step(BPP, BPO))) -> fun(() -> action(BPP)). +do_unfold(Initial, F) -> + fun() -> case F(Initial) of + {next, X, Acc} -> + {continue, X, do_unfold(Acc, F)}; + + done -> + stop + end end. + +-spec unfold(BPT, fun((BPT) -> step(BPU, BPT))) -> iterator(BPU). +unfold(Initial, F) -> + _pipe = Initial, + _pipe@1 = do_unfold(_pipe, F), + {iterator, _pipe@1}. + +-spec repeatedly(fun(() -> BPY)) -> iterator(BPY). +repeatedly(F) -> + unfold(nil, fun(_) -> {next, F(), nil} end). + +-spec repeat(BQA) -> iterator(BQA). +repeat(X) -> + repeatedly(fun() -> X end). + +-spec from_list(list(BQC)) -> iterator(BQC). +from_list(List) -> + Yield = fun(Acc) -> case Acc of + [] -> + done; + + [Head | Tail] -> + {next, Head, Tail} + end end, + unfold(List, Yield). + +-spec do_transform( + fun(() -> action(BQF)), + BQH, + fun((BQH, BQF) -> step(BQI, BQH)) +) -> fun(() -> action(BQI)). +do_transform(Continuation, State, F) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, El, Next} -> + case F(State, El) of + done -> + stop; + + {next, Yield, Next_state} -> + {continue, Yield, do_transform(Next, Next_state, F)} + end + end end. + +-spec transform(iterator(BQM), BQO, fun((BQO, BQM) -> step(BQP, BQO))) -> iterator(BQP). +transform(Iterator, Initial, F) -> + _pipe = do_transform(erlang:element(2, Iterator), Initial, F), + {iterator, _pipe}. + +-spec do_fold(fun(() -> action(BQT)), fun((BQV, BQT) -> BQV), BQV) -> BQV. +do_fold(Continuation, F, Accumulator) -> + case Continuation() of + {continue, Elem, Next} -> + do_fold(Next, F, F(Accumulator, Elem)); + + stop -> + Accumulator + end. + +-spec fold(iterator(BQW), BQY, fun((BQY, BQW) -> BQY)) -> BQY. +fold(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + do_fold(_pipe, F, Initial). + +-spec run(iterator(any())) -> nil. +run(Iterator) -> + fold(Iterator, nil, fun(_, _) -> nil end). + +-spec to_list(iterator(BRB)) -> list(BRB). +to_list(Iterator) -> + _pipe = Iterator, + _pipe@1 = fold(_pipe, [], fun(Acc, E) -> [E | Acc] end), + gleam@list:reverse(_pipe@1). + +-spec step(iterator(BRE)) -> step(BRE, iterator(BRE)). +step(Iterator) -> + case (erlang:element(2, Iterator))() of + stop -> + done; + + {continue, E, A} -> + {next, E, {iterator, A}} + end. + +-spec do_take(fun(() -> action(BRJ)), integer()) -> fun(() -> action(BRJ)). +do_take(Continuation, Desired) -> + fun() -> case Desired > 0 of + false -> + stop; + + true -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + {continue, E, do_take(Next, Desired - 1)} + end + end end. + +-spec take(iterator(BRM), integer()) -> iterator(BRM). +take(Iterator, Desired) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_take(_pipe, Desired), + {iterator, _pipe@1}. + +-spec do_drop(fun(() -> action(BRP)), integer()) -> action(BRP). +do_drop(Continuation, Desired) -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + case Desired > 0 of + true -> + do_drop(Next, Desired - 1); + + false -> + {continue, E, Next} + end + end. + +-spec drop(iterator(BRS), integer()) -> iterator(BRS). +drop(Iterator, Desired) -> + _pipe = fun() -> do_drop(erlang:element(2, Iterator), Desired) end, + {iterator, _pipe}. + +-spec do_map(fun(() -> action(BRV)), fun((BRV) -> BRX)) -> fun(() -> action(BRX)). +do_map(Continuation, F) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, E, Continuation@1} -> + {continue, F(E), do_map(Continuation@1, F)} + end end. + +-spec map(iterator(BRZ), fun((BRZ) -> BSB)) -> iterator(BSB). +map(Iterator, F) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_map(_pipe, F), + {iterator, _pipe@1}. + +-spec do_map2( + fun(() -> action(BSD)), + fun(() -> action(BSF)), + fun((BSD, BSF) -> BSH) +) -> fun(() -> action(BSH)). +do_map2(Continuation1, Continuation2, Fun) -> + fun() -> case Continuation1() of + stop -> + stop; + + {continue, A, Next_a} -> + case Continuation2() of + stop -> + stop; + + {continue, B, Next_b} -> + {continue, Fun(A, B), do_map2(Next_a, Next_b, Fun)} + end + end end. + +-spec map2(iterator(BSJ), iterator(BSL), fun((BSJ, BSL) -> BSN)) -> iterator(BSN). +map2(Iterator1, Iterator2, Fun) -> + _pipe = do_map2( + erlang:element(2, Iterator1), + erlang:element(2, Iterator2), + Fun + ), + {iterator, _pipe}. + +-spec do_append(fun(() -> action(BSP)), fun(() -> action(BSP))) -> action(BSP). +do_append(First, Second) -> + case First() of + {continue, E, First@1} -> + {continue, E, fun() -> do_append(First@1, Second) end}; + + stop -> + Second() + end. + +-spec append(iterator(BST), iterator(BST)) -> iterator(BST). +append(First, Second) -> + _pipe = fun() -> + do_append(erlang:element(2, First), erlang:element(2, Second)) + end, + {iterator, _pipe}. + +-spec do_flatten(fun(() -> action(iterator(BSX)))) -> action(BSX). +do_flatten(Flattened) -> + case Flattened() of + stop -> + stop; + + {continue, It, Next_iterator} -> + do_append( + erlang:element(2, It), + fun() -> do_flatten(Next_iterator) end + ) + end. + +-spec flatten(iterator(iterator(BTB))) -> iterator(BTB). +flatten(Iterator) -> + _pipe = fun() -> do_flatten(erlang:element(2, Iterator)) end, + {iterator, _pipe}. + +-spec concat(list(iterator(BTF))) -> iterator(BTF). +concat(Iterators) -> + flatten(from_list(Iterators)). + +-spec flat_map(iterator(BTJ), fun((BTJ) -> iterator(BTL))) -> iterator(BTL). +flat_map(Iterator, F) -> + _pipe = Iterator, + _pipe@1 = map(_pipe, F), + flatten(_pipe@1). + +-spec do_filter(fun(() -> action(BTO)), fun((BTO) -> boolean())) -> action(BTO). +do_filter(Continuation, Predicate) -> + case Continuation() of + stop -> + stop; + + {continue, E, Iterator} -> + case Predicate(E) of + true -> + {continue, E, fun() -> do_filter(Iterator, Predicate) end}; + + false -> + do_filter(Iterator, Predicate) + end + end. + +-spec filter(iterator(BTR), fun((BTR) -> boolean())) -> iterator(BTR). +filter(Iterator, Predicate) -> + _pipe = fun() -> do_filter(erlang:element(2, Iterator), Predicate) end, + {iterator, _pipe}. + +-spec cycle(iterator(BTU)) -> iterator(BTU). +cycle(Iterator) -> + _pipe = repeat(Iterator), + flatten(_pipe). + +-spec do_find(fun(() -> action(BTY)), fun((BTY) -> boolean())) -> {ok, BTY} | + {error, nil}. +do_find(Continuation, F) -> + case Continuation() of + stop -> + {error, nil}; + + {continue, E, Next} -> + case F(E) of + true -> + {ok, E}; + + false -> + do_find(Next, F) + end + end. + +-spec find(iterator(BUC), fun((BUC) -> boolean())) -> {ok, BUC} | {error, nil}. +find(Haystack, Is_desired) -> + _pipe = erlang:element(2, Haystack), + do_find(_pipe, Is_desired). + +-spec do_index(fun(() -> action(BUG)), integer()) -> fun(() -> action({integer(), + BUG})). +do_index(Continuation, Next) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, E, Continuation@1} -> + {continue, {Next, E}, do_index(Continuation@1, Next + 1)} + end end. + +-spec index(iterator(BUJ)) -> iterator({integer(), BUJ}). +index(Iterator) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_index(_pipe, 0), + {iterator, _pipe@1}. + +-spec iterate(BUM, fun((BUM) -> BUM)) -> iterator(BUM). +iterate(Initial, F) -> + unfold(Initial, fun(Element) -> {next, Element, F(Element)} end). + +-spec do_take_while(fun(() -> action(BUO)), fun((BUO) -> boolean())) -> fun(() -> action(BUO)). +do_take_while(Continuation, Predicate) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + case Predicate(E) of + false -> + stop; + + true -> + {continue, E, do_take_while(Next, Predicate)} + end + end end. + +-spec take_while(iterator(BUR), fun((BUR) -> boolean())) -> iterator(BUR). +take_while(Iterator, Predicate) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_take_while(_pipe, Predicate), + {iterator, _pipe@1}. + +-spec do_drop_while(fun(() -> action(BUU)), fun((BUU) -> boolean())) -> action(BUU). +do_drop_while(Continuation, Predicate) -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + case Predicate(E) of + false -> + {continue, E, Next}; + + true -> + do_drop_while(Next, Predicate) + end + end. + +-spec drop_while(iterator(BUX), fun((BUX) -> boolean())) -> iterator(BUX). +drop_while(Iterator, Predicate) -> + _pipe = fun() -> do_drop_while(erlang:element(2, Iterator), Predicate) end, + {iterator, _pipe}. + +-spec do_scan(fun(() -> action(BVA)), fun((BVC, BVA) -> BVC), BVC) -> fun(() -> action(BVC)). +do_scan(Continuation, F, Accumulator) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, El, Next} -> + Accumulated = F(Accumulator, El), + {continue, Accumulated, do_scan(Next, F, Accumulated)} + end end. + +-spec scan(iterator(BVE), BVG, fun((BVG, BVE) -> BVG)) -> iterator(BVG). +scan(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_scan(_pipe, F, Initial), + {iterator, _pipe@1}. + +-spec do_zip(fun(() -> action(BVI)), fun(() -> action(BVK))) -> fun(() -> action({BVI, + BVK})). +do_zip(Left, Right) -> + fun() -> case Left() of + stop -> + stop; + + {continue, El_left, Next_left} -> + case Right() of + stop -> + stop; + + {continue, El_right, Next_right} -> + {continue, + {El_left, El_right}, + do_zip(Next_left, Next_right)} + end + end end. + +-spec zip(iterator(BVN), iterator(BVP)) -> iterator({BVN, BVP}). +zip(Left, Right) -> + _pipe = do_zip(erlang:element(2, Left), erlang:element(2, Right)), + {iterator, _pipe}. + +-spec next_chunk(fun(() -> action(BVS)), fun((BVS) -> BVU), BVU, list(BVS)) -> chunk(BVS, BVU). +next_chunk(Continuation, F, Previous_key, Current_chunk) -> + case Continuation() of + stop -> + {last_by, gleam@list:reverse(Current_chunk)}; + + {continue, E, Next} -> + Key = F(E), + case Key =:= Previous_key of + true -> + next_chunk(Next, F, Key, [E | Current_chunk]); + + false -> + {another_by, + gleam@list:reverse(Current_chunk), + Key, + E, + Next} + end + end. + +-spec do_chunk(fun(() -> action(BVY)), fun((BVY) -> BWA), BWA, BVY) -> action(list(BVY)). +do_chunk(Continuation, F, Previous_key, Previous_element) -> + case next_chunk(Continuation, F, Previous_key, [Previous_element]) of + {last_by, Chunk} -> + {continue, Chunk, fun stop/0}; + + {another_by, Chunk@1, Key, El, Next} -> + {continue, Chunk@1, fun() -> do_chunk(Next, F, Key, El) end} + end. + +-spec chunk(iterator(BWD), fun((BWD) -> any())) -> iterator(list(BWD)). +chunk(Iterator, F) -> + _pipe = fun() -> case (erlang:element(2, Iterator))() of + stop -> + stop; + + {continue, E, Next} -> + do_chunk(Next, F, F(E), E) + end end, + {iterator, _pipe}. + +-spec next_sized_chunk(fun(() -> action(BWI)), integer(), list(BWI)) -> sized_chunk(BWI). +next_sized_chunk(Continuation, Left, Current_chunk) -> + case Continuation() of + stop -> + case Current_chunk of + [] -> + no_more; + + Remaining -> + {last, gleam@list:reverse(Remaining)} + end; + + {continue, E, Next} -> + Chunk = [E | Current_chunk], + case Left > 1 of + false -> + {another, gleam@list:reverse(Chunk), Next}; + + true -> + next_sized_chunk(Next, Left - 1, Chunk) + end + end. + +-spec do_sized_chunk(fun(() -> action(BWM)), integer()) -> fun(() -> action(list(BWM))). +do_sized_chunk(Continuation, Count) -> + fun() -> case next_sized_chunk(Continuation, Count, []) of + no_more -> + stop; + + {last, Chunk} -> + {continue, Chunk, fun stop/0}; + + {another, Chunk@1, Next_element} -> + {continue, Chunk@1, do_sized_chunk(Next_element, Count)} + end end. + +-spec sized_chunk(iterator(BWQ), integer()) -> iterator(list(BWQ)). +sized_chunk(Iterator, Count) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_sized_chunk(_pipe, Count), + {iterator, _pipe@1}. + +-spec do_intersperse(fun(() -> action(BWU)), BWU) -> action(BWU). +do_intersperse(Continuation, Separator) -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + Next_interspersed = fun() -> do_intersperse(Next, Separator) end, + {continue, Separator, fun() -> {continue, E, Next_interspersed} end} + end. + +-spec intersperse(iterator(BWX), BWX) -> iterator(BWX). +intersperse(Iterator, Elem) -> + _pipe = fun() -> case (erlang:element(2, Iterator))() of + stop -> + stop; + + {continue, E, Next} -> + {continue, E, fun() -> do_intersperse(Next, Elem) end} + end end, + {iterator, _pipe}. + +-spec do_any(fun(() -> action(BXA)), fun((BXA) -> boolean())) -> boolean(). +do_any(Continuation, Predicate) -> + case Continuation() of + stop -> + false; + + {continue, E, Next} -> + case Predicate(E) of + true -> + true; + + false -> + do_any(Next, Predicate) + end + end. + +-spec any(iterator(BXC), fun((BXC) -> boolean())) -> boolean(). +any(Iterator, Predicate) -> + _pipe = erlang:element(2, Iterator), + do_any(_pipe, Predicate). + +-spec do_all(fun(() -> action(BXE)), fun((BXE) -> boolean())) -> boolean(). +do_all(Continuation, Predicate) -> + case Continuation() of + stop -> + true; + + {continue, E, Next} -> + case Predicate(E) of + true -> + do_all(Next, Predicate); + + false -> + false + end + end. + +-spec all(iterator(BXG), fun((BXG) -> boolean())) -> boolean(). +all(Iterator, Predicate) -> + _pipe = erlang:element(2, Iterator), + do_all(_pipe, Predicate). + +-spec update_group_with(BXI) -> fun((gleam@option:option(list(BXI))) -> list(BXI)). +update_group_with(El) -> + fun(Maybe_group) -> case Maybe_group of + {some, Group} -> + [El | Group]; + + none -> + [El] + end end. + +-spec group_updater(fun((BXM) -> BXN)) -> fun((gleam@dict:dict(BXN, list(BXM)), BXM) -> gleam@dict:dict(BXN, list(BXM))). +group_updater(F) -> + fun(Groups, Elem) -> _pipe = Groups, + gleam@dict:update(_pipe, F(Elem), update_group_with(Elem)) end. + +-spec group(iterator(BXU), fun((BXU) -> BXW)) -> gleam@dict:dict(BXW, list(BXU)). +group(Iterator, Key) -> + _pipe = Iterator, + _pipe@1 = fold(_pipe, gleam@dict:new(), group_updater(Key)), + gleam@dict:map_values( + _pipe@1, + fun(_, Group) -> gleam@list:reverse(Group) end + ). + +-spec reduce(iterator(BYA), fun((BYA, BYA) -> BYA)) -> {ok, BYA} | {error, nil}. +reduce(Iterator, F) -> + case (erlang:element(2, Iterator))() of + stop -> + {error, nil}; + + {continue, E, Next} -> + _pipe = do_fold(Next, F, E), + {ok, _pipe} + end. + +-spec last(iterator(BYE)) -> {ok, BYE} | {error, nil}. +last(Iterator) -> + _pipe = Iterator, + reduce(_pipe, fun(_, Elem) -> Elem end). + +-spec empty() -> iterator(any()). +empty() -> + {iterator, fun stop/0}. + +-spec once(fun(() -> BYK)) -> iterator(BYK). +once(F) -> + _pipe = fun() -> {continue, F(), fun stop/0} end, + {iterator, _pipe}. + +-spec range(integer(), integer()) -> iterator(integer()). +range(Start, Stop) -> + case gleam@int:compare(Start, Stop) of + eq -> + once(fun() -> Start end); + + gt -> + unfold(Start, fun(Current) -> case Current < Stop of + false -> + {next, Current, Current - 1}; + + true -> + done + end end); + + lt -> + unfold(Start, fun(Current@1) -> case Current@1 > Stop of + false -> + {next, Current@1, Current@1 + 1}; + + true -> + done + end end) + end. + +-spec single(BYM) -> iterator(BYM). +single(Elem) -> + once(fun() -> Elem end). + +-spec do_interleave(fun(() -> action(BYO)), fun(() -> action(BYO))) -> action(BYO). +do_interleave(Current, Next) -> + case Current() of + stop -> + Next(); + + {continue, E, Next_other} -> + {continue, E, fun() -> do_interleave(Next, Next_other) end} + end. + +-spec interleave(iterator(BYS), iterator(BYS)) -> iterator(BYS). +interleave(Left, Right) -> + _pipe = fun() -> + do_interleave(erlang:element(2, Left), erlang:element(2, Right)) + end, + {iterator, _pipe}. + +-spec do_fold_until( + fun(() -> action(BYW)), + fun((BYY, BYW) -> gleam@list:continue_or_stop(BYY)), + BYY +) -> BYY. +do_fold_until(Continuation, F, Accumulator) -> + case Continuation() of + stop -> + Accumulator; + + {continue, Elem, Next} -> + case F(Accumulator, Elem) of + {continue, Accumulator@1} -> + do_fold_until(Next, F, Accumulator@1); + + {stop, Accumulator@2} -> + Accumulator@2 + end + end. + +-spec fold_until( + iterator(BZA), + BZC, + fun((BZC, BZA) -> gleam@list:continue_or_stop(BZC)) +) -> BZC. +fold_until(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + do_fold_until(_pipe, F, Initial). + +-spec do_try_fold( + fun(() -> action(BZE)), + fun((BZG, BZE) -> {ok, BZG} | {error, BZH}), + BZG +) -> {ok, BZG} | {error, BZH}. +do_try_fold(Continuation, F, Accumulator) -> + case Continuation() of + stop -> + {ok, Accumulator}; + + {continue, Elem, Next} -> + gleam@result:'try'( + F(Accumulator, Elem), + fun(Accumulator@1) -> do_try_fold(Next, F, Accumulator@1) end + ) + end. + +-spec try_fold(iterator(BZM), BZO, fun((BZO, BZM) -> {ok, BZO} | {error, BZP})) -> {ok, + BZO} | + {error, BZP}. +try_fold(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + do_try_fold(_pipe, F, Initial). + +-spec first(iterator(BZU)) -> {ok, BZU} | {error, nil}. +first(Iterator) -> + case (erlang:element(2, Iterator))() of + stop -> + {error, nil}; + + {continue, E, _} -> + {ok, E} + end. + +-spec at(iterator(BZY), integer()) -> {ok, BZY} | {error, nil}. +at(Iterator, Index) -> + _pipe = Iterator, + _pipe@1 = drop(_pipe, Index), + first(_pipe@1). + +-spec do_length(fun(() -> action(any())), integer()) -> integer(). +do_length(Continuation, Length) -> + case Continuation() of + stop -> + Length; + + {continue, _, Next} -> + do_length(Next, Length + 1) + end. + +-spec length(iterator(any())) -> integer(). +length(Iterator) -> + _pipe = erlang:element(2, Iterator), + do_length(_pipe, 0). + +-spec each(iterator(CAG), fun((CAG) -> any())) -> nil. +each(Iterator, F) -> + _pipe = Iterator, + _pipe@1 = map(_pipe, F), + run(_pipe@1). + +-spec yield(CAJ, fun(() -> iterator(CAJ))) -> iterator(CAJ). +yield(Element, Next) -> + {iterator, fun() -> {continue, Element, erlang:element(2, Next())} end}. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache Binary files differnew file mode 100644 index 0000000..a8c076a --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta Binary files differnew file mode 100644 index 0000000..56b294f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.erl new file mode 100644 index 0000000..ef8ad42 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.erl @@ -0,0 +1,1129 @@ +-module(gleam@list). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([length/1, reverse/1, is_empty/1, contains/2, first/1, rest/1, filter/2, filter_map/2, map/2, map2/3, index_map/2, try_map/2, drop/2, take/2, new/0, append/2, prepend/2, concat/1, flatten/1, flat_map/2, fold/3, group/2, map_fold/3, fold_right/3, index_fold/3, try_fold/3, fold_until/3, find/2, find_map/2, all/2, any/2, zip/2, strict_zip/2, unzip/1, intersperse/2, at/2, unique/1, sort/2, range/2, repeat/2, split/2, split_while/2, key_find/2, key_filter/2, pop/2, pop_map/2, key_pop/2, key_set/3, each/2, try_each/2, partition/2, permutations/1, window/2, window_by_2/1, drop_while/2, take_while/2, chunk/2, sized_chunk/2, reduce/2, scan/3, last/1, combinations/2, combination_pairs/1, transpose/1, interleave/1, shuffle/1]). +-export_type([length_mismatch/0, continue_or_stop/1]). + +-type length_mismatch() :: length_mismatch. + +-type continue_or_stop(UD) :: {continue, UD} | {stop, UD}. + +-spec length(list(any())) -> integer(). +length(List) -> + erlang:length(List). + +-spec reverse(list(UI)) -> list(UI). +reverse(Xs) -> + lists:reverse(Xs). + +-spec is_empty(list(any())) -> boolean(). +is_empty(List) -> + List =:= []. + +-spec contains(list(UQ), UQ) -> boolean(). +contains(List, Elem) -> + case List of + [] -> + false; + + [First | _] when First =:= Elem -> + true; + + [_ | Rest] -> + contains(Rest, Elem) + end. + +-spec first(list(US)) -> {ok, US} | {error, nil}. +first(List) -> + case List of + [] -> + {error, nil}; + + [X | _] -> + {ok, X} + end. + +-spec rest(list(UW)) -> {ok, list(UW)} | {error, nil}. +rest(List) -> + case List of + [] -> + {error, nil}; + + [_ | Xs] -> + {ok, Xs} + end. + +-spec update_group(fun((VB) -> VC)) -> fun((gleam@dict:dict(VC, list(VB)), VB) -> gleam@dict:dict(VC, list(VB))). +update_group(F) -> + fun(Groups, Elem) -> case gleam@dict:get(Groups, F(Elem)) of + {ok, Existing} -> + gleam@dict:insert(Groups, F(Elem), [Elem | Existing]); + + {error, _} -> + gleam@dict:insert(Groups, F(Elem), [Elem]) + end end. + +-spec do_filter(list(VP), fun((VP) -> boolean()), list(VP)) -> list(VP). +do_filter(List, Fun, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + New_acc = case Fun(X) of + true -> + [X | Acc]; + + false -> + Acc + end, + do_filter(Xs, Fun, New_acc) + end. + +-spec filter(list(VT), fun((VT) -> boolean())) -> list(VT). +filter(List, Predicate) -> + do_filter(List, Predicate, []). + +-spec do_filter_map(list(VW), fun((VW) -> {ok, VY} | {error, any()}), list(VY)) -> list(VY). +do_filter_map(List, Fun, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + New_acc = case Fun(X) of + {ok, X@1} -> + [X@1 | Acc]; + + {error, _} -> + Acc + end, + do_filter_map(Xs, Fun, New_acc) + end. + +-spec filter_map(list(WE), fun((WE) -> {ok, WG} | {error, any()})) -> list(WG). +filter_map(List, Fun) -> + do_filter_map(List, Fun, []). + +-spec do_map(list(WL), fun((WL) -> WN), list(WN)) -> list(WN). +do_map(List, Fun, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + do_map(Xs, Fun, [Fun(X) | Acc]) + end. + +-spec map(list(WQ), fun((WQ) -> WS)) -> list(WS). +map(List, Fun) -> + do_map(List, Fun, []). + +-spec do_map2(list(XA), list(XC), fun((XA, XC) -> XE), list(XE)) -> list(XE). +do_map2(List1, List2, Fun, Acc) -> + case {List1, List2} of + {[], _} -> + reverse(Acc); + + {_, []} -> + reverse(Acc); + + {[A | As_], [B | Bs]} -> + do_map2(As_, Bs, Fun, [Fun(A, B) | Acc]) + end. + +-spec map2(list(WU), list(WW), fun((WU, WW) -> WY)) -> list(WY). +map2(List1, List2, Fun) -> + do_map2(List1, List2, Fun, []). + +-spec do_index_map(list(XM), fun((integer(), XM) -> XO), integer(), list(XO)) -> list(XO). +do_index_map(List, Fun, Index, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + Acc@1 = [Fun(Index, X) | Acc], + do_index_map(Xs, Fun, Index + 1, Acc@1) + end. + +-spec index_map(list(XR), fun((integer(), XR) -> XT)) -> list(XT). +index_map(List, Fun) -> + do_index_map(List, Fun, 0, []). + +-spec do_try_map(list(XV), fun((XV) -> {ok, XX} | {error, XY}), list(XX)) -> {ok, + list(XX)} | + {error, XY}. +do_try_map(List, Fun, Acc) -> + case List of + [] -> + {ok, reverse(Acc)}; + + [X | Xs] -> + case Fun(X) of + {ok, Y} -> + do_try_map(Xs, Fun, [Y | Acc]); + + {error, Error} -> + {error, Error} + end + end. + +-spec try_map(list(YF), fun((YF) -> {ok, YH} | {error, YI})) -> {ok, list(YH)} | + {error, YI}. +try_map(List, Fun) -> + do_try_map(List, Fun, []). + +-spec drop(list(YO), integer()) -> list(YO). +drop(List, N) -> + case N =< 0 of + true -> + List; + + false -> + case List of + [] -> + []; + + [_ | Xs] -> + drop(Xs, N - 1) + end + end. + +-spec do_take(list(YR), integer(), list(YR)) -> list(YR). +do_take(List, N, Acc) -> + case N =< 0 of + true -> + reverse(Acc); + + false -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + do_take(Xs, N - 1, [X | Acc]) + end + end. + +-spec take(list(YV), integer()) -> list(YV). +take(List, N) -> + do_take(List, N, []). + +-spec new() -> list(any()). +new() -> + []. + +-spec append(list(AAA), list(AAA)) -> list(AAA). +append(First, Second) -> + lists:append(First, Second). + +-spec prepend(list(AAI), AAI) -> list(AAI). +prepend(List, Item) -> + [Item | List]. + +-spec reverse_and_prepend(list(AAL), list(AAL)) -> list(AAL). +reverse_and_prepend(Prefix, Suffix) -> + case Prefix of + [] -> + Suffix; + + [First | Rest] -> + reverse_and_prepend(Rest, [First | Suffix]) + end. + +-spec do_concat(list(list(AAP)), list(AAP)) -> list(AAP). +do_concat(Lists, Acc) -> + case Lists of + [] -> + reverse(Acc); + + [List | Further_lists] -> + do_concat(Further_lists, reverse_and_prepend(List, Acc)) + end. + +-spec concat(list(list(AAU))) -> list(AAU). +concat(Lists) -> + do_concat(Lists, []). + +-spec flatten(list(list(AAY))) -> list(AAY). +flatten(Lists) -> + do_concat(Lists, []). + +-spec flat_map(list(ABC), fun((ABC) -> list(ABE))) -> list(ABE). +flat_map(List, Fun) -> + _pipe = map(List, Fun), + concat(_pipe). + +-spec fold(list(ABH), ABJ, fun((ABJ, ABH) -> ABJ)) -> ABJ. +fold(List, Initial, Fun) -> + case List of + [] -> + Initial; + + [X | Rest] -> + fold(Rest, Fun(Initial, X), Fun) + end. + +-spec group(list(VJ), fun((VJ) -> VL)) -> gleam@dict:dict(VL, list(VJ)). +group(List, Key) -> + fold(List, gleam@dict:new(), update_group(Key)). + +-spec map_fold(list(XH), XJ, fun((XJ, XH) -> {XJ, XK})) -> {XJ, list(XK)}. +map_fold(List, Acc, Fun) -> + _pipe = fold( + List, + {Acc, []}, + fun(Acc@1, Item) -> + {Current_acc, Items} = Acc@1, + {Next_acc, Next_item} = Fun(Current_acc, Item), + {Next_acc, [Next_item | Items]} + end + ), + gleam@pair:map_second(_pipe, fun reverse/1). + +-spec fold_right(list(ABK), ABM, fun((ABM, ABK) -> ABM)) -> ABM. +fold_right(List, Initial, Fun) -> + case List of + [] -> + Initial; + + [X | Rest] -> + Fun(fold_right(Rest, Initial, Fun), X) + end. + +-spec do_index_fold( + list(ABN), + ABP, + fun((ABP, ABN, integer()) -> ABP), + integer() +) -> ABP. +do_index_fold(Over, Acc, With, Index) -> + case Over of + [] -> + Acc; + + [First | Rest] -> + do_index_fold(Rest, With(Acc, First, Index), With, Index + 1) + end. + +-spec index_fold(list(ABQ), ABS, fun((ABS, ABQ, integer()) -> ABS)) -> ABS. +index_fold(Over, Initial, Fun) -> + do_index_fold(Over, Initial, Fun, 0). + +-spec try_fold(list(ABT), ABV, fun((ABV, ABT) -> {ok, ABV} | {error, ABW})) -> {ok, + ABV} | + {error, ABW}. +try_fold(Collection, Accumulator, Fun) -> + case Collection of + [] -> + {ok, Accumulator}; + + [First | Rest] -> + case Fun(Accumulator, First) of + {ok, Result} -> + try_fold(Rest, Result, Fun); + + {error, _} = Error -> + Error + end + end. + +-spec fold_until(list(ACB), ACD, fun((ACD, ACB) -> continue_or_stop(ACD))) -> ACD. +fold_until(Collection, Accumulator, Fun) -> + case Collection of + [] -> + Accumulator; + + [First | Rest] -> + case Fun(Accumulator, First) of + {continue, Next_accumulator} -> + fold_until(Rest, Next_accumulator, Fun); + + {stop, B} -> + B + end + end. + +-spec find(list(ACF), fun((ACF) -> boolean())) -> {ok, ACF} | {error, nil}. +find(Haystack, Is_desired) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Is_desired(X) of + true -> + {ok, X}; + + _ -> + find(Rest, Is_desired) + end + end. + +-spec find_map(list(ACJ), fun((ACJ) -> {ok, ACL} | {error, any()})) -> {ok, ACL} | + {error, nil}. +find_map(Haystack, Fun) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Fun(X) of + {ok, X@1} -> + {ok, X@1}; + + _ -> + find_map(Rest, Fun) + end + end. + +-spec all(list(ACR), fun((ACR) -> boolean())) -> boolean(). +all(List, Predicate) -> + case List of + [] -> + true; + + [First | Rest] -> + case Predicate(First) of + true -> + all(Rest, Predicate); + + false -> + false + end + end. + +-spec any(list(ACT), fun((ACT) -> boolean())) -> boolean(). +any(List, Predicate) -> + case List of + [] -> + false; + + [First | Rest] -> + case Predicate(First) of + true -> + true; + + false -> + any(Rest, Predicate) + end + end. + +-spec do_zip(list(ACV), list(ACX), list({ACV, ACX})) -> list({ACV, ACX}). +do_zip(Xs, Ys, Acc) -> + case {Xs, Ys} of + {[X | Xs@1], [Y | Ys@1]} -> + do_zip(Xs@1, Ys@1, [{X, Y} | Acc]); + + {_, _} -> + reverse(Acc) + end. + +-spec zip(list(ADB), list(ADD)) -> list({ADB, ADD}). +zip(List, Other) -> + do_zip(List, Other, []). + +-spec strict_zip(list(ADG), list(ADI)) -> {ok, list({ADG, ADI})} | + {error, length_mismatch()}. +strict_zip(List, Other) -> + case length(List) =:= length(Other) of + true -> + {ok, zip(List, Other)}; + + false -> + {error, length_mismatch} + end. + +-spec do_unzip(list({ATA, ATB}), list(ATA), list(ATB)) -> {list(ATA), list(ATB)}. +do_unzip(Input, Xs, Ys) -> + case Input of + [] -> + {reverse(Xs), reverse(Ys)}; + + [{X, Y} | Rest] -> + do_unzip(Rest, [X | Xs], [Y | Ys]) + end. + +-spec unzip(list({ADR, ADS})) -> {list(ADR), list(ADS)}. +unzip(Input) -> + do_unzip(Input, [], []). + +-spec do_intersperse(list(ADW), ADW, list(ADW)) -> list(ADW). +do_intersperse(List, Separator, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Rest] -> + do_intersperse(Rest, Separator, [X, Separator | Acc]) + end. + +-spec intersperse(list(AEA), AEA) -> list(AEA). +intersperse(List, Elem) -> + case List of + [] -> + List; + + [_] -> + List; + + [X | Rest] -> + do_intersperse(Rest, Elem, [X]) + end. + +-spec at(list(AED), integer()) -> {ok, AED} | {error, nil}. +at(List, Index) -> + case Index >= 0 of + true -> + _pipe = List, + _pipe@1 = drop(_pipe, Index), + first(_pipe@1); + + false -> + {error, nil} + end. + +-spec unique(list(AEH)) -> list(AEH). +unique(List) -> + case List of + [] -> + []; + + [X | Rest] -> + [X | unique(filter(Rest, fun(Y) -> Y /= X end))] + end. + +-spec merge_up( + integer(), + integer(), + list(AEK), + list(AEK), + list(AEK), + fun((AEK, AEK) -> gleam@order:order()) +) -> list(AEK). +merge_up(Na, Nb, A, B, Acc, Compare) -> + case {Na, Nb, A, B} of + {0, 0, _, _} -> + Acc; + + {_, 0, [Ax | Ar], _} -> + merge_up(Na - 1, Nb, Ar, B, [Ax | Acc], Compare); + + {0, _, _, [Bx | Br]} -> + merge_up(Na, Nb - 1, A, Br, [Bx | Acc], Compare); + + {_, _, [Ax@1 | Ar@1], [Bx@1 | Br@1]} -> + case Compare(Ax@1, Bx@1) of + gt -> + merge_up(Na, Nb - 1, A, Br@1, [Bx@1 | Acc], Compare); + + _ -> + merge_up(Na - 1, Nb, Ar@1, B, [Ax@1 | Acc], Compare) + end; + + {_, _, _, _} -> + Acc + end. + +-spec merge_down( + integer(), + integer(), + list(AEP), + list(AEP), + list(AEP), + fun((AEP, AEP) -> gleam@order:order()) +) -> list(AEP). +merge_down(Na, Nb, A, B, Acc, Compare) -> + case {Na, Nb, A, B} of + {0, 0, _, _} -> + Acc; + + {_, 0, [Ax | Ar], _} -> + merge_down(Na - 1, Nb, Ar, B, [Ax | Acc], Compare); + + {0, _, _, [Bx | Br]} -> + merge_down(Na, Nb - 1, A, Br, [Bx | Acc], Compare); + + {_, _, [Ax@1 | Ar@1], [Bx@1 | Br@1]} -> + case Compare(Bx@1, Ax@1) of + lt -> + merge_down(Na - 1, Nb, Ar@1, B, [Ax@1 | Acc], Compare); + + _ -> + merge_down(Na, Nb - 1, A, Br@1, [Bx@1 | Acc], Compare) + end; + + {_, _, _, _} -> + Acc + end. + +-spec merge_sort( + list(AEU), + integer(), + fun((AEU, AEU) -> gleam@order:order()), + boolean() +) -> list(AEU). +merge_sort(L, Ln, Compare, Down) -> + N = Ln div 2, + A = L, + B = drop(L, N), + case Ln < 3 of + true -> + case Down of + true -> + merge_down(N, Ln - N, A, B, [], Compare); + + false -> + merge_up(N, Ln - N, A, B, [], Compare) + end; + + false -> + case Down of + true -> + merge_down( + N, + Ln - N, + merge_sort(A, N, Compare, false), + merge_sort(B, Ln - N, Compare, false), + [], + Compare + ); + + false -> + merge_up( + N, + Ln - N, + merge_sort(A, N, Compare, true), + merge_sort(B, Ln - N, Compare, true), + [], + Compare + ) + end + end. + +-spec sort(list(AEX), fun((AEX, AEX) -> gleam@order:order())) -> list(AEX). +sort(List, Compare) -> + merge_sort(List, length(List), Compare, true). + +-spec tail_recursive_range(integer(), integer(), list(integer())) -> list(integer()). +tail_recursive_range(Start, Stop, Acc) -> + case gleam@int:compare(Start, Stop) of + eq -> + [Stop | Acc]; + + gt -> + tail_recursive_range(Start, Stop + 1, [Stop | Acc]); + + lt -> + tail_recursive_range(Start, Stop - 1, [Stop | Acc]) + end. + +-spec range(integer(), integer()) -> list(integer()). +range(Start, Stop) -> + tail_recursive_range(Start, Stop, []). + +-spec do_repeat(AFD, integer(), list(AFD)) -> list(AFD). +do_repeat(A, Times, Acc) -> + case Times =< 0 of + true -> + Acc; + + false -> + do_repeat(A, Times - 1, [A | Acc]) + end. + +-spec repeat(AFG, integer()) -> list(AFG). +repeat(A, Times) -> + do_repeat(A, Times, []). + +-spec do_split(list(AFI), integer(), list(AFI)) -> {list(AFI), list(AFI)}. +do_split(List, N, Taken) -> + case N =< 0 of + true -> + {reverse(Taken), List}; + + false -> + case List of + [] -> + {reverse(Taken), []}; + + [X | Xs] -> + do_split(Xs, N - 1, [X | Taken]) + end + end. + +-spec split(list(AFN), integer()) -> {list(AFN), list(AFN)}. +split(List, Index) -> + do_split(List, Index, []). + +-spec do_split_while(list(AFR), fun((AFR) -> boolean()), list(AFR)) -> {list(AFR), + list(AFR)}. +do_split_while(List, F, Acc) -> + case List of + [] -> + {reverse(Acc), []}; + + [X | Xs] -> + case F(X) of + false -> + {reverse(Acc), List}; + + _ -> + do_split_while(Xs, F, [X | Acc]) + end + end. + +-spec split_while(list(AFW), fun((AFW) -> boolean())) -> {list(AFW), list(AFW)}. +split_while(List, Predicate) -> + do_split_while(List, Predicate, []). + +-spec key_find(list({AGA, AGB}), AGA) -> {ok, AGB} | {error, nil}. +key_find(Keyword_list, Desired_key) -> + find_map( + Keyword_list, + fun(Keyword) -> + {Key, Value} = Keyword, + case Key =:= Desired_key of + true -> + {ok, Value}; + + false -> + {error, nil} + end + end + ). + +-spec key_filter(list({AGF, AGG}), AGF) -> list(AGG). +key_filter(Keyword_list, Desired_key) -> + filter_map( + Keyword_list, + fun(Keyword) -> + {Key, Value} = Keyword, + case Key =:= Desired_key of + true -> + {ok, Value}; + + false -> + {error, nil} + end + end + ). + +-spec do_pop(list(AWT), fun((AWT) -> boolean()), list(AWT)) -> {ok, + {AWT, list(AWT)}} | + {error, nil}. +do_pop(Haystack, Predicate, Checked) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Predicate(X) of + true -> + {ok, {X, append(reverse(Checked), Rest)}}; + + false -> + do_pop(Rest, Predicate, [X | Checked]) + end + end. + +-spec pop(list(AGN), fun((AGN) -> boolean())) -> {ok, {AGN, list(AGN)}} | + {error, nil}. +pop(Haystack, Is_desired) -> + do_pop(Haystack, Is_desired, []). + +-spec do_pop_map(list(AXH), fun((AXH) -> {ok, AXU} | {error, any()}), list(AXH)) -> {ok, + {AXU, list(AXH)}} | + {error, nil}. +do_pop_map(Haystack, Mapper, Checked) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Mapper(X) of + {ok, Y} -> + {ok, {Y, append(reverse(Checked), Rest)}}; + + {error, _} -> + do_pop_map(Rest, Mapper, [X | Checked]) + end + end. + +-spec pop_map(list(AGW), fun((AGW) -> {ok, AGY} | {error, any()})) -> {ok, + {AGY, list(AGW)}} | + {error, nil}. +pop_map(Haystack, Is_desired) -> + do_pop_map(Haystack, Is_desired, []). + +-spec key_pop(list({AHF, AHG}), AHF) -> {ok, {AHG, list({AHF, AHG})}} | + {error, nil}. +key_pop(Haystack, Key) -> + pop_map( + Haystack, + fun(Entry) -> + {K, V} = Entry, + case K of + K@1 when K@1 =:= Key -> + {ok, V}; + + _ -> + {error, nil} + end + end + ). + +-spec key_set(list({AHL, AHM}), AHL, AHM) -> list({AHL, AHM}). +key_set(List, Key, Value) -> + case List of + [] -> + [{Key, Value}]; + + [{K, _} | Rest] when K =:= Key -> + [{Key, Value} | Rest]; + + [First | Rest@1] -> + [First | key_set(Rest@1, Key, Value)] + end. + +-spec each(list(AHP), fun((AHP) -> any())) -> nil. +each(List, F) -> + case List of + [] -> + nil; + + [X | Xs] -> + F(X), + each(Xs, F) + end. + +-spec try_each(list(AHS), fun((AHS) -> {ok, any()} | {error, AHV})) -> {ok, nil} | + {error, AHV}. +try_each(List, Fun) -> + case List of + [] -> + {ok, nil}; + + [X | Xs] -> + case Fun(X) of + {ok, _} -> + try_each(Xs, Fun); + + {error, E} -> + {error, E} + end + end. + +-spec do_partition(list(AZB), fun((AZB) -> boolean()), list(AZB), list(AZB)) -> {list(AZB), + list(AZB)}. +do_partition(List, Categorise, Trues, Falses) -> + case List of + [] -> + {reverse(Trues), reverse(Falses)}; + + [X | Xs] -> + case Categorise(X) of + true -> + do_partition(Xs, Categorise, [X | Trues], Falses); + + false -> + do_partition(Xs, Categorise, Trues, [X | Falses]) + end + end. + +-spec partition(list(AIF), fun((AIF) -> boolean())) -> {list(AIF), list(AIF)}. +partition(List, Categorise) -> + do_partition(List, Categorise, [], []). + +-spec permutations(list(AIJ)) -> list(list(AIJ)). +permutations(L) -> + case L of + [] -> + [[]]; + + _ -> + _pipe = L, + _pipe@5 = index_map(_pipe, fun(I_idx, I) -> _pipe@1 = L, + _pipe@2 = index_fold( + _pipe@1, + [], + fun(Acc, J, J_idx) -> case I_idx =:= J_idx of + true -> + Acc; + + false -> + [J | Acc] + end end + ), + _pipe@3 = reverse(_pipe@2), + _pipe@4 = permutations(_pipe@3), + map(_pipe@4, fun(Permutation) -> [I | Permutation] end) end), + concat(_pipe@5) + end. + +-spec do_window(list(list(AIN)), list(AIN), integer()) -> list(list(AIN)). +do_window(Acc, L, N) -> + Window = take(L, N), + case length(Window) =:= N of + true -> + do_window([Window | Acc], drop(L, 1), N); + + false -> + Acc + end. + +-spec window(list(AIT), integer()) -> list(list(AIT)). +window(L, N) -> + _pipe = do_window([], L, N), + reverse(_pipe). + +-spec window_by_2(list(AIX)) -> list({AIX, AIX}). +window_by_2(L) -> + zip(L, drop(L, 1)). + +-spec drop_while(list(AJA), fun((AJA) -> boolean())) -> list(AJA). +drop_while(List, Predicate) -> + case List of + [] -> + []; + + [X | Xs] -> + case Predicate(X) of + true -> + drop_while(Xs, Predicate); + + false -> + [X | Xs] + end + end. + +-spec do_take_while(list(AJD), fun((AJD) -> boolean()), list(AJD)) -> list(AJD). +do_take_while(List, Predicate, Acc) -> + case List of + [] -> + reverse(Acc); + + [First | Rest] -> + case Predicate(First) of + true -> + do_take_while(Rest, Predicate, [First | Acc]); + + false -> + reverse(Acc) + end + end. + +-spec take_while(list(AJH), fun((AJH) -> boolean())) -> list(AJH). +take_while(List, Predicate) -> + do_take_while(List, Predicate, []). + +-spec do_chunk(list(AJK), fun((AJK) -> AJM), AJM, list(AJK), list(list(AJK))) -> list(list(AJK)). +do_chunk(List, F, Previous_key, Current_chunk, Acc) -> + case List of + [First | Rest] -> + Key = F(First), + case Key =:= Previous_key of + false -> + New_acc = [reverse(Current_chunk) | Acc], + do_chunk(Rest, F, Key, [First], New_acc); + + _ -> + do_chunk(Rest, F, Key, [First | Current_chunk], Acc) + end; + + _ -> + reverse([reverse(Current_chunk) | Acc]) + end. + +-spec chunk(list(AJS), fun((AJS) -> any())) -> list(list(AJS)). +chunk(List, F) -> + case List of + [] -> + []; + + [First | Rest] -> + do_chunk(Rest, F, F(First), [First], []) + end. + +-spec do_sized_chunk( + list(AJX), + integer(), + integer(), + list(AJX), + list(list(AJX)) +) -> list(list(AJX)). +do_sized_chunk(List, Count, Left, Current_chunk, Acc) -> + case List of + [] -> + case Current_chunk of + [] -> + reverse(Acc); + + Remaining -> + reverse([reverse(Remaining) | Acc]) + end; + + [First | Rest] -> + Chunk = [First | Current_chunk], + case Left > 1 of + false -> + do_sized_chunk( + Rest, + Count, + Count, + [], + [reverse(Chunk) | Acc] + ); + + true -> + do_sized_chunk(Rest, Count, Left - 1, Chunk, Acc) + end + end. + +-spec sized_chunk(list(AKE), integer()) -> list(list(AKE)). +sized_chunk(List, Count) -> + do_sized_chunk(List, Count, Count, [], []). + +-spec reduce(list(AKI), fun((AKI, AKI) -> AKI)) -> {ok, AKI} | {error, nil}. +reduce(List, Fun) -> + case List of + [] -> + {error, nil}; + + [First | Rest] -> + {ok, fold(Rest, First, Fun)} + end. + +-spec do_scan(list(AKM), AKO, list(AKO), fun((AKO, AKM) -> AKO)) -> list(AKO). +do_scan(List, Accumulator, Accumulated, Fun) -> + case List of + [] -> + reverse(Accumulated); + + [X | Xs] -> + Next = Fun(Accumulator, X), + do_scan(Xs, Next, [Next | Accumulated], Fun) + end. + +-spec scan(list(AKR), AKT, fun((AKT, AKR) -> AKT)) -> list(AKT). +scan(List, Initial, Fun) -> + do_scan(List, Initial, [], Fun). + +-spec last(list(AKV)) -> {ok, AKV} | {error, nil}. +last(List) -> + _pipe = List, + reduce(_pipe, fun(_, Elem) -> Elem end). + +-spec combinations(list(AKZ), integer()) -> list(list(AKZ)). +combinations(Items, N) -> + case N of + 0 -> + [[]]; + + _ -> + case Items of + [] -> + []; + + [X | Xs] -> + First_combinations = begin + _pipe = map( + combinations(Xs, N - 1), + fun(Com) -> [X | Com] end + ), + reverse(_pipe) + end, + fold( + First_combinations, + combinations(Xs, N), + fun(Acc, C) -> [C | Acc] end + ) + end + end. + +-spec do_combination_pairs(list(ALD)) -> list(list({ALD, ALD})). +do_combination_pairs(Items) -> + case Items of + [] -> + []; + + [X | Xs] -> + First_combinations = map(Xs, fun(Other) -> {X, Other} end), + [First_combinations | do_combination_pairs(Xs)] + end. + +-spec combination_pairs(list(ALH)) -> list({ALH, ALH}). +combination_pairs(Items) -> + _pipe = do_combination_pairs(Items), + concat(_pipe). + +-spec transpose(list(list(ALO))) -> list(list(ALO)). +transpose(List_of_list) -> + Take_first = fun(List) -> case List of + [] -> + []; + + [F] -> + [F]; + + [F@1 | _] -> + [F@1] + end end, + case List_of_list of + [] -> + []; + + [[] | Xss] -> + transpose(Xss); + + Rows -> + Firsts = begin + _pipe = Rows, + _pipe@1 = map(_pipe, Take_first), + concat(_pipe@1) + end, + Rest = transpose(map(Rows, fun(_capture) -> drop(_capture, 1) end)), + [Firsts | Rest] + end. + +-spec interleave(list(list(ALK))) -> list(ALK). +interleave(List) -> + _pipe = transpose(List), + concat(_pipe). + +-spec do_shuffle_pair_unwrap(list({float(), ALT}), list(ALT)) -> list(ALT). +do_shuffle_pair_unwrap(List, Acc) -> + case List of + [] -> + Acc; + + [Elem_pair | Enumerable] -> + do_shuffle_pair_unwrap( + Enumerable, + [erlang:element(2, Elem_pair) | Acc] + ) + end. + +-spec do_shuffle_by_pair_indexes(list({float(), ALX})) -> list({float(), ALX}). +do_shuffle_by_pair_indexes(List_of_pairs) -> + sort( + List_of_pairs, + fun(A_pair, B_pair) -> + gleam@float:compare( + erlang:element(1, A_pair), + erlang:element(1, B_pair) + ) + end + ). + +-spec shuffle(list(AMA)) -> list(AMA). +shuffle(List) -> + _pipe = List, + _pipe@1 = fold( + _pipe, + [], + fun(Acc, A) -> [{gleam@float:random(+0.0, 1.0), A} | Acc] end + ), + _pipe@2 = do_shuffle_by_pair_indexes(_pipe@1), + do_shuffle_pair_unwrap(_pipe@2, []). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache Binary files differnew file mode 100644 index 0000000..0c28857 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta Binary files differnew file mode 100644 index 0000000..03b0ec9 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.erl new file mode 100644 index 0000000..885de7e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.erl @@ -0,0 +1,76 @@ +-module(gleam@map). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([size/1, to_list/1, from_list/1, has_key/2, new/0, get/2, insert/3, map_values/2, keys/1, values/1, filter/2, take/2, merge/2, delete/2, drop/2, update/3, fold/3]). + +-spec size(gleam@dict:dict(any(), any())) -> integer(). +size(Map) -> + gleam@dict:size(Map). + +-spec to_list(gleam@dict:dict(CZB, CZC)) -> list({CZB, CZC}). +to_list(Map) -> + gleam@dict:to_list(Map). + +-spec from_list(list({CZE, CZF})) -> gleam@dict:dict(CZE, CZF). +from_list(List) -> + gleam@dict:from_list(List). + +-spec has_key(gleam@dict:dict(CZJ, any()), CZJ) -> boolean(). +has_key(Map, Key) -> + gleam@dict:has_key(Map, Key). + +-spec new() -> gleam@dict:dict(any(), any()). +new() -> + gleam@dict:new(). + +-spec get(gleam@dict:dict(CZM, CZN), CZM) -> {ok, CZN} | {error, nil}. +get(From, Get) -> + gleam@dict:get(From, Get). + +-spec insert(gleam@dict:dict(CZR, CZS), CZR, CZS) -> gleam@dict:dict(CZR, CZS). +insert(Map, Key, Value) -> + gleam@dict:insert(Map, Key, Value). + +-spec map_values(gleam@dict:dict(CZV, CZW), fun((CZV, CZW) -> CZX)) -> gleam@dict:dict(CZV, CZX). +map_values(Map, Fun) -> + gleam@dict:map_values(Map, Fun). + +-spec keys(gleam@dict:dict(DAA, any())) -> list(DAA). +keys(Map) -> + gleam@dict:keys(Map). + +-spec values(gleam@dict:dict(any(), DAD)) -> list(DAD). +values(Map) -> + gleam@dict:values(Map). + +-spec filter(gleam@dict:dict(DAG, DAH), fun((DAG, DAH) -> boolean())) -> gleam@dict:dict(DAG, DAH). +filter(Map, Predicate) -> + gleam@dict:filter(Map, Predicate). + +-spec take(gleam@dict:dict(DAK, DCE), list(DAK)) -> gleam@dict:dict(DAK, DCE). +take(Map, Desired_keys) -> + gleam@dict:take(Map, Desired_keys). + +-spec merge(gleam@dict:dict(DCF, DCG), gleam@dict:dict(DCF, DCG)) -> gleam@dict:dict(DCF, DCG). +merge(Map, New_entries) -> + gleam@dict:merge(Map, New_entries). + +-spec delete(gleam@dict:dict(DAR, DCI), DAR) -> gleam@dict:dict(DAR, DCI). +delete(Map, Key) -> + gleam@dict:delete(Map, Key). + +-spec drop(gleam@dict:dict(DAU, DCK), list(DAU)) -> gleam@dict:dict(DAU, DCK). +drop(Map, Disallowed_keys) -> + gleam@dict:drop(Map, Disallowed_keys). + +-spec update( + gleam@dict:dict(DAY, DAZ), + DAY, + fun((gleam@option:option(DAZ)) -> DAZ) +) -> gleam@dict:dict(DAY, DAZ). +update(Map, Key, Fun) -> + gleam@dict:update(Map, Key, Fun). + +-spec fold(gleam@dict:dict(DBE, DBF), DBD, fun((DBD, DBE, DBF) -> DBD)) -> DBD. +fold(Map, Initial, Fun) -> + gleam@dict:fold(Map, Initial, Fun). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache Binary files differnew file mode 100644 index 0000000..7ac8412 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta Binary files differnew file mode 100644 index 0000000..ff8f8df --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.erl new file mode 100644 index 0000000..6c9768c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.erl @@ -0,0 +1,147 @@ +-module(gleam@option). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([all/1, is_some/1, is_none/1, to_result/2, from_result/1, unwrap/2, lazy_unwrap/2, map/2, flatten/1, then/2, 'or'/2, lazy_or/2, values/1]). +-export_type([option/1]). + +-type option(GB) :: {some, GB} | none. + +-spec do_all(list(option(GC)), list(GC)) -> option(list(GC)). +do_all(List, Acc) -> + case List of + [] -> + {some, Acc}; + + [X | Rest] -> + Accumulate = fun(Acc@1, Item) -> case {Acc@1, Item} of + {{some, Values}, {some, Value}} -> + {some, [Value | Values]}; + + {_, _} -> + none + end end, + Accumulate(do_all(Rest, Acc), X) + end. + +-spec all(list(option(GI))) -> option(list(GI)). +all(List) -> + do_all(List, []). + +-spec is_some(option(any())) -> boolean(). +is_some(Option) -> + Option /= none. + +-spec is_none(option(any())) -> boolean(). +is_none(Option) -> + Option =:= none. + +-spec to_result(option(GR), GU) -> {ok, GR} | {error, GU}. +to_result(Option, E) -> + case Option of + {some, A} -> + {ok, A}; + + _ -> + {error, E} + end. + +-spec from_result({ok, GX} | {error, any()}) -> option(GX). +from_result(Result) -> + case Result of + {ok, A} -> + {some, A}; + + _ -> + none + end. + +-spec unwrap(option(HC), HC) -> HC. +unwrap(Option, Default) -> + case Option of + {some, X} -> + X; + + none -> + Default + end. + +-spec lazy_unwrap(option(HE), fun(() -> HE)) -> HE. +lazy_unwrap(Option, Default) -> + case Option of + {some, X} -> + X; + + none -> + Default() + end. + +-spec map(option(HG), fun((HG) -> HI)) -> option(HI). +map(Option, Fun) -> + case Option of + {some, X} -> + {some, Fun(X)}; + + none -> + none + end. + +-spec flatten(option(option(HK))) -> option(HK). +flatten(Option) -> + case Option of + {some, X} -> + X; + + none -> + none + end. + +-spec then(option(HO), fun((HO) -> option(HQ))) -> option(HQ). +then(Option, Fun) -> + case Option of + {some, X} -> + Fun(X); + + none -> + none + end. + +-spec 'or'(option(HT), option(HT)) -> option(HT). +'or'(First, Second) -> + case First of + {some, _} -> + First; + + none -> + Second + end. + +-spec lazy_or(option(HX), fun(() -> option(HX))) -> option(HX). +lazy_or(First, Second) -> + case First of + {some, _} -> + First; + + none -> + Second() + end. + +-spec do_values(list(option(IB)), list(IB)) -> list(IB). +do_values(List, Acc) -> + case List of + [] -> + Acc; + + [X | Xs] -> + Accumulate = fun(Acc@1, Item) -> case Item of + {some, Value} -> + [Value | Acc@1]; + + none -> + Acc@1 + end end, + Accumulate(do_values(Xs, Acc), X) + end. + +-spec values(list(option(IG))) -> list(IG). +values(Options) -> + do_values(Options, []). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache Binary files differnew file mode 100644 index 0000000..42e5822 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta Binary files differnew file mode 100644 index 0000000..c304185 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.erl new file mode 100644 index 0000000..d4b225c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.erl @@ -0,0 +1,79 @@ +-module(gleam@order). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([negate/1, to_int/1, compare/2, max/2, min/2, reverse/1]). +-export_type([order/0]). + +-type order() :: lt | eq | gt. + +-spec negate(order()) -> order(). +negate(Order) -> + case Order of + lt -> + gt; + + eq -> + eq; + + gt -> + lt + end. + +-spec to_int(order()) -> integer(). +to_int(Order) -> + case Order of + lt -> + -1; + + eq -> + 0; + + gt -> + 1 + end. + +-spec compare(order(), order()) -> order(). +compare(A, B) -> + case {A, B} of + {X, Y} when X =:= Y -> + eq; + + {lt, _} -> + lt; + + {eq, gt} -> + lt; + + {_, _} -> + gt + end. + +-spec max(order(), order()) -> order(). +max(A, B) -> + case {A, B} of + {gt, _} -> + gt; + + {eq, lt} -> + eq; + + {_, _} -> + B + end. + +-spec min(order(), order()) -> order(). +min(A, B) -> + case {A, B} of + {lt, _} -> + lt; + + {eq, gt} -> + eq; + + {_, _} -> + B + end. + +-spec reverse(fun((I, I) -> order())) -> fun((I, I) -> order()). +reverse(Orderer) -> + fun(A, B) -> Orderer(B, A) end. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache Binary files differnew file mode 100644 index 0000000..891b8cd --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta Binary files differnew file mode 100644 index 0000000..8ee3fd8 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.erl new file mode 100644 index 0000000..8e5d10f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.erl @@ -0,0 +1,33 @@ +-module(gleam@pair). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([first/1, second/1, swap/1, map_first/2, map_second/2, new/2]). + +-spec first({FM, any()}) -> FM. +first(Pair) -> + {A, _} = Pair, + A. + +-spec second({any(), FP}) -> FP. +second(Pair) -> + {_, A} = Pair, + A. + +-spec swap({FQ, FR}) -> {FR, FQ}. +swap(Pair) -> + {A, B} = Pair, + {B, A}. + +-spec map_first({FS, FT}, fun((FS) -> FU)) -> {FU, FT}. +map_first(Pair, Fun) -> + {A, B} = Pair, + {Fun(A), B}. + +-spec map_second({FV, FW}, fun((FW) -> FX)) -> {FV, FX}. +map_second(Pair, Fun) -> + {A, B} = Pair, + {A, Fun(B)}. + +-spec new(FY, FZ) -> {FY, FZ}. +new(First, Second) -> + {First, Second}. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache Binary files differnew file mode 100644 index 0000000..c7b14d2 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta Binary files differnew file mode 100644 index 0000000..26ea872 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.erl new file mode 100644 index 0000000..1f763d0 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.erl @@ -0,0 +1,121 @@ +-module(gleam@queue). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-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]). +-export_type([queue/1]). + +-opaque queue(DNJ) :: {queue, list(DNJ), list(DNJ)}. + +-spec new() -> queue(any()). +new() -> + {queue, [], []}. + +-spec from_list(list(DNM)) -> queue(DNM). +from_list(List) -> + {queue, [], List}. + +-spec to_list(queue(DNP)) -> list(DNP). +to_list(Queue) -> + _pipe = erlang:element(3, Queue), + gleam@list:append(_pipe, gleam@list:reverse(erlang:element(2, Queue))). + +-spec is_empty(queue(any())) -> boolean(). +is_empty(Queue) -> + (erlang:element(2, Queue) =:= []) andalso (erlang:element(3, Queue) =:= []). + +-spec length(queue(any())) -> integer(). +length(Queue) -> + gleam@list:length(erlang:element(2, Queue)) + gleam@list:length( + erlang:element(3, Queue) + ). + +-spec push_back(queue(DNW), DNW) -> queue(DNW). +push_back(Queue, Item) -> + {queue, [Item | erlang:element(2, Queue)], erlang:element(3, Queue)}. + +-spec push_front(queue(DNZ), DNZ) -> queue(DNZ). +push_front(Queue, Item) -> + {queue, erlang:element(2, Queue), [Item | erlang:element(3, Queue)]}. + +-spec pop_back(queue(DOC)) -> {ok, {DOC, queue(DOC)}} | {error, nil}. +pop_back(Queue) -> + case Queue of + {queue, [], []} -> + {error, nil}; + + {queue, [], Out} -> + pop_back({queue, gleam@list:reverse(Out), []}); + + {queue, [First | Rest], Out@1} -> + Queue@1 = {queue, Rest, Out@1}, + {ok, {First, Queue@1}} + end. + +-spec pop_front(queue(DOH)) -> {ok, {DOH, queue(DOH)}} | {error, nil}. +pop_front(Queue) -> + case Queue of + {queue, [], []} -> + {error, nil}; + + {queue, In, []} -> + pop_front({queue, [], gleam@list:reverse(In)}); + + {queue, In@1, [First | Rest]} -> + Queue@1 = {queue, In@1, Rest}, + {ok, {First, Queue@1}} + end. + +-spec reverse(queue(DOM)) -> queue(DOM). +reverse(Queue) -> + {queue, erlang:element(3, Queue), erlang:element(2, Queue)}. + +-spec check_equal( + list(DOP), + list(DOP), + list(DOP), + list(DOP), + fun((DOP, DOP) -> boolean()) +) -> boolean(). +check_equal(Xs, X_tail, Ys, Y_tail, Eq) -> + case {Xs, X_tail, Ys, Y_tail} of + {[], [], [], []} -> + true; + + {[X | Xs@1], _, [Y | Ys@1], _} -> + case Eq(X, Y) of + false -> + false; + + true -> + check_equal(Xs@1, X_tail, Ys@1, Y_tail, Eq) + end; + + {[], [_ | _], _, _} -> + check_equal(gleam@list:reverse(X_tail), [], Ys, Y_tail, Eq); + + {_, _, [], [_ | _]} -> + check_equal(Xs, X_tail, gleam@list:reverse(Y_tail), [], Eq); + + {_, _, _, _} -> + false + end. + +-spec is_logically_equal(queue(DOU), queue(DOU), fun((DOU, DOU) -> boolean())) -> boolean(). +is_logically_equal(A, B, Element_is_equal) -> + check_equal( + erlang:element(3, A), + erlang:element(2, A), + erlang:element(3, B), + erlang:element(2, B), + Element_is_equal + ). + +-spec is_equal(queue(DOX), queue(DOX)) -> boolean(). +is_equal(A, B) -> + check_equal( + erlang:element(3, A), + erlang:element(2, A), + erlang:element(3, B), + erlang:element(2, B), + fun(A@1, B@1) -> A@1 =:= B@1 end + ). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache Binary files differnew file mode 100644 index 0000000..ba8d28b --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta Binary files differnew file mode 100644 index 0000000..ab416af --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.erl new file mode 100644 index 0000000..f49cc28 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.erl @@ -0,0 +1,33 @@ +-module(gleam@regex). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([compile/2, from_string/1, check/2, split/2, scan/2]). +-export_type([regex/0, match/0, compile_error/0, options/0]). + +-type regex() :: any(). + +-type match() :: {match, binary(), list(gleam@option:option(binary()))}. + +-type compile_error() :: {compile_error, binary(), integer()}. + +-type options() :: {options, boolean(), boolean()}. + +-spec compile(binary(), options()) -> {ok, regex()} | {error, compile_error()}. +compile(Pattern, Options) -> + gleam_stdlib:compile_regex(Pattern, Options). + +-spec from_string(binary()) -> {ok, regex()} | {error, compile_error()}. +from_string(Pattern) -> + compile(Pattern, {options, false, false}). + +-spec check(regex(), binary()) -> boolean(). +check(Regex, Content) -> + gleam_stdlib:regex_check(Regex, Content). + +-spec split(regex(), binary()) -> list(binary()). +split(Regex, String) -> + gleam_stdlib:regex_split(Regex, String). + +-spec scan(regex(), binary()) -> list(match()). +scan(Regex, String) -> + gleam_stdlib:regex_scan(Regex, String). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache Binary files differnew file mode 100644 index 0000000..1d77445 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta Binary files differnew file mode 100644 index 0000000..732654a --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.erl new file mode 100644 index 0000000..564982f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.erl @@ -0,0 +1,201 @@ +-module(gleam@result). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([is_ok/1, is_error/1, map/2, map_error/2, flatten/1, 'try'/2, then/2, unwrap/2, lazy_unwrap/2, unwrap_error/2, unwrap_both/1, nil_error/1, 'or'/2, lazy_or/2, all/1, partition/1, replace/2, replace_error/2, values/1, try_recover/2]). + +-spec is_ok({ok, any()} | {error, any()}) -> boolean(). +is_ok(Result) -> + case Result of + {error, _} -> + false; + + {ok, _} -> + true + end. + +-spec is_error({ok, any()} | {error, any()}) -> boolean(). +is_error(Result) -> + case Result of + {ok, _} -> + false; + + {error, _} -> + true + end. + +-spec map({ok, BFM} | {error, BFN}, fun((BFM) -> BFQ)) -> {ok, BFQ} | + {error, BFN}. +map(Result, Fun) -> + case Result of + {ok, X} -> + {ok, Fun(X)}; + + {error, E} -> + {error, E} + end. + +-spec map_error({ok, BFT} | {error, BFU}, fun((BFU) -> BFX)) -> {ok, BFT} | + {error, BFX}. +map_error(Result, Fun) -> + case Result of + {ok, X} -> + {ok, X}; + + {error, Error} -> + {error, Fun(Error)} + end. + +-spec flatten({ok, {ok, BGA} | {error, BGB}} | {error, BGB}) -> {ok, BGA} | + {error, BGB}. +flatten(Result) -> + case Result of + {ok, X} -> + X; + + {error, Error} -> + {error, Error} + end. + +-spec 'try'({ok, BGI} | {error, BGJ}, fun((BGI) -> {ok, BGM} | {error, BGJ})) -> {ok, + BGM} | + {error, BGJ}. +'try'(Result, Fun) -> + case Result of + {ok, X} -> + Fun(X); + + {error, E} -> + {error, E} + end. + +-spec then({ok, BGR} | {error, BGS}, fun((BGR) -> {ok, BGV} | {error, BGS})) -> {ok, + BGV} | + {error, BGS}. +then(Result, Fun) -> + 'try'(Result, Fun). + +-spec unwrap({ok, BHA} | {error, any()}, BHA) -> BHA. +unwrap(Result, Default) -> + case Result of + {ok, V} -> + V; + + {error, _} -> + Default + end. + +-spec lazy_unwrap({ok, BHE} | {error, any()}, fun(() -> BHE)) -> BHE. +lazy_unwrap(Result, Default) -> + case Result of + {ok, V} -> + V; + + {error, _} -> + Default() + end. + +-spec unwrap_error({ok, any()} | {error, BHJ}, BHJ) -> BHJ. +unwrap_error(Result, Default) -> + case Result of + {ok, _} -> + Default; + + {error, E} -> + E + end. + +-spec unwrap_both({ok, BHM} | {error, BHM}) -> BHM. +unwrap_both(Result) -> + case Result of + {ok, A} -> + A; + + {error, A@1} -> + A@1 + end. + +-spec nil_error({ok, BHP} | {error, any()}) -> {ok, BHP} | {error, nil}. +nil_error(Result) -> + map_error(Result, fun(_) -> nil end). + +-spec 'or'({ok, BHV} | {error, BHW}, {ok, BHV} | {error, BHW}) -> {ok, BHV} | + {error, BHW}. +'or'(First, Second) -> + case First of + {ok, _} -> + First; + + {error, _} -> + Second + end. + +-spec lazy_or({ok, BID} | {error, BIE}, fun(() -> {ok, BID} | {error, BIE})) -> {ok, + BID} | + {error, BIE}. +lazy_or(First, Second) -> + case First of + {ok, _} -> + First; + + {error, _} -> + Second() + end. + +-spec all(list({ok, BIL} | {error, BIM})) -> {ok, list(BIL)} | {error, BIM}. +all(Results) -> + gleam@list:try_map(Results, fun(X) -> X end). + +-spec do_partition(list({ok, BJA} | {error, BJB}), list(BJA), list(BJB)) -> {list(BJA), + list(BJB)}. +do_partition(Results, Oks, Errors) -> + case Results of + [] -> + {Oks, Errors}; + + [{ok, A} | Rest] -> + do_partition(Rest, [A | Oks], Errors); + + [{error, E} | Rest@1] -> + do_partition(Rest@1, Oks, [E | Errors]) + end. + +-spec partition(list({ok, BIT} | {error, BIU})) -> {list(BIT), list(BIU)}. +partition(Results) -> + do_partition(Results, [], []). + +-spec replace({ok, any()} | {error, BJJ}, BJM) -> {ok, BJM} | {error, BJJ}. +replace(Result, Value) -> + case Result of + {ok, _} -> + {ok, Value}; + + {error, Error} -> + {error, Error} + end. + +-spec replace_error({ok, BJP} | {error, any()}, BJT) -> {ok, BJP} | {error, BJT}. +replace_error(Result, Error) -> + case Result of + {ok, X} -> + {ok, X}; + + {error, _} -> + {error, Error} + end. + +-spec values(list({ok, BJW} | {error, any()})) -> list(BJW). +values(Results) -> + gleam@list:filter_map(Results, fun(R) -> R end). + +-spec try_recover( + {ok, BKC} | {error, BKD}, + fun((BKD) -> {ok, BKC} | {error, BKG}) +) -> {ok, BKC} | {error, BKG}. +try_recover(Result, Fun) -> + case Result of + {ok, Value} -> + {ok, Value}; + + {error, Error} -> + Fun(Error) + end. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache Binary files differnew file mode 100644 index 0000000..c86e73f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta Binary files differnew file mode 100644 index 0000000..ee9607b --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.erl new file mode 100644 index 0000000..1ccd4b1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.erl @@ -0,0 +1,85 @@ +-module(gleam@set). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([new/0, size/1, contains/2, delete/2, to_list/1, fold/3, filter/2, drop/2, take/2, intersection/2, insert/2, from_list/1, union/2]). +-export_type([set/1]). + +-opaque set(DIS) :: {set, gleam@dict:dict(DIS, list(nil))}. + +-spec new() -> set(any()). +new() -> + {set, gleam@dict:new()}. + +-spec size(set(any())) -> integer(). +size(Set) -> + gleam@dict:size(erlang:element(2, Set)). + +-spec contains(set(DJB), DJB) -> boolean(). +contains(Set, Member) -> + _pipe = erlang:element(2, Set), + _pipe@1 = gleam@dict:get(_pipe, Member), + gleam@result:is_ok(_pipe@1). + +-spec delete(set(DJD), DJD) -> set(DJD). +delete(Set, Member) -> + {set, gleam@dict:delete(erlang:element(2, Set), Member)}. + +-spec to_list(set(DJG)) -> list(DJG). +to_list(Set) -> + gleam@dict:keys(erlang:element(2, Set)). + +-spec fold(set(DJM), DJO, fun((DJO, DJM) -> DJO)) -> DJO. +fold(Set, Initial, Reducer) -> + gleam@dict:fold( + erlang:element(2, Set), + Initial, + fun(A, K, _) -> Reducer(A, K) end + ). + +-spec filter(set(DJP), fun((DJP) -> boolean())) -> set(DJP). +filter(Set, Predicate) -> + {set, + gleam@dict:filter(erlang:element(2, Set), fun(M, _) -> Predicate(M) end)}. + +-spec drop(set(DJS), list(DJS)) -> set(DJS). +drop(Set, Disallowed) -> + gleam@list:fold(Disallowed, Set, fun delete/2). + +-spec take(set(DJW), list(DJW)) -> set(DJW). +take(Set, Desired) -> + {set, gleam@dict:take(erlang:element(2, Set), Desired)}. + +-spec order(set(DKA), set(DKA)) -> {set(DKA), set(DKA)}. +order(First, Second) -> + case gleam@dict:size(erlang:element(2, First)) > gleam@dict:size( + erlang:element(2, Second) + ) of + true -> + {First, Second}; + + false -> + {Second, First} + end. + +-spec intersection(set(DKJ), set(DKJ)) -> set(DKJ). +intersection(First, Second) -> + {Larger, Smaller} = order(First, Second), + take(Larger, to_list(Smaller)). + +-spec insert(set(DIY), DIY) -> set(DIY). +insert(Set, Member) -> + {set, gleam@dict:insert(erlang:element(2, Set), Member, [])}. + +-spec from_list(list(DJJ)) -> set(DJJ). +from_list(Members) -> + Map = gleam@list:fold( + Members, + gleam@dict:new(), + fun(M, K) -> gleam@dict:insert(M, K, []) end + ), + {set, Map}. + +-spec union(set(DKF), set(DKF)) -> set(DKF). +union(First, Second) -> + {Larger, Smaller} = order(First, Second), + fold(Smaller, Larger, fun insert/2). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache Binary files differnew file mode 100644 index 0000000..580f9e1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta Binary files differnew file mode 100644 index 0000000..300d752 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.erl new file mode 100644 index 0000000..6df406b --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.erl @@ -0,0 +1,352 @@ +-module(gleam@string). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([is_empty/1, length/1, reverse/1, replace/3, lowercase/1, uppercase/1, compare/2, slice/3, crop/2, drop_left/2, drop_right/2, contains/2, starts_with/2, ends_with/2, split_once/2, append/2, concat/1, repeat/2, join/2, pad_left/3, pad_right/3, trim/1, trim_left/1, trim_right/1, pop_grapheme/1, to_graphemes/1, split/2, to_utf_codepoints/1, from_utf_codepoints/1, utf_codepoint/1, utf_codepoint_to_int/1, to_option/1, first/1, last/1, capitalise/1, inspect/1, byte_size/1]). +-export_type([direction/0]). + +-type direction() :: leading | trailing | both. + +-spec is_empty(binary()) -> boolean(). +is_empty(Str) -> + Str =:= <<""/utf8>>. + +-spec length(binary()) -> integer(). +length(String) -> + string:length(String). + +-spec do_reverse(binary()) -> binary(). +do_reverse(String) -> + _pipe = String, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:reverse(_pipe@1), + gleam@string_builder:to_string(_pipe@2). + +-spec reverse(binary()) -> binary(). +reverse(String) -> + do_reverse(String). + +-spec replace(binary(), binary(), binary()) -> binary(). +replace(String, Pattern, Substitute) -> + _pipe = String, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:replace(_pipe@1, Pattern, Substitute), + gleam@string_builder:to_string(_pipe@2). + +-spec lowercase(binary()) -> binary(). +lowercase(String) -> + string:lowercase(String). + +-spec uppercase(binary()) -> binary(). +uppercase(String) -> + string:uppercase(String). + +-spec compare(binary(), binary()) -> gleam@order:order(). +compare(A, B) -> + case A =:= B of + true -> + eq; + + _ -> + case gleam_stdlib:less_than(A, B) of + true -> + lt; + + _ -> + gt + end + end. + +-spec slice(binary(), integer(), integer()) -> binary(). +slice(String, Idx, Len) -> + case Len < 0 of + true -> + <<""/utf8>>; + + false -> + case Idx < 0 of + true -> + Translated_idx = length(String) + Idx, + case Translated_idx < 0 of + true -> + <<""/utf8>>; + + false -> + string:slice(String, Translated_idx, Len) + end; + + false -> + string:slice(String, Idx, Len) + end + end. + +-spec crop(binary(), binary()) -> binary(). +crop(String, Substring) -> + gleam_stdlib:crop_string(String, Substring). + +-spec drop_left(binary(), integer()) -> binary(). +drop_left(String, Num_graphemes) -> + case Num_graphemes < 0 of + true -> + String; + + false -> + slice(String, Num_graphemes, length(String) - Num_graphemes) + end. + +-spec drop_right(binary(), integer()) -> binary(). +drop_right(String, Num_graphemes) -> + case Num_graphemes < 0 of + true -> + String; + + false -> + slice(String, 0, length(String) - Num_graphemes) + end. + +-spec contains(binary(), binary()) -> boolean(). +contains(Haystack, Needle) -> + gleam_stdlib:contains_string(Haystack, Needle). + +-spec starts_with(binary(), binary()) -> boolean(). +starts_with(String, Prefix) -> + gleam_stdlib:string_starts_with(String, Prefix). + +-spec ends_with(binary(), binary()) -> boolean(). +ends_with(String, Suffix) -> + gleam_stdlib:string_ends_with(String, Suffix). + +-spec do_split_once(binary(), binary()) -> {ok, {binary(), binary()}} | + {error, nil}. +do_split_once(X, Substring) -> + case string:split(X, Substring) of + [First, Rest] -> + {ok, {First, Rest}}; + + _ -> + {error, nil} + end. + +-spec split_once(binary(), binary()) -> {ok, {binary(), binary()}} | + {error, nil}. +split_once(X, Substring) -> + do_split_once(X, Substring). + +-spec append(binary(), binary()) -> binary(). +append(First, Second) -> + _pipe = First, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:append(_pipe@1, Second), + gleam@string_builder:to_string(_pipe@2). + +-spec concat(list(binary())) -> binary(). +concat(Strings) -> + _pipe = Strings, + _pipe@1 = gleam@string_builder:from_strings(_pipe), + gleam@string_builder:to_string(_pipe@1). + +-spec repeat(binary(), integer()) -> binary(). +repeat(String, Times) -> + _pipe = gleam@iterator:repeat(String), + _pipe@1 = gleam@iterator:take(_pipe, Times), + _pipe@2 = gleam@iterator:to_list(_pipe@1), + concat(_pipe@2). + +-spec do_join(list(binary()), binary()) -> binary(). +do_join(Strings, Separator) -> + _pipe = Strings, + _pipe@1 = gleam@list:intersperse(_pipe, Separator), + concat(_pipe@1). + +-spec join(list(binary()), binary()) -> binary(). +join(Strings, Separator) -> + do_join(Strings, Separator). + +-spec padding(integer(), binary()) -> gleam@iterator:iterator(binary()). +padding(Size, Pad_string) -> + Pad_length = length(Pad_string), + Num_pads = case Pad_length of + 0 -> 0; + Gleam@denominator -> Size div Gleam@denominator + end, + Extra = case Pad_length of + 0 -> 0; + Gleam@denominator@1 -> Size rem Gleam@denominator@1 + end, + _pipe = gleam@iterator:repeat(Pad_string), + _pipe@1 = gleam@iterator:take(_pipe, Num_pads), + gleam@iterator:append( + _pipe@1, + gleam@iterator:single(slice(Pad_string, 0, Extra)) + ). + +-spec pad_left(binary(), integer(), binary()) -> binary(). +pad_left(String, Desired_length, Pad_string) -> + Current_length = length(String), + To_pad_length = Desired_length - Current_length, + _pipe = padding(To_pad_length, Pad_string), + _pipe@1 = gleam@iterator:append(_pipe, gleam@iterator:single(String)), + _pipe@2 = gleam@iterator:to_list(_pipe@1), + concat(_pipe@2). + +-spec pad_right(binary(), integer(), binary()) -> binary(). +pad_right(String, Desired_length, Pad_string) -> + Current_length = length(String), + To_pad_length = Desired_length - Current_length, + _pipe = gleam@iterator:single(String), + _pipe@1 = gleam@iterator:append(_pipe, padding(To_pad_length, Pad_string)), + _pipe@2 = gleam@iterator:to_list(_pipe@1), + concat(_pipe@2). + +-spec do_trim(binary()) -> binary(). +do_trim(String) -> + string:trim(String, both). + +-spec trim(binary()) -> binary(). +trim(String) -> + do_trim(String). + +-spec do_trim_left(binary()) -> binary(). +do_trim_left(String) -> + string:trim(String, leading). + +-spec trim_left(binary()) -> binary(). +trim_left(String) -> + do_trim_left(String). + +-spec do_trim_right(binary()) -> binary(). +do_trim_right(String) -> + string:trim(String, trailing). + +-spec trim_right(binary()) -> binary(). +trim_right(String) -> + do_trim_right(String). + +-spec pop_grapheme(binary()) -> {ok, {binary(), binary()}} | {error, nil}. +pop_grapheme(String) -> + gleam_stdlib:string_pop_grapheme(String). + +-spec do_to_graphemes(binary(), list(binary())) -> list(binary()). +do_to_graphemes(String, Acc) -> + case pop_grapheme(String) of + {ok, {Grapheme, Rest}} -> + do_to_graphemes(Rest, [Grapheme | Acc]); + + _ -> + Acc + end. + +-spec to_graphemes(binary()) -> list(binary()). +to_graphemes(String) -> + _pipe = do_to_graphemes(String, []), + gleam@list:reverse(_pipe). + +-spec split(binary(), binary()) -> list(binary()). +split(X, Substring) -> + case Substring of + <<""/utf8>> -> + to_graphemes(X); + + _ -> + _pipe = X, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:split(_pipe@1, Substring), + gleam@list:map(_pipe@2, fun gleam@string_builder:to_string/1) + end. + +-spec do_to_utf_codepoints_impl(bitstring(), list(integer())) -> list(integer()). +do_to_utf_codepoints_impl(Bit_array, Acc) -> + case Bit_array of + <<First/utf8, Rest/binary>> -> + do_to_utf_codepoints_impl(Rest, [First | Acc]); + + _ -> + Acc + end. + +-spec do_to_utf_codepoints(binary()) -> list(integer()). +do_to_utf_codepoints(String) -> + _pipe = do_to_utf_codepoints_impl(<<String/binary>>, []), + gleam@list:reverse(_pipe). + +-spec to_utf_codepoints(binary()) -> list(integer()). +to_utf_codepoints(String) -> + do_to_utf_codepoints(String). + +-spec from_utf_codepoints(list(integer())) -> binary(). +from_utf_codepoints(Utf_codepoints) -> + gleam_stdlib:utf_codepoint_list_to_string(Utf_codepoints). + +-spec utf_codepoint(integer()) -> {ok, integer()} | {error, nil}. +utf_codepoint(Value) -> + case Value of + I when I > 1114111 -> + {error, nil}; + + 65534 -> + {error, nil}; + + 65535 -> + {error, nil}; + + I@1 when (I@1 >= 55296) andalso (I@1 =< 57343) -> + {error, nil}; + + I@2 -> + {ok, gleam_stdlib:identity(I@2)} + end. + +-spec utf_codepoint_to_int(integer()) -> integer(). +utf_codepoint_to_int(Cp) -> + gleam_stdlib:identity(Cp). + +-spec to_option(binary()) -> gleam@option:option(binary()). +to_option(S) -> + case S of + <<""/utf8>> -> + none; + + _ -> + {some, S} + end. + +-spec first(binary()) -> {ok, binary()} | {error, nil}. +first(S) -> + case pop_grapheme(S) of + {ok, {First, _}} -> + {ok, First}; + + {error, E} -> + {error, E} + end. + +-spec last(binary()) -> {ok, binary()} | {error, nil}. +last(S) -> + case pop_grapheme(S) of + {ok, {First, <<""/utf8>>}} -> + {ok, First}; + + {ok, {_, Rest}} -> + {ok, slice(Rest, -1, 1)}; + + {error, E} -> + {error, E} + end. + +-spec capitalise(binary()) -> binary(). +capitalise(S) -> + case pop_grapheme(S) of + {ok, {First, Rest}} -> + append(uppercase(First), lowercase(Rest)); + + _ -> + <<""/utf8>> + end. + +-spec inspect(any()) -> binary(). +inspect(Term) -> + _pipe = gleam_stdlib:inspect(Term), + gleam@string_builder:to_string(_pipe). + +-spec byte_size(binary()) -> integer(). +byte_size(String) -> + erlang:byte_size(String). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache Binary files differnew file mode 100644 index 0000000..a92f14c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_meta Binary files differnew file mode 100644 index 0000000..2ef42cf --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.erl new file mode 100644 index 0000000..068bcc1 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.erl @@ -0,0 +1,91 @@ +-module(gleam@string_builder). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([prepend_builder/2, append_builder/2, new/0, from_strings/1, concat/1, from_string/1, prepend/2, append/2, to_string/1, byte_size/1, join/2, lowercase/1, uppercase/1, reverse/1, split/2, replace/3, is_equal/2, is_empty/1]). +-export_type([string_builder/0, direction/0]). + +-type string_builder() :: any(). + +-type direction() :: all. + +-spec prepend_builder(string_builder(), string_builder()) -> string_builder(). +prepend_builder(Builder, Prefix) -> + gleam_stdlib:iodata_append(Prefix, Builder). + +-spec append_builder(string_builder(), string_builder()) -> string_builder(). +append_builder(Builder, Suffix) -> + gleam_stdlib:iodata_append(Builder, Suffix). + +-spec new() -> string_builder(). +new() -> + gleam_stdlib:identity([]). + +-spec from_strings(list(binary())) -> string_builder(). +from_strings(Strings) -> + gleam_stdlib:identity(Strings). + +-spec concat(list(string_builder())) -> string_builder(). +concat(Builders) -> + gleam_stdlib:identity(Builders). + +-spec from_string(binary()) -> string_builder(). +from_string(String) -> + gleam_stdlib:identity(String). + +-spec prepend(string_builder(), binary()) -> string_builder(). +prepend(Builder, Prefix) -> + append_builder(from_string(Prefix), Builder). + +-spec append(string_builder(), binary()) -> string_builder(). +append(Builder, Second) -> + append_builder(Builder, from_string(Second)). + +-spec to_string(string_builder()) -> binary(). +to_string(Builder) -> + unicode:characters_to_binary(Builder). + +-spec byte_size(string_builder()) -> integer(). +byte_size(Builder) -> + erlang:iolist_size(Builder). + +-spec join(list(string_builder()), binary()) -> string_builder(). +join(Builders, Sep) -> + _pipe = Builders, + _pipe@1 = gleam@list:intersperse(_pipe, from_string(Sep)), + concat(_pipe@1). + +-spec lowercase(string_builder()) -> string_builder(). +lowercase(Builder) -> + string:lowercase(Builder). + +-spec uppercase(string_builder()) -> string_builder(). +uppercase(Builder) -> + string:uppercase(Builder). + +-spec reverse(string_builder()) -> string_builder(). +reverse(Builder) -> + string:reverse(Builder). + +-spec do_split(string_builder(), binary()) -> list(string_builder()). +do_split(Iodata, Pattern) -> + string:split(Iodata, Pattern, all). + +-spec split(string_builder(), binary()) -> list(string_builder()). +split(Iodata, Pattern) -> + do_split(Iodata, Pattern). + +-spec do_replace(string_builder(), binary(), binary()) -> string_builder(). +do_replace(Iodata, Pattern, Substitute) -> + string:replace(Iodata, Pattern, Substitute, all). + +-spec replace(string_builder(), binary(), binary()) -> string_builder(). +replace(Builder, Pattern, Substitute) -> + do_replace(Builder, Pattern, Substitute). + +-spec is_equal(string_builder(), string_builder()) -> boolean(). +is_equal(A, B) -> + string:equal(A, B). + +-spec is_empty(string_builder()) -> boolean(). +is_empty(Builder) -> + string:is_empty(Builder). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache Binary files differnew file mode 100644 index 0000000..f3328fc --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta Binary files differnew file mode 100644 index 0000000..a8195fc --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.erl new file mode 100644 index 0000000..c66ac2e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.erl @@ -0,0 +1,252 @@ +-module(gleam@uri). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([parse/1, parse_query/1, percent_encode/1, query_to_string/1, percent_decode/1, path_segments/1, to_string/1, origin/1, merge/2]). +-export_type([uri/0]). + +-type uri() :: {uri, + gleam@option:option(binary()), + gleam@option:option(binary()), + gleam@option:option(binary()), + gleam@option:option(integer()), + binary(), + gleam@option:option(binary()), + gleam@option:option(binary())}. + +-spec parse(binary()) -> {ok, uri()} | {error, nil}. +parse(Uri_string) -> + gleam_stdlib:uri_parse(Uri_string). + +-spec parse_query(binary()) -> {ok, list({binary(), binary()})} | {error, nil}. +parse_query(Query) -> + gleam_stdlib:parse_query(Query). + +-spec percent_encode(binary()) -> binary(). +percent_encode(Value) -> + gleam_stdlib:percent_encode(Value). + +-spec query_pair({binary(), binary()}) -> gleam@string_builder:string_builder(). +query_pair(Pair) -> + gleam@string_builder:from_strings( + [percent_encode(erlang:element(1, Pair)), + <<"="/utf8>>, + percent_encode(erlang:element(2, Pair))] + ). + +-spec query_to_string(list({binary(), binary()})) -> binary(). +query_to_string(Query) -> + _pipe = Query, + _pipe@1 = gleam@list:map(_pipe, fun query_pair/1), + _pipe@2 = gleam@list:intersperse( + _pipe@1, + gleam@string_builder:from_string(<<"&"/utf8>>) + ), + _pipe@3 = gleam@string_builder:concat(_pipe@2), + gleam@string_builder:to_string(_pipe@3). + +-spec percent_decode(binary()) -> {ok, binary()} | {error, nil}. +percent_decode(Value) -> + gleam_stdlib:percent_decode(Value). + +-spec do_remove_dot_segments(list(binary()), list(binary())) -> list(binary()). +do_remove_dot_segments(Input, Accumulator) -> + case Input of + [] -> + gleam@list:reverse(Accumulator); + + [Segment | Rest] -> + Accumulator@5 = case {Segment, Accumulator} of + {<<""/utf8>>, Accumulator@1} -> + Accumulator@1; + + {<<"."/utf8>>, Accumulator@2} -> + Accumulator@2; + + {<<".."/utf8>>, []} -> + []; + + {<<".."/utf8>>, [_ | Accumulator@3]} -> + Accumulator@3; + + {Segment@1, Accumulator@4} -> + [Segment@1 | Accumulator@4] + end, + do_remove_dot_segments(Rest, Accumulator@5) + end. + +-spec remove_dot_segments(list(binary())) -> list(binary()). +remove_dot_segments(Input) -> + do_remove_dot_segments(Input, []). + +-spec path_segments(binary()) -> list(binary()). +path_segments(Path) -> + remove_dot_segments(gleam@string:split(Path, <<"/"/utf8>>)). + +-spec to_string(uri()) -> binary(). +to_string(Uri) -> + Parts = case erlang:element(8, Uri) of + {some, Fragment} -> + [<<"#"/utf8>>, Fragment]; + + _ -> + [] + end, + Parts@1 = case erlang:element(7, Uri) of + {some, Query} -> + [<<"?"/utf8>>, Query | Parts]; + + _ -> + Parts + end, + Parts@2 = [erlang:element(6, Uri) | Parts@1], + Parts@3 = case {erlang:element(4, Uri), + gleam@string:starts_with(erlang:element(6, Uri), <<"/"/utf8>>)} of + {{some, Host}, false} when Host =/= <<""/utf8>> -> + [<<"/"/utf8>> | Parts@2]; + + {_, _} -> + Parts@2 + end, + Parts@4 = case {erlang:element(4, Uri), erlang:element(5, Uri)} of + {{some, _}, {some, Port}} -> + [<<":"/utf8>>, gleam@int:to_string(Port) | Parts@3]; + + {_, _} -> + Parts@3 + end, + Parts@5 = case {erlang:element(2, Uri), + erlang:element(3, Uri), + erlang:element(4, Uri)} of + {{some, S}, {some, U}, {some, H}} -> + [S, <<"://"/utf8>>, U, <<"@"/utf8>>, H | Parts@4]; + + {{some, S@1}, none, {some, H@1}} -> + [S@1, <<"://"/utf8>>, H@1 | Parts@4]; + + {{some, S@2}, {some, _}, none} -> + [S@2, <<":"/utf8>> | Parts@4]; + + {{some, S@2}, none, none} -> + [S@2, <<":"/utf8>> | Parts@4]; + + {none, none, {some, H@2}} -> + [<<"//"/utf8>>, H@2 | Parts@4]; + + {_, _, _} -> + Parts@4 + end, + gleam@string:concat(Parts@5). + +-spec origin(uri()) -> {ok, binary()} | {error, nil}. +origin(Uri) -> + {uri, Scheme, _, Host, Port, _, _, _} = Uri, + case Scheme of + {some, <<"https"/utf8>>} when Port =:= {some, 443} -> + Origin = {uri, Scheme, none, Host, none, <<""/utf8>>, none, none}, + {ok, to_string(Origin)}; + + {some, <<"http"/utf8>>} when Port =:= {some, 80} -> + Origin@1 = {uri, Scheme, none, Host, none, <<""/utf8>>, none, none}, + {ok, to_string(Origin@1)}; + + {some, S} when (S =:= <<"http"/utf8>>) orelse (S =:= <<"https"/utf8>>) -> + Origin@2 = {uri, Scheme, none, Host, Port, <<""/utf8>>, none, none}, + {ok, to_string(Origin@2)}; + + _ -> + {error, nil} + end. + +-spec drop_last(list(FDC)) -> list(FDC). +drop_last(Elements) -> + gleam@list:take(Elements, gleam@list:length(Elements) - 1). + +-spec join_segments(list(binary())) -> binary(). +join_segments(Segments) -> + gleam@string:join([<<""/utf8>> | Segments], <<"/"/utf8>>). + +-spec merge(uri(), uri()) -> {ok, uri()} | {error, nil}. +merge(Base, Relative) -> + case Base of + {uri, {some, _}, _, {some, _}, _, _, _, _} -> + case Relative of + {uri, _, _, {some, _}, _, _, _, _} -> + Path = begin + _pipe = gleam@string:split( + erlang:element(6, Relative), + <<"/"/utf8>> + ), + _pipe@1 = remove_dot_segments(_pipe), + join_segments(_pipe@1) + end, + Resolved = {uri, + gleam@option:'or'( + erlang:element(2, Relative), + erlang:element(2, Base) + ), + none, + erlang:element(4, Relative), + gleam@option:'or'( + erlang:element(5, Relative), + erlang:element(5, Base) + ), + Path, + erlang:element(7, Relative), + erlang:element(8, Relative)}, + {ok, Resolved}; + + _ -> + {New_path, New_query} = case erlang:element(6, Relative) of + <<""/utf8>> -> + {erlang:element(6, Base), + gleam@option:'or'( + erlang:element(7, Relative), + erlang:element(7, Base) + )}; + + _ -> + Path_segments = case gleam@string:starts_with( + erlang:element(6, Relative), + <<"/"/utf8>> + ) of + true -> + gleam@string:split( + erlang:element(6, Relative), + <<"/"/utf8>> + ); + + false -> + _pipe@2 = gleam@string:split( + erlang:element(6, Base), + <<"/"/utf8>> + ), + _pipe@3 = drop_last(_pipe@2), + gleam@list:append( + _pipe@3, + gleam@string:split( + erlang:element(6, Relative), + <<"/"/utf8>> + ) + ) + end, + Path@1 = begin + _pipe@4 = Path_segments, + _pipe@5 = remove_dot_segments(_pipe@4), + join_segments(_pipe@5) + end, + {Path@1, erlang:element(7, Relative)} + end, + Resolved@1 = {uri, + erlang:element(2, Base), + none, + erlang:element(4, Base), + erlang:element(5, Base), + New_path, + New_query, + erlang:element(8, Relative)}, + {ok, Resolved@1} + end; + + _ -> + {error, nil} + end. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.erl b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.erl new file mode 100644 index 0000000..c6ea125 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.erl @@ -0,0 +1,529 @@ +-module(gleam_stdlib). + +-export([ + map_get/2, iodata_append/2, identity/1, decode_int/1, decode_bool/1, + decode_float/1, decode_list/1, decode_option/2, decode_field/2, parse_int/1, + parse_float/1, less_than/2, string_pop_grapheme/1, string_starts_with/2, + wrap_list/1, string_ends_with/2, string_pad/4, decode_map/1, uri_parse/1, + bit_array_int_to_u32/1, bit_array_int_from_u32/1, decode_result/1, + bit_array_slice/3, decode_bit_array/1, compile_regex/2, regex_scan/2, + percent_encode/1, percent_decode/1, regex_check/2, regex_split/2, + base_decode64/1, parse_query/1, bit_array_concat/1, size_of_tuple/1, + decode_tuple/1, decode_tuple2/1, decode_tuple3/1, decode_tuple4/1, + decode_tuple5/1, decode_tuple6/1, tuple_get/2, classify_dynamic/1, print/1, + println/1, print_error/1, println_error/1, inspect/1, float_to_string/1, + int_from_base_string/2, utf_codepoint_list_to_string/1, contains_string/2, + crop_string/2, base16_decode/1 +]). + +%% Taken from OTP's uri_string module +-define(DEC2HEX(X), + if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0; + ((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10 + end). + +%% Taken from OTP's uri_string module +-define(HEX2DEC(X), + if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0; + ((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10; + ((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10 + end). + +-define(is_lowercase_char(X), (X > 96 andalso X < 123)). +-define(is_underscore_char(X), (X == 95)). +-define(is_digit_char(X), (X > 47 andalso X < 58)). + +uppercase(X) -> X - 32. + +map_get(Map, Key) -> + case maps:find(Key, Map) of + error -> {error, nil}; + OkFound -> OkFound + end. + +iodata_append(Iodata, String) -> [Iodata, String]. + +identity(X) -> X. + +decode_error_msg(Expected, Data) when is_binary(Expected) -> + decode_error(Expected, classify_dynamic(Data)). +decode_error(Expected, Got) when is_binary(Expected) andalso is_binary(Got) -> + {error, [{decode_error, Expected, Got, []}]}. + +classify_dynamic(nil) -> <<"Nil">>; +classify_dynamic(X) when is_atom(X) -> <<"Atom">>; +classify_dynamic(X) when is_binary(X) -> <<"String">>; +classify_dynamic(X) when is_bitstring(X) -> <<"BitArray">>; +classify_dynamic(X) when is_integer(X) -> <<"Int">>; +classify_dynamic(X) when is_float(X) -> <<"Float">>; +classify_dynamic(X) when is_list(X) -> <<"List">>; +classify_dynamic(X) when is_boolean(X) -> <<"Bool">>; +classify_dynamic(X) when is_map(X) -> <<"Map">>; +classify_dynamic(X) when is_tuple(X) -> + iolist_to_binary(["Tuple of ", integer_to_list(tuple_size(X)), " elements"]); +classify_dynamic(X) when + is_function(X, 0) orelse is_function(X, 1) orelse is_function(X, 2) orelse + is_function(X, 3) orelse is_function(X, 4) orelse is_function(X, 5) orelse + is_function(X, 6) orelse is_function(X, 7) orelse is_function(X, 8) orelse + is_function(X, 9) orelse is_function(X, 10) orelse is_function(X, 11) orelse + is_function(X, 12) -> <<"Function">>; +classify_dynamic(_) -> <<"Some other type">>. + +decode_map(Data) when is_map(Data) -> {ok, Data}; +decode_map(Data) -> decode_error_msg(<<"Map">>, Data). + +decode_bit_array(Data) when is_bitstring(Data) -> {ok, Data}; +decode_bit_array(Data) -> decode_error_msg(<<"BitArray">>, Data). + +decode_int(Data) when is_integer(Data) -> {ok, Data}; +decode_int(Data) -> decode_error_msg(<<"Int">>, Data). + +decode_float(Data) when is_float(Data) -> {ok, Data}; +decode_float(Data) -> decode_error_msg(<<"Float">>, Data). + +decode_bool(Data) when is_boolean(Data) -> {ok, Data}; +decode_bool(Data) -> decode_error_msg(<<"Bool">>, Data). + +decode_list(Data) when is_list(Data) -> {ok, Data}; +decode_list(Data) -> decode_error_msg(<<"List">>, Data). + +decode_field(Data, Key) when is_map(Data) -> + case Data of + #{Key := Value} -> {ok, {some, Value}}; + _ -> + {ok, none} + end; +decode_field(Data, _) -> + decode_error_msg(<<"Map">>, Data). + +size_of_tuple(Data) -> tuple_size(Data). + +tuple_get(_tup, Index) when Index < 0 -> {error, nil}; +tuple_get(Data, Index) when Index >= tuple_size(Data) -> {error, nil}; +tuple_get(Data, Index) -> {ok, element(Index + 1, Data)}. + +decode_tuple(Data) when is_tuple(Data) -> {ok, Data}; +decode_tuple(Data) -> decode_error_msg(<<"Tuple">>, Data). + +decode_tuple2({_,_} = A) -> {ok, A}; +decode_tuple2([A,B]) -> {ok, {A,B}}; +decode_tuple2(Data) -> decode_error_msg(<<"Tuple of 2 elements">>, Data). + +decode_tuple3({_,_,_} = A) -> {ok, A}; +decode_tuple3([A,B,C]) -> {ok, {A,B,C}}; +decode_tuple3(Data) -> decode_error_msg(<<"Tuple of 3 elements">>, Data). + +decode_tuple4({_,_,_,_} = A) -> {ok, A}; +decode_tuple4([A,B,C,D]) -> {ok, {A,B,C,D}}; +decode_tuple4(Data) -> decode_error_msg(<<"Tuple of 4 elements">>, Data). + +decode_tuple5({_,_,_,_,_} = A) -> {ok, A}; +decode_tuple5([A,B,C,D,E]) -> {ok, {A,B,C,D,E}}; +decode_tuple5(Data) -> decode_error_msg(<<"Tuple of 5 elements">>, Data). + +decode_tuple6({_,_,_,_,_,_} = A) -> {ok, A}; +decode_tuple6([A,B,C,D,E,F]) -> {ok, {A,B,C,D,E,F}}; +decode_tuple6(Data) -> decode_error_msg(<<"Tuple of 6 elements">>, Data). + +decode_option(Term, F) -> + Decode = fun(Inner) -> + case F(Inner) of + {ok, Decoded} -> {ok, {some, Decoded}}; + Error -> Error + end + end, + case Term of + undefined -> {ok, none}; + error -> {ok, none}; + null -> {ok, none}; + none -> {ok, none}; + nil -> {ok, none}; + {some, Inner} -> Decode(Inner); + _ -> Decode(Term) + end. + +decode_result(Term) -> + case Term of + {ok, Inner} -> {ok, {ok, Inner}}; + ok -> {ok, {ok, nil}}; + {error, Inner} -> {ok, {error, Inner}}; + error -> {ok, {error, nil}}; + _ -> decode_error_msg(<<"Result">>, Term) + end. + +int_from_base_string(String, Base) -> + case catch binary_to_integer(String, Base) of + Int when is_integer(Int) -> {ok, Int}; + _ -> {error, nil} + end. + +parse_int(String) -> + case catch binary_to_integer(String) of + Int when is_integer(Int) -> {ok, Int}; + _ -> {error, nil} + end. + +parse_float(String) -> + case catch binary_to_float(String) of + Float when is_float(Float) -> {ok, Float}; + _ -> {error, nil} + end. + +less_than(Lhs, Rhs) -> + Lhs < Rhs. + +string_starts_with(_, <<>>) -> true; +string_starts_with(String, Prefix) when byte_size(Prefix) > byte_size(String) -> false; +string_starts_with(String, Prefix) -> + PrefixSize = byte_size(Prefix), + Prefix == binary_part(String, 0, PrefixSize). + +string_ends_with(_, <<>>) -> true; +string_ends_with(String, Suffix) when byte_size(Suffix) > byte_size(String) -> false; +string_ends_with(String, Suffix) -> + SuffixSize = byte_size(Suffix), + Suffix == binary_part(String, byte_size(String) - SuffixSize, SuffixSize). + +string_pad(String, Length, Dir, PadString) -> + Chars = string:pad(String, Length, Dir, binary_to_list(PadString)), + case unicode:characters_to_binary(Chars) of + Bin when is_binary(Bin) -> Bin; + Error -> erlang:error({gleam_error, {string_invalid_utf8, Error}}) + end. + +string_pop_grapheme(String) -> + case string:next_grapheme(String) of + [ Next | Rest ] -> + {ok, {unicode:characters_to_binary([Next]), unicode:characters_to_binary(Rest)}}; + _ -> {error, nil} + end. + +bit_array_concat(BitArrays) -> + list_to_bitstring(BitArrays). + +bit_array_slice(Bin, Pos, Len) -> + try {ok, binary:part(Bin, Pos, Len)} + catch error:badarg -> {error, nil} + end. + +bit_array_int_to_u32(I) when 0 =< I, I < 4294967296 -> + {ok, <<I:32>>}; +bit_array_int_to_u32(_) -> + {error, nil}. + +bit_array_int_from_u32(<<I:32>>) -> + {ok, I}; +bit_array_int_from_u32(_) -> + {error, nil}. + +compile_regex(String, Options) -> + {options, Caseless, Multiline} = Options, + OptionsList = [ + unicode, + ucp, + Caseless andalso caseless, + Multiline andalso multiline + ], + FilteredOptions = [Option || Option <- OptionsList, Option /= false], + case re:compile(String, FilteredOptions) of + {ok, MP} -> {ok, MP}; + {error, {Str, Pos}} -> + {error, {compile_error, unicode:characters_to_binary(Str), Pos}} + end. + +regex_check(Regex, String) -> + re:run(String, Regex) /= nomatch. + +regex_split(Regex, String) -> + re:split(String, Regex). + +regex_submatches(_, {-1, 0}) -> none; +regex_submatches(String, {Start, Length}) -> + BinarySlice = binary:part(String, {Start, Length}), + case string:is_empty(binary_to_list(BinarySlice)) of + true -> none; + false -> {some, BinarySlice} + end. + +regex_matches(String, [{Start, Length} | Submatches]) -> + Submatches1 = lists:map(fun(X) -> regex_submatches(String, X) end, Submatches), + {match, binary:part(String, Start, Length), Submatches1}. + +regex_scan(Regex, String) -> + case re:run(String, Regex, [global]) of + {match, Captured} -> lists:map(fun(X) -> regex_matches(String, X) end, Captured); + nomatch -> [] + end. + +base_decode64(S) -> + try {ok, base64:decode(S)} + catch error:_ -> {error, nil} + end. + +wrap_list(X) when is_list(X) -> X; +wrap_list(X) -> [X]. + +parse_query(Query) -> + case uri_string:dissect_query(Query) of + {error, _, _} -> {error, nil}; + Pairs -> + Pairs1 = lists:map(fun + ({K, true}) -> {K, <<"">>}; + (Pair) -> Pair + end, Pairs), + {ok, Pairs1} + end. + +percent_encode(B) -> percent_encode(B, <<>>). +percent_encode(<<>>, Acc) -> + Acc; +percent_encode(<<H,T/binary>>, Acc) -> + case percent_ok(H) of + true -> + percent_encode(T, <<Acc/binary,H>>); + false -> + <<A:4,B:4>> = <<H>>, + percent_encode(T, <<Acc/binary,$%,(?DEC2HEX(A)),(?DEC2HEX(B))>>) + end. + +percent_decode(Cs) -> percent_decode(Cs, <<>>). +percent_decode(<<$%, C0, C1, Cs/binary>>, Acc) -> + case is_hex_digit(C0) andalso is_hex_digit(C1) of + true -> + B = ?HEX2DEC(C0)*16+?HEX2DEC(C1), + percent_decode(Cs, <<Acc/binary, B>>); + false -> + {error, nil} + end; +percent_decode(<<C,Cs/binary>>, Acc) -> + percent_decode(Cs, <<Acc/binary, C>>); +percent_decode(<<>>, Acc) -> + check_utf8(Acc). + +percent_ok($!) -> true; +percent_ok($$) -> true; +percent_ok($') -> true; +percent_ok($() -> true; +percent_ok($)) -> true; +percent_ok($*) -> true; +percent_ok($+) -> true; +percent_ok($-) -> true; +percent_ok($.) -> true; +percent_ok($_) -> true; +percent_ok($~) -> true; +percent_ok(C) when $0 =< C, C =< $9 -> true; +percent_ok(C) when $A =< C, C =< $Z -> true; +percent_ok(C) when $a =< C, C =< $z -> true; +percent_ok(_) -> false. + +is_hex_digit(C) -> + ($0 =< C andalso C =< $9) orelse ($a =< C andalso C =< $f) orelse ($A =< C andalso C =< $F). + +check_utf8(Cs) -> + case unicode:characters_to_list(Cs) of + {incomplete, _, _} -> {error, nil}; + {error, _, _} -> {error, nil}; + _ -> {ok, Cs} + end. + +uri_parse(String) -> + case uri_string:parse(String) of + {error, _, _} -> {error, nil}; + Uri -> + {ok, {uri, + maps_get_optional(Uri, scheme), + maps_get_optional(Uri, userinfo), + maps_get_optional(Uri, host), + maps_get_optional(Uri, port), + maps_get_or(Uri, path, <<>>), + maps_get_optional(Uri, query), + maps_get_optional(Uri, fragment) + }} + end. + +maps_get_optional(Map, Key) -> + try {some, maps:get(Key, Map)} + catch _:_ -> none + end. + +maps_get_or(Map, Key, Default) -> + try maps:get(Key, Map) + catch _:_ -> Default + end. + +print(String) -> + io:put_chars(String), + nil. + +println(String) -> + io:put_chars([String, $\n]), + nil. + +print_error(String) -> + io:put_chars(standard_error, String), + nil. + +println_error(String) -> + io:put_chars(standard_error, [String, $\n]), + nil. + +inspect(true) -> + "True"; +inspect(false) -> + "False"; +inspect(nil) -> + "Nil"; +inspect(Data) when is_map(Data) -> + Fields = [ + [<<"#(">>, inspect(Key), <<", ">>, inspect(Value), <<")">>] + || {Key, Value} <- maps:to_list(Data) + ], + ["dict.from_list([", lists:join(", ", Fields), "])"]; +inspect(Atom) when is_atom(Atom) -> + Binary = erlang:atom_to_binary(Atom), + case inspect_maybe_gleam_atom(Binary, none, <<>>) of + {ok, Inspected} -> Inspected; + {error, _} -> ["atom.create_from_string(\"", Binary, "\")"] + end; +inspect(Any) when is_integer(Any) -> + erlang:integer_to_list(Any); +inspect(Any) when is_float(Any) -> + io_lib_format:fwrite_g(Any); +inspect(Binary) when is_binary(Binary) -> + case inspect_maybe_utf8_string(Binary, <<>>) of + {ok, InspectedUtf8String} -> InspectedUtf8String; + {error, not_a_utf8_string} -> + Segments = [erlang:integer_to_list(X) || <<X>> <= Binary], + ["<<", lists:join(", ", Segments), ">>"] + end; +inspect(Bits) when is_bitstring(Bits) -> + inspect_bit_array(Bits); +inspect(List) when is_list(List) -> + case inspect_list(List) of + {proper, Elements} -> ["[", Elements, "]"]; + {improper, Elements} -> ["//erl([", Elements, "])"] + end; +inspect(Any) when is_tuple(Any) % Record constructors + andalso is_atom(element(1, Any)) + andalso element(1, Any) =/= false + andalso element(1, Any) =/= true + andalso element(1, Any) =/= nil +-> + [Atom | ArgsList] = erlang:tuple_to_list(Any), + Args = lists:join(<<", ">>, + lists:map(fun inspect/1, ArgsList) + ), + [inspect(Atom), "(", Args, ")"]; +inspect(Tuple) when is_tuple(Tuple) -> + Elements = lists:map(fun inspect/1, erlang:tuple_to_list(Tuple)), + ["#(", lists:join(", ", Elements), ")"]; +inspect(Any) when is_function(Any) -> + {arity, Arity} = erlang:fun_info(Any, arity), + ArgsAsciiCodes = lists:seq($a, $a + Arity - 1), + Args = lists:join(<<", ">>, + lists:map(fun(Arg) -> <<Arg>> end, ArgsAsciiCodes) + ), + ["//fn(", Args, ") { ... }"]; +inspect(Any) -> + ["//erl(", io_lib:format("~p", [Any]), ")"]. + + +inspect_maybe_gleam_atom(<<>>, none, _) -> + {error, nil}; +inspect_maybe_gleam_atom(<<First, _Rest/binary>>, none, _) when ?is_digit_char(First) -> + {error, nil}; +inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, none, _) -> + {error, nil}; +inspect_maybe_gleam_atom(<<"_">>, _PrevChar, _Acc) -> + {error, nil}; +inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, $_, _Acc) -> + {error, nil}; +inspect_maybe_gleam_atom(<<First, _Rest/binary>>, _PrevChar, _Acc) + when not (?is_lowercase_char(First) orelse ?is_underscore_char(First) orelse ?is_digit_char(First)) -> + {error, nil}; +inspect_maybe_gleam_atom(<<First, Rest/binary>>, none, Acc) -> + inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, (uppercase(First))>>); +inspect_maybe_gleam_atom(<<"_", Rest/binary>>, _PrevChar, Acc) -> + inspect_maybe_gleam_atom(Rest, $_, Acc); +inspect_maybe_gleam_atom(<<First, Rest/binary>>, $_, Acc) -> + inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, (uppercase(First))>>); +inspect_maybe_gleam_atom(<<First, Rest/binary>>, _PrevChar, Acc) -> + inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, First>>); +inspect_maybe_gleam_atom(<<>>, _PrevChar, Acc) -> + {ok, Acc}; +inspect_maybe_gleam_atom(A, B, C) -> + erlang:display({A, B, C}), + throw({gleam_error, A, B, C}). + +inspect_list([]) -> + {proper, []}; +inspect_list([First]) -> + {proper, [inspect(First)]}; +inspect_list([First | Rest]) when is_list(Rest) -> + {Kind, Inspected} = inspect_list(Rest), + {Kind, [inspect(First), <<", ">> | Inspected]}; +inspect_list([First | ImproperTail]) -> + {improper, [inspect(First), <<" | ">>, inspect(ImproperTail)]}. + +inspect_bit_array(Bits) -> + Text = inspect_bit_array(Bits, <<"<<">>), + <<Text/binary, ">>">>. + +inspect_bit_array(<<>>, Acc) -> + Acc; +inspect_bit_array(<<X, Rest/bitstring>>, Acc) -> + inspect_bit_array(Rest, append_segment(Acc, erlang:integer_to_binary(X))); +inspect_bit_array(Rest, Acc) -> + Size = bit_size(Rest), + <<X:Size>> = Rest, + X1 = erlang:integer_to_binary(X), + Size1 = erlang:integer_to_binary(Size), + Segment = <<X1/binary, ":size(", Size1/binary, ")">>, + inspect_bit_array(<<>>, append_segment(Acc, Segment)). + +append_segment(<<"<<">>, Segment) -> + <<"<<", Segment/binary>>; +append_segment(Acc, Segment) -> + <<Acc/binary, ", ", Segment/binary>>. + + +inspect_maybe_utf8_string(Binary, Acc) -> + case Binary of + <<>> -> {ok, <<$", Acc/binary, $">>}; + <<First/utf8, Rest/binary>> -> + Escaped = case First of + $" -> <<$\\, $">>; + $\\ -> <<$\\, $\\>>; + $\r -> <<$\\, $r>>; + $\n -> <<$\\, $n>>; + $\t -> <<$\\, $t>>; + Other -> <<Other/utf8>> + end, + inspect_maybe_utf8_string(Rest, <<Acc/binary, Escaped/binary>>); + _ -> {error, not_a_utf8_string} + end. + +float_to_string(Float) when is_float(Float) -> + erlang:iolist_to_binary(io_lib_format:fwrite_g(Float)). + +utf_codepoint_list_to_string(List) -> + case unicode:characters_to_binary(List) of + {error, _} -> erlang:error({gleam_error, {string_invalid_utf8, List}}); + Binary -> Binary + end. + +crop_string(String, Prefix) -> + case string:find(String, Prefix) of + nomatch -> String; + New -> New + end. + +contains_string(String, Substring) -> + is_bitstring(string:find(String, Substring)). + +base16_decode(String) -> + try + {ok, binary:decode_hex(String)} + catch + _:_ -> {error, nil} + end. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.mjs b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.mjs new file mode 100644 index 0000000..a908b23 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.mjs @@ -0,0 +1,875 @@ +import { + BitArray, + Error, + List, + Ok, + Result, + UtfCodepoint, + stringBits, + toBitArray, + NonEmpty, + CustomType, +} from "./gleam.mjs"; +import { + CompileError as RegexCompileError, + Match as RegexMatch, +} from "./gleam/regex.mjs"; +import { DecodeError } from "./gleam/dynamic.mjs"; +import { Some, None } from "./gleam/option.mjs"; +import Dict from "./dict.mjs"; + +const Nil = undefined; +const NOT_FOUND = {}; + +export function identity(x) { + return x; +} + +export function parse_int(value) { + if (/^[-+]?(\d+)$/.test(value)) { + return new Ok(parseInt(value)); + } else { + return new Error(Nil); + } +} + +export function parse_float(value) { + if (/^[-+]?(\d+)\.(\d+)$/.test(value)) { + return new Ok(parseFloat(value)); + } else { + return new Error(Nil); + } +} + +export function to_string(term) { + return term.toString(); +} + +export function float_to_string(float) { + const string = float.toString(); + if (string.indexOf(".") >= 0) { + return string; + } else { + return string + ".0"; + } +} + +export function int_to_base_string(int, base) { + return int.toString(base).toUpperCase(); +} + +const int_base_patterns = { + 2: /[^0-1]/, + 3: /[^0-2]/, + 4: /[^0-3]/, + 5: /[^0-4]/, + 6: /[^0-5]/, + 7: /[^0-6]/, + 8: /[^0-7]/, + 9: /[^0-8]/, + 10: /[^0-9]/, + 11: /[^0-9a]/, + 12: /[^0-9a-b]/, + 13: /[^0-9a-c]/, + 14: /[^0-9a-d]/, + 15: /[^0-9a-e]/, + 16: /[^0-9a-f]/, + 17: /[^0-9a-g]/, + 18: /[^0-9a-h]/, + 19: /[^0-9a-i]/, + 20: /[^0-9a-j]/, + 21: /[^0-9a-k]/, + 22: /[^0-9a-l]/, + 23: /[^0-9a-m]/, + 24: /[^0-9a-n]/, + 25: /[^0-9a-o]/, + 26: /[^0-9a-p]/, + 27: /[^0-9a-q]/, + 28: /[^0-9a-r]/, + 29: /[^0-9a-s]/, + 30: /[^0-9a-t]/, + 31: /[^0-9a-u]/, + 32: /[^0-9a-v]/, + 33: /[^0-9a-w]/, + 34: /[^0-9a-x]/, + 35: /[^0-9a-y]/, + 36: /[^0-9a-z]/, +}; + +export function int_from_base_string(string, base) { + if (int_base_patterns[base].test(string.replace(/^-/, "").toLowerCase())) { + return new Error(Nil); + } + + const result = parseInt(string, base); + + if (isNaN(result)) { + return new Error(Nil); + } + + return new Ok(result); +} + +export function string_replace(string, target, substitute) { + if (typeof string.replaceAll !== "undefined") { + return string.replaceAll(target, substitute); + } + // Fallback for older Node.js versions: + // 1. <https://stackoverflow.com/a/1144788> + // 2. <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping> + // TODO: This fallback could be remove once Node.js 14 is EOL + // aka <https://nodejs.org/en/about/releases/> on or after 2024-04-30 + return string.replace( + // $& means the whole matched string + new RegExp(target.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), + substitute + ); +} + +export function string_reverse(string) { + return [...string].reverse().join(""); +} + +export function string_length(string) { + if (string === "") { + return 0; + } + const iterator = graphemes_iterator(string); + if (iterator) { + let i = 0; + for (const _ of iterator) { + i++; + } + return i; + } else { + return string.match(/./gsu).length; + } +} + +export function graphemes(string) { + return List.fromArray( + Array.from(graphemes_iterator(string)).map((item) => item.segment) + ); +} + +function graphemes_iterator(string) { + if (Intl && Intl.Segmenter) { + return new Intl.Segmenter().segment(string)[Symbol.iterator](); + } +} + +export function pop_grapheme(string) { + let first; + const iterator = graphemes_iterator(string); + if (iterator) { + first = iterator.next().value?.segment; + } else { + first = string.match(/./su)?.[0]; + } + if (first) { + return new Ok([first, string.slice(first.length)]); + } else { + return new Error(Nil); + } +} + +export function lowercase(string) { + return string.toLowerCase(); +} + +export function uppercase(string) { + return string.toUpperCase(); +} + +export function less_than(a, b) { + return a < b; +} + +export function add(a, b) { + return a + b; +} + +export function equal(a, b) { + return a === b; +} + +export function split(xs, pattern) { + return List.fromArray(xs.split(pattern)); +} + +export function join(xs, separator) { + const iterator = xs[Symbol.iterator](); + let result = iterator.next().value || ""; + let current = iterator.next(); + while (!current.done) { + result = result + separator + current.value; + current = iterator.next(); + } + return result; +} + +export function concat(xs) { + let result = ""; + for (const x of xs) { + result = result + x; + } + return result; +} + +export function length(data) { + return data.length; +} + +export function crop_string(string, substring) { + return string.substring(string.indexOf(substring)); +} + +export function contains_string(haystack, needle) { + return haystack.indexOf(needle) >= 0; +} + +export function starts_with(haystack, needle) { + return haystack.startsWith(needle); +} + +export function ends_with(haystack, needle) { + return haystack.endsWith(needle); +} + +export function split_once(haystack, needle) { + const index = haystack.indexOf(needle); + if (index >= 0) { + const before = haystack.slice(0, index); + const after = haystack.slice(index + needle.length); + return new Ok([before, after]); + } else { + return new Error(Nil); + } +} + +export function trim(string) { + return string.trim(); +} + +export function trim_left(string) { + return string.trimLeft(); +} + +export function trim_right(string) { + return string.trimRight(); +} + +export function bit_array_from_string(string) { + return toBitArray([stringBits(string)]); +} + +export function bit_array_concat(bit_arrays) { + return toBitArray(bit_arrays.toArray().map((b) => b.buffer)); +} + +export function console_log(term) { + console.log(term); +} + +export function console_error(term) { + console.error(term); +} + +export function crash(message) { + throw new globalThis.Error(message); +} + +export function bit_array_to_string(bit_array) { + try { + const decoder = new TextDecoder("utf-8", { fatal: true }); + return new Ok(decoder.decode(bit_array.buffer)); + } catch (_error) { + return new Error(Nil); + } +} + +export function print(string) { + if (typeof process === "object") { + process.stdout.write(string); // We can write without a trailing newline + } else if (typeof Deno === "object") { + Deno.stdout.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline + } else { + console.log(string); // We're in a browser. Newlines are mandated + } +} + +export function print_error(string) { + if (typeof process === "object" && process.stderr?.write) { + process.stderr.write(string); // We can write without a trailing newline + } else if (typeof Deno === "object") { + Deno.stderr.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline + } else { + console.error(string); // We're in a browser. Newlines are mandated + } +} + +export function print_debug(string) { + if (typeof process === "object" && process.stderr?.write) { + process.stderr.write(string + "\n"); // If we're in Node.js, use `stderr` + } else if (typeof Deno === "object") { + Deno.stderr.writeSync(new TextEncoder().encode(string + "\n")); // If we're in Deno, use `stderr` + } else { + console.log(string); // Otherwise, use `console.log` (so that it doesn't look like an error) + } +} + +export function ceiling(float) { + return Math.ceil(float); +} + +export function floor(float) { + return Math.floor(float); +} + +export function round(float) { + return Math.round(float); +} + +export function truncate(float) { + return Math.trunc(float); +} + +export function power(base, exponent) { + // It is checked in Gleam that: + // - The base is non-negative and that the exponent is not fractional. + // - The base is non-zero and the exponent is non-negative (otherwise + // the result will essentially be division by zero). + // It can thus be assumed that valid input is passed to the Math.pow + // function and a NaN or Infinity value will not be produced. + return Math.pow(base, exponent); +} + +export function random_uniform() { + const random_uniform_result = Math.random(); + // With round-to-nearest-even behavior, the ranges claimed for the functions below + // (excluding the one for Math.random() itself) aren't exact. + // If extremely large bounds are chosen (2^53 or higher), + // it's possible in extremely rare cases to calculate the usually-excluded upper bound. + // Note that as numbers in JavaScript are IEEE 754 floating point numbers + // See: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random> + // Because of this, we just loop 'until' we get a valid result where 0.0 <= x < 1.0: + if (random_uniform_result === 1.0) { + return random_uniform(); + } + return random_uniform_result; +} + +export function bit_array_slice(bits, position, length) { + const start = Math.min(position, position + length); + const end = Math.max(position, position + length); + if (start < 0 || end > bits.length) return new Error(Nil); + const buffer = new Uint8Array(bits.buffer.buffer, start, Math.abs(length)); + return new Ok(new BitArray(buffer)); +} + +export function codepoint(int) { + return new UtfCodepoint(int); +} + +export function string_to_codepoint_integer_list(string) { + return List.fromArray(Array.from(string).map((item) => item.codePointAt(0))); +} + +export function utf_codepoint_list_to_string(utf_codepoint_integer_list) { + return utf_codepoint_integer_list + .toArray() + .map((x) => String.fromCodePoint(x.value)) + .join(""); +} + +export function utf_codepoint_to_int(utf_codepoint) { + return utf_codepoint.value; +} + +export function regex_check(regex, string) { + regex.lastIndex = 0; + return regex.test(string); +} + +export function compile_regex(pattern, options) { + try { + let flags = "gu"; + if (options.case_insensitive) flags += "i"; + if (options.multi_line) flags += "m"; + return new Ok(new RegExp(pattern, flags)); + } catch (error) { + const number = (error.columnNumber || 0) | 0; + return new Error(new RegexCompileError(error.message, number)); + } +} + +export function regex_scan(regex, string) { + const matches = Array.from(string.matchAll(regex)).map((match) => { + const content = match[0]; + const submatches = []; + for (let n = match.length - 1; n > 0; n--) { + if (match[n]) { + submatches[n - 1] = new Some(match[n]); + continue; + } + if (submatches.length > 0) { + submatches[n - 1] = new None(); + } + } + return new RegexMatch(content, List.fromArray(submatches)); + }); + return List.fromArray(matches); +} + +export function new_map() { + return Dict.new(); +} + +export function map_size(map) { + return map.size; +} + +export function map_to_list(map) { + return List.fromArray(map.entries()); +} + +export function map_remove(key, map) { + return map.delete(key); +} + +export function map_get(map, key) { + const value = map.get(key, NOT_FOUND); + if (value === NOT_FOUND) { + return new Error(Nil); + } + return new Ok(value); +} + +export function map_insert(key, value, map) { + return map.set(key, value); +} + +function unsafe_percent_decode(string) { + return decodeURIComponent((string || "").replace("+", " ")); +} + +export function percent_decode(string) { + try { + return new Ok(unsafe_percent_decode(string)); + } catch (_error) { + return new Error(Nil); + } +} + +export function percent_encode(string) { + return encodeURIComponent(string); +} + +export function parse_query(query) { + try { + const pairs = []; + for (const section of query.split("&")) { + const [key, value] = section.split("="); + if (!key) continue; + pairs.push([unsafe_percent_decode(key), unsafe_percent_decode(value)]); + } + return new Ok(List.fromArray(pairs)); + } catch (_error) { + return new Error(Nil); + } +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +export function encode64(bit_array) { + const aBytes = bit_array.buffer; + let nMod3 = 2; + let sB64Enc = ""; + + for (let nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) { + nMod3 = nIdx % 3; + if (nIdx > 0 && ((nIdx * 4) / 3) % 76 === 0) { + sB64Enc += "\r\n"; + } + nUint24 |= aBytes[nIdx] << ((16 >>> nMod3) & 24); + if (nMod3 === 2 || aBytes.length - nIdx === 1) { + sB64Enc += String.fromCharCode( + uint6ToB64((nUint24 >>> 18) & 63), + uint6ToB64((nUint24 >>> 12) & 63), + uint6ToB64((nUint24 >>> 6) & 63), + uint6ToB64(nUint24 & 63) + ); + nUint24 = 0; + } + } + + return ( + sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + + (nMod3 === 2 ? "" : nMod3 === 1 ? "=" : "==") + ); +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function uint6ToB64(nUint6) { + return nUint6 < 26 + ? nUint6 + 65 + : nUint6 < 52 + ? nUint6 + 71 + : nUint6 < 62 + ? nUint6 - 4 + : nUint6 === 62 + ? 43 + : nUint6 === 63 + ? 47 + : 65; +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function b64ToUint6(nChr) { + return nChr > 64 && nChr < 91 + ? nChr - 65 + : nChr > 96 && nChr < 123 + ? nChr - 71 + : nChr > 47 && nChr < 58 + ? nChr + 4 + : nChr === 43 + ? 62 + : nChr === 47 + ? 63 + : 0; +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +export function decode64(sBase64) { + if (sBase64.match(/[^A-Za-z0-9\+\/=]/g)) return new Error(Nil); + const sB64Enc = sBase64.replace(/=/g, ""); + const nInLen = sB64Enc.length; + const nOutLen = (nInLen * 3 + 1) >> 2; + const taBytes = new Uint8Array(nOutLen); + + for ( + let nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; + nInIdx < nInLen; + nInIdx++ + ) { + nMod4 = nInIdx & 3; + nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << (6 * (3 - nMod4)); + if (nMod4 === 3 || nInLen - nInIdx === 1) { + for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) { + taBytes[nOutIdx] = (nUint24 >>> ((16 >>> nMod3) & 24)) & 255; + } + nUint24 = 0; + } + } + + return new Ok(new BitArray(taBytes)); +} + +export function classify_dynamic(data) { + if (typeof data === "string") { + return "String"; + } else if (data instanceof Result) { + return "Result"; + } else if (data instanceof List) { + return "List"; + } else if (data instanceof BitArray) { + return "BitArray"; + } else if (data instanceof Dict) { + return "Map"; + } else if (Number.isInteger(data)) { + return "Int"; + } else if (Array.isArray(data)) { + return `Tuple of ${data.length} elements`; + } else if (typeof data === "number") { + return "Float"; + } else if (data === null) { + return "Null"; + } else if (data === undefined) { + return "Nil"; + } else { + const type = typeof data; + return type.charAt(0).toUpperCase() + type.slice(1); + } +} + +function decoder_error(expected, got) { + return decoder_error_no_classify(expected, classify_dynamic(got)); +} + +function decoder_error_no_classify(expected, got) { + return new Error( + List.fromArray([new DecodeError(expected, got, List.fromArray([]))]) + ); +} + +export function decode_string(data) { + return typeof data === "string" + ? new Ok(data) + : decoder_error("String", data); +} + +export function decode_int(data) { + return Number.isInteger(data) ? new Ok(data) : decoder_error("Int", data); +} + +export function decode_float(data) { + return typeof data === "number" ? new Ok(data) : decoder_error("Float", data); +} + +export function decode_bool(data) { + return typeof data === "boolean" ? new Ok(data) : decoder_error("Bool", data); +} + +export function decode_bit_array(data) { + if (data instanceof BitArray) { + return new Ok(data); + } + if (data instanceof Uint8Array) { + return new Ok(new BitArray(data)); + } + return decoder_error("BitArray", data); +} + +export function decode_tuple(data) { + return Array.isArray(data) ? new Ok(data) : decoder_error("Tuple", data); +} + +export function decode_tuple2(data) { + return decode_tupleN(data, 2); +} + +export function decode_tuple3(data) { + return decode_tupleN(data, 3); +} + +export function decode_tuple4(data) { + return decode_tupleN(data, 4); +} + +export function decode_tuple5(data) { + return decode_tupleN(data, 5); +} + +export function decode_tuple6(data) { + return decode_tupleN(data, 6); +} + +function decode_tupleN(data, n) { + if (Array.isArray(data) && data.length == n) { + return new Ok(data); + } + + const list = decode_exact_length_list(data, n); + if (list) return new Ok(list); + + return decoder_error(`Tuple of ${n} elements`, data); +} + +function decode_exact_length_list(data, n) { + if (!(data instanceof List)) return; + + const elements = []; + let current = data; + + for (let i = 0; i < n; i++) { + if (!(current instanceof NonEmpty)) break; + elements.push(current.head); + current = current.tail; + } + + if (elements.length === n && !(current instanceof NonEmpty)) return elements; +} + +export function tuple_get(data, index) { + return index >= 0 && data.length > index + ? new Ok(data[index]) + : new Error(Nil); +} + +export function decode_list(data) { + if (Array.isArray(data)) { + return new Ok(List.fromArray(data)); + } + return data instanceof List ? new Ok(data) : decoder_error("List", data); +} + +export function decode_result(data) { + return data instanceof Result ? new Ok(data) : decoder_error("Result", data); +} + +export function decode_map(data) { + if (data instanceof Dict) { + return new Ok(Dict.fromMap(data)); + } + if (data == null) { + return decoder_error("Map", data); + } + if (typeof data !== "object") { + return decoder_error("Map", data); + } + const proto = Object.getPrototypeOf(data); + if (proto === Object.prototype || proto === null) { + return new Ok(Dict.fromObject(data)); + } + return decoder_error("Map", data); +} + +export function decode_option(data, decoder) { + if (data === null || data === undefined || data instanceof None) + return new Ok(new None()); + if (data instanceof Some) data = data[0]; + const result = decoder(data); + if (result.isOk()) { + return new Ok(new Some(result[0])); + } else { + return result; + } +} + +export function decode_field(value, name) { + const not_a_map_error = () => decoder_error("Map", value); + + if ( + value instanceof Dict || + value instanceof WeakMap || + value instanceof Map + ) { + const entry = map_get(value, name); + return new Ok(entry.isOk() ? new Some(entry[0]) : new None()); + } else if (Object.getPrototypeOf(value) == Object.prototype) { + return try_get_field(value, name, () => new Ok(new None())); + } else { + return try_get_field(value, name, not_a_map_error); + } +} + +function try_get_field(value, field, or_else) { + try { + return field in value ? new Ok(new Some(value[field])) : or_else(); + } catch { + return or_else(); + } +} + +export function byte_size(string) { + return new TextEncoder().encode(string).length; +} + +// In Javascript bitwise operations convert numbers to a sequence of 32 bits +// while Erlang uses arbitrary precision. +// To get around this problem and get consistent results use BigInt and then +// downcast the value back to a Number value. + +export function bitwise_and(x, y) { + return Number(BigInt(x) & BigInt(y)); +} + +export function bitwise_not(x) { + return Number(~BigInt(x)); +} + +export function bitwise_or(x, y) { + return Number(BigInt(x) | BigInt(y)); +} + +export function bitwise_exclusive_or(x, y) { + return Number(BigInt(x) ^ BigInt(y)); +} + +export function bitwise_shift_left(x, y) { + return Number(BigInt(x) << BigInt(y)); +} + +export function bitwise_shift_right(x, y) { + return Number(BigInt(x) >> BigInt(y)); +} + +export function inspect(v) { + const t = typeof v; + if (v === true) return "True"; + if (v === false) return "False"; + if (v === null) return "//js(null)"; + if (v === undefined) return "Nil"; + if (t === "string") return JSON.stringify(v); + if (t === "bigint" || t === "number") return v.toString(); + if (Array.isArray(v)) return `#(${v.map(inspect).join(", ")})`; + if (v instanceof List) return inspectList(v); + if (v instanceof UtfCodepoint) return inspectUtfCodepoint(v); + if (v instanceof BitArray) return inspectBitArray(v); + if (v instanceof CustomType) return inspectCustomType(v); + if (v instanceof Dict) return inspectDict(v); + if (v instanceof Set) return `//js(Set(${[...v].map(inspect).join(", ")}))`; + if (v instanceof RegExp) return `//js(${v})`; + if (v instanceof Date) return `//js(Date("${v.toISOString()}"))`; + if (v instanceof Function) { + const args = []; + for (const i of Array(v.length).keys()) + args.push(String.fromCharCode(i + 97)); + return `//fn(${args.join(", ")}) { ... }`; + } + return inspectObject(v); +} + +function inspectDict(map) { + let body = "dict.from_list(["; + let first = true; + map.forEach((value, key) => { + if (!first) body = body + ", "; + body = body + "#(" + inspect(key) + ", " + inspect(value) + ")"; + first = false; + }); + return body + "])"; +} + +function inspectObject(v) { + const name = Object.getPrototypeOf(v)?.constructor?.name || "Object"; + const props = []; + for (const k of Object.keys(v)) { + props.push(`${inspect(k)}: ${inspect(v[k])}`); + } + const body = props.length ? " " + props.join(", ") + " " : ""; + const head = name === "Object" ? "" : name + " "; + return `//js(${head}{${body}})`; +} + +function inspectCustomType(record) { + const props = Object.keys(record) + .map((label) => { + const value = inspect(record[label]); + return isNaN(parseInt(label)) ? `${label}: ${value}` : value; + }) + .join(", "); + return props + ? `${record.constructor.name}(${props})` + : record.constructor.name; +} + +export function inspectList(list) { + return `[${list.toArray().map(inspect).join(", ")}]`; +} + +export function inspectBitArray(bits) { + return `<<${Array.from(bits.buffer).join(", ")}>>`; +} + +export function inspectUtfCodepoint(codepoint) { + return `//utfcodepoint(${String.fromCodePoint(codepoint.value)})`; +} + +export function base16_encode(bit_array) { + let result = ""; + for (const byte of bit_array.buffer) { + result += byte.toString(16).padStart(2, "0").toUpperCase(); + } + return result; +} + +export function base16_decode(string) { + const bytes = new Uint8Array(string.length / 2); + for (let i = 0; i < string.length; i += 2) { + const a = parseInt(string[i], 16); + const b = parseInt(string[i + 1], 16); + if (isNaN(a) || isNaN(b)) return new Error(Nil); + bytes[i / 2] = a * 16 + b; + } + return new Ok(new BitArray(bytes)); +} diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@base.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@base.beam Binary files differnew file mode 100644 index 0000000..1dc5df2 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@base.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_array.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_array.beam Binary files differnew file mode 100644 index 0000000..53dc014 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_array.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_builder.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_builder.beam Binary files differnew file mode 100644 index 0000000..bb8b7ad --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_builder.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_string.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_string.beam Binary files differnew file mode 100644 index 0000000..529dcbf --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_string.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bool.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bool.beam Binary files differnew file mode 100644 index 0000000..1c09889 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bool.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bytes_builder.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bytes_builder.beam Binary files differnew file mode 100644 index 0000000..5909435 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bytes_builder.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dict.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dict.beam Binary files differnew file mode 100644 index 0000000..4e29e67 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dict.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic.beam Binary files differnew file mode 100644 index 0000000..04a6ff4 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@float.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@float.beam Binary files differnew file mode 100644 index 0000000..4e514dd --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@float.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@function.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@function.beam Binary files differnew file mode 100644 index 0000000..26efa09 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@function.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@int.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@int.beam Binary files differnew file mode 100644 index 0000000..fdbc861 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@int.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@io.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@io.beam Binary files differnew file mode 100644 index 0000000..e26d173 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@io.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@iterator.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@iterator.beam Binary files differnew file mode 100644 index 0000000..27305e5 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@iterator.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@list.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@list.beam Binary files differnew file mode 100644 index 0000000..3bc877f --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@list.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@map.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@map.beam Binary files differnew file mode 100644 index 0000000..da9fae6 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@map.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@option.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@option.beam Binary files differnew file mode 100644 index 0000000..fc1c866 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@option.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@order.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@order.beam Binary files differnew file mode 100644 index 0000000..d2211bd --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@order.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@pair.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@pair.beam Binary files differnew file mode 100644 index 0000000..c54cf50 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@pair.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@queue.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@queue.beam Binary files differnew file mode 100644 index 0000000..f9bb77e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@queue.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@regex.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@regex.beam Binary files differnew file mode 100644 index 0000000..9f9f430 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@regex.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@result.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@result.beam Binary files differnew file mode 100644 index 0000000..fffb063 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@result.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@set.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@set.beam Binary files differnew file mode 100644 index 0000000..3f4118e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@set.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string.beam Binary files differnew file mode 100644 index 0000000..9febebb --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string_builder.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string_builder.beam Binary files differnew file mode 100644 index 0000000..4dee8d6 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string_builder.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@uri.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@uri.beam Binary files differnew file mode 100644 index 0000000..91e2a9c --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@uri.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.app b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.app new file mode 100644 index 0000000..8231979 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.app @@ -0,0 +1,7 @@ +{application, gleam_stdlib, [ + {vsn, "0.33.0"}, + {applications, []}, + {description, "A standard library for the Gleam programming language"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.beam Binary files differnew file mode 100644 index 0000000..7022f4d --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.beam diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl new file mode 100644 index 0000000..b1135f2 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl @@ -0,0 +1,5 @@ +-record(decode_error, { + expected :: binary(), + found :: binary(), + path :: list(binary()) +}). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@iterator_Iterator.hrl b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@iterator_Iterator.hrl new file mode 100644 index 0000000..b0d08dc --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@iterator_Iterator.hrl @@ -0,0 +1 @@ +-record(iterator, {continuation :: fun(() -> gleam@iterator:action(any()))}). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@iterator_Next.hrl b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@iterator_Next.hrl new file mode 100644 index 0000000..1f61922 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@iterator_Next.hrl @@ -0,0 +1 @@ +-record(next, {element :: any(), accumulator :: any()}). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@queue_Queue.hrl b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@queue_Queue.hrl new file mode 100644 index 0000000..88ac25e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@queue_Queue.hrl @@ -0,0 +1 @@ +-record(queue, {in :: list(any()), out :: list(any())}). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_CompileError.hrl b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_CompileError.hrl new file mode 100644 index 0000000..ad5511e --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_CompileError.hrl @@ -0,0 +1 @@ +-record(compile_error, {error :: binary(), byte_index :: integer()}). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_Match.hrl b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_Match.hrl new file mode 100644 index 0000000..4216619 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_Match.hrl @@ -0,0 +1,4 @@ +-record(match, { + content :: binary(), + submatches :: list(gleam@option:option(binary())) +}). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_Options.hrl b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_Options.hrl new file mode 100644 index 0000000..0074603 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_Options.hrl @@ -0,0 +1 @@ +-record(options, {case_insensitive :: boolean(), multi_line :: boolean()}). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@set_Set.hrl b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@set_Set.hrl new file mode 100644 index 0000000..6e1e226 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@set_Set.hrl @@ -0,0 +1 @@ +-record(set, {map :: gleam@dict:dict(any(), list(nil))}). diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@uri_Uri.hrl b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@uri_Uri.hrl new file mode 100644 index 0000000..50150f4 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@uri_Uri.hrl @@ -0,0 +1,9 @@ +-record(uri, { + scheme :: gleam@option:option(binary()), + userinfo :: gleam@option:option(binary()), + host :: gleam@option:option(binary()), + port :: gleam@option:option(integer()), + path :: binary(), + 'query' :: gleam@option:option(binary()), + fragment :: gleam@option:option(binary()) +}). diff --git a/aoc2023/build/dev/erlang/gleam_version b/aoc2023/build/dev/erlang/gleam_version new file mode 100644 index 0000000..e13b3d9 --- /dev/null +++ b/aoc2023/build/dev/erlang/gleam_version @@ -0,0 +1 @@ +0.34.0-rc1
\ No newline at end of file diff --git a/aoc2023/build/dev/erlang/glint/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cache b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cache Binary files differnew file mode 100644 index 0000000..2174df9 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cache diff --git a/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cache_meta b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cache_meta Binary files differnew file mode 100644 index 0000000..23d66d7 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cache_meta diff --git a/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.erl b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.erl new file mode 100644 index 0000000..76f7f3b --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.erl @@ -0,0 +1,513 @@ +-module(glint). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([with_config/2, with_pretty_help/2, without_pretty_help/1, with_name/2, command/1, description/2, flag/3, flag_tuple/2, flags/2, global_flag/3, global_flag_tuple/2, global_flags/2, default_pretty_help/0, add/3, add_command_from_stub/2, new/0, help_flag/0, execute/2, run_and_handle/3, run/2]). +-export_type([config/0, pretty_help/0, glint/1, command/1, command_input/0, command_node/1, out/1, stub/1]). + +-type config() :: {config, + gleam@option:option(pretty_help()), + gleam@option:option(binary())}. + +-type pretty_help() :: {pretty_help, + gleam_community@colour:colour(), + gleam_community@colour:colour(), + gleam_community@colour:colour()}. + +-opaque glint(KWB) :: {glint, + config(), + command_node(KWB), + gleam@dict:dict(binary(), glint@flag:flag())}. + +-opaque command(KWC) :: {command, + fun((command_input()) -> KWC), + gleam@dict:dict(binary(), glint@flag:flag()), + binary()}. + +-type command_input() :: {command_input, + list(binary()), + gleam@dict:dict(binary(), glint@flag:flag())}. + +-type command_node(KWD) :: {command_node, + gleam@option:option(command(KWD)), + gleam@dict:dict(binary(), command_node(KWD))}. + +-type out(KWE) :: {out, KWE} | {help, binary()}. + +-type stub(KWF) :: {stub, + list(binary()), + fun((command_input()) -> KWF), + list({binary(), glint@flag:flag()}), + binary()}. + +-spec with_config(glint(KWK), config()) -> glint(KWK). +with_config(Glint, Config) -> + erlang:setelement(2, Glint, Config). + +-spec with_pretty_help(glint(KWN), pretty_help()) -> glint(KWN). +with_pretty_help(Glint, Pretty) -> + _pipe = erlang:setelement(2, erlang:element(2, Glint), {some, Pretty}), + with_config(Glint, _pipe). + +-spec without_pretty_help(glint(KWQ)) -> glint(KWQ). +without_pretty_help(Glint) -> + _pipe = erlang:setelement(2, erlang:element(2, Glint), none), + with_config(Glint, _pipe). + +-spec with_name(glint(KWT), binary()) -> glint(KWT). +with_name(Glint, Name) -> + _pipe = erlang:setelement(3, erlang:element(2, Glint), {some, Name}), + with_config(Glint, _pipe). + +-spec empty_command() -> command_node(any()). +empty_command() -> + {command_node, none, gleam@map:new()}. + +-spec do_add(command_node(KXD), list(binary()), command(KXD)) -> command_node(KXD). +do_add(Root, Path, Contents) -> + case Path of + [] -> + erlang:setelement(2, Root, {some, Contents}); + + [X | Xs] -> + erlang:setelement( + 3, + Root, + (gleam@map:update( + erlang:element(3, Root), + X, + fun(Node) -> _pipe = Node, + _pipe@1 = gleam@option:lazy_unwrap( + _pipe, + fun empty_command/0 + ), + do_add(_pipe@1, Xs, Contents) end + )) + ) + end. + +-spec command(fun((command_input()) -> KXM)) -> command(KXM). +command(Runner) -> + {command, Runner, gleam@map:new(), <<""/utf8>>}. + +-spec description(command(KXP), binary()) -> command(KXP). +description(Cmd, Description) -> + erlang:setelement(4, Cmd, Description). + +-spec flag(command(KXS), binary(), glint@flag:flag_builder(any())) -> command(KXS). +flag(Cmd, Key, Flag) -> + erlang:setelement( + 3, + Cmd, + gleam@map:insert(erlang:element(3, Cmd), Key, glint@flag:build(Flag)) + ). + +-spec flag_tuple(command(KXX), {binary(), glint@flag:flag_builder(any())}) -> command(KXX). +flag_tuple(Cmd, Tup) -> + flag(Cmd, erlang:element(1, Tup), erlang:element(2, Tup)). + +-spec flags(command(KYC), list({binary(), glint@flag:flag()})) -> command(KYC). +flags(Cmd, Flags) -> + gleam@list:fold( + Flags, + Cmd, + fun(Cmd@1, _use1) -> + {Key, Flag} = _use1, + erlang:setelement( + 3, + Cmd@1, + gleam@map:insert(erlang:element(3, Cmd@1), Key, Flag) + ) + end + ). + +-spec global_flag(glint(KYG), binary(), glint@flag:flag_builder(any())) -> glint(KYG). +global_flag(Glint, Key, Flag) -> + erlang:setelement( + 4, + Glint, + gleam@map:insert(erlang:element(4, Glint), Key, glint@flag:build(Flag)) + ). + +-spec global_flag_tuple(glint(KYL), {binary(), glint@flag:flag_builder(any())}) -> glint(KYL). +global_flag_tuple(Glint, Tup) -> + global_flag(Glint, erlang:element(1, Tup), erlang:element(2, Tup)). + +-spec global_flags(glint(KYQ), list({binary(), glint@flag:flag()})) -> glint(KYQ). +global_flags(Glint, Flags) -> + erlang:setelement( + 4, + Glint, + (gleam@list:fold( + Flags, + erlang:element(4, Glint), + fun(Acc, Tup) -> + gleam@map:insert( + Acc, + erlang:element(1, Tup), + erlang:element(2, Tup) + ) + end + )) + ). + +-spec execute_root( + command_node(KZE), + gleam@dict:dict(binary(), glint@flag:flag()), + list(binary()), + list(binary()) +) -> {ok, out(KZE)} | {error, snag:snag()}. +execute_root(Cmd, Global_flags, Args, Flag_inputs) -> + _pipe@3 = case erlang:element(2, Cmd) of + {some, Contents} -> + gleam@result:'try'( + gleam@list:try_fold( + Flag_inputs, + gleam@map:merge(Global_flags, erlang:element(3, Contents)), + fun glint@flag:update_flags/2 + ), + fun(New_flags) -> _pipe = {command_input, Args, New_flags}, + _pipe@1 = (erlang:element(2, Contents))(_pipe), + _pipe@2 = {out, _pipe@1}, + {ok, _pipe@2} end + ); + + none -> + snag:error(<<"command not found"/utf8>>) + end, + snag:context(_pipe@3, <<"failed to run command"/utf8>>). + +-spec default_pretty_help() -> pretty_help(). +default_pretty_help() -> + _assert_subject = gleam_community@colour:from_rgb255(182, 255, 234), + {ok, Usage_colour} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"glint"/utf8>>, + function => <<"default_pretty_help"/utf8>>, + line => 404}) + end, + _assert_subject@1 = gleam_community@colour:from_rgb255(255, 175, 243), + {ok, Flags_colour} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"glint"/utf8>>, + function => <<"default_pretty_help"/utf8>>, + line => 405}) + end, + _assert_subject@2 = gleam_community@colour:from_rgb255(252, 226, 174), + {ok, Subcommands_colour} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"glint"/utf8>>, + function => <<"default_pretty_help"/utf8>>, + line => 406}) + end, + {pretty_help, Usage_colour, Flags_colour, Subcommands_colour}. + +-spec is_not_empty(binary()) -> boolean(). +is_not_empty(S) -> + S /= <<""/utf8>>. + +-spec sanitize_path(list(binary())) -> list(binary()). +sanitize_path(Path) -> + _pipe = Path, + _pipe@1 = gleam@list:map(_pipe, fun gleam@string:trim/1), + gleam@list:filter(_pipe@1, fun is_not_empty/1). + +-spec add(glint(KWY), list(binary()), command(KWY)) -> glint(KWY). +add(Glint, Path, Contents) -> + erlang:setelement( + 3, + Glint, + begin + _pipe = Path, + _pipe@1 = sanitize_path(_pipe), + do_add(erlang:element(3, Glint), _pipe@1, Contents) + end + ). + +-spec wrap_with_space(binary()) -> binary(). +wrap_with_space(S) -> + case S of + <<""/utf8>> -> + <<" "/utf8>>; + + _ -> + <<<<" "/utf8, S/binary>>/binary, " "/utf8>> + end. + +-spec subcommand_help(binary(), command_node(any())) -> binary(). +subcommand_help(Name, Cmd) -> + case erlang:element(2, Cmd) of + none -> + Name; + + {some, Contents} -> + <<<<Name/binary, "\t\t"/utf8>>/binary, + (erlang:element(4, Contents))/binary>> + end. + +-spec subcommands_help(gleam@dict:dict(binary(), command_node(any()))) -> binary(). +subcommands_help(Cmds) -> + _pipe = Cmds, + _pipe@1 = gleam@map:map_values(_pipe, fun subcommand_help/2), + _pipe@2 = gleam@map:values(_pipe@1), + _pipe@3 = gleam@list:sort(_pipe@2, fun gleam@string:compare/2), + gleam@string:join(_pipe@3, <<"\n\t"/utf8>>). + +-spec heading_style(binary(), gleam_community@colour:colour()) -> binary(). +heading_style(Heading, Colour) -> + _pipe = Heading, + _pipe@1 = gleam_community@ansi:bold(_pipe), + _pipe@2 = gleam_community@ansi:underline(_pipe@1), + _pipe@3 = gleam_community@ansi:italic(_pipe@2), + _pipe@4 = gleam_community@ansi:hex( + _pipe@3, + gleam_community@colour:to_rgb_hex(Colour) + ), + gleam_community@ansi:reset(_pipe@4). + +-spec add_command_from_stub(glint(KZZ), stub(KZZ)) -> glint(KZZ). +add_command_from_stub(Glint, Stub) -> + add( + Glint, + erlang:element(2, Stub), + begin + _pipe = command(erlang:element(3, Stub)), + _pipe@1 = flags(_pipe, erlang:element(4, Stub)), + description(_pipe@1, erlang:element(5, Stub)) + end + ). + +-spec new() -> glint(any()). +new() -> + {glint, {config, none, none}, empty_command(), gleam@map:new()}. + +-spec usage_help( + binary(), + gleam@dict:dict(binary(), glint@flag:flag()), + config() +) -> binary(). +usage_help(Cmd_name, Flags, Config) -> + App_name = gleam@option:unwrap( + erlang:element(3, Config), + <<"gleam run"/utf8>> + ), + Flags@1 = begin + _pipe = Flags, + _pipe@1 = gleam@map:to_list(_pipe), + _pipe@2 = gleam@list:map(_pipe@1, fun glint@flag:flag_type_help/1), + gleam@list:sort(_pipe@2, fun gleam@string:compare/2) + end, + Flag_sb = case Flags@1 of + [] -> + gleam@string_builder:new(); + + _ -> + _pipe@3 = Flags@1, + _pipe@4 = gleam@list:intersperse(_pipe@3, <<" "/utf8>>), + _pipe@5 = gleam@string_builder:from_strings(_pipe@4), + _pipe@6 = gleam@string_builder:prepend(_pipe@5, <<" [ "/utf8>>), + gleam@string_builder:append(_pipe@6, <<" ]"/utf8>>) + end, + _pipe@7 = [App_name, wrap_with_space(Cmd_name), <<"[ ARGS ]"/utf8>>], + _pipe@8 = gleam@string_builder:from_strings(_pipe@7), + _pipe@9 = gleam@string_builder:append_builder(_pipe@8, Flag_sb), + _pipe@12 = gleam@string_builder:prepend( + _pipe@9, + <<(begin + _pipe@10 = erlang:element(2, Config), + _pipe@11 = gleam@option:map( + _pipe@10, + fun(Styling) -> + heading_style( + <<"USAGE:"/utf8>>, + erlang:element(2, Styling) + ) + end + ), + gleam@option:unwrap(_pipe@11, <<"USAGE:"/utf8>>) + end)/binary, + "\n\t"/utf8>> + ), + gleam@string_builder:to_string(_pipe@12). + +-spec help_flag() -> binary(). +help_flag() -> + <<(<<"--"/utf8>>)/binary, "help"/utf8>>. + +-spec cmd_help( + list(binary()), + command_node(any()), + config(), + gleam@dict:dict(binary(), glint@flag:flag()) +) -> binary(). +cmd_help(Path, Cmd, Config, Global_flags) -> + Name = begin + _pipe = Path, + _pipe@1 = gleam@list:reverse(_pipe), + gleam@string:join(_pipe@1, <<" "/utf8>>) + end, + Flags = begin + _pipe@2 = gleam@option:map( + erlang:element(2, Cmd), + fun(Contents) -> erlang:element(3, Contents) end + ), + _pipe@3 = gleam@option:lazy_unwrap(_pipe@2, fun gleam@map:new/0), + gleam@map:merge(Global_flags, _pipe@3) + end, + Flags_help_body = <<<<(begin + _pipe@4 = erlang:element(2, Config), + _pipe@5 = gleam@option:map( + _pipe@4, + fun(P) -> + heading_style(<<"FLAGS:"/utf8>>, erlang:element(3, P)) + end + ), + gleam@option:unwrap(_pipe@5, <<"FLAGS:"/utf8>>) + end)/binary, + "\n\t"/utf8>>/binary, + (gleam@string:join( + gleam@list:sort( + [<<"--help\t\t\tPrint help information"/utf8>> | + glint@flag:flags_help(Flags)], + fun gleam@string:compare/2 + ), + <<"\n\t"/utf8>> + ))/binary>>, + Usage = usage_help(Name, Flags, Config), + Description = begin + _pipe@6 = erlang:element(2, Cmd), + _pipe@7 = gleam@option:map( + _pipe@6, + fun(Contents@1) -> erlang:element(4, Contents@1) end + ), + gleam@option:unwrap(_pipe@7, <<""/utf8>>) + end, + Header_items = begin + _pipe@8 = [Name, Description], + _pipe@9 = gleam@list:filter(_pipe@8, fun is_not_empty/1), + gleam@string:join(_pipe@9, <<"\n"/utf8>>) + end, + Subcommands = case subcommands_help(erlang:element(3, Cmd)) of + <<""/utf8>> -> + <<""/utf8>>; + + Subcommands_help_body -> + <<<<(begin + _pipe@10 = erlang:element(2, Config), + _pipe@11 = gleam@option:map( + _pipe@10, + fun(P@1) -> + heading_style( + <<"SUBCOMMANDS:"/utf8>>, + erlang:element(4, P@1) + ) + end + ), + gleam@option:unwrap(_pipe@11, <<"SUBCOMMANDS:"/utf8>>) + end)/binary, + "\n\t"/utf8>>/binary, + Subcommands_help_body/binary>> + end, + _pipe@12 = [Header_items, Usage, Flags_help_body, Subcommands], + _pipe@13 = gleam@list:filter(_pipe@12, fun is_not_empty/1), + gleam@string:join(_pipe@13, <<"\n\n"/utf8>>). + +-spec do_execute( + command_node(KYY), + config(), + gleam@dict:dict(binary(), glint@flag:flag()), + list(binary()), + list(binary()), + boolean(), + list(binary()) +) -> {ok, out(KYY)} | {error, snag:snag()}. +do_execute(Cmd, Config, Global_flags, Args, Flags, Help, Command_path) -> + case Args of + [] when Help -> + _pipe = Command_path, + _pipe@1 = cmd_help(_pipe, Cmd, Config, Global_flags), + _pipe@2 = {help, _pipe@1}, + {ok, _pipe@2}; + + [] -> + execute_root(Cmd, Global_flags, [], Flags); + + [Arg | Rest] -> + case gleam@map:get(erlang:element(3, Cmd), Arg) of + {ok, Cmd@1} -> + do_execute( + Cmd@1, + Config, + Global_flags, + Rest, + Flags, + Help, + [Arg | Command_path] + ); + + _ when Help -> + _pipe@3 = Command_path, + _pipe@4 = cmd_help(_pipe@3, Cmd, Config, Global_flags), + _pipe@5 = {help, _pipe@4}, + {ok, _pipe@5}; + + _ -> + execute_root(Cmd, Global_flags, Args, Flags) + end + end. + +-spec execute(glint(KYU), list(binary())) -> {ok, out(KYU)} | + {error, snag:snag()}. +execute(Glint, Args) -> + Help_flag = help_flag(), + {Help, Args@2} = case gleam@list:pop(Args, fun(S) -> S =:= Help_flag end) of + {ok, {_, Args@1}} -> + {true, Args@1}; + + _ -> + {false, Args} + end, + {Flags, Args@3} = gleam@list:partition( + Args@2, + fun(_capture) -> gleam@string:starts_with(_capture, <<"--"/utf8>>) end + ), + do_execute( + erlang:element(3, Glint), + erlang:element(2, Glint), + erlang:element(4, Glint), + Args@3, + Flags, + Help, + [] + ). + +-spec run_and_handle(glint(KZM), list(binary()), fun((KZM) -> any())) -> nil. +run_and_handle(Glint, Args, Handle) -> + case execute(Glint, Args) of + {error, Err} -> + _pipe = Err, + _pipe@1 = snag:pretty_print(_pipe), + gleam@io:println(_pipe@1); + + {ok, {help, Help}} -> + gleam@io:println(Help); + + {ok, {out, Out}} -> + Handle(Out), + nil + end. + +-spec run(glint(any()), list(binary())) -> nil. +run(Glint, Args) -> + run_and_handle(Glint, Args, gleam@function:constant(nil)). diff --git a/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.cache b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.cache Binary files differnew file mode 100644 index 0000000..7570f95 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.cache diff --git a/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.cache_meta b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.cache_meta Binary files differnew file mode 100644 index 0000000..be367e3 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.cache_meta diff --git a/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.erl b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.erl new file mode 100644 index 0000000..2b2a8c3 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.erl @@ -0,0 +1,523 @@ +-module(glint@flag). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([string/0, string_list/0, build/1, constraint/2, description/2, default/2, build_map/1, int/0, int_list/0, float/0, float_list/0, bool/0, get_int_value/1, get_int/2, get_ints_value/1, get_ints/2, get_bool_value/1, get_bool/2, get_string_value/1, get_string/2, get_strings_value/1, get_strings/2, get_float_value/1, get_float/2, get_floats_value/1, get_floats/2, update_flags/2, flag_type_help/1, flags_help/1]). +-export_type([value/0, flag_builder/1, internal/1, flag/0]). + +-type value() :: {b, internal(boolean())} | + {i, internal(integer())} | + {li, internal(list(integer()))} | + {f, internal(float())} | + {lf, internal(list(float()))} | + {s, internal(binary())} | + {ls, internal(list(binary()))}. + +-opaque flag_builder(KIJ) :: {flag_builder, + binary(), + fun((binary()) -> {ok, KIJ} | {error, snag:snag()}), + fun((internal(KIJ)) -> value()), + gleam@option:option(KIJ)}. + +-opaque internal(KIK) :: {internal, + gleam@option:option(KIK), + fun((binary()) -> {ok, KIK} | {error, snag:snag()})}. + +-type flag() :: {flag, value(), binary()}. + +-spec new( + fun((internal(KJB)) -> value()), + fun((binary()) -> {ok, KJB} | {error, snag:snag()}) +) -> flag_builder(KJB). +new(Valuer, P) -> + {flag_builder, <<""/utf8>>, P, Valuer, none}. + +-spec string() -> flag_builder(binary()). +string() -> + new(fun(Field@0) -> {s, Field@0} end, fun(S) -> {ok, S} end). + +-spec string_list() -> flag_builder(list(binary())). +string_list() -> + new(fun(Field@0) -> {ls, Field@0} end, fun(Input) -> _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<","/utf8>>), + {ok, _pipe@1} end). + +-spec build(flag_builder(any())) -> flag(). +build(Fb) -> + {flag, + (erlang:element(4, Fb))( + {internal, erlang:element(5, Fb), erlang:element(3, Fb)} + ), + erlang:element(2, Fb)}. + +-spec attempt( + {ok, KJS} | {error, KJT}, + fun((KJS) -> {ok, any()} | {error, KJT}) +) -> {ok, KJS} | {error, KJT}. +attempt(Val, F) -> + gleam@result:'try'(Val, fun(A) -> gleam@result:replace(F(A), A) end). + +-spec wrap_with_constraint( + fun((binary()) -> {ok, KJM} | {error, snag:snag()}), + fun((KJM) -> {ok, nil} | {error, snag:snag()}) +) -> fun((binary()) -> {ok, KJM} | {error, snag:snag()}). +wrap_with_constraint(P, Constraint) -> + fun(Input) -> attempt(P(Input), Constraint) end. + +-spec constraint( + flag_builder(KJI), + fun((KJI) -> {ok, nil} | {error, snag:snag()}) +) -> flag_builder(KJI). +constraint(Builder, Constraint) -> + erlang:setelement( + 3, + Builder, + wrap_with_constraint(erlang:element(3, Builder), Constraint) + ). + +-spec description(flag_builder(KKB), binary()) -> flag_builder(KKB). +description(Builder, Description) -> + erlang:setelement(2, Builder, Description). + +-spec default(flag_builder(KKE), KKE) -> flag_builder(KKE). +default(Builder, Default) -> + erlang:setelement(5, Builder, {some, Default}). + +-spec build_map(list({binary(), flag()})) -> gleam@dict:dict(binary(), flag()). +build_map(Flags) -> + gleam@map:from_list(Flags). + +-spec access_type_error(binary()) -> {ok, any()} | {error, snag:snag()}. +access_type_error(Flag_type) -> + snag:error(<<"cannot access flag as "/utf8, Flag_type/binary>>). + +-spec flag_not_provided_error() -> {ok, any()} | {error, snag:snag()}. +flag_not_provided_error() -> + snag:error(<<"no value provided"/utf8>>). + +-spec construct_value(binary(), internal(KKO), fun((internal(KKO)) -> value())) -> {ok, + value()} | + {error, snag:snag()}. +construct_value(Input, Internal, Constructor) -> + gleam@result:map( + (erlang:element(3, Internal))(Input), + fun(Val) -> Constructor(erlang:setelement(2, Internal, {some, Val})) end + ). + +-spec compute_flag(binary(), value()) -> {ok, value()} | {error, snag:snag()}. +compute_flag(Input, Current) -> + _pipe = Input, + _pipe@1 = case Current of + {i, Internal} -> + fun(_capture) -> + construct_value( + _capture, + Internal, + fun(Field@0) -> {i, Field@0} end + ) + end; + + {li, Internal@1} -> + fun(_capture@1) -> + construct_value( + _capture@1, + Internal@1, + fun(Field@0) -> {li, Field@0} end + ) + end; + + {f, Internal@2} -> + fun(_capture@2) -> + construct_value( + _capture@2, + Internal@2, + fun(Field@0) -> {f, Field@0} end + ) + end; + + {lf, Internal@3} -> + fun(_capture@3) -> + construct_value( + _capture@3, + Internal@3, + fun(Field@0) -> {lf, Field@0} end + ) + end; + + {s, Internal@4} -> + fun(_capture@4) -> + construct_value( + _capture@4, + Internal@4, + fun(Field@0) -> {s, Field@0} end + ) + end; + + {ls, Internal@5} -> + fun(_capture@5) -> + construct_value( + _capture@5, + Internal@5, + fun(Field@0) -> {ls, Field@0} end + ) + end; + + {b, Internal@6} -> + fun(_capture@6) -> + construct_value( + _capture@6, + Internal@6, + fun(Field@0) -> {b, Field@0} end + ) + end + end(_pipe), + snag:context(_pipe@1, <<"failed to compute value for flag"/utf8>>). + +-spec layer_invalid_flag(snag:snag(), binary()) -> snag:snag(). +layer_invalid_flag(Err, Flag) -> + snag:layer(Err, <<<<"invalid flag '"/utf8, Flag/binary>>/binary, "'"/utf8>>). + +-spec no_value_flag_err(binary()) -> snag:snag(). +no_value_flag_err(Flag_input) -> + _pipe = (<<<<"flag '"/utf8, Flag_input/binary>>/binary, + "' has no assigned value"/utf8>>), + _pipe@1 = snag:new(_pipe), + layer_invalid_flag(_pipe@1, Flag_input). + +-spec undefined_flag_err(binary()) -> snag:snag(). +undefined_flag_err(Key) -> + _pipe = <<"flag provided but not defined"/utf8>>, + _pipe@1 = snag:new(_pipe), + layer_invalid_flag(_pipe@1, Key). + +-spec cannot_parse(binary(), binary()) -> snag:snag(). +cannot_parse(Value, Kind) -> + _pipe = (<<<<<<"cannot parse value '"/utf8, Value/binary>>/binary, + "' as "/utf8>>/binary, + Kind/binary>>), + snag:new(_pipe). + +-spec int() -> flag_builder(integer()). +int() -> + new(fun(Field@0) -> {i, Field@0} end, fun(Input) -> _pipe = Input, + _pipe@1 = gleam@int:parse(_pipe), + gleam@result:replace_error( + _pipe@1, + cannot_parse(Input, <<"int"/utf8>>) + ) end). + +-spec int_list() -> flag_builder(list(integer())). +int_list() -> + new(fun(Field@0) -> {li, Field@0} end, fun(Input) -> _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<","/utf8>>), + _pipe@2 = gleam@list:try_map(_pipe@1, fun gleam@int:parse/1), + gleam@result:replace_error( + _pipe@2, + cannot_parse(Input, <<"int list"/utf8>>) + ) end). + +-spec float() -> flag_builder(float()). +float() -> + new(fun(Field@0) -> {f, Field@0} end, fun(Input) -> _pipe = Input, + _pipe@1 = gleam@float:parse(_pipe), + gleam@result:replace_error( + _pipe@1, + cannot_parse(Input, <<"float"/utf8>>) + ) end). + +-spec float_list() -> flag_builder(list(float())). +float_list() -> + new(fun(Field@0) -> {lf, Field@0} end, fun(Input) -> _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<","/utf8>>), + _pipe@2 = gleam@list:try_map(_pipe@1, fun gleam@float:parse/1), + gleam@result:replace_error( + _pipe@2, + cannot_parse(Input, <<"float list"/utf8>>) + ) end). + +-spec bool() -> flag_builder(boolean()). +bool() -> + new( + fun(Field@0) -> {b, Field@0} end, + fun(Input) -> case gleam@string:lowercase(Input) of + <<"true"/utf8>> -> + {ok, true}; + + <<"t"/utf8>> -> + {ok, true}; + + <<"false"/utf8>> -> + {ok, false}; + + <<"f"/utf8>> -> + {ok, false}; + + _ -> + {error, cannot_parse(Input, <<"bool"/utf8>>)} + end end + ). + +-spec access(gleam@dict:dict(binary(), flag()), binary()) -> {ok, flag()} | + {error, snag:snag()}. +access(Flags, Name) -> + _pipe = gleam@map:get(Flags, Name), + gleam@result:replace_error(_pipe, undefined_flag_err(Name)). + +-spec update_flag_value(gleam@dict:dict(binary(), flag()), {binary(), binary()}) -> {ok, + gleam@dict:dict(binary(), flag())} | + {error, snag:snag()}. +update_flag_value(Flags, Data) -> + {Key, Input} = Data, + gleam@result:'try'( + access(Flags, Key), + fun(Contents) -> + gleam@result:map( + begin + _pipe = compute_flag(Input, erlang:element(2, Contents)), + gleam@result:map_error( + _pipe, + fun(_capture) -> layer_invalid_flag(_capture, Key) end + ) + end, + fun(Value) -> + gleam@map:insert( + Flags, + Key, + erlang:setelement(2, Contents, Value) + ) + end + ) + end + ). + +-spec attempt_toggle_flag(gleam@dict:dict(binary(), flag()), binary()) -> {ok, + gleam@dict:dict(binary(), flag())} | + {error, snag:snag()}. +attempt_toggle_flag(Flags, Key) -> + gleam@result:'try'( + access(Flags, Key), + fun(Contents) -> case erlang:element(2, Contents) of + {b, {internal, none, _} = Internal} -> + _pipe = erlang:setelement(2, Internal, {some, true}), + _pipe@1 = {b, _pipe}, + _pipe@2 = (fun(Val) -> + erlang:setelement(2, Contents, Val) + end)(_pipe@1), + _pipe@3 = gleam@map:insert(Flags, Key, _pipe@2), + {ok, _pipe@3}; + + {b, {internal, {some, Val@1}, _} = Internal@1} -> + _pipe@4 = erlang:setelement( + 2, + Internal@1, + {some, not Val@1} + ), + _pipe@5 = {b, _pipe@4}, + _pipe@6 = (fun(Val@2) -> + erlang:setelement(2, Contents, Val@2) + end)(_pipe@5), + _pipe@7 = gleam@map:insert(Flags, Key, _pipe@6), + {ok, _pipe@7}; + + _ -> + {error, no_value_flag_err(Key)} + end end + ). + +-spec get_value( + gleam@dict:dict(binary(), flag()), + binary(), + fun((flag()) -> {ok, KKW} | {error, snag:snag()}) +) -> {ok, KKW} | {error, snag:snag()}. +get_value(Flags, Key, Kind) -> + _pipe = access(Flags, Key), + _pipe@1 = gleam@result:'try'(_pipe, Kind), + snag:context( + _pipe@1, + <<<<"failed to retrieve value for flag '"/utf8, Key/binary>>/binary, + "'"/utf8>> + ). + +-spec get_int_value(flag()) -> {ok, integer()} | {error, snag:snag()}. +get_int_value(Flag) -> + case erlang:element(2, Flag) of + {i, {internal, {some, Val}, _}} -> + {ok, Val}; + + {i, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"int"/utf8>>) + end. + +-spec get_int(gleam@dict:dict(binary(), flag()), binary()) -> {ok, integer()} | + {error, snag:snag()}. +get_int(Flags, Name) -> + get_value(Flags, Name, fun get_int_value/1). + +-spec get_ints_value(flag()) -> {ok, list(integer())} | {error, snag:snag()}. +get_ints_value(Flag) -> + case erlang:element(2, Flag) of + {li, {internal, {some, Val}, _}} -> + {ok, Val}; + + {li, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"int list"/utf8>>) + end. + +-spec get_ints(gleam@dict:dict(binary(), flag()), binary()) -> {ok, + list(integer())} | + {error, snag:snag()}. +get_ints(Flags, Name) -> + get_value(Flags, Name, fun get_ints_value/1). + +-spec get_bool_value(flag()) -> {ok, boolean()} | {error, snag:snag()}. +get_bool_value(Flag) -> + case erlang:element(2, Flag) of + {b, {internal, {some, Val}, _}} -> + {ok, Val}; + + {b, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"bool"/utf8>>) + end. + +-spec get_bool(gleam@dict:dict(binary(), flag()), binary()) -> {ok, boolean()} | + {error, snag:snag()}. +get_bool(Flags, Name) -> + get_value(Flags, Name, fun get_bool_value/1). + +-spec get_string_value(flag()) -> {ok, binary()} | {error, snag:snag()}. +get_string_value(Flag) -> + case erlang:element(2, Flag) of + {s, {internal, {some, Val}, _}} -> + {ok, Val}; + + {s, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"string"/utf8>>) + end. + +-spec get_string(gleam@dict:dict(binary(), flag()), binary()) -> {ok, binary()} | + {error, snag:snag()}. +get_string(Flags, Name) -> + get_value(Flags, Name, fun get_string_value/1). + +-spec get_strings_value(flag()) -> {ok, list(binary())} | {error, snag:snag()}. +get_strings_value(Flag) -> + case erlang:element(2, Flag) of + {ls, {internal, {some, Val}, _}} -> + {ok, Val}; + + {ls, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"string list"/utf8>>) + end. + +-spec get_strings(gleam@dict:dict(binary(), flag()), binary()) -> {ok, + list(binary())} | + {error, snag:snag()}. +get_strings(Flags, Name) -> + get_value(Flags, Name, fun get_strings_value/1). + +-spec get_float_value(flag()) -> {ok, float()} | {error, snag:snag()}. +get_float_value(Flag) -> + case erlang:element(2, Flag) of + {f, {internal, {some, Val}, _}} -> + {ok, Val}; + + {f, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"float"/utf8>>) + end. + +-spec get_float(gleam@dict:dict(binary(), flag()), binary()) -> {ok, float()} | + {error, snag:snag()}. +get_float(Flags, Name) -> + get_value(Flags, Name, fun get_float_value/1). + +-spec get_floats_value(flag()) -> {ok, list(float())} | {error, snag:snag()}. +get_floats_value(Flag) -> + case erlang:element(2, Flag) of + {lf, {internal, {some, Val}, _}} -> + {ok, Val}; + + {lf, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"float list"/utf8>>) + end. + +-spec get_floats(gleam@dict:dict(binary(), flag()), binary()) -> {ok, + list(float())} | + {error, snag:snag()}. +get_floats(Flags, Name) -> + get_value(Flags, Name, fun get_floats_value/1). + +-spec update_flags(gleam@dict:dict(binary(), flag()), binary()) -> {ok, + gleam@dict:dict(binary(), flag())} | + {error, snag:snag()}. +update_flags(Flags, Flag_input) -> + Flag_input@1 = gleam@string:drop_left( + Flag_input, + gleam@string:length(<<"--"/utf8>>) + ), + case gleam@string:split_once(Flag_input@1, <<"="/utf8>>) of + {ok, Data} -> + update_flag_value(Flags, Data); + + {error, _} -> + attempt_toggle_flag(Flags, Flag_input@1) + end. + +-spec flag_type_help({binary(), flag()}) -> binary(). +flag_type_help(Flag) -> + {Name, Contents} = Flag, + Kind = case erlang:element(2, Contents) of + {i, _} -> + <<"INT"/utf8>>; + + {b, _} -> + <<"BOOL"/utf8>>; + + {f, _} -> + <<"FLOAT"/utf8>>; + + {lf, _} -> + <<"FLOAT_LIST"/utf8>>; + + {li, _} -> + <<"INT_LIST"/utf8>>; + + {ls, _} -> + <<"STRING_LIST"/utf8>>; + + {s, _} -> + <<"STRING"/utf8>> + end, + <<<<<<<<<<"--"/utf8, Name/binary>>/binary, "="/utf8>>/binary, "<"/utf8>>/binary, + Kind/binary>>/binary, + ">"/utf8>>. + +-spec flag_help({binary(), flag()}) -> binary(). +flag_help(Flag) -> + <<<<(flag_type_help(Flag))/binary, "\t\t"/utf8>>/binary, + (erlang:element(3, (erlang:element(2, Flag))))/binary>>. + +-spec flags_help(gleam@dict:dict(binary(), flag())) -> list(binary()). +flags_help(Flags) -> + _pipe = Flags, + _pipe@1 = gleam@map:to_list(_pipe), + gleam@list:map(_pipe@1, fun flag_help/1). diff --git a/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache Binary files differnew file mode 100644 index 0000000..4c08669 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache diff --git a/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache_meta b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache_meta Binary files differnew file mode 100644 index 0000000..355567d --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache_meta diff --git a/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.erl b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.erl new file mode 100644 index 0000000..0e1cc04 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.erl @@ -0,0 +1,68 @@ +-module(glint@flag@constraint). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([one_of/1, none_of/1, each/1]). + +-spec one_of(list(KGS)) -> fun((KGS) -> {ok, nil} | {error, snag:snag()}). +one_of(Allowed) -> + Allowed_set = gleam@set:from_list(Allowed), + fun(Val) -> case gleam@set:contains(Allowed_set, Val) of + true -> + {ok, nil}; + + false -> + snag:error( + <<<<<<"invalid value '"/utf8, + (gleam@string:inspect(Val))/binary>>/binary, + "', must be one of: ["/utf8>>/binary, + ((<<(begin + _pipe = Allowed, + _pipe@1 = gleam@list:map( + _pipe, + fun(A) -> + <<<<"'"/utf8, + (gleam@string:inspect(A))/binary>>/binary, + "'"/utf8>> + end + ), + gleam@string:join(_pipe@1, <<", "/utf8>>) + end)/binary, + "]"/utf8>>))/binary>> + ) + end end. + +-spec none_of(list(KGV)) -> fun((KGV) -> {ok, nil} | {error, snag:snag()}). +none_of(Disallowed) -> + Disallowed_set = gleam@set:from_list(Disallowed), + fun(Val) -> case gleam@set:contains(Disallowed_set, Val) of + false -> + {ok, nil}; + + true -> + snag:error( + <<<<<<"invalid value '"/utf8, + (gleam@string:inspect(Val))/binary>>/binary, + "', must not be one of: ["/utf8>>/binary, + (((<<(begin + _pipe = Disallowed, + _pipe@1 = gleam@list:map( + _pipe, + fun(A) -> + <<<<"'"/utf8, + (gleam@string:inspect(A))/binary>>/binary, + "'"/utf8>> + end + ), + gleam@string:join(_pipe@1, <<", "/utf8>>) + end)/binary, + "]"/utf8>>)))/binary>> + ) + end end. + +-spec each(fun((KGY) -> {ok, nil} | {error, snag:snag()})) -> fun((list(KGY)) -> {ok, + nil} | + {error, snag:snag()}). +each(Constraint) -> + fun(L) -> _pipe = L, + _pipe@1 = gleam@list:try_map(_pipe, Constraint), + gleam@result:replace(_pipe@1, nil) end. diff --git a/aoc2023/build/dev/erlang/glint/ebin/glint.app b/aoc2023/build/dev/erlang/glint/ebin/glint.app new file mode 100644 index 0000000..41fba79 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/ebin/glint.app @@ -0,0 +1,10 @@ +{application, glint, [ + {vsn, "0.13.0"}, + {applications, [gleam_community_ansi, + gleam_community_colour, + gleam_stdlib, + snag]}, + {description, "Gleam command line argument parsing with basic flag support."}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/glint/ebin/glint.beam b/aoc2023/build/dev/erlang/glint/ebin/glint.beam Binary files differnew file mode 100644 index 0000000..80ab9b9 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/ebin/glint.beam diff --git a/aoc2023/build/dev/erlang/glint/ebin/glint@flag.beam b/aoc2023/build/dev/erlang/glint/ebin/glint@flag.beam Binary files differnew file mode 100644 index 0000000..66ef4f0 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/ebin/glint@flag.beam diff --git a/aoc2023/build/dev/erlang/glint/ebin/glint@flag@constraint.beam b/aoc2023/build/dev/erlang/glint/ebin/glint@flag@constraint.beam Binary files differnew file mode 100644 index 0000000..c6377ad --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/ebin/glint@flag@constraint.beam diff --git a/aoc2023/build/dev/erlang/glint/include/glint@flag_Flag.hrl b/aoc2023/build/dev/erlang/glint/include/glint@flag_Flag.hrl new file mode 100644 index 0000000..645cb12 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/include/glint@flag_Flag.hrl @@ -0,0 +1 @@ +-record(flag, {value :: glint@flag:value(), description :: binary()}). diff --git a/aoc2023/build/dev/erlang/glint/include/glint@flag_FlagBuilder.hrl b/aoc2023/build/dev/erlang/glint/include/glint@flag_FlagBuilder.hrl new file mode 100644 index 0000000..b5e21a2 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/include/glint@flag_FlagBuilder.hrl @@ -0,0 +1,6 @@ +-record(flag_builder, { + desc :: binary(), + parser :: fun((binary()) -> {ok, any()} | {error, snag:snag()}), + value :: fun((glint@flag:internal(any())) -> glint@flag:value()), + default :: gleam@option:option(any()) +}). diff --git a/aoc2023/build/dev/erlang/glint/include/glint@flag_Internal.hrl b/aoc2023/build/dev/erlang/glint/include/glint@flag_Internal.hrl new file mode 100644 index 0000000..281bbd0 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/include/glint@flag_Internal.hrl @@ -0,0 +1,4 @@ +-record(internal, { + value :: gleam@option:option(any()), + parser :: fun((binary()) -> {ok, any()} | {error, snag:snag()}) +}). diff --git a/aoc2023/build/dev/erlang/glint/include/glint_Command.hrl b/aoc2023/build/dev/erlang/glint/include/glint_Command.hrl new file mode 100644 index 0000000..2761365 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/include/glint_Command.hrl @@ -0,0 +1,5 @@ +-record(command, { + do :: fun((glint:command_input()) -> any()), + flags :: gleam@dict:dict(binary(), glint@flag:flag()), + description :: binary() +}). diff --git a/aoc2023/build/dev/erlang/glint/include/glint_CommandInput.hrl b/aoc2023/build/dev/erlang/glint/include/glint_CommandInput.hrl new file mode 100644 index 0000000..e0e1a81 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/include/glint_CommandInput.hrl @@ -0,0 +1,4 @@ +-record(command_input, { + args :: list(binary()), + flags :: gleam@dict:dict(binary(), glint@flag:flag()) +}). diff --git a/aoc2023/build/dev/erlang/glint/include/glint_Config.hrl b/aoc2023/build/dev/erlang/glint/include/glint_Config.hrl new file mode 100644 index 0000000..70cf645 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/include/glint_Config.hrl @@ -0,0 +1,4 @@ +-record(config, { + pretty_help :: gleam@option:option(glint:pretty_help()), + name :: gleam@option:option(binary()) +}). diff --git a/aoc2023/build/dev/erlang/glint/include/glint_Glint.hrl b/aoc2023/build/dev/erlang/glint/include/glint_Glint.hrl new file mode 100644 index 0000000..f14c34c --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/include/glint_Glint.hrl @@ -0,0 +1,5 @@ +-record(glint, { + config :: glint:config(), + cmd :: glint:command_node(any()), + global_flags :: gleam@dict:dict(binary(), glint@flag:flag()) +}). diff --git a/aoc2023/build/dev/erlang/glint/include/glint_PrettyHelp.hrl b/aoc2023/build/dev/erlang/glint/include/glint_PrettyHelp.hrl new file mode 100644 index 0000000..79bd887 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/include/glint_PrettyHelp.hrl @@ -0,0 +1,5 @@ +-record(pretty_help, { + usage :: gleam_community@colour:colour(), + flags :: gleam_community@colour:colour(), + subcommands :: gleam_community@colour:colour() +}). diff --git a/aoc2023/build/dev/erlang/glint/include/glint_Stub.hrl b/aoc2023/build/dev/erlang/glint/include/glint_Stub.hrl new file mode 100644 index 0000000..5aa5d83 --- /dev/null +++ b/aoc2023/build/dev/erlang/glint/include/glint_Stub.hrl @@ -0,0 +1,6 @@ +-record(stub, { + path :: list(binary()), + run :: fun((glint:command_input()) -> any()), + flags :: list({binary(), glint@flag:flag()}), + description :: binary() +}). diff --git a/aoc2023/build/dev/erlang/pqueue/LICENSE b/aoc2023/build/dev/erlang/pqueue/LICENSE new file mode 100644 index 0000000..5697803 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/LICENSE @@ -0,0 +1,21 @@ +MIT License
+
+Copyright (c) 2011-2023 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.
diff --git a/aoc2023/build/dev/erlang/pqueue/README.markdown b/aoc2023/build/dev/erlang/pqueue/README.markdown new file mode 100644 index 0000000..77aaf1c --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/README.markdown @@ -0,0 +1,31 @@ +Erlang Priority Queue Implementation +==================================== + +The priority queue implementations implement a subset of the stdlib Erlang queue interface as seen in the implementation used by both [Riak and RabbitMQ](https://github.com/basho/riak_core/blob/master/src/riak_core_priority_queue.erl). + +The implementations: + +* `priority_queue` (fastest for any priorities when only using a single priority at a time) +* `pqueue` (fastest for 41 priorities, -20 (high) to 20 (low), when using 2 or more priorities at the same time) +* `pqueue2` (slower heap implementation) +* `pqueue3` (faster than `pqueue2` and `priority_queue` when using 64 or more priorities at the same time) +* `pqueue4` (slightly slower than `pqueue` but fastest for allowing 257 priorities, -128 (high) to 128 (low), i.e., fastest when using 42 or more priorities at the same time) + +[The latest results are here](http://okeuday.livejournal.com/19539.html), with [the benchmark here](http://github.com/okeuday/erlbench). + +Author +------ + +Michael Truog (mjtruog at protonmail dot com) + +Thanks +------ + +* Jesper Louis andersen (PropEr integration and testing) +* Ulf Wiger (suggestions and insight) + +License +------- + +MIT License + diff --git a/aoc2023/build/dev/erlang/pqueue/_build/prod/lib/.rebar3/rebar_compiler_erl/source.dag b/aoc2023/build/dev/erlang/pqueue/_build/prod/lib/.rebar3/rebar_compiler_erl/source.dag Binary files differnew file mode 100644 index 0000000..28d7520 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/_build/prod/lib/.rebar3/rebar_compiler_erl/source.dag diff --git a/aoc2023/build/dev/erlang/pqueue/doc/edoc-info b/aoc2023/build/dev/erlang/pqueue/doc/edoc-info new file mode 100644 index 0000000..5e5a8d3 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/doc/edoc-info @@ -0,0 +1,3 @@ +%% encoding: UTF-8 +{application,pqueue}. +{modules,[pqueue,pqueue2,pqueue3,pqueue4]}. diff --git a/aoc2023/build/dev/erlang/pqueue/doc/erlang.png b/aoc2023/build/dev/erlang/pqueue/doc/erlang.png Binary files differnew file mode 100644 index 0000000..987a618 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/doc/erlang.png diff --git a/aoc2023/build/dev/erlang/pqueue/doc/index.html b/aoc2023/build/dev/erlang/pqueue/doc/index.html new file mode 100644 index 0000000..d55b5e6 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/doc/index.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<title>The pqueue application</title> +</head> +<frameset cols="20%,80%"> +<frame src="modules-frame.html" name="modulesFrame" title=""> + +<frame src="overview-summary.html" name="overviewFrame" title=""> +<noframes> +<h2>This page uses frames</h2> +<p>Your browser does not accept frames. +<br>You should go to the <a href="overview-summary.html">non-frame version</a> instead. +</p> +</noframes> +</frameset> +</html>
\ No newline at end of file diff --git a/aoc2023/build/dev/erlang/pqueue/doc/modules-frame.html b/aoc2023/build/dev/erlang/pqueue/doc/modules-frame.html new file mode 100644 index 0000000..5a87cc4 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/doc/modules-frame.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<title>The pqueue application</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<h2 class="indextitle">Modules</h2> +<table width="100%" border="0" summary="list of modules"> +<tr><td><a href="pqueue.html" target="overviewFrame" class="module">pqueue</a></td></tr> +<tr><td><a href="pqueue2.html" target="overviewFrame" class="module">pqueue2</a></td></tr> +<tr><td><a href="pqueue3.html" target="overviewFrame" class="module">pqueue3</a></td></tr> +<tr><td><a href="pqueue4.html" target="overviewFrame" class="module">pqueue4</a></td></tr></table> +</body> +</html>
\ No newline at end of file diff --git a/aoc2023/build/dev/erlang/pqueue/doc/overview-summary.html b/aoc2023/build/dev/erlang/pqueue/doc/overview-summary.html new file mode 100644 index 0000000..e2f8906 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/doc/overview-summary.html @@ -0,0 +1,16 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>The pqueue application</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<h1>The pqueue application</h1> + +<hr> +<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<p><i>Generated by EDoc</i></p> +</body> +</html> diff --git a/aoc2023/build/dev/erlang/pqueue/doc/pqueue.html b/aoc2023/build/dev/erlang/pqueue/doc/pqueue.html new file mode 100644 index 0000000..40b05ac --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/doc/pqueue.html @@ -0,0 +1,166 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Module pqueue</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<hr> + +<h1>Module pqueue</h1> +<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul> + <h3><a name="Static_Priority_Queue.">Static Priority Queue.</a></h3> + This priority queue implementation depends on a static number of priorities + (-20 (high) to 20 (low)) so that tuple access times can be exploited for + quick in/out priority queue operations. +<p>Copyright © 2011-2020 Michael Truog</p> + +<p><b>Version:</b> 2.0.1 Nov 26 2020 14:55:34 + ------------------------------------------------------------------------</p> +<p><b>Authors:</b> Michael Truog (<a href="mailto:mjtruog at protonmail dot com"><tt>mjtruog at protonmail dot com</tt></a>).</p> + +<h2><a name="description">Description</a></h2> + <h3><a name="Static_Priority_Queue.">Static Priority Queue.</a></h3> + This priority queue implementation depends on a static number of priorities + (-20 (high) to 20 (low)) so that tuple access times can be exploited for + quick in/out priority queue operations. This implementation was created to + avoid the slowness within the priority queue used by both RabbitMQ and Riak + (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +<h2><a name="types">Data Types</a></h2> + +<h3 class="typedecl"><a name="type-pqueue">pqueue()</a></h3> +<p><tt>pqueue() = {integer(), {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, <a href="queue.html#type-queue">queue:queue()</a>, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}} | {empty, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, <a href="queue.html#type-queue">queue:queue()</a>, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}}</tt></p> + + +<h2><a name="index">Function Index</a></h2> +<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#in-2">in/2</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#in-3">in/3</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_empty-1">is_empty/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_queue-1">is_queue/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#join-2">join/2</a></td><td> + <h4><a name="Join_two_priority_queues.">Join two priority queues.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#len-1">len/1</a></td><td> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#new-0">new/0</a></td><td> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#out-1">out/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#out-2">out/2</a></td><td> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#pout-1">pout/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value.</td></tr> +<tr><td valign="top"><a href="#test-0">test/0</a></td><td> + <h4><a name="Regression_test.">Regression test.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#to_list-1">to_list/1</a></td><td> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N).</td></tr> +</table> + +<h2><a name="functions">Function Details</a></h2> + +<h3 class="function"><a name="in-2">in/2</a></h3> +<div class="spec"> +<p><tt>in(X::term(), Q::<a href="#type-pqueue">pqueue()</a>) -> <a href="#type-pqueue">pqueue()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="in-3">in/3</a></h3> +<div class="spec"> +<p><tt>in(X::term(), P::integer(), Q::<a href="#type-pqueue">pqueue()</a>) -> <a href="#type-pqueue">pqueue()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_empty-1">is_empty/1</a></h3> +<div class="spec"> +<p><tt>is_empty(X1::<a href="#type-pqueue">pqueue()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_queue-1">is_queue/1</a></h3> +<div class="spec"> +<p><tt>is_queue(X1::<a href="#type-pqueue">pqueue()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1)</p> + +<h3 class="function"><a name="join-2">join/2</a></h3> +<div class="spec"> +<p><tt>join(X1::<a href="#type-pqueue">pqueue()</a>, X2::<a href="#type-pqueue">pqueue()</a>) -> <a href="#type-pqueue">pqueue()</a></tt><br></p> +</div><p> + <h4><a name="Join_two_priority_queues.">Join two priority queues.</a></h4> + O(N)</p> + +<h3 class="function"><a name="len-1">len/1</a></h3> +<div class="spec"> +<p><tt>len(X1::<a href="#type-pqueue">pqueue()</a>) -> non_neg_integer()</tt><br></p> +</div><p> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(N)</p> + +<h3 class="function"><a name="new-0">new/0</a></h3> +<div class="spec"> +<p><tt>new() -> <a href="#type-pqueue">pqueue()</a></tt><br></p> +</div><p> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="out-1">out/1</a></h3> +<div class="spec"> +<p><tt>out(Q::<a href="#type-pqueue">pqueue()</a>) -> {{value, term()}, <a href="#type-pqueue">pqueue()</a>} | {empty, <a href="#type-pqueue">pqueue()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="out-2">out/2</a></h3> +<div class="spec"> +<p><tt>out(P::integer(), Q::<a href="#type-pqueue">pqueue()</a>) -> {{value, term()}, <a href="#type-pqueue">pqueue()</a>} | {empty, <a href="#type-pqueue">pqueue()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="pout-1">pout/1</a></h3> +<div class="spec"> +<p><tt>pout(Q::<a href="#type-pqueue">pqueue()</a>) -> {{value, term(), integer()}, <a href="#type-pqueue">pqueue()</a>} | {empty, <a href="#type-pqueue">pqueue()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value. + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="test-0">test/0</a></h3> +<div class="spec"> +<p><tt>test() -> any()</tt></p> +</div><p> + <h4><a name="Regression_test.">Regression test.</a></h4> +</p> + +<h3 class="function"><a name="to_list-1">to_list/1</a></h3> +<div class="spec"> +<p><tt>to_list(X1::<a href="#type-pqueue">pqueue()</a>) -> [term()]</tt><br></p> +</div><p> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N)</p> +<hr> + +<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<p><i>Generated by EDoc</i></p> +</body> +</html> diff --git a/aoc2023/build/dev/erlang/pqueue/doc/pqueue2.html b/aoc2023/build/dev/erlang/pqueue/doc/pqueue2.html new file mode 100644 index 0000000..2942b84 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/doc/pqueue2.html @@ -0,0 +1,143 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Module pqueue2</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<hr> + +<h1>Module pqueue2</h1> +<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul> + <h3><a name="Skew_Heap_Priority_Queue.">Skew Heap Priority Queue.</a></h3> + Ulf Wiger suggested pursuing a skew heap as an optimal Erlang priority + queue implementation. +<p>Copyright © 2011-2020 Michael Truog</p> + +<p><b>Version:</b> 2.0.1 Nov 26 2020 14:55:32 + ------------------------------------------------------------------------</p> +<p><b>Authors:</b> Michael Truog (<a href="mailto:mjtruog at protonmail dot com"><tt>mjtruog at protonmail dot com</tt></a>).</p> + +<h2><a name="description">Description</a></h2> + <h3><a name="Skew_Heap_Priority_Queue.">Skew Heap Priority Queue.</a></h3> + 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. +<h2><a name="types">Data Types</a></h2> + +<h3 class="typedecl"><a name="type-pqueue2">pqueue2()</a></h3> +<p><tt>pqueue2() = empty | {integer(), <a href="#type-pqueue2">pqueue2()</a>, <a href="#type-pqueue2">pqueue2()</a>, element, term()} | {integer(), <a href="#type-pqueue2">pqueue2()</a>, <a href="#type-pqueue2">pqueue2()</a>, queue, <a href="queue.html#type-queue">queue:queue()</a>}</tt></p> + + +<h2><a name="index">Function Index</a></h2> +<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#in-2">in/2</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#in-3">in/3</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#is_empty-1">is_empty/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#is_queue-1">is_queue/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#len-1">len/1</a></td><td> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#new-0">new/0</a></td><td> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#out-1">out/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#out-2">out/2</a></td><td> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#pout-1">pout/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value.</td></tr> +<tr><td valign="top"><a href="#test-0">test/0</a></td><td> + <h4><a name="Regression_test.">Regression test.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#to_list-1">to_list/1</a></td><td> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4>.</td></tr> +</table> + +<h2><a name="functions">Function Details</a></h2> + +<h3 class="function"><a name="in-2">in/2</a></h3> +<div class="spec"> +<p><tt>in(Value::term(), H::<a href="#type-pqueue2">pqueue2()</a>) -> <a href="#type-pqueue2">pqueue2()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> +</p> + +<h3 class="function"><a name="in-3">in/3</a></h3> +<div class="spec"> +<p><tt>in(Value::term(), P::integer(), H::<a href="#type-pqueue2">pqueue2()</a>) -> <a href="#type-pqueue2">pqueue2()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> +</p> + +<h3 class="function"><a name="is_empty-1">is_empty/1</a></h3> +<div class="spec"> +<p><tt>is_empty(X1::<a href="#type-pqueue2">pqueue2()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> +</p> + +<h3 class="function"><a name="is_queue-1">is_queue/1</a></h3> +<div class="spec"> +<p><tt>is_queue(X1::<a href="#type-pqueue2">pqueue2()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> +</p> + +<h3 class="function"><a name="len-1">len/1</a></h3> +<div class="spec"> +<p><tt>len(H::<a href="#type-pqueue2">pqueue2()</a>) -> non_neg_integer()</tt><br></p> +</div><p> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> +</p> + +<h3 class="function"><a name="new-0">new/0</a></h3> +<div class="spec"> +<p><tt>new() -> <a href="#type-pqueue2">pqueue2()</a></tt><br></p> +</div><p> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> +</p> + +<h3 class="function"><a name="out-1">out/1</a></h3> +<div class="spec"> +<p><tt>out(X1::<a href="#type-pqueue2">pqueue2()</a>) -> {{value, term()}, <a href="#type-pqueue2">pqueue2()</a>} | {empty, <a href="#type-pqueue2">pqueue2()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> +</p> + +<h3 class="function"><a name="out-2">out/2</a></h3> +<div class="spec"> +<p><tt>out(P::integer(), H::<a href="#type-pqueue2">pqueue2()</a>) -> {{value, term()}, <a href="#type-pqueue2">pqueue2()</a>} | {empty, <a href="#type-pqueue2">pqueue2()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> +</p> + +<h3 class="function"><a name="pout-1">pout/1</a></h3> +<div class="spec"> +<p><tt>pout(X1::<a href="#type-pqueue2">pqueue2()</a>) -> {{value, term(), integer()}, <a href="#type-pqueue2">pqueue2()</a>} | {empty, <a href="#type-pqueue2">pqueue2()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value.</p> + +<h3 class="function"><a name="test-0">test/0</a></h3> +<div class="spec"> +<p><tt>test() -> any()</tt></p> +</div><p> + <h4><a name="Regression_test.">Regression test.</a></h4> +</p> + +<h3 class="function"><a name="to_list-1">to_list/1</a></h3> +<div class="spec"> +<p><tt>to_list(H::<a href="#type-pqueue2">pqueue2()</a>) -> [term()]</tt><br></p> +</div><p> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> +</p> +<hr> + +<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<p><i>Generated by EDoc</i></p> +</body> +</html> diff --git a/aoc2023/build/dev/erlang/pqueue/doc/pqueue3.html b/aoc2023/build/dev/erlang/pqueue/doc/pqueue3.html new file mode 100644 index 0000000..35f1a7b --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/doc/pqueue3.html @@ -0,0 +1,162 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Module pqueue3</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<hr> + +<h1>Module pqueue3</h1> +<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul> + <h3><a name="A_Large_Priority_Queue.">A Large Priority Queue.</a></h3> + This priority queue implementation depends on layered tuples, so that tuple + access times can be exploited for quick in/out priority queue operations + when using 64 or more total priorities. +<p>Copyright © 2011-2020 Michael Truog</p> + +<p><b>Version:</b> 2.0.1 Nov 26 2020 14:55:32 + ------------------------------------------------------------------------</p> +<p><b>Authors:</b> Michael Truog (<a href="mailto:mjtruog at protonmail dot com"><tt>mjtruog at protonmail dot com</tt></a>).</p> + +<h2><a name="description">Description</a></h2> + <h3><a name="A_Large_Priority_Queue.">A Large Priority Queue.</a></h3> + This priority queue implementation depends on layered tuples, so that tuple + access times can be exploited for quick in/out priority queue operations + when using 64 or more total priorities. This implementation was created + to avoid the slowness within the priority queue used by + both RabbitMQ and Riak + (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +<h2><a name="types">Data Types</a></h2> + +<h3 class="typedecl"><a name="type-pqueue3">pqueue3()</a></h3> +<p><tt>pqueue3() = {integer(), integer(), empty | integer(), tuple()}</tt></p> + + +<h3 class="typedecl"><a name="type-pqueue3_empty">pqueue3_empty()</a></h3> +<p><tt>pqueue3_empty() = {integer(), integer(), empty, tuple()}</tt></p> + + +<h2><a name="index">Function Index</a></h2> +<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#in-2">in/2</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#in-3">in/3</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_empty-1">is_empty/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_queue-1">is_queue/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#len-1">len/1</a></td><td> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#new-0">new/0</a></td><td> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#new-1">new/1</a></td><td> + <h4><a name="Create_a_new_priority_queue_with_customization_options.">Create a new priority queue with customization options.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#out-1">out/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#out-2">out/2</a></td><td> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#pout-1">pout/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value.</td></tr> +<tr><td valign="top"><a href="#to_list-1">to_list/1</a></td><td> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N).</td></tr> +</table> + +<h2><a name="functions">Function Details</a></h2> + +<h3 class="function"><a name="in-2">in/2</a></h3> +<div class="spec"> +<p><tt>in(Value::term(), Q::<a href="#type-pqueue3">pqueue3()</a>) -> <a href="#type-pqueue3">pqueue3()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="in-3">in/3</a></h3> +<div class="spec"> +<p><tt>in(Value::term(), P::integer(), X3::<a href="#type-pqueue3">pqueue3()</a>) -> <a href="#type-pqueue3">pqueue3()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_empty-1">is_empty/1</a></h3> +<div class="spec"> +<p><tt>is_empty(Q::<a href="#type-pqueue3">pqueue3()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_queue-1">is_queue/1</a></h3> +<div class="spec"> +<p><tt>is_queue(X1::<a href="#type-pqueue3">pqueue3()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1)</p> + +<h3 class="function"><a name="len-1">len/1</a></h3> +<div class="spec"> +<p><tt>len(Q::<a href="#type-pqueue3">pqueue3()</a>) -> non_neg_integer()</tt><br></p> +</div><p> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(N)</p> + +<h3 class="function"><a name="new-0">new/0</a></h3> +<div class="spec"> +<p><tt>new() -> <a href="#type-pqueue3_empty">pqueue3_empty()</a></tt><br></p> +</div><p> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="new-1">new/1</a></h3> +<div class="spec"> +<p><tt>new(Options::[{atom(), term()}]) -> <a href="#type-pqueue3">pqueue3()</a></tt><br></p> +</div><p> + <h4><a name="Create_a_new_priority_queue_with_customization_options.">Create a new priority queue with customization options.</a></h4> + O(1)</p> + +<h3 class="function"><a name="out-1">out/1</a></h3> +<div class="spec"> +<p><tt>out(Q::<a href="#type-pqueue3">pqueue3()</a>) -> {{value, term()}, <a href="#type-pqueue3">pqueue3()</a>} | {empty, <a href="#type-pqueue3">pqueue3()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="out-2">out/2</a></h3> +<div class="spec"> +<p><tt>out(P::integer(), Q::<a href="#type-pqueue3">pqueue3()</a>) -> {{value, term()}, <a href="#type-pqueue3">pqueue3()</a>} | {empty, <a href="#type-pqueue3">pqueue3()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="pout-1">pout/1</a></h3> +<div class="spec"> +<p><tt>pout(Q::<a href="#type-pqueue3">pqueue3()</a>) -> {{value, term(), integer()}, <a href="#type-pqueue3">pqueue3()</a>} | {empty, <a href="#type-pqueue3">pqueue3()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value. + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="to_list-1">to_list/1</a></h3> +<div class="spec"> +<p><tt>to_list(Q::<a href="#type-pqueue3">pqueue3()</a>) -> [term()]</tt><br></p> +</div><p> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N)</p> +<hr> + +<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<p><i>Generated by EDoc</i></p> +</body> +</html> diff --git a/aoc2023/build/dev/erlang/pqueue/doc/pqueue4.html b/aoc2023/build/dev/erlang/pqueue/doc/pqueue4.html new file mode 100644 index 0000000..edcdb6e --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/doc/pqueue4.html @@ -0,0 +1,205 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Module pqueue4</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<hr> + +<h1>Module pqueue4</h1> +<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul> + <h3><a name="Static_Priority_Queue.">Static Priority Queue.</a></h3> + This priority queue implementation depends on a static number of priorities + (-128 (high) to 128 (low)) so that tuple access times can be exploited for + quick in/out priority queue operations. +<p>Copyright © 2011-2020 Michael Truog</p> + +<p><b>Version:</b> 2.0.1 Nov 26 2020 14:55:34 + ------------------------------------------------------------------------</p> +<p><b>Authors:</b> Michael Truog (<a href="mailto:mjtruog at protonmail dot com"><tt>mjtruog at protonmail dot com</tt></a>).</p> + +<h2><a name="description">Description</a></h2> + <h3><a name="Static_Priority_Queue.">Static Priority Queue.</a></h3> + This priority queue implementation depends on a static number of priorities + (-128 (high) to 128 (low)) so that tuple access times can be exploited for + quick in/out priority queue operations. This implementation was created to + avoid the slowness within the priority queue used by both RabbitMQ and Riak + (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +<h2><a name="types">Data Types</a></h2> + +<h3 class="typedecl"><a name="type-pqueue4">pqueue4()</a></h3> +<p><tt>pqueue4() = <a href="#type-pqueue4">pqueue4</a>(any())</tt></p> + + +<h3 class="typedecl"><a name="type-pqueue4">pqueue4()</a></h3> +<p><tt>pqueue4(T) = {<a href="#type-priority">priority()</a> | empty, non_neg_integer(), {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, <a href="queue.html#type-queue">queue:queue</a>(T), {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}}</tt></p> + + +<h3 class="typedecl"><a name="type-priority">priority()</a></h3> +<p><tt>priority() = -128..128</tt></p> + + +<h2><a name="index">Function Index</a></h2> +<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#filter-2">filter/2</a></td><td> + <h4><a name="Filter_the_priority_queue.">Filter the priority queue.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#filter-3">filter/3</a></td><td> + <h4><a name="Filter_a_specific_priority_within_the_priority_queue.">Filter a specific priority within the priority queue.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#in-2">in/2</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#in-3">in/3</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_empty-1">is_empty/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_queue-1">is_queue/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#len-1">len/1</a></td><td> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#new-0">new/0</a></td><td> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#out-1">out/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#out-2">out/2</a></td><td> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#pout-1">pout/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value.</td></tr> +<tr><td valign="top"><a href="#remove_unique-2">remove_unique/2</a></td><td> + <h4><a name="Remove_a_unique_value_from_the_priority_queue_with_a_binary_predicate.">Remove a unique value from the priority queue with a binary predicate.</a></h4> + O(N) but smaller constant than filter/2.</td></tr> +<tr><td valign="top"><a href="#remove_unique-3">remove_unique/3</a></td><td> + <h4><a name="Remove_a_unique_value_in_a_specific_priority_within_the_priority_queue_with_a_binary_predicate.">Remove a unique value in a specific priority within the priority queue with a binary predicate.</a></h4> + O(N) but smaller constant than filter/3.</td></tr> +<tr><td valign="top"><a href="#to_list-1">to_list/1</a></td><td> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#to_plist-1">to_plist/1</a></td><td> + <h4><a name="Convert_the_priority_queue_to_a_list_with_priorities.">Convert the priority queue to a list with priorities.</a></h4> + O(N).</td></tr> +</table> + +<h2><a name="functions">Function Details</a></h2> + +<h3 class="function"><a name="filter-2">filter/2</a></h3> +<div class="spec"> +<p><tt>filter(F::fun((any()) -> boolean()), Q::<a href="#type-pqueue4">pqueue4()</a>) -> <a href="#type-pqueue4">pqueue4()</a></tt><br></p> +</div><p> + <h4><a name="Filter_the_priority_queue.">Filter the priority queue.</a></h4> + O(N)</p> + +<h3 class="function"><a name="filter-3">filter/3</a></h3> +<div class="spec"> +<p><tt>filter(F::fun((any()) -> boolean()), P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -> <a href="#type-pqueue4">pqueue4()</a></tt><br></p> +</div><p> + <h4><a name="Filter_a_specific_priority_within_the_priority_queue.">Filter a specific priority within the priority queue.</a></h4> + O(N)</p> + +<h3 class="function"><a name="in-2">in/2</a></h3> +<div class="spec"> +<p><tt>in(X::any(), Q::<a href="#type-pqueue4">pqueue4()</a>) -> <a href="#type-pqueue4">pqueue4()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="in-3">in/3</a></h3> +<div class="spec"> +<p><tt>in(X::any(), P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -> <a href="#type-pqueue4">pqueue4()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_empty-1">is_empty/1</a></h3> +<div class="spec"> +<p><tt>is_empty(X1::<a href="#type-pqueue4">pqueue4()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_queue-1">is_queue/1</a></h3> +<div class="spec"> +<p><tt>is_queue(X1::<a href="#type-pqueue4">pqueue4()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1)</p> + +<h3 class="function"><a name="len-1">len/1</a></h3> +<div class="spec"> +<p><tt>len(X1::<a href="#type-pqueue4">pqueue4()</a>) -> non_neg_integer()</tt><br></p> +</div><p> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="new-0">new/0</a></h3> +<div class="spec"> +<p><tt>new() -> <a href="#type-pqueue4">pqueue4()</a></tt><br></p> +</div><p> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="out-1">out/1</a></h3> +<div class="spec"> +<p><tt>out(Q::<a href="#type-pqueue4">pqueue4()</a>) -> {{value, any()}, <a href="#type-pqueue4">pqueue4()</a>} | {empty, <a href="#type-pqueue4">pqueue4()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="out-2">out/2</a></h3> +<div class="spec"> +<p><tt>out(P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -> {{value, any()}, <a href="#type-pqueue4">pqueue4()</a>} | {empty, <a href="#type-pqueue4">pqueue4()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="pout-1">pout/1</a></h3> +<div class="spec"> +<p><tt>pout(Q::<a href="#type-pqueue4">pqueue4()</a>) -> {{value, any(), integer()}, <a href="#type-pqueue4">pqueue4()</a>} | {empty, <a href="#type-pqueue4">pqueue4()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value. + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="remove_unique-2">remove_unique/2</a></h3> +<div class="spec"> +<p><tt>remove_unique(F::fun((any()) -> boolean()), Q::<a href="#type-pqueue4">pqueue4()</a>) -> {boolean(), <a href="#type-pqueue4">pqueue4()</a>}</tt><br></p> +</div><p> + <h4><a name="Remove_a_unique_value_from_the_priority_queue_with_a_binary_predicate.">Remove a unique value from the priority queue with a binary predicate.</a></h4> + O(N) but smaller constant than filter/2</p> + +<h3 class="function"><a name="remove_unique-3">remove_unique/3</a></h3> +<div class="spec"> +<p><tt>remove_unique(F::fun((any()) -> boolean()), P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -> {boolean(), <a href="#type-pqueue4">pqueue4()</a>}</tt><br></p> +</div><p> + <h4><a name="Remove_a_unique_value_in_a_specific_priority_within_the_priority_queue_with_a_binary_predicate.">Remove a unique value in a specific priority within the priority queue with a binary predicate.</a></h4> + O(N) but smaller constant than filter/3</p> + +<h3 class="function"><a name="to_list-1">to_list/1</a></h3> +<div class="spec"> +<p><tt>to_list(Q::<a href="#type-pqueue4">pqueue4()</a>) -> list()</tt><br></p> +</div><p> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N)</p> + +<h3 class="function"><a name="to_plist-1">to_plist/1</a></h3> +<div class="spec"> +<p><tt>to_plist(Q::<a href="#type-pqueue4">pqueue4()</a>) -> [{<a href="#type-priority">priority()</a>, list()}]</tt><br></p> +</div><p> + <h4><a name="Convert_the_priority_queue_to_a_list_with_priorities.">Convert the priority queue to a list with priorities.</a></h4> + O(N)</p> +<hr> + +<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<p><i>Generated by EDoc</i></p> +</body> +</html> diff --git a/aoc2023/build/dev/erlang/pqueue/doc/stylesheet.css b/aoc2023/build/dev/erlang/pqueue/doc/stylesheet.css new file mode 100644 index 0000000..ab170c0 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/doc/stylesheet.css @@ -0,0 +1,55 @@ +/* standard EDoc style sheet */ +body { + font-family: Verdana, Arial, Helvetica, sans-serif; + margin-left: .25in; + margin-right: .2in; + margin-top: 0.2in; + margin-bottom: 0.2in; + color: #000000; + background-color: #ffffff; +} +h1,h2 { + margin-left: -0.2in; +} +div.navbar { + background-color: #add8e6; + padding: 0.2em; +} +h2.indextitle { + padding: 0.4em; + background-color: #add8e6; +} +h3.function,h3.typedecl { + background-color: #add8e6; + padding-left: 1em; +} +div.spec { + margin-left: 2em; + background-color: #eeeeee; +} +a.module { + text-decoration:none +} +a.module:hover { + background-color: #eeeeee; +} +ul.definitions { + list-style-type: none; +} +ul.index { + list-style-type: none; + background-color: #eeeeee; +} + +/* + * Minor style tweaks + */ +ul { + list-style-type: square; +} +table { + border-collapse: collapse; +} +td { + padding: 3 +} diff --git a/aoc2023/build/dev/erlang/pqueue/ebin/pqueue.app b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue.app new file mode 100644 index 0000000..974098f --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue.app @@ -0,0 +1,6 @@ +{application,pqueue, + [{description,"Priority Queue Data Structures"}, + {vsn,"2.0.7"}, + {modules,[pqueue,pqueue2,pqueue3,pqueue4]}, + {registered,[]}, + {applications,[stdlib,kernel]}]}. diff --git a/aoc2023/build/dev/erlang/pqueue/ebin/pqueue.beam b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue.beam Binary files differnew file mode 100644 index 0000000..218d67e --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue.beam diff --git a/aoc2023/build/dev/erlang/pqueue/ebin/pqueue2.beam b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue2.beam Binary files differnew file mode 100644 index 0000000..597dc12 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue2.beam diff --git a/aoc2023/build/dev/erlang/pqueue/ebin/pqueue3.beam b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue3.beam Binary files differnew file mode 100644 index 0000000..ecf341a --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue3.beam diff --git a/aoc2023/build/dev/erlang/pqueue/ebin/pqueue4.beam b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue4.beam Binary files differnew file mode 100644 index 0000000..8e575fc --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue4.beam diff --git a/aoc2023/build/dev/erlang/pqueue/rebar.config b/aoc2023/build/dev/erlang/pqueue/rebar.config new file mode 100644 index 0000000..f8022f0 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/rebar.config @@ -0,0 +1,14 @@ +%-*-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: + +{erl_opts, + [{platform_define, "^R16", 'ERLANG_OTP_VERSION_16'}, + {platform_define, "^17\.", 'ERLANG_OTP_VERSION_17'}, + {platform_define, "^18\.", 'ERLANG_OTP_VERSION_18'}, + {platform_define, "^19\.", 'ERLANG_OTP_VERSION_19'}, + {platform_define, "^20\.", 'ERLANG_OTP_VERSION_20'}, + warn_export_vars, + warn_unused_import, + %warn_missing_spec, + warnings_as_errors]}. +{edoc_opts, [{preprocess, true}]}. diff --git a/aoc2023/build/dev/erlang/pqueue/src/pqueue.app.src b/aoc2023/build/dev/erlang/pqueue/src/pqueue.app.src new file mode 100644 index 0000000..b153ad1 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/src/pqueue.app.src @@ -0,0 +1,10 @@ +%-*-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: + +{application, pqueue, + [{description, "Priority Queue Data Structures"}, + {vsn, "2.0.7"}, + {modules, [pqueue, pqueue2, pqueue3, pqueue4]}, + {registered, []}, + {applications, [stdlib, kernel]}]}. + diff --git a/aoc2023/build/dev/erlang/pqueue/src/pqueue.erl b/aoc2023/build/dev/erlang/pqueue/src/pqueue.erl new file mode 100644 index 0000000..2c57fa2 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/src/pqueue.erl @@ -0,0 +1,2246 @@ +%-*-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 +%%% ==Static Priority Queue.== +%%% This priority queue implementation depends on a static number of priorities +%%% (-20 (high) to 20 (low)) so that tuple access times can be exploited for +%%% quick in/out priority queue operations. This implementation was created to +%%% avoid the slowness within the priority queue used by both RabbitMQ and Riak +%%% (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +%%% @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(pqueue). +-author('mjtruog at protonmail dot com'). + +%% external interface +-export([in/2, % O(1) + in/3, % O(1) + is_empty/1, % O(1) + is_queue/1, % O(1) + join/2, % O(N) typically (?) + len/1, % O(N) + new/0, % O(1) + out/1, % O(1) amortized, O(N) worst case + out/2, % O(1) amortized, O(N) worst case + pout/1, % O(1) amortized, O(N) worst case + to_list/1, % O(N) + test/0]). + +%%%------------------------------------------------------------------------ +%%% External interface functions +%%%------------------------------------------------------------------------ + +-ifdef(ERLANG_OTP_VERSION_16). +-type pqueue() :: + {integer(), + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue()}, + queue(), + {queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}} | + {'empty', + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue()}, + queue(), + {queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}}. +-else. +-type pqueue() :: + {integer(), + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue()}, + queue:queue(), + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}} | + {'empty', + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue()}, + queue:queue(), + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}}. +-endif. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of the 0 priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(term(), pqueue()) -> pqueue(). + +in(X, Q) -> + in(X, 0, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of a specific priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(term(), integer(), pqueue()) -> pqueue(). + +in(_, P, _) + when P < -20; P > 20 -> + erlang:exit(badarg); +in(X, P, {empty, _, _, _, _, _, _, _} = Q) -> + in_higher(P, Q, X); +in(X, P, {Pc, _, _, _, _, _, _, _} = Q) + when P < Pc -> + in_higher(P, Q, X); +in(X, P, Q) -> + in_lower(P, Q, X). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue is empty.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_empty(pqueue()) -> 'true' | 'false'. + +is_empty({empty, _, _, _, _, _, _, _}) -> + true; +is_empty({_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + queue:is_empty(Qn20) and queue:is_empty(Qn19) and queue:is_empty(Qn18) and + queue:is_empty(Qn17) and queue:is_empty(Qn16) and queue:is_empty(Qn15) and + queue:is_empty(Qn14) and + queue:is_empty(Qn13) and queue:is_empty(Qn12) and queue:is_empty(Qn11) and + queue:is_empty(Qn10) and queue:is_empty(Qn9) and queue:is_empty(Qn8) and + queue:is_empty(Qn7) and + queue:is_empty(Qn6) and queue:is_empty(Qn5) and queue:is_empty(Qn4) and + queue:is_empty(Qn3) and queue:is_empty(Qn2) and queue:is_empty(Qn1) and + queue:is_empty(Q0) and + queue:is_empty(Qp1) and queue:is_empty(Qp2) and queue:is_empty(Qp3) and + queue:is_empty(Qp4) and queue:is_empty(Qp5) and queue:is_empty(Qp6) and + queue:is_empty(Qp7) and queue:is_empty(Qp8) and queue:is_empty(Qp9) and + queue:is_empty(Qp10) and queue:is_empty(Qp11) and queue:is_empty(Qp12) and + queue:is_empty(Qp13) and + queue:is_empty(Qp14) and queue:is_empty(Qp15) and queue:is_empty(Qp16) and + queue:is_empty(Qp17) and queue:is_empty(Qp18) and queue:is_empty(Qp19) and + queue:is_empty(Qp20). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue type is as expected.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_queue(pqueue()) -> 'true' | 'false'. + +is_queue({Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) + when tuple_size(Qsn14) == 7, tuple_size(Qsn7) == 7, tuple_size(Qsn1) == 6, + tuple_size(Qsp14) == 7, tuple_size(Qsp7) == 7, tuple_size(Qsp1) == 6 -> + (((Pc =:= empty) or is_integer(Pc)) and queue:is_queue(Q0)); +is_queue(_) -> + false. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Join two priority queues.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec join(pqueue(), pqueue()) -> pqueue(). + +join({P1c, + {Q1_n20, Q1_n19, Q1_n18, Q1_n17, Q1_n16, Q1_n15, Q1_n14}, + {Q1_n13, Q1_n12, Q1_n11, Q1_n10, Q1_n9, Q1_n8, Q1_n7}, + {Q1_n6, Q1_n5, Q1_n4, Q1_n3, Q1_n2, Q1_n1}, + Q1_0, + {Q1_p1, Q1_p2, Q1_p3, Q1_p4, Q1_p5, Q1_p6}, + {Q1_p7, Q1_p8, Q1_p9, Q1_p10, Q1_p11, Q1_p12, Q1_p13}, + {Q1_p14, Q1_p15, Q1_p16, Q1_p17, Q1_p18, Q1_p19, Q1_p20}}, + {P2c, + {Q2_n20, Q2_n19, Q2_n18, Q2_n17, Q2_n16, Q2_n15, Q2_n14}, + {Q2_n13, Q2_n12, Q2_n11, Q2_n10, Q2_n9, Q2_n8, Q2_n7}, + {Q2_n6, Q2_n5, Q2_n4, Q2_n3, Q2_n2, Q2_n1}, + Q2_0, + {Q2_p1, Q2_p2, Q2_p3, Q2_p4, Q2_p5, Q2_p6}, + {Q2_p7, Q2_p8, Q2_p9, Q2_p10, Q2_p11, Q2_p12, Q2_p13}, + {Q2_p14, Q2_p15, Q2_p16, Q2_p17, Q2_p18, Q2_p19, Q2_p20}}) -> + {erlang:min(P1c, P2c), + {queue:join(Q1_n20, Q2_n20), queue:join(Q1_n19, Q2_n19), + queue:join(Q1_n18, Q2_n18), queue:join(Q1_n17, Q2_n17), + queue:join(Q1_n16, Q2_n16), queue:join(Q1_n15, Q2_n15), + queue:join(Q1_n14, Q2_n14)}, + {queue:join(Q1_n13, Q2_n13), queue:join(Q1_n12, Q2_n12), + queue:join(Q1_n11, Q2_n11), queue:join(Q1_n10, Q2_n10), + queue:join(Q1_n9, Q2_n9), queue:join(Q1_n8, Q2_n8), + queue:join(Q1_n7, Q2_n7)}, + {queue:join(Q1_n6, Q2_n6), queue:join(Q1_n5, Q2_n5), + queue:join(Q1_n4, Q2_n4), queue:join(Q1_n3, Q2_n3), + queue:join(Q1_n2, Q2_n2), queue:join(Q1_n1, Q2_n1)}, + queue:join(Q1_0, Q2_0), + {queue:join(Q1_p1, Q2_p1), queue:join(Q1_p2, Q2_p2), + queue:join(Q1_p3, Q2_p3), queue:join(Q1_p4, Q2_p4), + queue:join(Q1_p5, Q2_p5), queue:join(Q1_p6, Q2_p6)}, + {queue:join(Q1_p7, Q2_p7), queue:join(Q1_p8, Q2_p8), + queue:join(Q1_p9, Q2_p9), queue:join(Q1_p10, Q2_p10), + queue:join(Q1_p11, Q2_p11), queue:join(Q1_p12, Q2_p12), + queue:join(Q1_p13, Q2_p13)}, + {queue:join(Q1_p14, Q2_p14), queue:join(Q1_p15, Q2_p15), + queue:join(Q1_p16, Q2_p16), queue:join(Q1_p17, Q2_p17), + queue:join(Q1_p18, Q2_p18), queue:join(Q1_p19, Q2_p19), + queue:join(Q1_p20, Q2_p20)}}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Determine the length of a priority queue.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec len(pqueue()) -> non_neg_integer(). + +len({_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + queue:len(Qn20) + queue:len(Qn19) + queue:len(Qn18) + queue:len(Qn17) + + queue:len(Qn16) + queue:len(Qn15) + queue:len(Qn14) + + queue:len(Qn13) + queue:len(Qn12) + queue:len(Qn11) + queue:len(Qn10) + + queue:len(Qn9) + queue:len(Qn8) + queue:len(Qn7) + + queue:len(Qn6) + queue:len(Qn5) + queue:len(Qn4) + queue:len(Qn3) + + queue:len(Qn2) + queue:len(Qn1) + + queue:len(Q0) + + queue:len(Qp1) + queue:len(Qp2) + queue:len(Qp3) + queue:len(Qp4) + + queue:len(Qp5) + queue:len(Qp6) + + queue:len(Qp7) + queue:len(Qp8) + queue:len(Qp9) + queue:len(Qp10) + + queue:len(Qp11) + queue:len(Qp12) + queue:len(Qp13) + + queue:len(Qp14) + queue:len(Qp15) + queue:len(Qp16) + queue:len(Qp17) + + queue:len(Qp18) + queue:len(Qp19) + queue:len(Qp20). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Create a new priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec new() -> pqueue(). + +new() -> + {empty, % current priority + erlang:make_tuple(7, queue:new()), % priority [-20..-14] + erlang:make_tuple(7, queue:new()), % priority [-13.. -7] + erlang:make_tuple(6, queue:new()), % priority [ -6.. -1] + queue:new(), % priority 0 (default) + erlang:make_tuple(6, queue:new()), % priority [ 1.. 6] + erlang:make_tuple(7, queue:new()), % priority [ 7.. 13] + erlang:make_tuple(7, queue:new())}. % priority [ 14.. 20] + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(pqueue()) -> + {{'value', term()}, pqueue()} | {'empty', pqueue()}. + +out({empty, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +out({Pc, _, _, _, _, _, _, _} = Q) -> + out_current(Pc, Q, nopriority). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item of a specific priority from the head of the queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(integer(), pqueue()) -> + {{'value', term()}, pqueue()} | {'empty', pqueue()}. + +out(P, _) + when P < -20; P > 20 -> + erlang:exit(badarg); +out(_, {empty, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +out(P, Q) -> + out_specific(P, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% Includes the priority in the return value. +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec pout(pqueue()) -> + {{'value', term(), integer()}, pqueue()} | {'empty', pqueue()}. + +pout({empty, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +pout({Pc, _, _, _, _, _, _, _} = Q) -> + out_current(Pc, Q, priority). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Convert the priority queue to a list.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec to_list(pqueue()) -> list(term()). + +to_list({_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + queue:to_list(Qn20) ++ queue:to_list(Qn19) ++ queue:to_list(Qn18) ++ + queue:to_list(Qn17) ++ queue:to_list(Qn16) ++ queue:to_list(Qn15) ++ + queue:to_list(Qn14) ++ + queue:to_list(Qn13) ++ queue:to_list(Qn12) ++ queue:to_list(Qn11) ++ + queue:to_list(Qn10) ++ queue:to_list(Qn9) ++ queue:to_list(Qn8) ++ + queue:to_list(Qn7) ++ + queue:to_list(Qn6) ++ queue:to_list(Qn5) ++ queue:to_list(Qn4) ++ + queue:to_list(Qn3) ++ queue:to_list(Qn2) ++ queue:to_list(Qn1) ++ + queue:to_list(Q0) ++ + queue:to_list(Qp1) ++ queue:to_list(Qp2) ++ queue:to_list(Qp3) ++ + queue:to_list(Qp4) ++ queue:to_list(Qp5) ++ queue:to_list(Qp6) ++ + queue:to_list(Qp7) ++ queue:to_list(Qp8) ++ queue:to_list(Qp9) ++ + queue:to_list(Qp10) ++ queue:to_list(Qp11) ++ queue:to_list(Qp12) ++ + queue:to_list(Qp13) ++ + queue:to_list(Qp14) ++ queue:to_list(Qp15) ++ queue:to_list(Qp16) ++ + queue:to_list(Qp17) ++ queue:to_list(Qp18) ++ queue:to_list(Qp19) ++ + queue:to_list(Qp20). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Regression test.=== +%% @end +%%------------------------------------------------------------------------- + +test() -> + Q0 = pqueue:new(), + true = pqueue:is_queue(Q0), + Q1 = pqueue:in(20, 20, Q0), + Q2 = pqueue:in(19, 19, Q1), + Q3 = pqueue:in(18, 18, Q2), + Q4 = pqueue:in(17, 17, Q3), + Q5 = pqueue:in(16, 16, Q4), + Q6 = pqueue:in(15, 15, Q5), + Q7 = pqueue:in(14, 14, Q6), + Q8 = pqueue:in(13, 13, Q7), + Q9 = pqueue:in(12, 12, Q8), + Q10 = pqueue:in(11, 11, Q9), + Q11 = pqueue:in(10, 10, Q10), + Q12 = pqueue:in(9, 9, Q11), + Q13 = pqueue:in(8, 8, Q12), + Q14 = pqueue:in(7, 7, Q13), + Q15 = pqueue:in(6, 6, Q14), + Q16 = pqueue:in(5, 5, Q15), + Q17 = pqueue:in(4, 4, Q16), + Q18 = pqueue:in(3, 3, Q17), + Q19 = pqueue:in(2, 2, Q18), + Q20 = pqueue:in(1, 1, Q19), + Q21 = pqueue:in(0, 0, Q20), + Q22 = pqueue:in(-1, -1, Q21), + Q23 = pqueue:in(-2, -2, Q22), + Q24 = pqueue:in(-3, -3, Q23), + Q25 = pqueue:in(-4, -4, Q24), + Q26 = pqueue:in(-5, -5, Q25), + Q27 = pqueue:in(-6, -6, Q26), + Q28 = pqueue:in(-7, -7, Q27), + Q29 = pqueue:in(-8, -8, Q28), + Q30 = pqueue:in(-9, -9, Q29), + Q31 = pqueue:in(-10, -10, Q30), + Q32 = pqueue:in(-11, -11, Q31), + Q33 = pqueue:in(-12, -12, Q32), + Q34 = pqueue:in(-13, -13, Q33), + Q35 = pqueue:in(-14, -14, Q34), + Q36 = pqueue:in(-15, -15, Q35), + Q37 = pqueue:in(-16, -16, Q36), + Q38 = pqueue:in(-17, -17, Q37), + Q39 = pqueue:in(-18, -18, Q38), + Q40 = pqueue:in(-19, -19, Q39), + Q41 = pqueue:in(-20, -20, Q40), + Q42 = pqueue:in(-20, -20, Q41), + Q43 = pqueue:in(-19, -19, Q42), + Q44 = pqueue:in(-18, -18, Q43), + Q45 = pqueue:in(-17, -17, Q44), + Q46 = pqueue:in(-16, -16, Q45), + Q47 = pqueue:in(-15, -15, Q46), + Q48 = pqueue:in(-14, -14, Q47), + Q49 = pqueue:in(-13, -13, Q48), + Q50 = pqueue:in(-12, -12, Q49), + Q51 = pqueue:in(-11, -11, Q50), + Q52 = pqueue:in(-10, -10, Q51), + Q53 = pqueue:in(-9, -9, Q52), + Q54 = pqueue:in(-8, -8, Q53), + Q55 = pqueue:in(-7, -7, Q54), + Q56 = pqueue:in(-6, -6, Q55), + Q57 = pqueue:in(-5, -5, Q56), + Q58 = pqueue:in(-4, -4, Q57), + Q59 = pqueue:in(-3, -3, Q58), + Q60 = pqueue:in(-2, -2, Q59), + Q61 = pqueue:in(-1, -1, Q60), + Q62 = pqueue:in(0, 0, Q61), + Q63 = pqueue:in(1, 1, Q62), + Q64 = pqueue:in(2, 2, Q63), + Q65 = pqueue:in(3, 3, Q64), + Q66 = pqueue:in(4, 4, Q65), + Q67 = pqueue:in(5, 5, Q66), + Q68 = pqueue:in(6, 6, Q67), + Q69 = pqueue:in(7, 7, Q68), + Q70 = pqueue:in(8, 8, Q69), + Q71 = pqueue:in(9, 9, Q70), + Q72 = pqueue:in(10, 10, Q71), + Q73 = pqueue:in(11, 11, Q72), + Q74 = pqueue:in(12, 12, Q73), + Q75 = pqueue:in(13, 13, Q74), + Q76 = pqueue:in(14, 14, Q75), + Q77 = pqueue:in(15, 15, Q76), + Q78 = pqueue:in(16, 16, Q77), + Q79 = pqueue:in(17, 17, Q78), + Q80 = pqueue:in(18, 18, Q79), + Q81 = pqueue:in(19, 19, Q80), + Q82 = pqueue:in(20, 20, Q81), + true = pqueue:is_queue(Q82), + 82 = pqueue: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] = pqueue:to_list(Q82), + {{value, -20}, Q83} = pqueue:out(Q82), + {{value, -20}, Q84} = pqueue:out(Q83), + {{value, -19}, Q85} = pqueue:out(Q84), + {{value, -19}, Q86} = pqueue:out(Q85), + {{value, -18}, Q87} = pqueue:out(Q86), + {{value, -18}, Q88} = pqueue:out(Q87), + {{value, 0}, Q89} = pqueue:out(0, Q88), + {{value, 0}, Q90} = pqueue:out(0, Q89), + {empty, _} = pqueue:out(0, Q90), + {{value, -17, -17}, Q91} = pqueue:pout(Q90), + {{value, -17, -17}, Q92} = pqueue:pout(Q91), + {{value, -16, -16}, Q93} = pqueue:pout(Q92), + {{value, -16, -16}, Q94} = pqueue:pout(Q93), + {{value, -15, -15}, Q95} = pqueue:pout(Q94), + {{value, -15, -15}, Q96} = pqueue:pout(Q95), + {{value, -14, -14}, Q97} = pqueue:pout(Q96), + {{value, -14, -14}, Q98} = pqueue:pout(Q97), + {{value, -13, -13}, Q99} = pqueue:pout(Q98), + {{value, -13, -13}, Q100} = pqueue:pout(Q99), + {{value, -12, -12}, Q101} = pqueue:pout(Q100), + {{value, -12, -12}, Q102} = pqueue:pout(Q101), + {{value, -11, -11}, Q103} = pqueue:pout(Q102), + {{value, -11, -11}, Q104} = pqueue:pout(Q103), + {{value, -10, -10}, Q105} = pqueue:pout(Q104), + {{value, -10, -10}, Q106} = pqueue:pout(Q105), + {{value, -9, -9}, Q107} = pqueue:pout(Q106), + {{value, -9, -9}, Q108} = pqueue:pout(Q107), + {{value, -8, -8}, Q109} = pqueue:pout(Q108), + {{value, -8, -8}, Q110} = pqueue:pout(Q109), + {{value, -7, -7}, Q111} = pqueue:pout(Q110), + {{value, -7, -7}, Q112} = pqueue:pout(Q111), + {{value, -6, -6}, Q113} = pqueue:pout(Q112), + {{value, -6, -6}, Q114} = pqueue:pout(Q113), + {{value, -5, -5}, Q115} = pqueue:pout(Q114), + {{value, -5, -5}, Q116} = pqueue:pout(Q115), + {{value, -4, -4}, Q117} = pqueue:pout(Q116), + {{value, -4, -4}, Q118} = pqueue:pout(Q117), + {{value, -3, -3}, Q119} = pqueue:pout(Q118), + {{value, -3, -3}, Q120} = pqueue:pout(Q119), + {{value, -2, -2}, Q121} = pqueue:pout(Q120), + {{value, -2, -2}, Q122} = pqueue:pout(Q121), + {{value, -1, -1}, Q123} = pqueue:pout(Q122), + {{value, -1, -1}, Q124} = pqueue:pout(Q123), + {{value, 1, 1}, Q125} = pqueue:pout(Q124), + {{value, 1, 1}, Q126} = pqueue:pout(Q125), + {{value, 2, 2}, Q127} = pqueue:pout(Q126), + {{value, 2, 2}, Q128} = pqueue:pout(Q127), + {{value, 3, 3}, Q129} = pqueue:pout(Q128), + {{value, 3, 3}, Q130} = pqueue:pout(Q129), + {{value, 4, 4}, Q131} = pqueue:pout(Q130), + {{value, 4, 4}, Q132} = pqueue:pout(Q131), + {{value, 5, 5}, Q133} = pqueue:pout(Q132), + {{value, 5, 5}, Q134} = pqueue:pout(Q133), + {{value, 6, 6}, Q135} = pqueue:pout(Q134), + {{value, 6, 6}, Q136} = pqueue:pout(Q135), + {{value, 7, 7}, Q137} = pqueue:pout(Q136), + {{value, 7, 7}, Q138} = pqueue:pout(Q137), + {{value, 8, 8}, Q139} = pqueue:pout(Q138), + {{value, 8, 8}, Q140} = pqueue:pout(Q139), + {{value, 9, 9}, Q141} = pqueue:pout(Q140), + {{value, 9, 9}, Q142} = pqueue:pout(Q141), + {{value, 10, 10}, Q143} = pqueue:pout(Q142), + {{value, 10, 10}, Q144} = pqueue:pout(Q143), + {{value, 11, 11}, Q145} = pqueue:pout(Q144), + {{value, 11, 11}, Q146} = pqueue:pout(Q145), + {{value, 12, 12}, Q147} = pqueue:pout(Q146), + {{value, 12, 12}, Q148} = pqueue:pout(Q147), + {{value, 13, 13}, Q149} = pqueue:pout(Q148), + {{value, 13, 13}, Q150} = pqueue:pout(Q149), + {{value, 14, 14}, Q151} = pqueue:pout(Q150), + {{value, 14, 14}, Q152} = pqueue:pout(Q151), + {{value, 15, 15}, Q153} = pqueue:pout(Q152), + {{value, 15, 15}, Q154} = pqueue:pout(Q153), + {{value, 16, 16}, Q155} = pqueue:pout(Q154), + {{value, 16, 16}, Q156} = pqueue:pout(Q155), + {{value, 17, 17}, Q157} = pqueue:pout(Q156), + {{value, 17, 17}, Q158} = pqueue:pout(Q157), + {{value, 18, 18}, Q159} = pqueue:pout(Q158), + {{value, 18, 18}, Q160} = pqueue:pout(Q159), + {{value, 19, 19}, Q161} = pqueue:pout(Q160), + {{value, 19, 19}, Q162} = pqueue:pout(Q161), + {{value, 20, 20}, Q163} = pqueue:pout(Q162), + {{value, 20, 20}, Q164} = pqueue:pout(Q163), + true = pqueue:is_empty(Q164), + {empty, Q165} = pqueue:pout(Q164), + true = pqueue:is_empty(Q165), + ok. + +%%%------------------------------------------------------------------------ +%%% Private functions +%%%------------------------------------------------------------------------ + +in_higher(-20, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-20, + {queue:in(X, Qn20), Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-19, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-19, + {Qn20, queue:in(X, Qn19), Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-18, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-18, + {Qn20, Qn19, queue:in(X, Qn18), Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-17, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-17, + {Qn20, Qn19, Qn18, queue:in(X, Qn17), Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-16, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-16, + {Qn20, Qn19, Qn18, Qn17, queue:in(X, Qn16), Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-15, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-15, + {Qn20, Qn19, Qn18, Qn17, Qn16, queue:in(X, Qn15), Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-14, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-14, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, queue:in(X, Qn14)}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-13, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-13, Qsn14, + {queue:in(X, Qn13), Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-12, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-12, Qsn14, + {Qn13, queue:in(X, Qn12), Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-11, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-11, Qsn14, + {Qn13, Qn12, queue:in(X, Qn11), Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-10, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-10, Qsn14, + {Qn13, Qn12, Qn11, queue:in(X, Qn10), Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-9, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-9, Qsn14, + {Qn13, Qn12, Qn11, Qn10, queue:in(X, Qn9), Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-8, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-8, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, queue:in(X, Qn8), Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-7, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-7, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, queue:in(X, Qn7)}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-6, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-6, Qsn14, Qsn7, + {queue:in(X, Qn6), Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-5, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-5, Qsn14, Qsn7, + {Qn6, queue:in(X, Qn5), Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-4, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-4, Qsn14, Qsn7, + {Qn6, Qn5, queue:in(X, Qn4), Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-3, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-3, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, queue:in(X, Qn3), Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-2, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-2, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, queue:in(X, Qn2), Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-1, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-1, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, queue:in(X, Qn1)}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(0, {_, Qsn14, Qsn7, Qsn1, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {0, Qsn14, Qsn7, Qsn1, + queue:in(X, Q0), + Qsp1, Qsp7, Qsp14}; +in_higher(1, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {1, Qsn14, Qsn7, Qsn1, Q0, + {queue:in(X, Qp1), Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_higher(2, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {2, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, queue:in(X, Qp2), Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_higher(3, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {3, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, queue:in(X, Qp3), Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_higher(4, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {4, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, queue:in(X, Qp4), Qp5, Qp6}, + Qsp7, Qsp14}; +in_higher(5, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {5, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, queue:in(X, Qp5), Qp6}, + Qsp7, Qsp14}; +in_higher(6, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {6, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, queue:in(X, Qp6)}, + Qsp7, Qsp14}; +in_higher(7, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {7, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {queue:in(X, Qp7), Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_higher(8, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {8, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, queue:in(X, Qp8), Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_higher(9, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {9, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, queue:in(X, Qp9), Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_higher(10, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {10, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, queue:in(X, Qp10), Qp11, Qp12, Qp13}, + Qsp14}; +in_higher(11, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {11, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, queue:in(X, Qp11), Qp12, Qp13}, + Qsp14}; +in_higher(12, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {12, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, queue:in(X, Qp12), Qp13}, + Qsp14}; +in_higher(13, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {13, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, queue:in(X, Qp13)}, + Qsp14}; +in_higher(14, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {14, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {queue:in(X, Qp14), Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}; +in_higher(15, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {15, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, queue:in(X, Qp15), Qp16, Qp17, Qp18, Qp19, Qp20}}; +in_higher(16, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {16, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, queue:in(X, Qp16), Qp17, Qp18, Qp19, Qp20}}; +in_higher(17, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {17, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, queue:in(X, Qp17), Qp18, Qp19, Qp20}}; +in_higher(18, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {18, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, queue:in(X, Qp18), Qp19, Qp20}}; +in_higher(19, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {19, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, queue:in(X, Qp19), Qp20}}; +in_higher(20, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {20, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, queue:in(X, Qp20)}}. + +in_lower(-20, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {queue:in(X, Qn20), Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-19, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, queue:in(X, Qn19), Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-18, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, Qn19, queue:in(X, Qn18), Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-17, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, Qn19, Qn18, queue:in(X, Qn17), Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-16, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, Qn19, Qn18, Qn17, queue:in(X, Qn16), Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-15, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, queue:in(X, Qn15), Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-14, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, queue:in(X, Qn14)}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-13, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {queue:in(X, Qn13), Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-12, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, queue:in(X, Qn12), Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-11, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, Qn12, queue:in(X, Qn11), Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-10, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, Qn12, Qn11, queue:in(X, Qn10), Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-9, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, queue:in(X, Qn9), Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-8, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, queue:in(X, Qn8), Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-7, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, queue:in(X, Qn7)}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-6, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {queue:in(X, Qn6), Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-5, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {Qn6, queue:in(X, Qn5), Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-4, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, queue:in(X, Qn4), Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-3, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, queue:in(X, Qn3), Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-2, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, queue:in(X, Qn2), Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-1, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, queue:in(X, Qn1)}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(0, {Pc, Qsn14, Qsn7, Qsn1, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, + queue:in(X, Q0), + Qsp1, Qsp7, Qsp14}; +in_lower(1, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {queue:in(X, Qp1), Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_lower(2, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, queue:in(X, Qp2), Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_lower(3, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, queue:in(X, Qp3), Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_lower(4, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, queue:in(X, Qp4), Qp5, Qp6}, + Qsp7, Qsp14}; +in_lower(5, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, queue:in(X, Qp5), Qp6}, + Qsp7, Qsp14}; +in_lower(6, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, queue:in(X, Qp6)}, + Qsp7, Qsp14}; +in_lower(7, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {queue:in(X, Qp7), Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_lower(8, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, queue:in(X, Qp8), Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_lower(9, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, queue:in(X, Qp9), Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_lower(10, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, queue:in(X, Qp10), Qp11, Qp12, Qp13}, + Qsp14}; +in_lower(11, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, queue:in(X, Qp11), Qp12, Qp13}, + Qsp14}; +in_lower(12, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, queue:in(X, Qp12), Qp13}, + Qsp14}; +in_lower(13, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, queue:in(X, Qp13)}, + Qsp14}; +in_lower(14, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {queue:in(X, Qp14), Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}; +in_lower(15, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, queue:in(X, Qp15), Qp16, Qp17, Qp18, Qp19, Qp20}}; +in_lower(16, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, queue:in(X, Qp16), Qp17, Qp18, Qp19, Qp20}}; +in_lower(17, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, queue:in(X, Qp17), Qp18, Qp19, Qp20}}; +in_lower(18, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, queue:in(X, Qp18), Qp19, Qp20}}; +in_lower(19, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, queue:in(X, Qp19), Qp20}}; +in_lower(20, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, queue:in(X, Qp20)}}. + +out_current(-20, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn20} = queue:out(Qn20), + if + Value =:= empty -> + out_current(-19, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -20}; + true -> + Value + end, + {NewValue, + {-20, + {NewQn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-19, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn19} = queue:out(Qn19), + if + Value =:= empty -> + out_current(-18, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -19}; + true -> + Value + end, + {NewValue, + {-19, + {Qn20, NewQn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-18, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn18} = queue:out(Qn18), + if + Value =:= empty -> + out_current(-17, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -18}; + true -> + Value + end, + {NewValue, + {-18, + {Qn20, Qn19, NewQn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-17, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn17} = queue:out(Qn17), + if + Value =:= empty -> + out_current(-16, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -17}; + true -> + Value + end, + {NewValue, + {-17, + {Qn20, Qn19, Qn18, NewQn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-16, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn16} = queue:out(Qn16), + if + Value =:= empty -> + out_current(-15, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -16}; + true -> + Value + end, + {NewValue, + {-16, + {Qn20, Qn19, Qn18, Qn17, NewQn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-15, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn15} = queue:out(Qn15), + if + Value =:= empty -> + out_current(-14, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -15}; + true -> + Value + end, + {NewValue, + {-15, + {Qn20, Qn19, Qn18, Qn17, Qn16, NewQn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-14, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn14} = queue:out(Qn14), + if + Value =:= empty -> + out_current(-13, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -14}; + true -> + Value + end, + {NewValue, + {-14, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, NewQn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-13, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn13} = queue:out(Qn13), + if + Value =:= empty -> + out_current(-12, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -13}; + true -> + Value + end, + {NewValue, + {-13, Qsn14, + {NewQn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-12, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn12} = queue:out(Qn12), + if + Value =:= empty -> + out_current(-11, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -12}; + true -> + Value + end, + {NewValue, + {-12, Qsn14, + {Qn13, NewQn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-11, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn11} = queue:out(Qn11), + if + Value =:= empty -> + out_current(-10, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -11}; + true -> + Value + end, + {NewValue, + {-11, Qsn14, + {Qn13, Qn12, NewQn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-10, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn10} = queue:out(Qn10), + if + Value =:= empty -> + out_current(-9, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -10}; + true -> + Value + end, + {NewValue, + {-10, Qsn14, + {Qn13, Qn12, Qn11, NewQn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-9, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn9} = queue:out(Qn9), + if + Value =:= empty -> + out_current(-8, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -9}; + true -> + Value + end, + {NewValue, + {-9, Qsn14, + {Qn13, Qn12, Qn11, Qn10, NewQn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-8, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn8} = queue:out(Qn8), + if + Value =:= empty -> + out_current(-7, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -8}; + true -> + Value + end, + {NewValue, + {-8, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, NewQn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-7, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn7} = queue:out(Qn7), + if + Value =:= empty -> + out_current(-6, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -7}; + true -> + Value + end, + {NewValue, + {-7, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, NewQn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-6, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn6} = queue:out(Qn6), + if + Value =:= empty -> + out_current(-5, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -6}; + true -> + Value + end, + {NewValue, + {-6, Qsn14, Qsn7, + {NewQn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-5, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn5} = queue:out(Qn5), + if + Value =:= empty -> + out_current(-4, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -5}; + true -> + Value + end, + {NewValue, + {-5, Qsn14, Qsn7, + {Qn6, NewQn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-4, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn4} = queue:out(Qn4), + if + Value =:= empty -> + out_current(-3, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -4}; + true -> + Value + end, + {NewValue, + {-4, Qsn14, Qsn7, + {Qn6, Qn5, NewQn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-3, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn3} = queue:out(Qn3), + if + Value =:= empty -> + out_current(-2, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -3}; + true -> + Value + end, + {NewValue, + {-3, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, NewQn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-2, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn2} = queue:out(Qn2), + if + Value =:= empty -> + out_current(-1, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -2}; + true -> + Value + end, + {NewValue, + {-2, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, NewQn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-1, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn1} = queue:out(Qn1), + if + Value =:= empty -> + out_current(0, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -1}; + true -> + Value + end, + {NewValue, + {-1, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, NewQn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(0, + {_, Qsn14, Qsn7, Qsn1, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQ0} = queue:out(Q0), + if + Value =:= empty -> + out_current(1, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 0}; + true -> + Value + end, + {NewValue, + {0, Qsn14, Qsn7, Qsn1, + NewQ0, + Qsp1, Qsp7, Qsp14}} + end; +out_current(1, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp1} = queue:out(Qp1), + if + Value =:= empty -> + out_current(2, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 1}; + true -> + Value + end, + {NewValue, + {1, Qsn14, Qsn7, Qsn1, Q0, + {NewQp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}} + end; +out_current(2, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp2} = queue:out(Qp2), + if + Value =:= empty -> + out_current(3, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 2}; + true -> + Value + end, + {NewValue, + {2, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, NewQp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}} + end; +out_current(3, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp3} = queue:out(Qp3), + if + Value =:= empty -> + out_current(4, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 3}; + true -> + Value + end, + {NewValue, + {3, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, NewQp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}} + end; +out_current(4, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp4} = queue:out(Qp4), + if + Value =:= empty -> + out_current(5, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 4}; + true -> + Value + end, + {NewValue, + {4, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, NewQp4, Qp5, Qp6}, + Qsp7, Qsp14}} + end; +out_current(5, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp5} = queue:out(Qp5), + if + Value =:= empty -> + out_current(6, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 5}; + true -> + Value + end, + {NewValue, + {5, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, NewQp5, Qp6}, + Qsp7, Qsp14}} + end; +out_current(6, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp6} = queue:out(Qp6), + if + Value =:= empty -> + out_current(7, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 6}; + true -> + Value + end, + {NewValue, + {6, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, NewQp6}, + Qsp7, Qsp14}} + end; +out_current(7, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp7} = queue:out(Qp7), + if + Value =:= empty -> + out_current(8, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 7}; + true -> + Value + end, + {NewValue, + {7, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {NewQp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}} + end; +out_current(8, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp8} = queue:out(Qp8), + if + Value =:= empty -> + out_current(9, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 8}; + true -> + Value + end, + {NewValue, + {8, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, NewQp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}} + end; +out_current(9, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp9} = queue:out(Qp9), + if + Value =:= empty -> + out_current(10, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 9}; + true -> + Value + end, + {NewValue, + {9, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, NewQp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}} + end; +out_current(10, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp10} = queue:out(Qp10), + if + Value =:= empty -> + out_current(11, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 10}; + true -> + Value + end, + {NewValue, + {10, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, NewQp10, Qp11, Qp12, Qp13}, + Qsp14}} + end; +out_current(11, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp11} = queue:out(Qp11), + if + Value =:= empty -> + out_current(12, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 11}; + true -> + Value + end, + {NewValue, + {11, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, NewQp11, Qp12, Qp13}, + Qsp14}} + end; +out_current(12, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp12} = queue:out(Qp12), + if + Value =:= empty -> + out_current(13, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 12}; + true -> + Value + end, + {NewValue, + {12, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, NewQp12, Qp13}, + Qsp14}} + end; +out_current(13, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp13} = queue:out(Qp13), + if + Value =:= empty -> + out_current(14, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 13}; + true -> + Value + end, + {NewValue, + {13, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, NewQp13}, + Qsp14}} + end; +out_current(14, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp14} = queue:out(Qp14), + if + Value =:= empty -> + out_current(15, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 14}; + true -> + Value + end, + {NewValue, + {14, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {NewQp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}} + end; +out_current(15, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp15} = queue:out(Qp15), + if + Value =:= empty -> + out_current(16, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 15}; + true -> + Value + end, + {NewValue, + {15, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, NewQp15, Qp16, Qp17, Qp18, Qp19, Qp20}}} + end; +out_current(16, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp16} = queue:out(Qp16), + if + Value =:= empty -> + out_current(17, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 16}; + true -> + Value + end, + {NewValue, + {16, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, NewQp16, Qp17, Qp18, Qp19, Qp20}}} + end; +out_current(17, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp17} = queue:out(Qp17), + if + Value =:= empty -> + out_current(18, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 17}; + true -> + Value + end, + {NewValue, + {17, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, NewQp17, Qp18, Qp19, Qp20}}} + end; +out_current(18, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp18} = queue:out(Qp18), + if + Value =:= empty -> + out_current(19, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 18}; + true -> + Value + end, + {NewValue, + {18, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, NewQp18, Qp19, Qp20}}} + end; +out_current(19, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp19} = queue:out(Qp19), + if + Value =:= empty -> + out_current(20, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 19}; + true -> + Value + end, + {NewValue, + {19, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, NewQp19, Qp20}}} + end; +out_current(20, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20} = Qsp14}, ReturnType) -> + {Value, NewQp20} = queue:out(Qp20), + if + Value =:= empty -> + {empty, {empty, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 20}; + true -> + Value + end, + {NewValue, + {20, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, NewQp20}}} + end. + +out_specific(-20, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn20} = queue:out(Qn20), + {Value, + {Pc, + {NewQn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-19, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn19} = queue:out(Qn19), + {Value, + {Pc, + {Qn20, NewQn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-18, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn18} = queue:out(Qn18), + {Value, + {Pc, + {Qn20, Qn19, NewQn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-17, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn17} = queue:out(Qn17), + {Value, + {Pc, + {Qn20, Qn19, Qn18, NewQn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-16, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn16} = queue:out(Qn16), + {Value, + {Pc, + {Qn20, Qn19, Qn18, Qn17, NewQn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-15, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn15} = queue:out(Qn15), + {Value, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, NewQn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-14, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn14} = queue:out(Qn14), + {Value, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, NewQn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-13, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn13} = queue:out(Qn13), + {Value, + {Pc, Qsn14, + {NewQn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-12, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn12} = queue:out(Qn12), + {Value, + {Pc, Qsn14, + {Qn13, NewQn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-11, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn11} = queue:out(Qn11), + {Value, + {Pc, Qsn14, + {Qn13, Qn12, NewQn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-10, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn10} = queue:out(Qn10), + {Value, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, NewQn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-9, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn9} = queue:out(Qn9), + {Value, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, NewQn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-8, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn8} = queue:out(Qn8), + {Value, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, NewQn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-7, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn7} = queue:out(Qn7), + {Value, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, NewQn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-6, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn6} = queue:out(Qn6), + {Value, + {Pc, Qsn14, Qsn7, + {NewQn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-5, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn5} = queue:out(Qn5), + {Value, + {Pc, Qsn14, Qsn7, + {Qn6, NewQn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-4, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn4} = queue:out(Qn4), + {Value, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, NewQn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-3, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn3} = queue:out(Qn3), + {Value, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, NewQn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-2, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn2} = queue:out(Qn2), + {Value, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, NewQn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-1, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn1} = queue:out(Qn1), + {Value, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, NewQn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(0, + {Pc, Qsn14, Qsn7, Qsn1, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQ0} = queue:out(Q0), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, + NewQ0, + Qsp1, Qsp7, Qsp14}}; +out_specific(1, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp1} = queue:out(Qp1), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {NewQp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}}; +out_specific(2, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp2} = queue:out(Qp2), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, NewQp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}}; +out_specific(3, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp3} = queue:out(Qp3), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, NewQp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}}; +out_specific(4, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp4} = queue:out(Qp4), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, NewQp4, Qp5, Qp6}, + Qsp7, Qsp14}}; +out_specific(5, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp5} = queue:out(Qp5), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, NewQp5, Qp6}, + Qsp7, Qsp14}}; +out_specific(6, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp6} = queue:out(Qp6), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, NewQp6}, + Qsp7, Qsp14}}; +out_specific(7, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp7} = queue:out(Qp7), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {NewQp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}}; +out_specific(8, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp8} = queue:out(Qp8), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, NewQp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}}; +out_specific(9, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp9} = queue:out(Qp9), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, NewQp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}}; +out_specific(10, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp10} = queue:out(Qp10), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, NewQp10, Qp11, Qp12, Qp13}, + Qsp14}}; +out_specific(11, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp11} = queue:out(Qp11), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, NewQp11, Qp12, Qp13}, + Qsp14}}; +out_specific(12, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp12} = queue:out(Qp12), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, NewQp12, Qp13}, + Qsp14}}; +out_specific(13, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp13} = queue:out(Qp13), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, NewQp13}, + Qsp14}}; +out_specific(14, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp14} = queue:out(Qp14), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {NewQp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}}; +out_specific(15, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp15} = queue:out(Qp15), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, NewQp15, Qp16, Qp17, Qp18, Qp19, Qp20}}}; +out_specific(16, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp16} = queue:out(Qp16), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, NewQp16, Qp17, Qp18, Qp19, Qp20}}}; +out_specific(17, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp17} = queue:out(Qp17), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, NewQp17, Qp18, Qp19, Qp20}}}; +out_specific(18, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp18} = queue:out(Qp18), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, NewQp18, Qp19, Qp20}}}; +out_specific(19, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp19} = queue:out(Qp19), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, NewQp19, Qp20}}}; +out_specific(20, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp20} = queue:out(Qp20), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, NewQp20}}}. + +-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_pq())} + ], ?CLOUDI_LONG_TEST_TIMEOUT). + +-endif. + diff --git a/aoc2023/build/dev/erlang/pqueue/src/pqueue2.erl b/aoc2023/build/dev/erlang/pqueue/src/pqueue2.erl new file mode 100644 index 0000000..bbdeaaf --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/src/pqueue2.erl @@ -0,0 +1,483 @@ +%-*-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. + diff --git a/aoc2023/build/dev/erlang/pqueue/src/pqueue3.erl b/aoc2023/build/dev/erlang/pqueue/src/pqueue3.erl new file mode 100644 index 0000000..03b370a --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/src/pqueue3.erl @@ -0,0 +1,404 @@ +%-*-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 +%%% ==A Large Priority Queue.== +%%% This priority queue implementation depends on layered tuples, so that tuple +%%% access times can be exploited for quick in/out priority queue operations +%%% when using 64 or more total priorities. This implementation was created +%%% to avoid the slowness within the priority queue used by +%%% both RabbitMQ and Riak +%%% (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +%%% @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(pqueue3). +-author('mjtruog at protonmail dot com'). + +%% external interface +-export([in/2, % O(1) + in/3, % O(1) + is_empty/1, % O(1) + is_queue/1, % O(1) + len/1, % O(N) + new/0, % O(1) + new/1, % O(1) + out/1, % O(1) amortized, O(N) worst case + out/2, % O(1) amortized, O(N) worst case + pout/1, % O(1) amortized, O(N) worst case + to_list/1]). % O(N) + +%%%------------------------------------------------------------------------ +%%% External interface functions +%%%------------------------------------------------------------------------ + +-type pqueue3() :: {integer(), integer(), empty | integer(), tuple()}. +-type pqueue3_empty() :: {integer(), integer(), empty, tuple()}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of the 0 priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(term(), pqueue3()) -> pqueue3(). + +in(Value, Q) -> + in(Value, 0, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of a specific priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(term(), integer(), pqueue3()) -> pqueue3(). + +in(_, P, {Size, Offset, _, _}) + when (P + Offset) < 0; (P + Offset) > Size -> + erlang:exit(badarg); +in(Value, P, {Size, Offset, empty, Bins}) -> + PriorityIndex = P + Offset, + {Size, Offset, PriorityIndex, + in_queue(layer_indexes(Size, PriorityIndex), Value, Bins)}; +in(Value, P, {Size, Offset, I, Bins}) + when (P + Offset) < I -> + PriorityIndex = P + Offset, + {Size, Offset, PriorityIndex, + in_queue(layer_indexes(Size, PriorityIndex), Value, Bins)}; +in(Value, P, {Size, Offset, I, Bins}) -> + {Size, Offset, I, + in_queue(layer_indexes(Size, P + Offset), Value, Bins)}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue is empty.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_empty(pqueue3()) -> 'true' | 'false'. + +is_empty({_, _, empty, _}) -> + true; +is_empty({_, _, _, _} = Q) -> + case out(Q) of + {empty, _} -> + true; + {{value, _}, _} -> + false + end. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue type is as expected.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_queue(pqueue3()) -> 'true' | 'false'. + +is_queue({Size, Offset, I, Bins}) + when is_integer(Size), is_integer(Offset), is_tuple(Bins) -> + (I =:= empty) or is_integer(I); +is_queue(_) -> + false. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Determine the length of a priority queue.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec len(pqueue3()) -> non_neg_integer(). + +len(Q) -> + len(0, out(Q)). +len(I, {empty, _}) -> + I; +len(I, {{value, _}, Q}) -> + len(I + 1, out(Q)). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Create a new priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec new() -> pqueue3_empty(). + +new() -> + new([]). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Create a new priority queue with customization options.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec new(list({atom(), term()})) -> pqueue3(). + +new(Options) -> + Size = proplists:get_value(priorities, Options, 256), + MiddleZero = proplists:get_value(middle_priority_zero, Options, true), + Offset = if + MiddleZero =:= true -> + erlang:round((Size / 2) + 0.5) - 1; + true -> + 0 + end, + {Size, Offset, empty, create(layer_sizes(Size))}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(pqueue3()) -> + {{'value', term()}, pqueue3()} | {'empty', pqueue3()}. + +out({_, _, empty, _} = Q) -> + {empty, Q}; +out({Size, Offset, I, Bins}) -> + {Result, NewI, NewBins} = out_check( + I, Size, out_queue(layer_indexes(Size, I), Bins) + ), + {Result, {Size, Offset, NewI, NewBins}}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item of a specific priority from the head of the queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(integer(), pqueue3()) -> + {{'value', term()}, pqueue3()} | {'empty', pqueue3()}. + +out(P, {Size, Offset, _, _}) + when (P + Offset) < 0; (P + Offset) > Size -> + erlang:exit(badarg); +out(_, {_, _, empty, _} = Q) -> + {empty, Q}; +out(P, {Size, Offset, I, Bins}) -> + {Result, NewBins} = out_queue(layer_indexes(Size, P + Offset), Bins), + {Result, {Size, Offset, I, NewBins}}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% Includes the priority in the return value. +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec pout(pqueue3()) -> + {{'value', term(), integer()}, pqueue3()} | {'empty', pqueue3()}. + +pout({_, _, empty, _} = Q) -> + {empty, Q}; +pout({Size, Offset, I, Bins}) -> + {Result, NewI, NewBins} = pout_check( + I, Size, Offset, out_queue(layer_indexes(Size, I), Bins) + ), + {Result, {Size, Offset, NewI, NewBins}}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Convert the priority queue to a list.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec to_list(pqueue3()) -> list(term()). + +to_list(Q) -> + to_list([], out(Q)). +to_list(L, {empty, _}) -> + lists:reverse(L); +to_list(L, {{value, Value}, Q}) -> + to_list([Value | L], out(Q)). + +%%%------------------------------------------------------------------------ +%%% Private functions +%%%------------------------------------------------------------------------ + +create([]) -> + queue:new(); + +create([I | Is]) -> + erlang:make_tuple(I + 1, create(Is)). + +in_queue({I1}, Value, Bins1) -> + erlang:setelement(I1, Bins1, queue:in(Value, erlang:element(I1, Bins1))); + +in_queue({I1, I2}, Value, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, queue:in(Value, erlang:element(I2, Bins2)))); + +in_queue({I1, I2, I3}, Value, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + Bins3 = erlang:element(I2, Bins2), + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, + erlang:setelement(I3, Bins3, queue:in(Value, erlang:element(I3, Bins3))))); + +in_queue({I1, I2, I3, I4}, Value, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + Bins3 = erlang:element(I2, Bins2), + Bins4 = erlang:element(I3, Bins3), + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, + erlang:setelement(I3, Bins3, + erlang:setelement(I4, Bins4, queue:in(Value, erlang:element(I4, Bins4)))))). + +pout_check(Size, Size, _, {empty, Bins}) -> + {empty, empty, Bins}; +pout_check(I, _, Offset, {{value, Value}, Bins}) -> + {{value, Value, I - Offset}, I, Bins}; +pout_check(I, Size, Offset, {empty, Bins}) -> + NewI = I + 1, + pout_check(NewI, Size, Offset, out_queue(layer_indexes(Size, NewI), Bins)). + +out_check(Size, Size, {empty, Bins}) -> + {empty, empty, Bins}; +out_check(I, _, {{value, _} = Result, Bins}) -> + {Result, I, Bins}; +out_check(I, Size, {empty, Bins}) -> + NewI = I + 1, + out_check(NewI, Size, out_queue(layer_indexes(Size, NewI), Bins)). + +out_queue({I1}, Bins1) -> + {Result, NewQueue} = queue:out(erlang:element(I1, Bins1)), + {Result, + erlang:setelement(I1, Bins1, NewQueue)}; + +out_queue({I1, I2}, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + {Result, NewQueue} = queue:out(erlang:element(I2, Bins2)), + {Result, + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, NewQueue))}; + +out_queue({I1, I2, I3}, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + Bins3 = erlang:element(I2, Bins2), + {Result, NewQueue} = queue:out(erlang:element(I3, Bins3)), + {Result, + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, + erlang:setelement(I3, Bins3, NewQueue)))}; + +out_queue({I1, I2, I3, I4}, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + Bins3 = erlang:element(I2, Bins2), + Bins4 = erlang:element(I3, Bins3), + {Result, NewQueue} = queue:out(erlang:element(I4, Bins4)), + {Result, + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, + erlang:setelement(I3, Bins3, + erlang:setelement(I4, Bins4, NewQueue))))}. + +layer_indexes(Size, PriorityIndex) -> + if + Size =< 127 -> + {PriorityIndex + 1}; + Size =< 255 -> + <<I1:4, I2:4>> = <<PriorityIndex:8>>, + {I1 + 1, I2 + 1}; + Size =< 511 -> + <<I1:4, I2:5>> = <<PriorityIndex:9>>, + {I1 + 1, I2 + 1}; + Size =< 1023 -> + <<I1:3, I2:3, I3:4>> = <<PriorityIndex:10>>, + {I1 + 1, I2 + 1, I3 + 1}; + Size =< 2047 -> + <<I1:3, I2:4, I3:4>> = <<PriorityIndex:11>>, + {I1 + 1, I2 + 1, I3 + 1}; + Size =< 4095 -> + <<I1:4, I2:4, I3:4>> = <<PriorityIndex:12>>, + {I1 + 1, I2 + 1, I3 + 1}; + Size =< 8191 -> + <<I1:4, I2:4, I3:5>> = <<PriorityIndex:13>>, + {I1 + 1, I2 + 1, I3 + 1}; + Size =< 16383 -> + <<I1:4, I2:5, I3:5>> = <<PriorityIndex:14>>, + {I1 + 1, I2 + 1, I3 + 1}; + Size =< 32767 -> + <<I1:3, I2:4, I3:4, I4:4>> = <<PriorityIndex:15>>, + {I1 + 1, I2 + 1, I3 + 1, I4 + 1}; + Size =< 65535 -> + <<I1:4, I2:4, I3:4, I4:4>> = <<PriorityIndex:16>>, + {I1 + 1, I2 + 1, I3 + 1, I4 + 1} + end. + +layer_sizes(Size) -> + if + Size =< 127 -> + <<I1:7>> = <<127:7>>, + [I1]; + Size =< 255 -> + <<I1:4, I2:4>> = <<255:8>>, + [I1, I2]; + Size =< 511 -> + <<I1:4, I2:5>> = <<511:9>>, + [I1, I2]; + Size =< 1023 -> + <<I1:3, I2:3, I3:4>> = <<1023:10>>, + [I1, I2, I3]; + Size =< 2047 -> + <<I1:3, I2:4, I3:4>> = <<2047:11>>, + [I1, I2, I3]; + Size =< 4095 -> + <<I1:4, I2:4, I3:4>> = <<4095:12>>, + [I1, I2, I3]; + Size =< 8191 -> + <<I1:4, I2:4, I3:5>> = <<8191:13>>, + [I1, I2, I3]; + Size =< 16383 -> + <<I1:4, I2:5, I3:5>> = <<16383:14>>, + [I1, I2, I3]; + Size =< 32767 -> + <<I1:3, I2:4, I3:4, I4:4>> = <<32767:15>>, + [I1, I2, I3, I4]; + Size =< 65535 -> + <<I1:4, I2:4, I3:4, I4:4>> = <<65535:16>>, + [I1, I2, I3, I4] + end. + diff --git a/aoc2023/build/dev/erlang/pqueue/src/pqueue4.erl b/aoc2023/build/dev/erlang/pqueue/src/pqueue4.erl new file mode 100644 index 0000000..30b188d --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/src/pqueue4.erl @@ -0,0 +1,11662 @@ +%-*-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 +%%% ==Static Priority Queue.== +%%% This priority queue implementation depends on a static number of priorities +%%% (-128 (high) to 128 (low)) so that tuple access times can be exploited for +%%% quick in/out priority queue operations. This implementation was created to +%%% avoid the slowness within the priority queue used by both RabbitMQ and Riak +%%% (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +%%% @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. +%%% +%%% +%%% queue_remove_unique/2 is based on queue:filter/2 +%%% which is under the Apache License 2.0: +%%% +%%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%%% +%%% Licensed under the Apache License, Version 2.0 (the "License"); +%%% you may not use this file except in compliance with the License. +%%% You may obtain a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, software +%%% distributed under the License is distributed on an "AS IS" BASIS, +%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%%% See the License for the specific language governing permissions and +%%% limitations under the License. +%%% +%%% @author Michael Truog <mjtruog at protonmail dot com> +%%% @copyright 2011-2020 Michael Truog +%%% @version 2.0.1 {@date} {@time} +%%%------------------------------------------------------------------------ + +-module(pqueue4). +-author('mjtruog at protonmail dot com'). + +%% external interface +-export([filter/2, % O(N) + filter/3, % O(N) + in/2, % O(1) + in/3, % O(1) + is_empty/1, % O(1) + is_queue/1, % O(1) + len/1, % O(1) + new/0, % O(1) + out/1, % O(1) amortized, O(N) worst case + out/2, % O(1) amortized, O(N) worst case + pout/1, % O(1) amortized, O(N) worst case + remove_unique/2, % O(N) but smaller constant than filter/2 + remove_unique/3, % O(N) but smaller constant than filter/3 + to_list/1, % O(N) + to_plist/1, % O(N) + test/0]). + +%%%------------------------------------------------------------------------ +%%% External interface functions +%%%------------------------------------------------------------------------ + +-type priority() :: -128..128. +-ifdef(ERLANG_OTP_VERSION_16). +-type pqueue4(_) :: + {priority() | 'empty', % current priority + non_neg_integer(), % total size + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + queue(), + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}}. +-else. +-type pqueue4(T) :: + {priority() | 'empty', % current priority + non_neg_integer(), % total size + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + queue:queue(T), + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}}. +-endif. +-type pqueue4() :: pqueue4(any()). +-export_type([pqueue4/0, pqueue4/1]). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Filter the priority queue.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec filter(fun((any()) -> boolean()), pqueue4()) -> pqueue4(). + +filter(F, {empty, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) + when is_function(F, 1) -> + Q; +filter(F, {Pc, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) + when is_function(F, 1) -> + filter_all(Pc, F, Q). + +filter_all(_, _, {_, 0, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _} = Q) -> + Q; +filter_all(128, F, Q) -> + filter_priority(128, F, Q); +filter_all(P, F, Q) when is_integer(P) -> + filter_all(P + 1, F, filter_priority(P, F, Q)). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Filter a specific priority within the priority queue.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec filter(fun((any()) -> boolean()), integer(), pqueue4()) -> pqueue4(). + +filter(_, P, _) + when P < -128; P > 128 -> + erlang:exit(badarg); +filter(F, P, Q) when is_function(F, 1) -> + filter_priority(P, F, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of the 0 priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(any(), pqueue4()) -> pqueue4(). + +in(X, Q) -> + in(X, 0, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of a specific priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(any(), integer(), pqueue4()) -> pqueue4(). + +in(_, P, _) + when P < -128; P > 128 -> + erlang:exit(badarg); +in(X, P, {empty, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + in_higher(P, Q, X); % (in a higher priority) +in(X, P, {Pc, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) + when P < Pc -> + in_higher(P, Q, X); % (in a higher priority) +in(X, P, Q) -> + in_lower(P, Q, X). % (in a lower priority) + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue is empty.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_empty(pqueue4()) -> 'true' | 'false'. + +is_empty({_, 0, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> + true; +is_empty({_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> + false. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue type is as expected.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_queue(pqueue4()) -> 'true' | 'false'. + +is_queue({Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) + when is_integer(Size), + tuple_size(Qn128) == 16, tuple_size(Qn112) == 16, + tuple_size(Qn96) == 16, tuple_size(Qn80) == 16, + tuple_size(Qn64) == 16, tuple_size(Qn48) == 16, + tuple_size(Qn32) == 16, tuple_size(Qn16) == 16, + tuple_size(Qp16) == 16, tuple_size(Qp32) == 16, + tuple_size(Qp48) == 16, tuple_size(Qp64) == 16, + tuple_size(Qp80) == 16, tuple_size(Qp96) == 16, + tuple_size(Qp112) == 16, tuple_size(Qp128) == 16 -> + (((Pc =:= empty) or is_integer(Pc)) and queue:is_queue(Q0)); +is_queue(_) -> + false. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Determine the length of a priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec len(pqueue4()) -> non_neg_integer(). + +len({_, Size, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> + Size. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Create a new priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec new() -> pqueue4(). + +new() -> + {empty, % current priority + 0, % current size + erlang:make_tuple(16, queue:new()), % priority [-128..-113] + erlang:make_tuple(16, queue:new()), % priority [-112.. -97] + erlang:make_tuple(16, queue:new()), % priority [ -96.. -81] + erlang:make_tuple(16, queue:new()), % priority [ -80.. -65] + erlang:make_tuple(16, queue:new()), % priority [ -64.. -49] + erlang:make_tuple(16, queue:new()), % priority [ -48.. -33] + erlang:make_tuple(16, queue:new()), % priority [ -32.. -17] + erlang:make_tuple(16, queue:new()), % priority [ -16.. -1] + queue:new(), % priority 0 (default) + erlang:make_tuple(16, queue:new()), % priority [ 1.. 16] + erlang:make_tuple(16, queue:new()), % priority [ 17.. 32] + erlang:make_tuple(16, queue:new()), % priority [ 33.. 48] + erlang:make_tuple(16, queue:new()), % priority [ 49.. 64] + erlang:make_tuple(16, queue:new()), % priority [ 65.. 80] + erlang:make_tuple(16, queue:new()), % priority [ 81.. 96] + erlang:make_tuple(16, queue:new()), % priority [ 97.. 112] + erlang:make_tuple(16, queue:new())}. % priority [ 113.. 128] + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(pqueue4()) -> + {{'value', any()}, pqueue4()} | {'empty', pqueue4()}. + +out({empty, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +out({Pc, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + out_current(Pc, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item of a specific priority from the head of the queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(integer(), pqueue4()) -> + {{'value', any()}, pqueue4()} | {'empty', pqueue4()}. + +out(P, _) + when P < -128; P > 128 -> + erlang:exit(badarg); +out(_, {empty, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +out(P, Q) -> + out_specific(P, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% Includes the priority in the return value. +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec pout(pqueue4()) -> + {{'value', any(), integer()}, pqueue4()} | {'empty', pqueue4()}. + +pout({empty, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +pout({Pc, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + out_current_p(Pc, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Remove a unique value from the priority queue with a binary predicate.=== +%% O(N) but smaller constant than filter/2 +%% @end +%%------------------------------------------------------------------------- + +-spec remove_unique(fun((any()) -> boolean()), pqueue4()) -> + {boolean(), pqueue4()}. + +remove_unique(F, {_, 0, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _} = Q) + when is_function(F, 1) -> + {false, Q}; +remove_unique(F, {Pc, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _} = Q) + when is_function(F, 1) -> + remove_unique_all(Pc, F, Q). + +remove_unique_all(128, F, Q) -> + remove_unique_p(128, F, Q); +remove_unique_all(P, F, Q) when is_integer(P) -> + case remove_unique_p(P, F, Q) of + {true, _} = Result -> + Result; + {false, Q} -> + remove_unique_all(P + 1, F, Q) + end. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Remove a unique value in a specific priority within the priority queue with a binary predicate.=== +%% O(N) but smaller constant than filter/3 +%% @end +%%------------------------------------------------------------------------- + +-spec remove_unique(fun((any()) -> boolean()), integer(), pqueue4()) -> + {boolean(), pqueue4()}. + +remove_unique(_, P, _) + when P < -128; P > 128 -> + erlang:exit(badarg); +remove_unique(F, P, Q) when is_function(F, 1) -> + remove_unique_p(P, F, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Convert the priority queue to a list.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec to_list(pqueue4()) -> list(). + +to_list(Q) -> + to_list([], out(Q)). +to_list(L, {empty, _}) -> + lists:reverse(L); +to_list(L, {{value, Value}, Q}) -> + to_list([Value | L], out(Q)). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Convert the priority queue to a list with priorities.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec to_plist(pqueue4()) -> list({priority(), list()}). + +to_plist(Q) -> + to_plist([], [], undefined, pout(Q)). +to_plist(L, [], _, {empty, _}) -> + lists:reverse(L); +to_plist(L, Lp, Pc, {empty, _}) -> + lists:reverse([{Pc, lists:reverse(Lp)} | L]); +to_plist(L, Lp, Pc, {{value, Value, Pc}, Q}) -> + to_plist(L, [Value | Lp], Pc, pout(Q)); +to_plist(L, [], _, {{value, Value, Pc}, Q}) -> + to_plist(L, [Value], Pc, pout(Q)); +to_plist(L, Lp, P, {{value, Value, Pc}, Q}) -> + to_plist([{P, lists:reverse(Lp)} | L], [Value], Pc, pout(Q)). + +%%------------------------------------------------------------------------- +%% @private +%% @doc +%% ===Regression test.=== +%% @end +%%------------------------------------------------------------------------- + +test() -> + Q0 = pqueue4:new(), + true = pqueue4:is_queue(Q0), + Q1 = pqueue4:in(20, 20, Q0), + Q2 = pqueue4:in(19, 19, Q1), + Q3 = pqueue4:in(18, 18, Q2), + Q4 = pqueue4:in(17, 17, Q3), + Q5 = pqueue4:in(16, 16, Q4), + Q6 = pqueue4:in(15, 15, Q5), + Q7 = pqueue4:in(14, 14, Q6), + Q8 = pqueue4:in(13, 13, Q7), + Q9 = pqueue4:in(12, 12, Q8), + Q10 = pqueue4:in(11, 11, Q9), + Q11 = pqueue4:in(10, 10, Q10), + Q12 = pqueue4:in(9, 9, Q11), + Q13 = pqueue4:in(8, 8, Q12), + Q14 = pqueue4:in(7, 7, Q13), + Q15 = pqueue4:in(6, 6, Q14), + Q16 = pqueue4:in(5, 5, Q15), + Q17 = pqueue4:in(4, 4, Q16), + Q18 = pqueue4:in(3, 3, Q17), + Q19 = pqueue4:in(2, 2, Q18), + Q20 = pqueue4:in(1, 1, Q19), + Q21 = pqueue4:in(0, 0, Q20), + Q22 = pqueue4:in(-1, -1, Q21), + Q23 = pqueue4:in(-2, -2, Q22), + Q24 = pqueue4:in(-3, -3, Q23), + Q25 = pqueue4:in(-4, -4, Q24), + Q26 = pqueue4:in(-5, -5, Q25), + Q27 = pqueue4:in(-6, -6, Q26), + Q28 = pqueue4:in(-7, -7, Q27), + Q29 = pqueue4:in(-8, -8, Q28), + Q30 = pqueue4:in(-9, -9, Q29), + Q31 = pqueue4:in(-10, -10, Q30), + Q32 = pqueue4:in(-11, -11, Q31), + Q33 = pqueue4:in(-12, -12, Q32), + Q34 = pqueue4:in(-13, -13, Q33), + Q35 = pqueue4:in(-14, -14, Q34), + Q36 = pqueue4:in(-15, -15, Q35), + Q37 = pqueue4:in(-16, -16, Q36), + Q38 = pqueue4:in(-17, -17, Q37), + Q39 = pqueue4:in(-18, -18, Q38), + Q40 = pqueue4:in(-19, -19, Q39), + Q41 = pqueue4:in(-20, -20, Q40), + Q42 = pqueue4:in(-20, -20, Q41), + Q43 = pqueue4:in(-19, -19, Q42), + Q44 = pqueue4:in(-18, -18, Q43), + Q45 = pqueue4:in(-17, -17, Q44), + Q46 = pqueue4:in(-16, -16, Q45), + Q47 = pqueue4:in(-15, -15, Q46), + Q48 = pqueue4:in(-14, -14, Q47), + Q49 = pqueue4:in(-13, -13, Q48), + Q50 = pqueue4:in(-12, -12, Q49), + Q51 = pqueue4:in(-11, -11, Q50), + Q52 = pqueue4:in(-10, -10, Q51), + Q53 = pqueue4:in(-9, -9, Q52), + Q54 = pqueue4:in(-8, -8, Q53), + Q55 = pqueue4:in(-7, -7, Q54), + Q56 = pqueue4:in(-6, -6, Q55), + Q57 = pqueue4:in(-5, -5, Q56), + Q58 = pqueue4:in(-4, -4, Q57), + Q59 = pqueue4:in(-3, -3, Q58), + Q60 = pqueue4:in(-2, -2, Q59), + Q61 = pqueue4:in(-1, -1, Q60), + Q62 = pqueue4:in(0, 0, Q61), + Q63 = pqueue4:in(1, 1, Q62), + Q64 = pqueue4:in(2, 2, Q63), + Q65 = pqueue4:in(3, 3, Q64), + Q66 = pqueue4:in(4, 4, Q65), + Q67 = pqueue4:in(5, 5, Q66), + Q68 = pqueue4:in(6, 6, Q67), + Q69 = pqueue4:in(7, 7, Q68), + Q70 = pqueue4:in(8, 8, Q69), + Q71 = pqueue4:in(9, 9, Q70), + Q72 = pqueue4:in(10, 10, Q71), + Q73 = pqueue4:in(11, 11, Q72), + Q74 = pqueue4:in(12, 12, Q73), + Q75 = pqueue4:in(13, 13, Q74), + Q76 = pqueue4:in(14, 14, Q75), + Q77 = pqueue4:in(15, 15, Q76), + Q78 = pqueue4:in(16, 16, Q77), + Q79 = pqueue4:in(17, 17, Q78), + Q80 = pqueue4:in(18, 18, Q79), + Q81 = pqueue4:in(19, 19, Q80), + Q82 = pqueue4:in(20, 20, Q81), + true = pqueue4:is_queue(Q82), + 82 = pqueue4: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] = pqueue4:to_list(Q82), + [{-20, [-20, -20]}, {-19, [-19, -19]}, {-18, [-18, -18]}, + {-17, [-17, -17]}, {-16, [-16, -16]}, {-15, [-15, -15]}, + {-14, [-14, -14]}, {-13, [-13, -13]}, {-12, [-12, -12]}, + {-11, [-11, -11]}, {-10, [-10, -10]}, {-9, [-9, -9]}, + {-8, [-8, -8]}, {-7, [-7, -7]}, {-6, [-6, -6]}, + {-5, [-5, -5]}, {-4, [-4, -4]}, {-3, [-3, -3]}, + {-2, [-2, -2]}, {-1, [-1, -1]}, {0, [0, 0]}, + {1, [1, 1]}, {2, [2, 2]}, {3, [3, 3]}, + {4, [4, 4]}, {5, [5, 5]}, {6, [6, 6]}, + {7, [7, 7]}, {8, [8, 8]}, {9, [9, 9]}, + {10, [10, 10]}, {11, [11, 11]}, {12, [12, 12]}, + {13, [13, 13]}, {14, [14, 14]}, {15, [15, 15]}, + {16, [16, 16]}, {17, [17, 17]}, {18, [18, 18]}, + {19, [19, 19]}, {20, [20, 20]}] = pqueue4:to_plist(Q82), + {{value, -20}, Q83} = pqueue4:out(Q82), + {{value, -20}, Q84} = pqueue4:out(Q83), + {{value, -19}, Q85} = pqueue4:out(Q84), + {{value, -19}, Q86} = pqueue4:out(Q85), + {{value, -18}, Q87} = pqueue4:out(Q86), + {{value, -18}, Q88} = pqueue4:out(Q87), + {{value, 0}, Q89} = pqueue4:out(0, Q88), + {{value, 0}, Q90} = pqueue4:out(0, Q89), + {empty, _} = pqueue4:out(0, Q90), + {{value, -17, -17}, Q91} = pqueue4:pout(Q90), + {{value, -17, -17}, Q92} = pqueue4:pout(Q91), + {{value, -16, -16}, Q93} = pqueue4:pout(Q92), + {{value, -16, -16}, Q94} = pqueue4:pout(Q93), + {{value, -15, -15}, Q95} = pqueue4:pout(Q94), + {{value, -15, -15}, Q96} = pqueue4:pout(Q95), + {{value, -14, -14}, Q97} = pqueue4:pout(Q96), + {{value, -14, -14}, Q98} = pqueue4:pout(Q97), + {{value, -13, -13}, Q99} = pqueue4:pout(Q98), + {{value, -13, -13}, Q100} = pqueue4:pout(Q99), + {{value, -12, -12}, Q101} = pqueue4:pout(Q100), + {{value, -12, -12}, Q102} = pqueue4:pout(Q101), + {{value, -11, -11}, Q103} = pqueue4:pout(Q102), + {{value, -11, -11}, Q104} = pqueue4:pout(Q103), + {{value, -10, -10}, Q105} = pqueue4:pout(Q104), + {{value, -10, -10}, Q106} = pqueue4:pout(Q105), + {{value, -9, -9}, Q107} = pqueue4:pout(Q106), + {{value, -9, -9}, Q108} = pqueue4:pout(Q107), + {{value, -8, -8}, Q109} = pqueue4:pout(Q108), + {{value, -8, -8}, Q110} = pqueue4:pout(Q109), + {{value, -7, -7}, Q111} = pqueue4:pout(Q110), + {{value, -7, -7}, Q112} = pqueue4:pout(Q111), + {{value, -6, -6}, Q113} = pqueue4:pout(Q112), + {{value, -6, -6}, Q114} = pqueue4:pout(Q113), + {{value, -5, -5}, Q115} = pqueue4:pout(Q114), + {{value, -5, -5}, Q116} = pqueue4:pout(Q115), + {{value, -4, -4}, Q117} = pqueue4:pout(Q116), + {{value, -4, -4}, Q118} = pqueue4:pout(Q117), + {{value, -3, -3}, Q119} = pqueue4:pout(Q118), + {{value, -3, -3}, Q120} = pqueue4:pout(Q119), + {{value, -2, -2}, Q121} = pqueue4:pout(Q120), + {{value, -2, -2}, Q122} = pqueue4:pout(Q121), + {{value, -1, -1}, Q123} = pqueue4:pout(Q122), + {{value, -1, -1}, Q124} = pqueue4:pout(Q123), + {{value, 1, 1}, Q125} = pqueue4:pout(Q124), + {{value, 1, 1}, Q126} = pqueue4:pout(Q125), + {{value, 2, 2}, Q127} = pqueue4:pout(Q126), + {{value, 2, 2}, Q128} = pqueue4:pout(Q127), + {{value, 3, 3}, Q129} = pqueue4:pout(Q128), + {{value, 3, 3}, Q130} = pqueue4:pout(Q129), + {{value, 4, 4}, Q131} = pqueue4:pout(Q130), + {{value, 4, 4}, Q132} = pqueue4:pout(Q131), + {{value, 5, 5}, Q133} = pqueue4:pout(Q132), + {{value, 5, 5}, Q134} = pqueue4:pout(Q133), + {{value, 6, 6}, Q135} = pqueue4:pout(Q134), + {{value, 6, 6}, Q136} = pqueue4:pout(Q135), + {{value, 7, 7}, Q137} = pqueue4:pout(Q136), + {{value, 7, 7}, Q138} = pqueue4:pout(Q137), + {{value, 8, 8}, Q139} = pqueue4:pout(Q138), + {{value, 8, 8}, Q140} = pqueue4:pout(Q139), + {{value, 9, 9}, Q141} = pqueue4:pout(Q140), + {{value, 9, 9}, Q142} = pqueue4:pout(Q141), + {{value, 10, 10}, Q143} = pqueue4:pout(Q142), + {{value, 10, 10}, Q144} = pqueue4:pout(Q143), + {{value, 11, 11}, Q145} = pqueue4:pout(Q144), + {{value, 11, 11}, Q146} = pqueue4:pout(Q145), + {{value, 12, 12}, Q147} = pqueue4:pout(Q146), + {{value, 12, 12}, Q148} = pqueue4:pout(Q147), + {{value, 13, 13}, Q149} = pqueue4:pout(Q148), + {{value, 13, 13}, Q150} = pqueue4:pout(Q149), + {{value, 14, 14}, Q151} = pqueue4:pout(Q150), + {{value, 14, 14}, Q152} = pqueue4:pout(Q151), + {{value, 15, 15}, Q153} = pqueue4:pout(Q152), + {{value, 15, 15}, Q154} = pqueue4:pout(Q153), + {{value, 16, 16}, Q155} = pqueue4:pout(Q154), + {{value, 16, 16}, Q156} = pqueue4:pout(Q155), + {{value, 17, 17}, Q157} = pqueue4:pout(Q156), + {{value, 17, 17}, Q158} = pqueue4:pout(Q157), + {{value, 18, 18}, Q159} = pqueue4:pout(Q158), + {{value, 18, 18}, Q160} = pqueue4:pout(Q159), + {{value, 19, 19}, Q161} = pqueue4:pout(Q160), + {{value, 19, 19}, Q162} = pqueue4:pout(Q161), + {{value, 20, 20}, Q163} = pqueue4:pout(Q162), + {{value, 20, 20}, Q164} = pqueue4:pout(Q163), + {{value, 20}, Q164} = pqueue4:out(Q163), + {{value, 20}, Q164} = pqueue4:out(20, Q163), + true = pqueue4:is_empty(Q164), + empty = erlang:element(1, Q164), % current priority + 0 = erlang:element(2, Q164), % size + {empty, Q164} = pqueue4:pout(Q164), + {empty, Q164} = pqueue4:out(Q164), + {empty, Q164} = pqueue4:out(20, Q164), + + Queue0 = queue:new(), + "{[],[]}" = lists:flatten(io_lib:format("~p", [Queue0])), + Queue1 = queue:in(1, Queue0), + Queue2 = queue:in(2, Queue1), + Queue3 = queue:in(3, Queue2), + {{value, 1}, _} = queue:out(Queue2), + "{[3,2],[1]}" = lists:flatten(io_lib:format("~p", [Queue3])), + {true, {[3],[1]}} = queue_remove_unique(fun(I) -> I == 2 end, {[3,2],[1]}), + Queue4 = queue:filter(fun(I) -> not (I == 2) end, Queue3), + "{[3],[1]}" = lists:flatten(io_lib:format("~p", [Queue4])), + 2 = queue:len(Queue4), + {{value, 1}, _} = queue:out(Queue4), + [1, 3] = queue:to_list(Queue4), + + Q166 = pqueue4:new(), + true = pqueue4:is_queue(Q166), + Q167 = pqueue4:in(6, 1, Q166), + Q168 = pqueue4:in(7, 1, Q167), + Q169 = pqueue4:in(8, 1, Q168), + Q170 = pqueue4:in(3, 0, Q169), + Q171 = pqueue4:in(4, 0, Q170), + Q172 = pqueue4:in(5, 0, Q171), + Q173 = pqueue4:in(0, -1, Q172), + Q174 = pqueue4:in(1, -1, Q173), + Q175 = pqueue4:in(2, -1, Q174), + [{-1, [0, 1, 2]}, {0, [3, 4, 5]}, {1, [6, 7, 8]}] = pqueue4:to_plist(Q175), + 3 = pqueue4:len(pqueue4:filter(fun(I) -> I > 5 end, Q175)), + 3 = pqueue4:len(pqueue4:filter(fun(I) -> I < 3 end, Q175)), + 3 = pqueue4:len(pqueue4:filter(fun(I) -> (I < 1) orelse (I > 6) end, Q175)), + {true, Q176} = pqueue4:remove_unique(fun(I) -> I == 4 end, Q175), + [{-1, [0, 1, 2]}, {0, [3, 5]}, {1, [6, 7, 8]}] = pqueue4:to_plist(Q176), + {true, Q177} = pqueue4:remove_unique(fun(I) -> I == 1 end, Q176), + [{-1, [0, 2]}, {0, [3, 5]}, {1, [6, 7, 8]}] = pqueue4:to_plist(Q177), + {true, Q178} = pqueue4:remove_unique(fun(I) -> I == 7 end, Q177), + [{-1, [0, 2]}, {0, [3, 5]}, {1, [6, 8]}] = pqueue4:to_plist(Q178), + 6 = pqueue4:len(Q178), + {{value, 0, -1}, Q179} = pqueue4:pout(Q178), + {{value, 2}, Q180} = pqueue4:out(Q179), + {{value, 6}, Q181} = pqueue4:out(1, Q180), + {false, Q181} = pqueue4:remove_unique(fun(I) -> I == 7 end, Q181), + [{0, [3, 5]}, {1, [8]}] = pqueue4:to_plist(Q181), + {true, Q182} = pqueue4:remove_unique(fun(I) -> I == 5 end, Q181), + {true, Q183} = pqueue4:remove_unique(fun(I) -> I == 8 end, 1, Q182), + {true, Q184} = pqueue4:remove_unique(fun(I) -> I == 3 end, Q183), + {empty, Q184} = pqueue4:pout(Q184), + {empty, Q184} = pqueue4:out(Q184), + {empty, Q184} = pqueue4:out(0, Q184), + ok. + +%%%------------------------------------------------------------------------ +%%% Private functions +%%%------------------------------------------------------------------------ + +%% @hidden +-define(FILTER_P_Qn128(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + V3, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn112(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, + V3, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn96(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, + V3, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn80(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, + V3, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn64(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, + V3, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn48(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, + V3, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn32(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V3, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn16(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V3, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp16(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V3, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp32(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V3, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp48(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V3, + Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp64(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V3, + Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp80(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V3, + Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp96(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V3, + Qp112, Qp128}). +-define(FILTER_P_Qp112(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V3, + Qp128}). +-define(FILTER_P_Qp128(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V3}). + +?FILTER_P_Qn128(-128, + Qn128, NewQn128, + {NewQn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-127, + Qn127, NewQn127, + {Qn128, NewQn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-126, + Qn126, NewQn126, + {Qn128, Qn127, NewQn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-125, + Qn125, NewQn125, + {Qn128, Qn127, Qn126, NewQn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-124, + Qn124, NewQn124, + {Qn128, Qn127, Qn126, Qn125, NewQn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-123, + Qn123, NewQn123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + NewQn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-122, + Qn122, NewQn122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, NewQn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-121, + Qn121, NewQn121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, NewQn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-120, + Qn120, NewQn120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, NewQn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-119, + Qn119, NewQn119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, NewQn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-118, + Qn118, NewQn118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, NewQn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-117, + Qn117, NewQn117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + NewQn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-116, + Qn116, NewQn116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, NewQn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-115, + Qn115, NewQn115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, NewQn115, Qn114, Qn113}); +?FILTER_P_Qn128(-114, + Qn114, NewQn114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, NewQn114, Qn113}); +?FILTER_P_Qn128(-113, + Qn113, NewQn113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, NewQn113}); +?FILTER_P_Qn112(-112, + Qn112, NewQn112, + {NewQn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-111, + Qn111, NewQn111, + {Qn112, NewQn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-110, + Qn110, NewQn110, + {Qn112, Qn111, NewQn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-109, + Qn109, NewQn109, + {Qn112, Qn111, Qn110, NewQn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-108, + Qn108, NewQn108, + {Qn112, Qn111, Qn110, Qn109, NewQn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-107, + Qn107, NewQn107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + NewQn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-106, + Qn106, NewQn106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, NewQn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-105, + Qn105, NewQn105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, NewQn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-104, + Qn104, NewQn104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, NewQn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-103, + Qn103, NewQn103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, NewQn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-102, + Qn102, NewQn102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, NewQn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-101, + Qn101, NewQn101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + NewQn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-100, + Qn100, NewQn100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, NewQn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-99, + Qn99, NewQn99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, NewQn99, Qn98, Qn97}); +?FILTER_P_Qn112(-98, + Qn98, NewQn98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, NewQn98, Qn97}); +?FILTER_P_Qn112(-97, + Qn97, NewQn97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, NewQn97}); +?FILTER_P_Qn96(-96, + Qn96, NewQn96, + {NewQn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-95, + Qn95, NewQn95, + {Qn96, NewQn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-94, + Qn94, NewQn94, + {Qn96, Qn95, NewQn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-93, + Qn93, NewQn93, + {Qn96, Qn95, Qn94, NewQn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-92, + Qn92, NewQn92, + {Qn96, Qn95, Qn94, Qn93, NewQn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-91, + Qn91, NewQn91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + NewQn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-90, + Qn90, NewQn90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, NewQn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-89, + Qn89, NewQn89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, NewQn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-88, + Qn88, NewQn88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, NewQn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-87, + Qn87, NewQn87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, NewQn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-86, + Qn86, NewQn86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, NewQn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-85, + Qn85, NewQn85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + NewQn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-84, + Qn84, NewQn84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, NewQn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-83, + Qn83, NewQn83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, NewQn83, Qn82, Qn81}); +?FILTER_P_Qn96(-82, + Qn82, NewQn82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, NewQn82, Qn81}); +?FILTER_P_Qn96(-81, + Qn81, NewQn81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, NewQn81}); +?FILTER_P_Qn80(-80, + Qn80, NewQn80, + {NewQn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-79, + Qn79, NewQn79, + {Qn80, NewQn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-78, + Qn78, NewQn78, + {Qn80, Qn79, NewQn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-77, + Qn77, NewQn77, + {Qn80, Qn79, Qn78, NewQn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-76, + Qn76, NewQn76, + {Qn80, Qn79, Qn78, Qn77, NewQn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-75, + Qn75, NewQn75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + NewQn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-74, + Qn74, NewQn74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, NewQn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-73, + Qn73, NewQn73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, NewQn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-72, + Qn72, NewQn72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, NewQn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-71, + Qn71, NewQn71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, NewQn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-70, + Qn70, NewQn70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, NewQn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-69, + Qn69, NewQn69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + NewQn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-68, + Qn68, NewQn68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, NewQn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-67, + Qn67, NewQn67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, NewQn67, Qn66, Qn65}); +?FILTER_P_Qn80(-66, + Qn66, NewQn66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, NewQn66, Qn65}); +?FILTER_P_Qn80(-65, + Qn65, NewQn65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, NewQn65}); +?FILTER_P_Qn64(-64, + Qn64, NewQn64, + {NewQn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-63, + Qn63, NewQn63, + {Qn64, NewQn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-62, + Qn62, NewQn62, + {Qn64, Qn63, NewQn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-61, + Qn61, NewQn61, + {Qn64, Qn63, Qn62, NewQn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-60, + Qn60, NewQn60, + {Qn64, Qn63, Qn62, Qn61, NewQn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-59, + Qn59, NewQn59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + NewQn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-58, + Qn58, NewQn58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, NewQn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-57, + Qn57, NewQn57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, NewQn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-56, + Qn56, NewQn56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, NewQn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-55, + Qn55, NewQn55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, NewQn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-54, + Qn54, NewQn54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, NewQn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-53, + Qn53, NewQn53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + NewQn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-52, + Qn52, NewQn52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, NewQn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-51, + Qn51, NewQn51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, NewQn51, Qn50, Qn49}); +?FILTER_P_Qn64(-50, + Qn50, NewQn50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, NewQn50, Qn49}); +?FILTER_P_Qn64(-49, + Qn49, NewQn49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, NewQn49}); +?FILTER_P_Qn48(-48, + Qn48, NewQn48, + {NewQn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-47, + Qn47, NewQn47, + {Qn48, NewQn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-46, + Qn46, NewQn46, + {Qn48, Qn47, NewQn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-45, + Qn45, NewQn45, + {Qn48, Qn47, Qn46, NewQn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-44, + Qn44, NewQn44, + {Qn48, Qn47, Qn46, Qn45, NewQn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-43, + Qn43, NewQn43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + NewQn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-42, + Qn42, NewQn42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, NewQn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-41, + Qn41, NewQn41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, NewQn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-40, + Qn40, NewQn40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, NewQn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-39, + Qn39, NewQn39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, NewQn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-38, + Qn38, NewQn38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, NewQn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-37, + Qn37, NewQn37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + NewQn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-36, + Qn36, NewQn36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, NewQn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-35, + Qn35, NewQn35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, NewQn35, Qn34, Qn33}); +?FILTER_P_Qn48(-34, + Qn34, NewQn34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, NewQn34, Qn33}); +?FILTER_P_Qn48(-33, + Qn33, NewQn33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, NewQn33}); +?FILTER_P_Qn32(-32, + Qn32, NewQn32, + {NewQn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-31, + Qn31, NewQn31, + {Qn32, NewQn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-30, + Qn30, NewQn30, + {Qn32, Qn31, NewQn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-29, + Qn29, NewQn29, + {Qn32, Qn31, Qn30, NewQn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-28, + Qn28, NewQn28, + {Qn32, Qn31, Qn30, Qn29, NewQn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-27, + Qn27, NewQn27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + NewQn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-26, + Qn26, NewQn26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, NewQn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-25, + Qn25, NewQn25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, NewQn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-24, + Qn24, NewQn24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, NewQn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-23, + Qn23, NewQn23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, NewQn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-22, + Qn22, NewQn22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, NewQn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-21, + Qn21, NewQn21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + NewQn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-20, + Qn20, NewQn20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, NewQn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-19, + Qn19, NewQn19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, NewQn19, Qn18, Qn17}); +?FILTER_P_Qn32(-18, + Qn18, NewQn18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, NewQn18, Qn17}); +?FILTER_P_Qn32(-17, + Qn17, NewQn17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, NewQn17}); +?FILTER_P_Qn16(-16, + Qn16, NewQn16, + {NewQn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-15, + Qn15, NewQn15, + {Qn16, NewQn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-14, + Qn14, NewQn14, + {Qn16, Qn15, NewQn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-13, + Qn13, NewQn13, + {Qn16, Qn15, Qn14, NewQn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-12, + Qn12, NewQn12, + {Qn16, Qn15, Qn14, Qn13, NewQn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-11, + Qn11, NewQn11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + NewQn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-10, + Qn10, NewQn10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, NewQn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-9, + Qn9, NewQn9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, NewQn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-8, + Qn8, NewQn8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, NewQn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-7, + Qn7, NewQn7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, NewQn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-6, + Qn6, NewQn6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, NewQn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-5, + Qn5, NewQn5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + NewQn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-4, + Qn4, NewQn4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, NewQn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-3, + Qn3, NewQn3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, NewQn3, Qn2, Qn1}); +?FILTER_P_Qn16(-2, + Qn2, NewQn2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, NewQn2, Qn1}); +?FILTER_P_Qn16(-1, + Qn1, NewQn1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, NewQn1}); +filter_priority(0, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + NewQ0 = queue:filter(F, Q0), + NewSize = Size - (queue:len(Q0) - queue:len(NewQ0)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + NewQ0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}; +?FILTER_P_Qp16(1, + Qp1, NewQp1, + {NewQp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(2, + Qp2, NewQp2, + {Qp1, NewQp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(3, + Qp3, NewQp3, + {Qp1, Qp2, NewQp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(4, + Qp4, NewQp4, + {Qp1, Qp2, Qp3, NewQp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(5, + Qp5, NewQp5, + {Qp1, Qp2, Qp3, Qp4, NewQp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(6, + Qp6, NewQp6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + NewQp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(7, + Qp7, NewQp7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, NewQp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(8, + Qp8, NewQp8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, NewQp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(9, + Qp9, NewQp9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, NewQp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(10, + Qp10, NewQp10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, NewQp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(11, + Qp11, NewQp11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, NewQp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(12, + Qp12, NewQp12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + NewQp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(13, + Qp13, NewQp13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, NewQp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(14, + Qp14, NewQp14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, NewQp14, Qp15, Qp16}); +?FILTER_P_Qp16(15, + Qp15, NewQp15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, NewQp15, Qp16}); +?FILTER_P_Qp16(16, + Qp16, NewQp16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, NewQp16}); +?FILTER_P_Qp32(17, + Qp17, NewQp17, + {NewQp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(18, + Qp18, NewQp18, + {Qp17, NewQp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(19, + Qp19, NewQp19, + {Qp17, Qp18, NewQp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(20, + Qp20, NewQp20, + {Qp17, Qp18, Qp19, NewQp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(21, + Qp21, NewQp21, + {Qp17, Qp18, Qp19, Qp20, NewQp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(22, + Qp22, NewQp22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + NewQp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(23, + Qp23, NewQp23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, NewQp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(24, + Qp24, NewQp24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, NewQp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(25, + Qp25, NewQp25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, NewQp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(26, + Qp26, NewQp26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, NewQp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(27, + Qp27, NewQp27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, NewQp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(28, + Qp28, NewQp28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + NewQp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(29, + Qp29, NewQp29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, NewQp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(30, + Qp30, NewQp30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, NewQp30, Qp31, Qp32}); +?FILTER_P_Qp32(31, + Qp31, NewQp31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, NewQp31, Qp32}); +?FILTER_P_Qp32(32, + Qp32, NewQp32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, NewQp32}); +?FILTER_P_Qp48(33, + Qp33, NewQp33, + {NewQp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(34, + Qp34, NewQp34, + {Qp33, NewQp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(35, + Qp35, NewQp35, + {Qp33, Qp34, NewQp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(36, + Qp36, NewQp36, + {Qp33, Qp34, Qp35, NewQp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(37, + Qp37, NewQp37, + {Qp33, Qp34, Qp35, Qp36, NewQp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(38, + Qp38, NewQp38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + NewQp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(39, + Qp39, NewQp39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, NewQp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(40, + Qp40, NewQp40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, NewQp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(41, + Qp41, NewQp41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, NewQp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(42, + Qp42, NewQp42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, NewQp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(43, + Qp43, NewQp43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, NewQp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(44, + Qp44, NewQp44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + NewQp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(45, + Qp45, NewQp45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, NewQp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(46, + Qp46, NewQp46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, NewQp46, Qp47, Qp48}); +?FILTER_P_Qp48(47, + Qp47, NewQp47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, NewQp47, Qp48}); +?FILTER_P_Qp48(48, + Qp48, NewQp48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, NewQp48}); +?FILTER_P_Qp64(49, + Qp49, NewQp49, + {NewQp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(50, + Qp50, NewQp50, + {Qp49, NewQp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(51, + Qp51, NewQp51, + {Qp49, Qp50, NewQp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(52, + Qp52, NewQp52, + {Qp49, Qp50, Qp51, NewQp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(53, + Qp53, NewQp53, + {Qp49, Qp50, Qp51, Qp52, NewQp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(54, + Qp54, NewQp54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + NewQp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(55, + Qp55, NewQp55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, NewQp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(56, + Qp56, NewQp56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, NewQp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(57, + Qp57, NewQp57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, NewQp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(58, + Qp58, NewQp58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, NewQp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(59, + Qp59, NewQp59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, NewQp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(60, + Qp60, NewQp60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + NewQp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(61, + Qp61, NewQp61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, NewQp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(62, + Qp62, NewQp62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, NewQp62, Qp63, Qp64}); +?FILTER_P_Qp64(63, + Qp63, NewQp63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, NewQp63, Qp64}); +?FILTER_P_Qp64(64, + Qp64, NewQp64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, NewQp64}); +?FILTER_P_Qp80(65, + Qp65, NewQp65, + {NewQp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(66, + Qp66, NewQp66, + {Qp65, NewQp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(67, + Qp67, NewQp67, + {Qp65, Qp66, NewQp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(68, + Qp68, NewQp68, + {Qp65, Qp66, Qp67, NewQp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(69, + Qp69, NewQp69, + {Qp65, Qp66, Qp67, Qp68, NewQp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(70, + Qp70, NewQp70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + NewQp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(71, + Qp71, NewQp71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, NewQp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(72, + Qp72, NewQp72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, NewQp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(73, + Qp73, NewQp73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, NewQp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(74, + Qp74, NewQp74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, NewQp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(75, + Qp75, NewQp75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, NewQp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(76, + Qp76, NewQp76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + NewQp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(77, + Qp77, NewQp77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, NewQp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(78, + Qp78, NewQp78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, NewQp78, Qp79, Qp80}); +?FILTER_P_Qp80(79, + Qp79, NewQp79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, NewQp79, Qp80}); +?FILTER_P_Qp80(80, + Qp80, NewQp80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, NewQp80}); +?FILTER_P_Qp96(81, + Qp81, NewQp81, + {NewQp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(82, + Qp82, NewQp82, + {Qp81, NewQp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(83, + Qp83, NewQp83, + {Qp81, Qp82, NewQp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(84, + Qp84, NewQp84, + {Qp81, Qp82, Qp83, NewQp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(85, + Qp85, NewQp85, + {Qp81, Qp82, Qp83, Qp84, NewQp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(86, + Qp86, NewQp86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + NewQp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(87, + Qp87, NewQp87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, NewQp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(88, + Qp88, NewQp88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, NewQp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(89, + Qp89, NewQp89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, NewQp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(90, + Qp90, NewQp90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, NewQp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(91, + Qp91, NewQp91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, NewQp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(92, + Qp92, NewQp92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + NewQp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(93, + Qp93, NewQp93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, NewQp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(94, + Qp94, NewQp94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, NewQp94, Qp95, Qp96}); +?FILTER_P_Qp96(95, + Qp95, NewQp95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, NewQp95, Qp96}); +?FILTER_P_Qp96(96, + Qp96, NewQp96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, NewQp96}); +?FILTER_P_Qp112(97, + Qp97, NewQp97, + {NewQp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(98, + Qp98, NewQp98, + {Qp97, NewQp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(99, + Qp99, NewQp99, + {Qp97, Qp98, NewQp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(100, + Qp100, NewQp100, + {Qp97, Qp98, Qp99, NewQp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(101, + Qp101, NewQp101, + {Qp97, Qp98, Qp99, Qp100, NewQp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(102, + Qp102, NewQp102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + NewQp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(103, + Qp103, NewQp103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, NewQp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(104, + Qp104, NewQp104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, NewQp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(105, + Qp105, NewQp105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, NewQp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(106, + Qp106, NewQp106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, NewQp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(107, + Qp107, NewQp107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, NewQp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(108, + Qp108, NewQp108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + NewQp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(109, + Qp109, NewQp109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, NewQp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(110, + Qp110, NewQp110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, NewQp110, Qp111, Qp112}); +?FILTER_P_Qp112(111, + Qp111, NewQp111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, NewQp111, Qp112}); +?FILTER_P_Qp112(112, + Qp112, NewQp112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, NewQp112}); +?FILTER_P_Qp128(113, + Qp113, NewQp113, + {NewQp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(114, + Qp114, NewQp114, + {Qp113, NewQp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(115, + Qp115, NewQp115, + {Qp113, Qp114, NewQp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(116, + Qp116, NewQp116, + {Qp113, Qp114, Qp115, NewQp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(117, + Qp117, NewQp117, + {Qp113, Qp114, Qp115, Qp116, NewQp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(118, + Qp118, NewQp118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + NewQp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(119, + Qp119, NewQp119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, NewQp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(120, + Qp120, NewQp120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, NewQp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(121, + Qp121, NewQp121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, NewQp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(122, + Qp122, NewQp122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, NewQp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(123, + Qp123, NewQp123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, NewQp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(124, + Qp124, NewQp124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + NewQp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(125, + Qp125, NewQp125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, NewQp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(126, + Qp126, NewQp126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, NewQp126, Qp127, Qp128}); +?FILTER_P_Qp128(127, + Qp127, NewQp127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, NewQp127, Qp128}); +?FILTER_P_Qp128(128, + Qp128, NewQp128, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, NewQp128}). + +%% @hidden +-define(IN_HIGHER_Qn128(P, V), +in_higher(P, + {_, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + V, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn112(P, V), +in_higher(P, + {_, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, + V, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn96(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, + V, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn80(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, + V, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn64(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, + V, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn48(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, + V, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn32(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn16(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp16(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp32(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp48(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V, + Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp64(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V, + Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp80(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V, + Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp96(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V, + Qp112, Qp128}). +-define(IN_HIGHER_Qp112(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V, + Qp128}). +-define(IN_HIGHER_Qp128(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V}). + +?IN_HIGHER_Qn128(-128, + {queue:in(X, Qn128), Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-127, + {Qn128, queue:in(X, Qn127), Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-126, + {Qn128, Qn127, queue:in(X, Qn126), Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-125, + {Qn128, Qn127, Qn126, queue:in(X, Qn125), Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-124, + {Qn128, Qn127, Qn126, Qn125, queue:in(X, Qn124), + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + queue:in(X, Qn123), Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, queue:in(X, Qn122), Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, queue:in(X, Qn121), Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, queue:in(X, Qn120), Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, queue:in(X, Qn119), Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, queue:in(X, Qn118), + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + queue:in(X, Qn117), Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, queue:in(X, Qn116), Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, queue:in(X, Qn115), Qn114, Qn113}); +?IN_HIGHER_Qn128(-114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, queue:in(X, Qn114), Qn113}); +?IN_HIGHER_Qn128(-113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, queue:in(X, Qn113)}); +?IN_HIGHER_Qn112(-112, + {queue:in(X, Qn112), Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-111, + {Qn112, queue:in(X, Qn111), Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-110, + {Qn112, Qn111, queue:in(X, Qn110), Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-109, + {Qn112, Qn111, Qn110, queue:in(X, Qn109), Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-108, + {Qn112, Qn111, Qn110, Qn109, queue:in(X, Qn108), + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + queue:in(X, Qn107), Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, queue:in(X, Qn106), Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, queue:in(X, Qn105), Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, queue:in(X, Qn104), Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, queue:in(X, Qn103), Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, queue:in(X, Qn102), + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + queue:in(X, Qn101), Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, queue:in(X, Qn100), Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, queue:in(X, Qn99), Qn98, Qn97}); +?IN_HIGHER_Qn112(-98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, queue:in(X, Qn98), Qn97}); +?IN_HIGHER_Qn112(-97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, queue:in(X, Qn97)}); +?IN_HIGHER_Qn96(-96, + {queue:in(X, Qn96), Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-95, + {Qn96, queue:in(X, Qn95), Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-94, + {Qn96, Qn95, queue:in(X, Qn94), Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-93, + {Qn96, Qn95, Qn94, queue:in(X, Qn93), Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-92, + {Qn96, Qn95, Qn94, Qn93, queue:in(X, Qn92), + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + queue:in(X, Qn91), Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, queue:in(X, Qn90), Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, queue:in(X, Qn89), Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, queue:in(X, Qn88), Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, queue:in(X, Qn87), Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, queue:in(X, Qn86), + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + queue:in(X, Qn85), Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, queue:in(X, Qn84), Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, queue:in(X, Qn83), Qn82, Qn81}); +?IN_HIGHER_Qn96(-82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, queue:in(X, Qn82), Qn81}); +?IN_HIGHER_Qn96(-81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, queue:in(X, Qn81)}); +?IN_HIGHER_Qn80(-80, + {queue:in(X, Qn80), Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-79, + {Qn80, queue:in(X, Qn79), Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-78, + {Qn80, Qn79, queue:in(X, Qn78), Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-77, + {Qn80, Qn79, Qn78, queue:in(X, Qn77), Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-76, + {Qn80, Qn79, Qn78, Qn77, queue:in(X, Qn76), + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + queue:in(X, Qn75), Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, queue:in(X, Qn74), Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, queue:in(X, Qn73), Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, queue:in(X, Qn72), Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, queue:in(X, Qn71), Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, queue:in(X, Qn70), + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + queue:in(X, Qn69), Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, queue:in(X, Qn68), Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, queue:in(X, Qn67), Qn66, Qn65}); +?IN_HIGHER_Qn80(-66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, queue:in(X, Qn66), Qn65}); +?IN_HIGHER_Qn80(-65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, queue:in(X, Qn65)}); +?IN_HIGHER_Qn64(-64, + {queue:in(X, Qn64), Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-63, + {Qn64, queue:in(X, Qn63), Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-62, + {Qn64, Qn63, queue:in(X, Qn62), Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-61, + {Qn64, Qn63, Qn62, queue:in(X, Qn61), Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-60, + {Qn64, Qn63, Qn62, Qn61, queue:in(X, Qn60), + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + queue:in(X, Qn59), Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, queue:in(X, Qn58), Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, queue:in(X, Qn57), Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, queue:in(X, Qn56), Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, queue:in(X, Qn55), Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, queue:in(X, Qn54), + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + queue:in(X, Qn53), Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, queue:in(X, Qn52), Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, queue:in(X, Qn51), Qn50, Qn49}); +?IN_HIGHER_Qn64(-50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, queue:in(X, Qn50), Qn49}); +?IN_HIGHER_Qn64(-49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, queue:in(X, Qn49)}); +?IN_HIGHER_Qn48(-48, + {queue:in(X, Qn48), Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-47, + {Qn48, queue:in(X, Qn47), Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-46, + {Qn48, Qn47, queue:in(X, Qn46), Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-45, + {Qn48, Qn47, Qn46, queue:in(X, Qn45), Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-44, + {Qn48, Qn47, Qn46, Qn45, queue:in(X, Qn44), + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + queue:in(X, Qn43), Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, queue:in(X, Qn42), Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, queue:in(X, Qn41), Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, queue:in(X, Qn40), Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, queue:in(X, Qn39), Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, queue:in(X, Qn38), + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + queue:in(X, Qn37), Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, queue:in(X, Qn36), Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, queue:in(X, Qn35), Qn34, Qn33}); +?IN_HIGHER_Qn48(-34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, queue:in(X, Qn34), Qn33}); +?IN_HIGHER_Qn48(-33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, queue:in(X, Qn33)}); +?IN_HIGHER_Qn32(-32, + {queue:in(X, Qn32), Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-31, + {Qn32, queue:in(X, Qn31), Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-30, + {Qn32, Qn31, queue:in(X, Qn30), Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-29, + {Qn32, Qn31, Qn30, queue:in(X, Qn29), Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-28, + {Qn32, Qn31, Qn30, Qn29, queue:in(X, Qn28), + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + queue:in(X, Qn27), Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, queue:in(X, Qn26), Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, queue:in(X, Qn25), Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, queue:in(X, Qn24), Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, queue:in(X, Qn23), Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, queue:in(X, Qn22), + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + queue:in(X, Qn21), Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, queue:in(X, Qn20), Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, queue:in(X, Qn19), Qn18, Qn17}); +?IN_HIGHER_Qn32(-18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, queue:in(X, Qn18), Qn17}); +?IN_HIGHER_Qn32(-17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, queue:in(X, Qn17)}); +?IN_HIGHER_Qn16(-16, + {queue:in(X, Qn16), Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-15, + {Qn16, queue:in(X, Qn15), Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-14, + {Qn16, Qn15, queue:in(X, Qn14), Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-13, + {Qn16, Qn15, Qn14, queue:in(X, Qn13), Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-12, + {Qn16, Qn15, Qn14, Qn13, queue:in(X, Qn12), + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + queue:in(X, Qn11), Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, queue:in(X, Qn10), Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, queue:in(X, Qn9), Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, queue:in(X, Qn8), Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, queue:in(X, Qn7), Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, queue:in(X, Qn6), + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + queue:in(X, Qn5), Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, queue:in(X, Qn4), Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, queue:in(X, Qn3), Qn2, Qn1}); +?IN_HIGHER_Qn16(-2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, queue:in(X, Qn2), Qn1}); +?IN_HIGHER_Qn16(-1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, queue:in(X, Qn1)}); +in_higher(0, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {0, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + queue:in(X, Q0), + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}; +?IN_HIGHER_Qp16(1, + {queue:in(X, Qp1), Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(2, + {Qp1, queue:in(X, Qp2), Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(3, + {Qp1, Qp2, queue:in(X, Qp3), Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(4, + {Qp1, Qp2, Qp3, queue:in(X, Qp4), Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(5, + {Qp1, Qp2, Qp3, Qp4, queue:in(X, Qp5), + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + queue:in(X, Qp6), Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, queue:in(X, Qp7), Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, queue:in(X, Qp8), Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, queue:in(X, Qp9), Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, queue:in(X, Qp10), Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, queue:in(X, Qp11), + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + queue:in(X, Qp12), Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, queue:in(X, Qp13), Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, queue:in(X, Qp14), Qp15, Qp16}); +?IN_HIGHER_Qp16(15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, queue:in(X, Qp15), Qp16}); +?IN_HIGHER_Qp16(16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, queue:in(X, Qp16)}); +?IN_HIGHER_Qp32(17, + {queue:in(X, Qp17), Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(18, + {Qp17, queue:in(X, Qp18), Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(19, + {Qp17, Qp18, queue:in(X, Qp19), Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(20, + {Qp17, Qp18, Qp19, queue:in(X, Qp20), Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(21, + {Qp17, Qp18, Qp19, Qp20, queue:in(X, Qp21), + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + queue:in(X, Qp22), Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, queue:in(X, Qp23), Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, queue:in(X, Qp24), Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, queue:in(X, Qp25), Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, queue:in(X, Qp26), Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, queue:in(X, Qp27), + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + queue:in(X, Qp28), Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, queue:in(X, Qp29), Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, queue:in(X, Qp30), Qp31, Qp32}); +?IN_HIGHER_Qp32(31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, queue:in(X, Qp31), Qp32}); +?IN_HIGHER_Qp32(32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, queue:in(X, Qp32)}); +?IN_HIGHER_Qp48(33, + {queue:in(X, Qp33), Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(34, + {Qp33, queue:in(X, Qp34), Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(35, + {Qp33, Qp34, queue:in(X, Qp35), Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(36, + {Qp33, Qp34, Qp35, queue:in(X, Qp36), Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(37, + {Qp33, Qp34, Qp35, Qp36, queue:in(X, Qp37), + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + queue:in(X, Qp38), Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, queue:in(X, Qp39), Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, queue:in(X, Qp40), Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, queue:in(X, Qp41), Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, queue:in(X, Qp42), Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, queue:in(X, Qp43), + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + queue:in(X, Qp44), Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, queue:in(X, Qp45), Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, queue:in(X, Qp46), Qp47, Qp48}); +?IN_HIGHER_Qp48(47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, queue:in(X, Qp47), Qp48}); +?IN_HIGHER_Qp48(48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, queue:in(X, Qp48)}); +?IN_HIGHER_Qp64(49, + {queue:in(X, Qp49), Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(50, + {Qp49, queue:in(X, Qp50), Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(51, + {Qp49, Qp50, queue:in(X, Qp51), Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(52, + {Qp49, Qp50, Qp51, queue:in(X, Qp52), Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(53, + {Qp49, Qp50, Qp51, Qp52, queue:in(X, Qp53), + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + queue:in(X, Qp54), Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, queue:in(X, Qp55), Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, queue:in(X, Qp56), Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, queue:in(X, Qp57), Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, queue:in(X, Qp58), Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, queue:in(X, Qp59), + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + queue:in(X, Qp60), Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, queue:in(X, Qp61), Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, queue:in(X, Qp62), Qp63, Qp64}); +?IN_HIGHER_Qp64(63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, queue:in(X, Qp63), Qp64}); +?IN_HIGHER_Qp64(64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, queue:in(X, Qp64)}); +?IN_HIGHER_Qp80(65, + {queue:in(X, Qp65), Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(66, + {Qp65, queue:in(X, Qp66), Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(67, + {Qp65, Qp66, queue:in(X, Qp67), Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(68, + {Qp65, Qp66, Qp67, queue:in(X, Qp68), Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(69, + {Qp65, Qp66, Qp67, Qp68, queue:in(X, Qp69), + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + queue:in(X, Qp70), Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, queue:in(X, Qp71), Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, queue:in(X, Qp72), Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, queue:in(X, Qp73), Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, queue:in(X, Qp74), Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, queue:in(X, Qp75), + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + queue:in(X, Qp76), Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, queue:in(X, Qp77), Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, queue:in(X, Qp78), Qp79, Qp80}); +?IN_HIGHER_Qp80(79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, queue:in(X, Qp79), Qp80}); +?IN_HIGHER_Qp80(80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, queue:in(X, Qp80)}); +?IN_HIGHER_Qp96(81, + {queue:in(X, Qp81), Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(82, + {Qp81, queue:in(X, Qp82), Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(83, + {Qp81, Qp82, queue:in(X, Qp83), Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(84, + {Qp81, Qp82, Qp83, queue:in(X, Qp84), Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(85, + {Qp81, Qp82, Qp83, Qp84, queue:in(X, Qp85), + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + queue:in(X, Qp86), Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, queue:in(X, Qp87), Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, queue:in(X, Qp88), Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, queue:in(X, Qp89), Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, queue:in(X, Qp90), Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, queue:in(X, Qp91), + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + queue:in(X, Qp92), Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, queue:in(X, Qp93), Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, queue:in(X, Qp94), Qp95, Qp96}); +?IN_HIGHER_Qp96(95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, queue:in(X, Qp95), Qp96}); +?IN_HIGHER_Qp96(96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, queue:in(X, Qp96)}); +?IN_HIGHER_Qp112(97, + {queue:in(X, Qp97), Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(98, + {Qp97, queue:in(X, Qp98), Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(99, + {Qp97, Qp98, queue:in(X, Qp99), Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(100, + {Qp97, Qp98, Qp99, queue:in(X, Qp100), Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(101, + {Qp97, Qp98, Qp99, Qp100, queue:in(X, Qp101), + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + queue:in(X, Qp102), Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, queue:in(X, Qp103), Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, queue:in(X, Qp104), Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, queue:in(X, Qp105), Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, queue:in(X, Qp106), Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, queue:in(X, Qp107), + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + queue:in(X, Qp108), Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, queue:in(X, Qp109), Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, queue:in(X, Qp110), Qp111, Qp112}); +?IN_HIGHER_Qp112(111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, queue:in(X, Qp111), Qp112}); +?IN_HIGHER_Qp112(112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, queue:in(X, Qp112)}); +?IN_HIGHER_Qp128(113, + {queue:in(X, Qp113), Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(114, + {Qp113, queue:in(X, Qp114), Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(115, + {Qp113, Qp114, queue:in(X, Qp115), Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(116, + {Qp113, Qp114, Qp115, queue:in(X, Qp116), Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(117, + {Qp113, Qp114, Qp115, Qp116, queue:in(X, Qp117), + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + queue:in(X, Qp118), Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, queue:in(X, Qp119), Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, queue:in(X, Qp120), Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, queue:in(X, Qp121), Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, queue:in(X, Qp122), Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, queue:in(X, Qp123), + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + queue:in(X, Qp124), Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, queue:in(X, Qp125), Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, queue:in(X, Qp126), Qp127, Qp128}); +?IN_HIGHER_Qp128(127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, queue:in(X, Qp127), Qp128}); +?IN_HIGHER_Qp128(128, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, queue:in(X, Qp128)}). + +%% @hidden +-define(IN_LOWER_Qn128(P, V), +in_lower(P, + {Pc, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + V, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn112(P, V), +in_lower(P, + {Pc, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, + V, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn96(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, + V, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn80(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, + V, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn64(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, + V, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn48(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, + V, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn32(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn16(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp16(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp32(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp48(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V, + Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp64(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V, + Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp80(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V, + Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp96(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V, + Qp112, Qp128}). +-define(IN_LOWER_Qp112(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V, + Qp128}). +-define(IN_LOWER_Qp128(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V}). + +?IN_LOWER_Qn128(-128, + {queue:in(X, Qn128), Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-127, + {Qn128, queue:in(X, Qn127), Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-126, + {Qn128, Qn127, queue:in(X, Qn126), Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-125, + {Qn128, Qn127, Qn126, queue:in(X, Qn125), Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-124, + {Qn128, Qn127, Qn126, Qn125, queue:in(X, Qn124), + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + queue:in(X, Qn123), Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, queue:in(X, Qn122), Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, queue:in(X, Qn121), Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, queue:in(X, Qn120), Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, queue:in(X, Qn119), Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, queue:in(X, Qn118), + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + queue:in(X, Qn117), Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, queue:in(X, Qn116), Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, queue:in(X, Qn115), Qn114, Qn113}); +?IN_LOWER_Qn128(-114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, queue:in(X, Qn114), Qn113}); +?IN_LOWER_Qn128(-113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, queue:in(X, Qn113)}); +?IN_LOWER_Qn112(-112, + {queue:in(X, Qn112), Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-111, + {Qn112, queue:in(X, Qn111), Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-110, + {Qn112, Qn111, queue:in(X, Qn110), Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-109, + {Qn112, Qn111, Qn110, queue:in(X, Qn109), Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-108, + {Qn112, Qn111, Qn110, Qn109, queue:in(X, Qn108), + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + queue:in(X, Qn107), Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, queue:in(X, Qn106), Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, queue:in(X, Qn105), Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, queue:in(X, Qn104), Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, queue:in(X, Qn103), Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, queue:in(X, Qn102), + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + queue:in(X, Qn101), Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, queue:in(X, Qn100), Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, queue:in(X, Qn99), Qn98, Qn97}); +?IN_LOWER_Qn112(-98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, queue:in(X, Qn98), Qn97}); +?IN_LOWER_Qn112(-97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, queue:in(X, Qn97)}); +?IN_LOWER_Qn96(-96, + {queue:in(X, Qn96), Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-95, + {Qn96, queue:in(X, Qn95), Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-94, + {Qn96, Qn95, queue:in(X, Qn94), Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-93, + {Qn96, Qn95, Qn94, queue:in(X, Qn93), Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-92, + {Qn96, Qn95, Qn94, Qn93, queue:in(X, Qn92), + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + queue:in(X, Qn91), Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, queue:in(X, Qn90), Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, queue:in(X, Qn89), Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, queue:in(X, Qn88), Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, queue:in(X, Qn87), Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, queue:in(X, Qn86), + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + queue:in(X, Qn85), Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, queue:in(X, Qn84), Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, queue:in(X, Qn83), Qn82, Qn81}); +?IN_LOWER_Qn96(-82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, queue:in(X, Qn82), Qn81}); +?IN_LOWER_Qn96(-81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, queue:in(X, Qn81)}); +?IN_LOWER_Qn80(-80, + {queue:in(X, Qn80), Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-79, + {Qn80, queue:in(X, Qn79), Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-78, + {Qn80, Qn79, queue:in(X, Qn78), Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-77, + {Qn80, Qn79, Qn78, queue:in(X, Qn77), Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-76, + {Qn80, Qn79, Qn78, Qn77, queue:in(X, Qn76), + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + queue:in(X, Qn75), Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, queue:in(X, Qn74), Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, queue:in(X, Qn73), Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, queue:in(X, Qn72), Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, queue:in(X, Qn71), Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, queue:in(X, Qn70), + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + queue:in(X, Qn69), Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, queue:in(X, Qn68), Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, queue:in(X, Qn67), Qn66, Qn65}); +?IN_LOWER_Qn80(-66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, queue:in(X, Qn66), Qn65}); +?IN_LOWER_Qn80(-65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, queue:in(X, Qn65)}); +?IN_LOWER_Qn64(-64, + {queue:in(X, Qn64), Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-63, + {Qn64, queue:in(X, Qn63), Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-62, + {Qn64, Qn63, queue:in(X, Qn62), Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-61, + {Qn64, Qn63, Qn62, queue:in(X, Qn61), Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-60, + {Qn64, Qn63, Qn62, Qn61, queue:in(X, Qn60), + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + queue:in(X, Qn59), Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, queue:in(X, Qn58), Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, queue:in(X, Qn57), Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, queue:in(X, Qn56), Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, queue:in(X, Qn55), Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, queue:in(X, Qn54), + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + queue:in(X, Qn53), Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, queue:in(X, Qn52), Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, queue:in(X, Qn51), Qn50, Qn49}); +?IN_LOWER_Qn64(-50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, queue:in(X, Qn50), Qn49}); +?IN_LOWER_Qn64(-49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, queue:in(X, Qn49)}); +?IN_LOWER_Qn48(-48, + {queue:in(X, Qn48), Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-47, + {Qn48, queue:in(X, Qn47), Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-46, + {Qn48, Qn47, queue:in(X, Qn46), Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-45, + {Qn48, Qn47, Qn46, queue:in(X, Qn45), Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-44, + {Qn48, Qn47, Qn46, Qn45, queue:in(X, Qn44), + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + queue:in(X, Qn43), Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, queue:in(X, Qn42), Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, queue:in(X, Qn41), Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, queue:in(X, Qn40), Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, queue:in(X, Qn39), Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, queue:in(X, Qn38), + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + queue:in(X, Qn37), Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, queue:in(X, Qn36), Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, queue:in(X, Qn35), Qn34, Qn33}); +?IN_LOWER_Qn48(-34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, queue:in(X, Qn34), Qn33}); +?IN_LOWER_Qn48(-33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, queue:in(X, Qn33)}); +?IN_LOWER_Qn32(-32, + {queue:in(X, Qn32), Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-31, + {Qn32, queue:in(X, Qn31), Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-30, + {Qn32, Qn31, queue:in(X, Qn30), Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-29, + {Qn32, Qn31, Qn30, queue:in(X, Qn29), Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-28, + {Qn32, Qn31, Qn30, Qn29, queue:in(X, Qn28), + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + queue:in(X, Qn27), Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, queue:in(X, Qn26), Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, queue:in(X, Qn25), Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, queue:in(X, Qn24), Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, queue:in(X, Qn23), Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, queue:in(X, Qn22), + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + queue:in(X, Qn21), Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, queue:in(X, Qn20), Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, queue:in(X, Qn19), Qn18, Qn17}); +?IN_LOWER_Qn32(-18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, queue:in(X, Qn18), Qn17}); +?IN_LOWER_Qn32(-17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, queue:in(X, Qn17)}); +?IN_LOWER_Qn16(-16, + {queue:in(X, Qn16), Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-15, + {Qn16, queue:in(X, Qn15), Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-14, + {Qn16, Qn15, queue:in(X, Qn14), Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-13, + {Qn16, Qn15, Qn14, queue:in(X, Qn13), Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-12, + {Qn16, Qn15, Qn14, Qn13, queue:in(X, Qn12), + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + queue:in(X, Qn11), Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, queue:in(X, Qn10), Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, queue:in(X, Qn9), Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, queue:in(X, Qn8), Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, queue:in(X, Qn7), Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, queue:in(X, Qn6), + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + queue:in(X, Qn5), Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, queue:in(X, Qn4), Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, queue:in(X, Qn3), Qn2, Qn1}); +?IN_LOWER_Qn16(-2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, queue:in(X, Qn2), Qn1}); +?IN_LOWER_Qn16(-1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, queue:in(X, Qn1)}); +in_lower(0, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + queue:in(X, Q0), + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}; +?IN_LOWER_Qp16(1, + {queue:in(X, Qp1), Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(2, + {Qp1, queue:in(X, Qp2), Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(3, + {Qp1, Qp2, queue:in(X, Qp3), Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(4, + {Qp1, Qp2, Qp3, queue:in(X, Qp4), Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(5, + {Qp1, Qp2, Qp3, Qp4, queue:in(X, Qp5), + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + queue:in(X, Qp6), Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, queue:in(X, Qp7), Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, queue:in(X, Qp8), Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, queue:in(X, Qp9), Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, queue:in(X, Qp10), Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, queue:in(X, Qp11), + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + queue:in(X, Qp12), Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, queue:in(X, Qp13), Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, queue:in(X, Qp14), Qp15, Qp16}); +?IN_LOWER_Qp16(15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, queue:in(X, Qp15), Qp16}); +?IN_LOWER_Qp16(16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, queue:in(X, Qp16)}); +?IN_LOWER_Qp32(17, + {queue:in(X, Qp17), Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(18, + {Qp17, queue:in(X, Qp18), Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(19, + {Qp17, Qp18, queue:in(X, Qp19), Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(20, + {Qp17, Qp18, Qp19, queue:in(X, Qp20), Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(21, + {Qp17, Qp18, Qp19, Qp20, queue:in(X, Qp21), + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + queue:in(X, Qp22), Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, queue:in(X, Qp23), Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, queue:in(X, Qp24), Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, queue:in(X, Qp25), Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, queue:in(X, Qp26), Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, queue:in(X, Qp27), + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + queue:in(X, Qp28), Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, queue:in(X, Qp29), Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, queue:in(X, Qp30), Qp31, Qp32}); +?IN_LOWER_Qp32(31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, queue:in(X, Qp31), Qp32}); +?IN_LOWER_Qp32(32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, queue:in(X, Qp32)}); +?IN_LOWER_Qp48(33, + {queue:in(X, Qp33), Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(34, + {Qp33, queue:in(X, Qp34), Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(35, + {Qp33, Qp34, queue:in(X, Qp35), Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(36, + {Qp33, Qp34, Qp35, queue:in(X, Qp36), Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(37, + {Qp33, Qp34, Qp35, Qp36, queue:in(X, Qp37), + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + queue:in(X, Qp38), Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, queue:in(X, Qp39), Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, queue:in(X, Qp40), Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, queue:in(X, Qp41), Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, queue:in(X, Qp42), Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, queue:in(X, Qp43), + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + queue:in(X, Qp44), Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, queue:in(X, Qp45), Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, queue:in(X, Qp46), Qp47, Qp48}); +?IN_LOWER_Qp48(47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, queue:in(X, Qp47), Qp48}); +?IN_LOWER_Qp48(48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, queue:in(X, Qp48)}); +?IN_LOWER_Qp64(49, + {queue:in(X, Qp49), Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(50, + {Qp49, queue:in(X, Qp50), Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(51, + {Qp49, Qp50, queue:in(X, Qp51), Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(52, + {Qp49, Qp50, Qp51, queue:in(X, Qp52), Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(53, + {Qp49, Qp50, Qp51, Qp52, queue:in(X, Qp53), + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + queue:in(X, Qp54), Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, queue:in(X, Qp55), Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, queue:in(X, Qp56), Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, queue:in(X, Qp57), Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, queue:in(X, Qp58), Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, queue:in(X, Qp59), + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + queue:in(X, Qp60), Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, queue:in(X, Qp61), Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, queue:in(X, Qp62), Qp63, Qp64}); +?IN_LOWER_Qp64(63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, queue:in(X, Qp63), Qp64}); +?IN_LOWER_Qp64(64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, queue:in(X, Qp64)}); +?IN_LOWER_Qp80(65, + {queue:in(X, Qp65), Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(66, + {Qp65, queue:in(X, Qp66), Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(67, + {Qp65, Qp66, queue:in(X, Qp67), Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(68, + {Qp65, Qp66, Qp67, queue:in(X, Qp68), Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(69, + {Qp65, Qp66, Qp67, Qp68, queue:in(X, Qp69), + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + queue:in(X, Qp70), Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, queue:in(X, Qp71), Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, queue:in(X, Qp72), Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, queue:in(X, Qp73), Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, queue:in(X, Qp74), Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, queue:in(X, Qp75), + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + queue:in(X, Qp76), Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, queue:in(X, Qp77), Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, queue:in(X, Qp78), Qp79, Qp80}); +?IN_LOWER_Qp80(79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, queue:in(X, Qp79), Qp80}); +?IN_LOWER_Qp80(80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, queue:in(X, Qp80)}); +?IN_LOWER_Qp96(81, + {queue:in(X, Qp81), Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(82, + {Qp81, queue:in(X, Qp82), Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(83, + {Qp81, Qp82, queue:in(X, Qp83), Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(84, + {Qp81, Qp82, Qp83, queue:in(X, Qp84), Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(85, + {Qp81, Qp82, Qp83, Qp84, queue:in(X, Qp85), + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + queue:in(X, Qp86), Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, queue:in(X, Qp87), Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, queue:in(X, Qp88), Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, queue:in(X, Qp89), Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, queue:in(X, Qp90), Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, queue:in(X, Qp91), + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + queue:in(X, Qp92), Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, queue:in(X, Qp93), Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, queue:in(X, Qp94), Qp95, Qp96}); +?IN_LOWER_Qp96(95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, queue:in(X, Qp95), Qp96}); +?IN_LOWER_Qp96(96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, queue:in(X, Qp96)}); +?IN_LOWER_Qp112(97, + {queue:in(X, Qp97), Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(98, + {Qp97, queue:in(X, Qp98), Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(99, + {Qp97, Qp98, queue:in(X, Qp99), Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(100, + {Qp97, Qp98, Qp99, queue:in(X, Qp100), Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(101, + {Qp97, Qp98, Qp99, Qp100, queue:in(X, Qp101), + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + queue:in(X, Qp102), Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, queue:in(X, Qp103), Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, queue:in(X, Qp104), Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, queue:in(X, Qp105), Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, queue:in(X, Qp106), Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, queue:in(X, Qp107), + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + queue:in(X, Qp108), Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, queue:in(X, Qp109), Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, queue:in(X, Qp110), Qp111, Qp112}); +?IN_LOWER_Qp112(111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, queue:in(X, Qp111), Qp112}); +?IN_LOWER_Qp112(112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, queue:in(X, Qp112)}); +?IN_LOWER_Qp128(113, + {queue:in(X, Qp113), Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(114, + {Qp113, queue:in(X, Qp114), Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(115, + {Qp113, Qp114, queue:in(X, Qp115), Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(116, + {Qp113, Qp114, Qp115, queue:in(X, Qp116), Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(117, + {Qp113, Qp114, Qp115, Qp116, queue:in(X, Qp117), + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + queue:in(X, Qp118), Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, queue:in(X, Qp119), Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, queue:in(X, Qp120), Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, queue:in(X, Qp121), Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, queue:in(X, Qp122), Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, queue:in(X, Qp123), + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + queue:in(X, Qp124), Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, queue:in(X, Qp125), Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, queue:in(X, Qp126), Qp127, Qp128}); +?IN_LOWER_Qp128(127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, queue:in(X, Qp127), Qp128}); +?IN_LOWER_Qp128(128, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, queue:in(X, Qp128)}). + +%% @hidden +-define(OUT_CURRENT_Qn128(P, V1, V2, V3), +out_current(P, + {_, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + V3, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn112(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, + V3, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn96(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, + V3, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn80(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, + V3, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn64(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, + V3, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn48(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, + V3, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn32(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V3, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn16(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V3, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp16(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V3, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp32(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V3, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp48(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V3, + Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp64(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V3, + Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp80(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V3, + Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp96(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V3, + Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp112(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V3, + Qp128}} + end). +-define(OUT_CURRENT_Qp128(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V3}} + end). + +?OUT_CURRENT_Qn128(-128, + Qn128, NewQn128, + {NewQn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-127, + Qn127, NewQn127, + {Qn128, NewQn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-126, + Qn126, NewQn126, + {Qn128, Qn127, NewQn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-125, + Qn125, NewQn125, + {Qn128, Qn127, Qn126, NewQn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-124, + Qn124, NewQn124, + {Qn128, Qn127, Qn126, Qn125, NewQn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-123, + Qn123, NewQn123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + NewQn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-122, + Qn122, NewQn122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, NewQn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-121, + Qn121, NewQn121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, NewQn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-120, + Qn120, NewQn120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, NewQn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-119, + Qn119, NewQn119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, NewQn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-118, + Qn118, NewQn118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, NewQn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-117, + Qn117, NewQn117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + NewQn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-116, + Qn116, NewQn116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, NewQn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-115, + Qn115, NewQn115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, NewQn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-114, + Qn114, NewQn114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, NewQn114, Qn113}); +?OUT_CURRENT_Qn128(-113, + Qn113, NewQn113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, NewQn113}); +?OUT_CURRENT_Qn112(-112, + Qn112, NewQn112, + {NewQn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-111, + Qn111, NewQn111, + {Qn112, NewQn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-110, + Qn110, NewQn110, + {Qn112, Qn111, NewQn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-109, + Qn109, NewQn109, + {Qn112, Qn111, Qn110, NewQn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-108, + Qn108, NewQn108, + {Qn112, Qn111, Qn110, Qn109, NewQn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-107, + Qn107, NewQn107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + NewQn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-106, + Qn106, NewQn106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, NewQn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-105, + Qn105, NewQn105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, NewQn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-104, + Qn104, NewQn104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, NewQn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-103, + Qn103, NewQn103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, NewQn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-102, + Qn102, NewQn102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, NewQn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-101, + Qn101, NewQn101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + NewQn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-100, + Qn100, NewQn100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, NewQn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-99, + Qn99, NewQn99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, NewQn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-98, + Qn98, NewQn98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, NewQn98, Qn97}); +?OUT_CURRENT_Qn112(-97, + Qn97, NewQn97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, NewQn97}); +?OUT_CURRENT_Qn96(-96, + Qn96, NewQn96, + {NewQn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-95, + Qn95, NewQn95, + {Qn96, NewQn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-94, + Qn94, NewQn94, + {Qn96, Qn95, NewQn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-93, + Qn93, NewQn93, + {Qn96, Qn95, Qn94, NewQn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-92, + Qn92, NewQn92, + {Qn96, Qn95, Qn94, Qn93, NewQn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-91, + Qn91, NewQn91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + NewQn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-90, + Qn90, NewQn90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, NewQn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-89, + Qn89, NewQn89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, NewQn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-88, + Qn88, NewQn88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, NewQn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-87, + Qn87, NewQn87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, NewQn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-86, + Qn86, NewQn86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, NewQn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-85, + Qn85, NewQn85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + NewQn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-84, + Qn84, NewQn84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, NewQn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-83, + Qn83, NewQn83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, NewQn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-82, + Qn82, NewQn82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, NewQn82, Qn81}); +?OUT_CURRENT_Qn96(-81, + Qn81, NewQn81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, NewQn81}); +?OUT_CURRENT_Qn80(-80, + Qn80, NewQn80, + {NewQn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-79, + Qn79, NewQn79, + {Qn80, NewQn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-78, + Qn78, NewQn78, + {Qn80, Qn79, NewQn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-77, + Qn77, NewQn77, + {Qn80, Qn79, Qn78, NewQn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-76, + Qn76, NewQn76, + {Qn80, Qn79, Qn78, Qn77, NewQn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-75, + Qn75, NewQn75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + NewQn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-74, + Qn74, NewQn74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, NewQn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-73, + Qn73, NewQn73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, NewQn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-72, + Qn72, NewQn72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, NewQn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-71, + Qn71, NewQn71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, NewQn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-70, + Qn70, NewQn70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, NewQn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-69, + Qn69, NewQn69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + NewQn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-68, + Qn68, NewQn68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, NewQn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-67, + Qn67, NewQn67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, NewQn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-66, + Qn66, NewQn66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, NewQn66, Qn65}); +?OUT_CURRENT_Qn80(-65, + Qn65, NewQn65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, NewQn65}); +?OUT_CURRENT_Qn64(-64, + Qn64, NewQn64, + {NewQn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-63, + Qn63, NewQn63, + {Qn64, NewQn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-62, + Qn62, NewQn62, + {Qn64, Qn63, NewQn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-61, + Qn61, NewQn61, + {Qn64, Qn63, Qn62, NewQn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-60, + Qn60, NewQn60, + {Qn64, Qn63, Qn62, Qn61, NewQn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-59, + Qn59, NewQn59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + NewQn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-58, + Qn58, NewQn58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, NewQn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-57, + Qn57, NewQn57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, NewQn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-56, + Qn56, NewQn56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, NewQn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-55, + Qn55, NewQn55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, NewQn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-54, + Qn54, NewQn54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, NewQn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-53, + Qn53, NewQn53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + NewQn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-52, + Qn52, NewQn52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, NewQn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-51, + Qn51, NewQn51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, NewQn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-50, + Qn50, NewQn50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, NewQn50, Qn49}); +?OUT_CURRENT_Qn64(-49, + Qn49, NewQn49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, NewQn49}); +?OUT_CURRENT_Qn48(-48, + Qn48, NewQn48, + {NewQn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-47, + Qn47, NewQn47, + {Qn48, NewQn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-46, + Qn46, NewQn46, + {Qn48, Qn47, NewQn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-45, + Qn45, NewQn45, + {Qn48, Qn47, Qn46, NewQn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-44, + Qn44, NewQn44, + {Qn48, Qn47, Qn46, Qn45, NewQn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-43, + Qn43, NewQn43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + NewQn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-42, + Qn42, NewQn42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, NewQn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-41, + Qn41, NewQn41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, NewQn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-40, + Qn40, NewQn40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, NewQn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-39, + Qn39, NewQn39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, NewQn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-38, + Qn38, NewQn38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, NewQn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-37, + Qn37, NewQn37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + NewQn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-36, + Qn36, NewQn36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, NewQn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-35, + Qn35, NewQn35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, NewQn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-34, + Qn34, NewQn34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, NewQn34, Qn33}); +?OUT_CURRENT_Qn48(-33, + Qn33, NewQn33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, NewQn33}); +?OUT_CURRENT_Qn32(-32, + Qn32, NewQn32, + {NewQn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-31, + Qn31, NewQn31, + {Qn32, NewQn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-30, + Qn30, NewQn30, + {Qn32, Qn31, NewQn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-29, + Qn29, NewQn29, + {Qn32, Qn31, Qn30, NewQn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-28, + Qn28, NewQn28, + {Qn32, Qn31, Qn30, Qn29, NewQn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-27, + Qn27, NewQn27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + NewQn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-26, + Qn26, NewQn26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, NewQn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-25, + Qn25, NewQn25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, NewQn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-24, + Qn24, NewQn24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, NewQn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-23, + Qn23, NewQn23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, NewQn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-22, + Qn22, NewQn22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, NewQn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-21, + Qn21, NewQn21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + NewQn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-20, + Qn20, NewQn20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, NewQn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-19, + Qn19, NewQn19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, NewQn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-18, + Qn18, NewQn18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, NewQn18, Qn17}); +?OUT_CURRENT_Qn32(-17, + Qn17, NewQn17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, NewQn17}); +?OUT_CURRENT_Qn16(-16, + Qn16, NewQn16, + {NewQn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-15, + Qn15, NewQn15, + {Qn16, NewQn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-14, + Qn14, NewQn14, + {Qn16, Qn15, NewQn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-13, + Qn13, NewQn13, + {Qn16, Qn15, Qn14, NewQn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-12, + Qn12, NewQn12, + {Qn16, Qn15, Qn14, Qn13, NewQn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-11, + Qn11, NewQn11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + NewQn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-10, + Qn10, NewQn10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, NewQn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-9, + Qn9, NewQn9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, NewQn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-8, + Qn8, NewQn8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, NewQn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-7, + Qn7, NewQn7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, NewQn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-6, + Qn6, NewQn6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, NewQn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-5, + Qn5, NewQn5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + NewQn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-4, + Qn4, NewQn4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, NewQn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-3, + Qn3, NewQn3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, NewQn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-2, + Qn2, NewQn2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, NewQn2, Qn1}); +?OUT_CURRENT_Qn16(-1, + Qn1, NewQn1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, NewQn1}); +out_current(0, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, NewQ0} = queue:out(Q0), + if + Value =:= empty -> + out_current(1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> 0 end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + NewQ0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end; +?OUT_CURRENT_Qp16(1, + Qp1, NewQp1, + {NewQp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(2, + Qp2, NewQp2, + {Qp1, NewQp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(3, + Qp3, NewQp3, + {Qp1, Qp2, NewQp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(4, + Qp4, NewQp4, + {Qp1, Qp2, Qp3, NewQp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(5, + Qp5, NewQp5, + {Qp1, Qp2, Qp3, Qp4, NewQp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(6, + Qp6, NewQp6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + NewQp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(7, + Qp7, NewQp7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, NewQp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(8, + Qp8, NewQp8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, NewQp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(9, + Qp9, NewQp9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, NewQp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(10, + Qp10, NewQp10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, NewQp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(11, + Qp11, NewQp11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, NewQp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(12, + Qp12, NewQp12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + NewQp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(13, + Qp13, NewQp13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, NewQp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(14, + Qp14, NewQp14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, NewQp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(15, + Qp15, NewQp15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, NewQp15, Qp16}); +?OUT_CURRENT_Qp16(16, + Qp16, NewQp16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, NewQp16}); +?OUT_CURRENT_Qp32(17, + Qp17, NewQp17, + {NewQp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(18, + Qp18, NewQp18, + {Qp17, NewQp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(19, + Qp19, NewQp19, + {Qp17, Qp18, NewQp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(20, + Qp20, NewQp20, + {Qp17, Qp18, Qp19, NewQp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(21, + Qp21, NewQp21, + {Qp17, Qp18, Qp19, Qp20, NewQp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(22, + Qp22, NewQp22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + NewQp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(23, + Qp23, NewQp23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, NewQp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(24, + Qp24, NewQp24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, NewQp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(25, + Qp25, NewQp25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, NewQp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(26, + Qp26, NewQp26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, NewQp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(27, + Qp27, NewQp27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, NewQp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(28, + Qp28, NewQp28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + NewQp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(29, + Qp29, NewQp29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, NewQp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(30, + Qp30, NewQp30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, NewQp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(31, + Qp31, NewQp31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, NewQp31, Qp32}); +?OUT_CURRENT_Qp32(32, + Qp32, NewQp32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, NewQp32}); +?OUT_CURRENT_Qp48(33, + Qp33, NewQp33, + {NewQp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(34, + Qp34, NewQp34, + {Qp33, NewQp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(35, + Qp35, NewQp35, + {Qp33, Qp34, NewQp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(36, + Qp36, NewQp36, + {Qp33, Qp34, Qp35, NewQp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(37, + Qp37, NewQp37, + {Qp33, Qp34, Qp35, Qp36, NewQp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(38, + Qp38, NewQp38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + NewQp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(39, + Qp39, NewQp39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, NewQp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(40, + Qp40, NewQp40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, NewQp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(41, + Qp41, NewQp41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, NewQp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(42, + Qp42, NewQp42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, NewQp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(43, + Qp43, NewQp43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, NewQp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(44, + Qp44, NewQp44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + NewQp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(45, + Qp45, NewQp45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, NewQp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(46, + Qp46, NewQp46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, NewQp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(47, + Qp47, NewQp47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, NewQp47, Qp48}); +?OUT_CURRENT_Qp48(48, + Qp48, NewQp48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, NewQp48}); +?OUT_CURRENT_Qp64(49, + Qp49, NewQp49, + {NewQp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(50, + Qp50, NewQp50, + {Qp49, NewQp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(51, + Qp51, NewQp51, + {Qp49, Qp50, NewQp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(52, + Qp52, NewQp52, + {Qp49, Qp50, Qp51, NewQp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(53, + Qp53, NewQp53, + {Qp49, Qp50, Qp51, Qp52, NewQp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(54, + Qp54, NewQp54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + NewQp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(55, + Qp55, NewQp55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, NewQp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(56, + Qp56, NewQp56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, NewQp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(57, + Qp57, NewQp57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, NewQp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(58, + Qp58, NewQp58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, NewQp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(59, + Qp59, NewQp59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, NewQp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(60, + Qp60, NewQp60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + NewQp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(61, + Qp61, NewQp61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, NewQp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(62, + Qp62, NewQp62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, NewQp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(63, + Qp63, NewQp63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, NewQp63, Qp64}); +?OUT_CURRENT_Qp64(64, + Qp64, NewQp64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, NewQp64}); +?OUT_CURRENT_Qp80(65, + Qp65, NewQp65, + {NewQp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(66, + Qp66, NewQp66, + {Qp65, NewQp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(67, + Qp67, NewQp67, + {Qp65, Qp66, NewQp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(68, + Qp68, NewQp68, + {Qp65, Qp66, Qp67, NewQp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(69, + Qp69, NewQp69, + {Qp65, Qp66, Qp67, Qp68, NewQp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(70, + Qp70, NewQp70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + NewQp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(71, + Qp71, NewQp71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, NewQp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(72, + Qp72, NewQp72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, NewQp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(73, + Qp73, NewQp73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, NewQp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(74, + Qp74, NewQp74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, NewQp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(75, + Qp75, NewQp75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, NewQp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(76, + Qp76, NewQp76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + NewQp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(77, + Qp77, NewQp77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, NewQp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(78, + Qp78, NewQp78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, NewQp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(79, + Qp79, NewQp79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, NewQp79, Qp80}); +?OUT_CURRENT_Qp80(80, + Qp80, NewQp80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, NewQp80}); +?OUT_CURRENT_Qp96(81, + Qp81, NewQp81, + {NewQp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(82, + Qp82, NewQp82, + {Qp81, NewQp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(83, + Qp83, NewQp83, + {Qp81, Qp82, NewQp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(84, + Qp84, NewQp84, + {Qp81, Qp82, Qp83, NewQp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(85, + Qp85, NewQp85, + {Qp81, Qp82, Qp83, Qp84, NewQp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(86, + Qp86, NewQp86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + NewQp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(87, + Qp87, NewQp87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, NewQp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(88, + Qp88, NewQp88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, NewQp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(89, + Qp89, NewQp89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, NewQp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(90, + Qp90, NewQp90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, NewQp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(91, + Qp91, NewQp91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, NewQp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(92, + Qp92, NewQp92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + NewQp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(93, + Qp93, NewQp93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, NewQp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(94, + Qp94, NewQp94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, NewQp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(95, + Qp95, NewQp95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, NewQp95, Qp96}); +?OUT_CURRENT_Qp96(96, + Qp96, NewQp96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, NewQp96}); +?OUT_CURRENT_Qp112(97, + Qp97, NewQp97, + {NewQp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(98, + Qp98, NewQp98, + {Qp97, NewQp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(99, + Qp99, NewQp99, + {Qp97, Qp98, NewQp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(100, + Qp100, NewQp100, + {Qp97, Qp98, Qp99, NewQp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(101, + Qp101, NewQp101, + {Qp97, Qp98, Qp99, Qp100, NewQp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(102, + Qp102, NewQp102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + NewQp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(103, + Qp103, NewQp103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, NewQp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(104, + Qp104, NewQp104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, NewQp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(105, + Qp105, NewQp105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, NewQp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(106, + Qp106, NewQp106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, NewQp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(107, + Qp107, NewQp107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, NewQp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(108, + Qp108, NewQp108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + NewQp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(109, + Qp109, NewQp109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, NewQp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(110, + Qp110, NewQp110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, NewQp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(111, + Qp111, NewQp111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, NewQp111, Qp112}); +?OUT_CURRENT_Qp112(112, + Qp112, NewQp112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, NewQp112}); +?OUT_CURRENT_Qp128(113, + Qp113, NewQp113, + {NewQp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(114, + Qp114, NewQp114, + {Qp113, NewQp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(115, + Qp115, NewQp115, + {Qp113, Qp114, NewQp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(116, + Qp116, NewQp116, + {Qp113, Qp114, Qp115, NewQp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(117, + Qp117, NewQp117, + {Qp113, Qp114, Qp115, Qp116, NewQp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(118, + Qp118, NewQp118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + NewQp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(119, + Qp119, NewQp119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, NewQp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(120, + Qp120, NewQp120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, NewQp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(121, + Qp121, NewQp121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, NewQp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(122, + Qp122, NewQp122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, NewQp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(123, + Qp123, NewQp123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, NewQp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(124, + Qp124, NewQp124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + NewQp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(125, + Qp125, NewQp125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, NewQp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(126, + Qp126, NewQp126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, NewQp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(127, + Qp127, NewQp127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, NewQp127, Qp128}); +out_current(128, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}) -> + {Value, NewQp128} = queue:out(Qp128), + if + Value =:= empty -> + {empty, + {empty, + 0, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, NewQp128}}}; + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> 128 end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, NewQp128}}} + end. + +%% @hidden +-define(OUT_CURRENT_P_Qn128(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + V3, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn112(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, + V3, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn96(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, + V3, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn80(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, + V3, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn64(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, + V3, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn48(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, + V3, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn32(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V3, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn16(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V3, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp16(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V3, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp32(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V3, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp48(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V3, + Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp64(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V3, + Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp80(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V3, + Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp96(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V3, + Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp112(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V3, + Qp128}} + end). +-define(OUT_CURRENT_P_Qp128(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V3}} + end). + +?OUT_CURRENT_P_Qn128(-128, + Qn128, NewQn128, + {NewQn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-127, + Qn127, NewQn127, + {Qn128, NewQn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-126, + Qn126, NewQn126, + {Qn128, Qn127, NewQn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-125, + Qn125, NewQn125, + {Qn128, Qn127, Qn126, NewQn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-124, + Qn124, NewQn124, + {Qn128, Qn127, Qn126, Qn125, NewQn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-123, + Qn123, NewQn123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + NewQn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-122, + Qn122, NewQn122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, NewQn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-121, + Qn121, NewQn121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, NewQn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-120, + Qn120, NewQn120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, NewQn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-119, + Qn119, NewQn119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, NewQn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-118, + Qn118, NewQn118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, NewQn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-117, + Qn117, NewQn117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + NewQn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-116, + Qn116, NewQn116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, NewQn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-115, + Qn115, NewQn115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, NewQn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-114, + Qn114, NewQn114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, NewQn114, Qn113}); +?OUT_CURRENT_P_Qn128(-113, + Qn113, NewQn113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, NewQn113}); +?OUT_CURRENT_P_Qn112(-112, + Qn112, NewQn112, + {NewQn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-111, + Qn111, NewQn111, + {Qn112, NewQn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-110, + Qn110, NewQn110, + {Qn112, Qn111, NewQn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-109, + Qn109, NewQn109, + {Qn112, Qn111, Qn110, NewQn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-108, + Qn108, NewQn108, + {Qn112, Qn111, Qn110, Qn109, NewQn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-107, + Qn107, NewQn107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + NewQn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-106, + Qn106, NewQn106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, NewQn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-105, + Qn105, NewQn105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, NewQn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-104, + Qn104, NewQn104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, NewQn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-103, + Qn103, NewQn103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, NewQn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-102, + Qn102, NewQn102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, NewQn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-101, + Qn101, NewQn101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + NewQn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-100, + Qn100, NewQn100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, NewQn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-99, + Qn99, NewQn99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, NewQn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-98, + Qn98, NewQn98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, NewQn98, Qn97}); +?OUT_CURRENT_P_Qn112(-97, + Qn97, NewQn97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, NewQn97}); +?OUT_CURRENT_P_Qn96(-96, + Qn96, NewQn96, + {NewQn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-95, + Qn95, NewQn95, + {Qn96, NewQn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-94, + Qn94, NewQn94, + {Qn96, Qn95, NewQn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-93, + Qn93, NewQn93, + {Qn96, Qn95, Qn94, NewQn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-92, + Qn92, NewQn92, + {Qn96, Qn95, Qn94, Qn93, NewQn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-91, + Qn91, NewQn91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + NewQn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-90, + Qn90, NewQn90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, NewQn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-89, + Qn89, NewQn89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, NewQn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-88, + Qn88, NewQn88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, NewQn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-87, + Qn87, NewQn87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, NewQn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-86, + Qn86, NewQn86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, NewQn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-85, + Qn85, NewQn85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + NewQn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-84, + Qn84, NewQn84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, NewQn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-83, + Qn83, NewQn83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, NewQn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-82, + Qn82, NewQn82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, NewQn82, Qn81}); +?OUT_CURRENT_P_Qn96(-81, + Qn81, NewQn81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, NewQn81}); +?OUT_CURRENT_P_Qn80(-80, + Qn80, NewQn80, + {NewQn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-79, + Qn79, NewQn79, + {Qn80, NewQn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-78, + Qn78, NewQn78, + {Qn80, Qn79, NewQn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-77, + Qn77, NewQn77, + {Qn80, Qn79, Qn78, NewQn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-76, + Qn76, NewQn76, + {Qn80, Qn79, Qn78, Qn77, NewQn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-75, + Qn75, NewQn75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + NewQn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-74, + Qn74, NewQn74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, NewQn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-73, + Qn73, NewQn73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, NewQn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-72, + Qn72, NewQn72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, NewQn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-71, + Qn71, NewQn71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, NewQn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-70, + Qn70, NewQn70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, NewQn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-69, + Qn69, NewQn69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + NewQn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-68, + Qn68, NewQn68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, NewQn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-67, + Qn67, NewQn67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, NewQn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-66, + Qn66, NewQn66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, NewQn66, Qn65}); +?OUT_CURRENT_P_Qn80(-65, + Qn65, NewQn65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, NewQn65}); +?OUT_CURRENT_P_Qn64(-64, + Qn64, NewQn64, + {NewQn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-63, + Qn63, NewQn63, + {Qn64, NewQn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-62, + Qn62, NewQn62, + {Qn64, Qn63, NewQn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-61, + Qn61, NewQn61, + {Qn64, Qn63, Qn62, NewQn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-60, + Qn60, NewQn60, + {Qn64, Qn63, Qn62, Qn61, NewQn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-59, + Qn59, NewQn59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + NewQn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-58, + Qn58, NewQn58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, NewQn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-57, + Qn57, NewQn57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, NewQn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-56, + Qn56, NewQn56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, NewQn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-55, + Qn55, NewQn55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, NewQn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-54, + Qn54, NewQn54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, NewQn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-53, + Qn53, NewQn53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + NewQn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-52, + Qn52, NewQn52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, NewQn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-51, + Qn51, NewQn51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, NewQn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-50, + Qn50, NewQn50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, NewQn50, Qn49}); +?OUT_CURRENT_P_Qn64(-49, + Qn49, NewQn49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, NewQn49}); +?OUT_CURRENT_P_Qn48(-48, + Qn48, NewQn48, + {NewQn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-47, + Qn47, NewQn47, + {Qn48, NewQn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-46, + Qn46, NewQn46, + {Qn48, Qn47, NewQn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-45, + Qn45, NewQn45, + {Qn48, Qn47, Qn46, NewQn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-44, + Qn44, NewQn44, + {Qn48, Qn47, Qn46, Qn45, NewQn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-43, + Qn43, NewQn43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + NewQn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-42, + Qn42, NewQn42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, NewQn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-41, + Qn41, NewQn41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, NewQn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-40, + Qn40, NewQn40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, NewQn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-39, + Qn39, NewQn39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, NewQn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-38, + Qn38, NewQn38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, NewQn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-37, + Qn37, NewQn37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + NewQn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-36, + Qn36, NewQn36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, NewQn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-35, + Qn35, NewQn35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, NewQn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-34, + Qn34, NewQn34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, NewQn34, Qn33}); +?OUT_CURRENT_P_Qn48(-33, + Qn33, NewQn33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, NewQn33}); +?OUT_CURRENT_P_Qn32(-32, + Qn32, NewQn32, + {NewQn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-31, + Qn31, NewQn31, + {Qn32, NewQn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-30, + Qn30, NewQn30, + {Qn32, Qn31, NewQn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-29, + Qn29, NewQn29, + {Qn32, Qn31, Qn30, NewQn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-28, + Qn28, NewQn28, + {Qn32, Qn31, Qn30, Qn29, NewQn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-27, + Qn27, NewQn27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + NewQn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-26, + Qn26, NewQn26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, NewQn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-25, + Qn25, NewQn25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, NewQn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-24, + Qn24, NewQn24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, NewQn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-23, + Qn23, NewQn23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, NewQn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-22, + Qn22, NewQn22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, NewQn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-21, + Qn21, NewQn21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + NewQn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-20, + Qn20, NewQn20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, NewQn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-19, + Qn19, NewQn19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, NewQn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-18, + Qn18, NewQn18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, NewQn18, Qn17}); +?OUT_CURRENT_P_Qn32(-17, + Qn17, NewQn17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, NewQn17}); +?OUT_CURRENT_P_Qn16(-16, + Qn16, NewQn16, + {NewQn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-15, + Qn15, NewQn15, + {Qn16, NewQn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-14, + Qn14, NewQn14, + {Qn16, Qn15, NewQn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-13, + Qn13, NewQn13, + {Qn16, Qn15, Qn14, NewQn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-12, + Qn12, NewQn12, + {Qn16, Qn15, Qn14, Qn13, NewQn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-11, + Qn11, NewQn11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + NewQn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-10, + Qn10, NewQn10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, NewQn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-9, + Qn9, NewQn9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, NewQn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-8, + Qn8, NewQn8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, NewQn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-7, + Qn7, NewQn7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, NewQn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-6, + Qn6, NewQn6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, NewQn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-5, + Qn5, NewQn5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + NewQn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-4, + Qn4, NewQn4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, NewQn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-3, + Qn3, NewQn3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, NewQn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-2, + Qn2, NewQn2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, NewQn2, Qn1}); +?OUT_CURRENT_P_Qn16(-1, + Qn1, NewQn1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, NewQn1}); +out_current_p(0, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(Q0) of + {empty, _} -> + out_current_p(1, Q); + {{value, X}, NewQ0} -> + NewSize = Size - 1, + {{value, X, 0}, + {if NewSize == 0 -> empty; true -> 0 end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + NewQ0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end; +?OUT_CURRENT_P_Qp16(1, + Qp1, NewQp1, + {NewQp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(2, + Qp2, NewQp2, + {Qp1, NewQp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(3, + Qp3, NewQp3, + {Qp1, Qp2, NewQp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(4, + Qp4, NewQp4, + {Qp1, Qp2, Qp3, NewQp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(5, + Qp5, NewQp5, + {Qp1, Qp2, Qp3, Qp4, NewQp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(6, + Qp6, NewQp6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + NewQp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(7, + Qp7, NewQp7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, NewQp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(8, + Qp8, NewQp8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, NewQp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(9, + Qp9, NewQp9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, NewQp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(10, + Qp10, NewQp10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, NewQp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(11, + Qp11, NewQp11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, NewQp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(12, + Qp12, NewQp12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + NewQp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(13, + Qp13, NewQp13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, NewQp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(14, + Qp14, NewQp14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, NewQp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(15, + Qp15, NewQp15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, NewQp15, Qp16}); +?OUT_CURRENT_P_Qp16(16, + Qp16, NewQp16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, NewQp16}); +?OUT_CURRENT_P_Qp32(17, + Qp17, NewQp17, + {NewQp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(18, + Qp18, NewQp18, + {Qp17, NewQp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(19, + Qp19, NewQp19, + {Qp17, Qp18, NewQp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(20, + Qp20, NewQp20, + {Qp17, Qp18, Qp19, NewQp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(21, + Qp21, NewQp21, + {Qp17, Qp18, Qp19, Qp20, NewQp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(22, + Qp22, NewQp22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + NewQp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(23, + Qp23, NewQp23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, NewQp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(24, + Qp24, NewQp24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, NewQp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(25, + Qp25, NewQp25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, NewQp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(26, + Qp26, NewQp26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, NewQp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(27, + Qp27, NewQp27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, NewQp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(28, + Qp28, NewQp28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + NewQp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(29, + Qp29, NewQp29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, NewQp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(30, + Qp30, NewQp30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, NewQp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(31, + Qp31, NewQp31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, NewQp31, Qp32}); +?OUT_CURRENT_P_Qp32(32, + Qp32, NewQp32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, NewQp32}); +?OUT_CURRENT_P_Qp48(33, + Qp33, NewQp33, + {NewQp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(34, + Qp34, NewQp34, + {Qp33, NewQp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(35, + Qp35, NewQp35, + {Qp33, Qp34, NewQp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(36, + Qp36, NewQp36, + {Qp33, Qp34, Qp35, NewQp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(37, + Qp37, NewQp37, + {Qp33, Qp34, Qp35, Qp36, NewQp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(38, + Qp38, NewQp38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + NewQp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(39, + Qp39, NewQp39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, NewQp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(40, + Qp40, NewQp40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, NewQp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(41, + Qp41, NewQp41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, NewQp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(42, + Qp42, NewQp42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, NewQp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(43, + Qp43, NewQp43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, NewQp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(44, + Qp44, NewQp44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + NewQp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(45, + Qp45, NewQp45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, NewQp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(46, + Qp46, NewQp46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, NewQp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(47, + Qp47, NewQp47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, NewQp47, Qp48}); +?OUT_CURRENT_P_Qp48(48, + Qp48, NewQp48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, NewQp48}); +?OUT_CURRENT_P_Qp64(49, + Qp49, NewQp49, + {NewQp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(50, + Qp50, NewQp50, + {Qp49, NewQp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(51, + Qp51, NewQp51, + {Qp49, Qp50, NewQp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(52, + Qp52, NewQp52, + {Qp49, Qp50, Qp51, NewQp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(53, + Qp53, NewQp53, + {Qp49, Qp50, Qp51, Qp52, NewQp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(54, + Qp54, NewQp54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + NewQp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(55, + Qp55, NewQp55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, NewQp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(56, + Qp56, NewQp56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, NewQp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(57, + Qp57, NewQp57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, NewQp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(58, + Qp58, NewQp58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, NewQp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(59, + Qp59, NewQp59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, NewQp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(60, + Qp60, NewQp60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + NewQp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(61, + Qp61, NewQp61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, NewQp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(62, + Qp62, NewQp62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, NewQp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(63, + Qp63, NewQp63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, NewQp63, Qp64}); +?OUT_CURRENT_P_Qp64(64, + Qp64, NewQp64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, NewQp64}); +?OUT_CURRENT_P_Qp80(65, + Qp65, NewQp65, + {NewQp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(66, + Qp66, NewQp66, + {Qp65, NewQp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(67, + Qp67, NewQp67, + {Qp65, Qp66, NewQp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(68, + Qp68, NewQp68, + {Qp65, Qp66, Qp67, NewQp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(69, + Qp69, NewQp69, + {Qp65, Qp66, Qp67, Qp68, NewQp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(70, + Qp70, NewQp70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + NewQp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(71, + Qp71, NewQp71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, NewQp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(72, + Qp72, NewQp72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, NewQp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(73, + Qp73, NewQp73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, NewQp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(74, + Qp74, NewQp74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, NewQp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(75, + Qp75, NewQp75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, NewQp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(76, + Qp76, NewQp76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + NewQp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(77, + Qp77, NewQp77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, NewQp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(78, + Qp78, NewQp78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, NewQp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(79, + Qp79, NewQp79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, NewQp79, Qp80}); +?OUT_CURRENT_P_Qp80(80, + Qp80, NewQp80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, NewQp80}); +?OUT_CURRENT_P_Qp96(81, + Qp81, NewQp81, + {NewQp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(82, + Qp82, NewQp82, + {Qp81, NewQp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(83, + Qp83, NewQp83, + {Qp81, Qp82, NewQp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(84, + Qp84, NewQp84, + {Qp81, Qp82, Qp83, NewQp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(85, + Qp85, NewQp85, + {Qp81, Qp82, Qp83, Qp84, NewQp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(86, + Qp86, NewQp86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + NewQp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(87, + Qp87, NewQp87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, NewQp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(88, + Qp88, NewQp88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, NewQp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(89, + Qp89, NewQp89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, NewQp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(90, + Qp90, NewQp90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, NewQp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(91, + Qp91, NewQp91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, NewQp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(92, + Qp92, NewQp92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + NewQp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(93, + Qp93, NewQp93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, NewQp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(94, + Qp94, NewQp94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, NewQp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(95, + Qp95, NewQp95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, NewQp95, Qp96}); +?OUT_CURRENT_P_Qp96(96, + Qp96, NewQp96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, NewQp96}); +?OUT_CURRENT_P_Qp112(97, + Qp97, NewQp97, + {NewQp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(98, + Qp98, NewQp98, + {Qp97, NewQp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(99, + Qp99, NewQp99, + {Qp97, Qp98, NewQp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(100, + Qp100, NewQp100, + {Qp97, Qp98, Qp99, NewQp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(101, + Qp101, NewQp101, + {Qp97, Qp98, Qp99, Qp100, NewQp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(102, + Qp102, NewQp102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + NewQp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(103, + Qp103, NewQp103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, NewQp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(104, + Qp104, NewQp104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, NewQp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(105, + Qp105, NewQp105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, NewQp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(106, + Qp106, NewQp106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, NewQp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(107, + Qp107, NewQp107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, NewQp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(108, + Qp108, NewQp108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + NewQp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(109, + Qp109, NewQp109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, NewQp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(110, + Qp110, NewQp110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, NewQp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(111, + Qp111, NewQp111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, NewQp111, Qp112}); +?OUT_CURRENT_P_Qp112(112, + Qp112, NewQp112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, NewQp112}); +?OUT_CURRENT_P_Qp128(113, + Qp113, NewQp113, + {NewQp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(114, + Qp114, NewQp114, + {Qp113, NewQp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(115, + Qp115, NewQp115, + {Qp113, Qp114, NewQp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(116, + Qp116, NewQp116, + {Qp113, Qp114, Qp115, NewQp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(117, + Qp117, NewQp117, + {Qp113, Qp114, Qp115, Qp116, NewQp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(118, + Qp118, NewQp118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + NewQp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(119, + Qp119, NewQp119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, NewQp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(120, + Qp120, NewQp120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, NewQp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(121, + Qp121, NewQp121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, NewQp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(122, + Qp122, NewQp122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, NewQp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(123, + Qp123, NewQp123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, NewQp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(124, + Qp124, NewQp124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + NewQp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(125, + Qp125, NewQp125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, NewQp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(126, + Qp126, NewQp126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, NewQp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(127, + Qp127, NewQp127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, NewQp127, Qp128}); +out_current_p(128, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}) -> + case queue:out(Qp128) of + {empty, _} -> + {empty, + {empty, + 0, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}}; + {{value, X}, NewQp128} -> + NewSize = Size - 1, + {{value, X, 128}, + {if NewSize == 0 -> empty; true -> 128 end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, NewQp128}}} + end. + +%% @hidden +-define(OUT_SPECIFIC_Qn128(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + V3, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn112(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, + V3, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn96(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, + V3, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn80(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, + V3, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn64(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, + V3, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn48(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, + V3, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn32(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V3, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn16(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V3, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp16(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V3, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp32(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V3, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp48(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V3, + Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp64(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V3, + Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp80(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V3, + Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp96(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V3, + Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp112(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V3, + Qp128}}). +-define(OUT_SPECIFIC_Qp128(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V3}}). + +?OUT_SPECIFIC_Qn128(-128, + Qn128, NewQn128, + {NewQn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-127, + Qn127, NewQn127, + {Qn128, NewQn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-126, + Qn126, NewQn126, + {Qn128, Qn127, NewQn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-125, + Qn125, NewQn125, + {Qn128, Qn127, Qn126, NewQn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-124, + Qn124, NewQn124, + {Qn128, Qn127, Qn126, Qn125, NewQn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-123, + Qn123, NewQn123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + NewQn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-122, + Qn122, NewQn122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, NewQn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-121, + Qn121, NewQn121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, NewQn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-120, + Qn120, NewQn120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, NewQn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-119, + Qn119, NewQn119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, NewQn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-118, + Qn118, NewQn118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, NewQn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-117, + Qn117, NewQn117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + NewQn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-116, + Qn116, NewQn116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, NewQn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-115, + Qn115, NewQn115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, NewQn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-114, + Qn114, NewQn114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, NewQn114, Qn113}); +?OUT_SPECIFIC_Qn128(-113, + Qn113, NewQn113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, NewQn113}); +?OUT_SPECIFIC_Qn112(-112, + Qn112, NewQn112, + {NewQn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-111, + Qn111, NewQn111, + {Qn112, NewQn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-110, + Qn110, NewQn110, + {Qn112, Qn111, NewQn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-109, + Qn109, NewQn109, + {Qn112, Qn111, Qn110, NewQn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-108, + Qn108, NewQn108, + {Qn112, Qn111, Qn110, Qn109, NewQn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-107, + Qn107, NewQn107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + NewQn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-106, + Qn106, NewQn106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, NewQn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-105, + Qn105, NewQn105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, NewQn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-104, + Qn104, NewQn104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, NewQn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-103, + Qn103, NewQn103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, NewQn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-102, + Qn102, NewQn102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, NewQn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-101, + Qn101, NewQn101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + NewQn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-100, + Qn100, NewQn100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, NewQn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-99, + Qn99, NewQn99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, NewQn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-98, + Qn98, NewQn98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, NewQn98, Qn97}); +?OUT_SPECIFIC_Qn112(-97, + Qn97, NewQn97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, NewQn97}); +?OUT_SPECIFIC_Qn96(-96, + Qn96, NewQn96, + {NewQn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-95, + Qn95, NewQn95, + {Qn96, NewQn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-94, + Qn94, NewQn94, + {Qn96, Qn95, NewQn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-93, + Qn93, NewQn93, + {Qn96, Qn95, Qn94, NewQn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-92, + Qn92, NewQn92, + {Qn96, Qn95, Qn94, Qn93, NewQn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-91, + Qn91, NewQn91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + NewQn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-90, + Qn90, NewQn90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, NewQn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-89, + Qn89, NewQn89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, NewQn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-88, + Qn88, NewQn88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, NewQn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-87, + Qn87, NewQn87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, NewQn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-86, + Qn86, NewQn86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, NewQn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-85, + Qn85, NewQn85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + NewQn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-84, + Qn84, NewQn84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, NewQn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-83, + Qn83, NewQn83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, NewQn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-82, + Qn82, NewQn82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, NewQn82, Qn81}); +?OUT_SPECIFIC_Qn96(-81, + Qn81, NewQn81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, NewQn81}); +?OUT_SPECIFIC_Qn80(-80, + Qn80, NewQn80, + {NewQn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-79, + Qn79, NewQn79, + {Qn80, NewQn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-78, + Qn78, NewQn78, + {Qn80, Qn79, NewQn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-77, + Qn77, NewQn77, + {Qn80, Qn79, Qn78, NewQn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-76, + Qn76, NewQn76, + {Qn80, Qn79, Qn78, Qn77, NewQn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-75, + Qn75, NewQn75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + NewQn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-74, + Qn74, NewQn74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, NewQn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-73, + Qn73, NewQn73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, NewQn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-72, + Qn72, NewQn72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, NewQn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-71, + Qn71, NewQn71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, NewQn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-70, + Qn70, NewQn70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, NewQn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-69, + Qn69, NewQn69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + NewQn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-68, + Qn68, NewQn68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, NewQn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-67, + Qn67, NewQn67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, NewQn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-66, + Qn66, NewQn66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, NewQn66, Qn65}); +?OUT_SPECIFIC_Qn80(-65, + Qn65, NewQn65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, NewQn65}); +?OUT_SPECIFIC_Qn64(-64, + Qn64, NewQn64, + {NewQn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-63, + Qn63, NewQn63, + {Qn64, NewQn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-62, + Qn62, NewQn62, + {Qn64, Qn63, NewQn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-61, + Qn61, NewQn61, + {Qn64, Qn63, Qn62, NewQn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-60, + Qn60, NewQn60, + {Qn64, Qn63, Qn62, Qn61, NewQn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-59, + Qn59, NewQn59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + NewQn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-58, + Qn58, NewQn58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, NewQn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-57, + Qn57, NewQn57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, NewQn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-56, + Qn56, NewQn56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, NewQn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-55, + Qn55, NewQn55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, NewQn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-54, + Qn54, NewQn54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, NewQn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-53, + Qn53, NewQn53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + NewQn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-52, + Qn52, NewQn52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, NewQn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-51, + Qn51, NewQn51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, NewQn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-50, + Qn50, NewQn50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, NewQn50, Qn49}); +?OUT_SPECIFIC_Qn64(-49, + Qn49, NewQn49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, NewQn49}); +?OUT_SPECIFIC_Qn48(-48, + Qn48, NewQn48, + {NewQn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-47, + Qn47, NewQn47, + {Qn48, NewQn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-46, + Qn46, NewQn46, + {Qn48, Qn47, NewQn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-45, + Qn45, NewQn45, + {Qn48, Qn47, Qn46, NewQn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-44, + Qn44, NewQn44, + {Qn48, Qn47, Qn46, Qn45, NewQn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-43, + Qn43, NewQn43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + NewQn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-42, + Qn42, NewQn42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, NewQn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-41, + Qn41, NewQn41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, NewQn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-40, + Qn40, NewQn40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, NewQn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-39, + Qn39, NewQn39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, NewQn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-38, + Qn38, NewQn38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, NewQn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-37, + Qn37, NewQn37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + NewQn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-36, + Qn36, NewQn36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, NewQn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-35, + Qn35, NewQn35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, NewQn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-34, + Qn34, NewQn34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, NewQn34, Qn33}); +?OUT_SPECIFIC_Qn48(-33, + Qn33, NewQn33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, NewQn33}); +?OUT_SPECIFIC_Qn32(-32, + Qn32, NewQn32, + {NewQn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-31, + Qn31, NewQn31, + {Qn32, NewQn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-30, + Qn30, NewQn30, + {Qn32, Qn31, NewQn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-29, + Qn29, NewQn29, + {Qn32, Qn31, Qn30, NewQn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-28, + Qn28, NewQn28, + {Qn32, Qn31, Qn30, Qn29, NewQn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-27, + Qn27, NewQn27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + NewQn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-26, + Qn26, NewQn26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, NewQn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-25, + Qn25, NewQn25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, NewQn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-24, + Qn24, NewQn24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, NewQn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-23, + Qn23, NewQn23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, NewQn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-22, + Qn22, NewQn22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, NewQn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-21, + Qn21, NewQn21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + NewQn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-20, + Qn20, NewQn20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, NewQn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-19, + Qn19, NewQn19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, NewQn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-18, + Qn18, NewQn18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, NewQn18, Qn17}); +?OUT_SPECIFIC_Qn32(-17, + Qn17, NewQn17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, NewQn17}); +?OUT_SPECIFIC_Qn16(-16, + Qn16, NewQn16, + {NewQn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-15, + Qn15, NewQn15, + {Qn16, NewQn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-14, + Qn14, NewQn14, + {Qn16, Qn15, NewQn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-13, + Qn13, NewQn13, + {Qn16, Qn15, Qn14, NewQn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-12, + Qn12, NewQn12, + {Qn16, Qn15, Qn14, Qn13, NewQn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-11, + Qn11, NewQn11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + NewQn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-10, + Qn10, NewQn10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, NewQn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-9, + Qn9, NewQn9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, NewQn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-8, + Qn8, NewQn8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, NewQn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-7, + Qn7, NewQn7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, NewQn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-6, + Qn6, NewQn6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, NewQn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-5, + Qn5, NewQn5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + NewQn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-4, + Qn4, NewQn4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, NewQn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-3, + Qn3, NewQn3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, NewQn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-2, + Qn2, NewQn2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, NewQn2, Qn1}); +?OUT_SPECIFIC_Qn16(-1, + Qn1, NewQn1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, NewQn1}); +out_specific(0, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, NewQ0} = queue:out(Q0), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + NewQ0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}; +?OUT_SPECIFIC_Qp16(1, + Qp1, NewQp1, + {NewQp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(2, + Qp2, NewQp2, + {Qp1, NewQp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(3, + Qp3, NewQp3, + {Qp1, Qp2, NewQp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(4, + Qp4, NewQp4, + {Qp1, Qp2, Qp3, NewQp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(5, + Qp5, NewQp5, + {Qp1, Qp2, Qp3, Qp4, NewQp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(6, + Qp6, NewQp6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + NewQp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(7, + Qp7, NewQp7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, NewQp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(8, + Qp8, NewQp8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, NewQp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(9, + Qp9, NewQp9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, NewQp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(10, + Qp10, NewQp10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, NewQp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(11, + Qp11, NewQp11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, NewQp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(12, + Qp12, NewQp12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + NewQp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(13, + Qp13, NewQp13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, NewQp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(14, + Qp14, NewQp14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, NewQp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(15, + Qp15, NewQp15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, NewQp15, Qp16}); +?OUT_SPECIFIC_Qp16(16, + Qp16, NewQp16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, NewQp16}); +?OUT_SPECIFIC_Qp32(17, + Qp17, NewQp17, + {NewQp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(18, + Qp18, NewQp18, + {Qp17, NewQp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(19, + Qp19, NewQp19, + {Qp17, Qp18, NewQp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(20, + Qp20, NewQp20, + {Qp17, Qp18, Qp19, NewQp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(21, + Qp21, NewQp21, + {Qp17, Qp18, Qp19, Qp20, NewQp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(22, + Qp22, NewQp22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + NewQp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(23, + Qp23, NewQp23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, NewQp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(24, + Qp24, NewQp24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, NewQp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(25, + Qp25, NewQp25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, NewQp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(26, + Qp26, NewQp26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, NewQp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(27, + Qp27, NewQp27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, NewQp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(28, + Qp28, NewQp28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + NewQp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(29, + Qp29, NewQp29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, NewQp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(30, + Qp30, NewQp30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, NewQp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(31, + Qp31, NewQp31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, NewQp31, Qp32}); +?OUT_SPECIFIC_Qp32(32, + Qp32, NewQp32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, NewQp32}); +?OUT_SPECIFIC_Qp48(33, + Qp33, NewQp33, + {NewQp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(34, + Qp34, NewQp34, + {Qp33, NewQp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(35, + Qp35, NewQp35, + {Qp33, Qp34, NewQp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(36, + Qp36, NewQp36, + {Qp33, Qp34, Qp35, NewQp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(37, + Qp37, NewQp37, + {Qp33, Qp34, Qp35, Qp36, NewQp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(38, + Qp38, NewQp38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + NewQp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(39, + Qp39, NewQp39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, NewQp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(40, + Qp40, NewQp40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, NewQp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(41, + Qp41, NewQp41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, NewQp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(42, + Qp42, NewQp42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, NewQp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(43, + Qp43, NewQp43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, NewQp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(44, + Qp44, NewQp44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + NewQp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(45, + Qp45, NewQp45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, NewQp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(46, + Qp46, NewQp46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, NewQp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(47, + Qp47, NewQp47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, NewQp47, Qp48}); +?OUT_SPECIFIC_Qp48(48, + Qp48, NewQp48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, NewQp48}); +?OUT_SPECIFIC_Qp64(49, + Qp49, NewQp49, + {NewQp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(50, + Qp50, NewQp50, + {Qp49, NewQp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(51, + Qp51, NewQp51, + {Qp49, Qp50, NewQp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(52, + Qp52, NewQp52, + {Qp49, Qp50, Qp51, NewQp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(53, + Qp53, NewQp53, + {Qp49, Qp50, Qp51, Qp52, NewQp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(54, + Qp54, NewQp54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + NewQp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(55, + Qp55, NewQp55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, NewQp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(56, + Qp56, NewQp56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, NewQp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(57, + Qp57, NewQp57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, NewQp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(58, + Qp58, NewQp58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, NewQp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(59, + Qp59, NewQp59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, NewQp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(60, + Qp60, NewQp60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + NewQp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(61, + Qp61, NewQp61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, NewQp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(62, + Qp62, NewQp62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, NewQp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(63, + Qp63, NewQp63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, NewQp63, Qp64}); +?OUT_SPECIFIC_Qp64(64, + Qp64, NewQp64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, NewQp64}); +?OUT_SPECIFIC_Qp80(65, + Qp65, NewQp65, + {NewQp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(66, + Qp66, NewQp66, + {Qp65, NewQp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(67, + Qp67, NewQp67, + {Qp65, Qp66, NewQp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(68, + Qp68, NewQp68, + {Qp65, Qp66, Qp67, NewQp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(69, + Qp69, NewQp69, + {Qp65, Qp66, Qp67, Qp68, NewQp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(70, + Qp70, NewQp70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + NewQp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(71, + Qp71, NewQp71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, NewQp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(72, + Qp72, NewQp72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, NewQp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(73, + Qp73, NewQp73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, NewQp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(74, + Qp74, NewQp74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, NewQp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(75, + Qp75, NewQp75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, NewQp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(76, + Qp76, NewQp76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + NewQp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(77, + Qp77, NewQp77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, NewQp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(78, + Qp78, NewQp78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, NewQp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(79, + Qp79, NewQp79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, NewQp79, Qp80}); +?OUT_SPECIFIC_Qp80(80, + Qp80, NewQp80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, NewQp80}); +?OUT_SPECIFIC_Qp96(81, + Qp81, NewQp81, + {NewQp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(82, + Qp82, NewQp82, + {Qp81, NewQp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(83, + Qp83, NewQp83, + {Qp81, Qp82, NewQp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(84, + Qp84, NewQp84, + {Qp81, Qp82, Qp83, NewQp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(85, + Qp85, NewQp85, + {Qp81, Qp82, Qp83, Qp84, NewQp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(86, + Qp86, NewQp86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + NewQp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(87, + Qp87, NewQp87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, NewQp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(88, + Qp88, NewQp88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, NewQp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(89, + Qp89, NewQp89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, NewQp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(90, + Qp90, NewQp90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, NewQp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(91, + Qp91, NewQp91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, NewQp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(92, + Qp92, NewQp92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + NewQp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(93, + Qp93, NewQp93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, NewQp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(94, + Qp94, NewQp94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, NewQp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(95, + Qp95, NewQp95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, NewQp95, Qp96}); +?OUT_SPECIFIC_Qp96(96, + Qp96, NewQp96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, NewQp96}); +?OUT_SPECIFIC_Qp112(97, + Qp97, NewQp97, + {NewQp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(98, + Qp98, NewQp98, + {Qp97, NewQp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(99, + Qp99, NewQp99, + {Qp97, Qp98, NewQp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(100, + Qp100, NewQp100, + {Qp97, Qp98, Qp99, NewQp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(101, + Qp101, NewQp101, + {Qp97, Qp98, Qp99, Qp100, NewQp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(102, + Qp102, NewQp102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + NewQp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(103, + Qp103, NewQp103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, NewQp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(104, + Qp104, NewQp104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, NewQp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(105, + Qp105, NewQp105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, NewQp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(106, + Qp106, NewQp106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, NewQp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(107, + Qp107, NewQp107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, NewQp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(108, + Qp108, NewQp108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + NewQp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(109, + Qp109, NewQp109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, NewQp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(110, + Qp110, NewQp110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, NewQp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(111, + Qp111, NewQp111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, NewQp111, Qp112}); +?OUT_SPECIFIC_Qp112(112, + Qp112, NewQp112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, NewQp112}); +?OUT_SPECIFIC_Qp128(113, + Qp113, NewQp113, + {NewQp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(114, + Qp114, NewQp114, + {Qp113, NewQp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(115, + Qp115, NewQp115, + {Qp113, Qp114, NewQp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(116, + Qp116, NewQp116, + {Qp113, Qp114, Qp115, NewQp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(117, + Qp117, NewQp117, + {Qp113, Qp114, Qp115, Qp116, NewQp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(118, + Qp118, NewQp118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + NewQp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(119, + Qp119, NewQp119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, NewQp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(120, + Qp120, NewQp120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, NewQp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(121, + Qp121, NewQp121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, NewQp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(122, + Qp122, NewQp122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, NewQp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(123, + Qp123, NewQp123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, NewQp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(124, + Qp124, NewQp124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + NewQp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(125, + Qp125, NewQp125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, NewQp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(126, + Qp126, NewQp126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, NewQp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(127, + Qp127, NewQp127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, NewQp127, Qp128}); +?OUT_SPECIFIC_Qp128(128, + Qp128, NewQp128, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, NewQp128}). + +%% @hidden +-define(REMOVE_UNIQ_P_Qn128(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + V3, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn112(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, + V3, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn96(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, + V3, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn80(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, + V3, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn64(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, + V3, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn48(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, + V3, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn32(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V3, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn16(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V3, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp16(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V3, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp32(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V3, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp48(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V3, + Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp64(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V3, + Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp80(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V3, + Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp96(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V3, + Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp112(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V3, + Qp128}}). +-define(REMOVE_UNIQ_P_Qp128(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V3}}). + +?REMOVE_UNIQ_P_Qn128(-128, + Qn128, NewQn128, + {NewQn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-127, + Qn127, NewQn127, + {Qn128, NewQn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-126, + Qn126, NewQn126, + {Qn128, Qn127, NewQn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-125, + Qn125, NewQn125, + {Qn128, Qn127, Qn126, NewQn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-124, + Qn124, NewQn124, + {Qn128, Qn127, Qn126, Qn125, NewQn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-123, + Qn123, NewQn123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + NewQn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-122, + Qn122, NewQn122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, NewQn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-121, + Qn121, NewQn121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, NewQn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-120, + Qn120, NewQn120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, NewQn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-119, + Qn119, NewQn119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, NewQn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-118, + Qn118, NewQn118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, NewQn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-117, + Qn117, NewQn117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + NewQn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-116, + Qn116, NewQn116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, NewQn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-115, + Qn115, NewQn115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, NewQn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-114, + Qn114, NewQn114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, NewQn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-113, + Qn113, NewQn113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, NewQn113}); +?REMOVE_UNIQ_P_Qn112(-112, + Qn112, NewQn112, + {NewQn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-111, + Qn111, NewQn111, + {Qn112, NewQn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-110, + Qn110, NewQn110, + {Qn112, Qn111, NewQn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-109, + Qn109, NewQn109, + {Qn112, Qn111, Qn110, NewQn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-108, + Qn108, NewQn108, + {Qn112, Qn111, Qn110, Qn109, NewQn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-107, + Qn107, NewQn107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + NewQn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-106, + Qn106, NewQn106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, NewQn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-105, + Qn105, NewQn105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, NewQn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-104, + Qn104, NewQn104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, NewQn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-103, + Qn103, NewQn103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, NewQn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-102, + Qn102, NewQn102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, NewQn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-101, + Qn101, NewQn101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + NewQn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-100, + Qn100, NewQn100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, NewQn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-99, + Qn99, NewQn99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, NewQn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-98, + Qn98, NewQn98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, NewQn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-97, + Qn97, NewQn97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, NewQn97}); +?REMOVE_UNIQ_P_Qn96(-96, + Qn96, NewQn96, + {NewQn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-95, + Qn95, NewQn95, + {Qn96, NewQn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-94, + Qn94, NewQn94, + {Qn96, Qn95, NewQn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-93, + Qn93, NewQn93, + {Qn96, Qn95, Qn94, NewQn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-92, + Qn92, NewQn92, + {Qn96, Qn95, Qn94, Qn93, NewQn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-91, + Qn91, NewQn91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + NewQn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-90, + Qn90, NewQn90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, NewQn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-89, + Qn89, NewQn89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, NewQn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-88, + Qn88, NewQn88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, NewQn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-87, + Qn87, NewQn87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, NewQn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-86, + Qn86, NewQn86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, NewQn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-85, + Qn85, NewQn85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + NewQn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-84, + Qn84, NewQn84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, NewQn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-83, + Qn83, NewQn83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, NewQn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-82, + Qn82, NewQn82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, NewQn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-81, + Qn81, NewQn81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, NewQn81}); +?REMOVE_UNIQ_P_Qn80(-80, + Qn80, NewQn80, + {NewQn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-79, + Qn79, NewQn79, + {Qn80, NewQn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-78, + Qn78, NewQn78, + {Qn80, Qn79, NewQn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-77, + Qn77, NewQn77, + {Qn80, Qn79, Qn78, NewQn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-76, + Qn76, NewQn76, + {Qn80, Qn79, Qn78, Qn77, NewQn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-75, + Qn75, NewQn75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + NewQn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-74, + Qn74, NewQn74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, NewQn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-73, + Qn73, NewQn73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, NewQn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-72, + Qn72, NewQn72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, NewQn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-71, + Qn71, NewQn71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, NewQn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-70, + Qn70, NewQn70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, NewQn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-69, + Qn69, NewQn69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + NewQn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-68, + Qn68, NewQn68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, NewQn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-67, + Qn67, NewQn67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, NewQn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-66, + Qn66, NewQn66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, NewQn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-65, + Qn65, NewQn65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, NewQn65}); +?REMOVE_UNIQ_P_Qn64(-64, + Qn64, NewQn64, + {NewQn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-63, + Qn63, NewQn63, + {Qn64, NewQn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-62, + Qn62, NewQn62, + {Qn64, Qn63, NewQn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-61, + Qn61, NewQn61, + {Qn64, Qn63, Qn62, NewQn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-60, + Qn60, NewQn60, + {Qn64, Qn63, Qn62, Qn61, NewQn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-59, + Qn59, NewQn59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + NewQn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-58, + Qn58, NewQn58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, NewQn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-57, + Qn57, NewQn57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, NewQn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-56, + Qn56, NewQn56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, NewQn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-55, + Qn55, NewQn55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, NewQn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-54, + Qn54, NewQn54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, NewQn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-53, + Qn53, NewQn53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + NewQn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-52, + Qn52, NewQn52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, NewQn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-51, + Qn51, NewQn51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, NewQn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-50, + Qn50, NewQn50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, NewQn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-49, + Qn49, NewQn49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, NewQn49}); +?REMOVE_UNIQ_P_Qn48(-48, + Qn48, NewQn48, + {NewQn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-47, + Qn47, NewQn47, + {Qn48, NewQn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-46, + Qn46, NewQn46, + {Qn48, Qn47, NewQn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-45, + Qn45, NewQn45, + {Qn48, Qn47, Qn46, NewQn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-44, + Qn44, NewQn44, + {Qn48, Qn47, Qn46, Qn45, NewQn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-43, + Qn43, NewQn43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + NewQn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-42, + Qn42, NewQn42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, NewQn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-41, + Qn41, NewQn41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, NewQn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-40, + Qn40, NewQn40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, NewQn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-39, + Qn39, NewQn39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, NewQn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-38, + Qn38, NewQn38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, NewQn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-37, + Qn37, NewQn37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + NewQn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-36, + Qn36, NewQn36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, NewQn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-35, + Qn35, NewQn35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, NewQn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-34, + Qn34, NewQn34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, NewQn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-33, + Qn33, NewQn33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, NewQn33}); +?REMOVE_UNIQ_P_Qn32(-32, + Qn32, NewQn32, + {NewQn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-31, + Qn31, NewQn31, + {Qn32, NewQn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-30, + Qn30, NewQn30, + {Qn32, Qn31, NewQn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-29, + Qn29, NewQn29, + {Qn32, Qn31, Qn30, NewQn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-28, + Qn28, NewQn28, + {Qn32, Qn31, Qn30, Qn29, NewQn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-27, + Qn27, NewQn27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + NewQn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-26, + Qn26, NewQn26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, NewQn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-25, + Qn25, NewQn25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, NewQn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-24, + Qn24, NewQn24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, NewQn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-23, + Qn23, NewQn23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, NewQn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-22, + Qn22, NewQn22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, NewQn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-21, + Qn21, NewQn21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + NewQn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-20, + Qn20, NewQn20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, NewQn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-19, + Qn19, NewQn19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, NewQn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-18, + Qn18, NewQn18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, NewQn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-17, + Qn17, NewQn17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, NewQn17}); +?REMOVE_UNIQ_P_Qn16(-16, + Qn16, NewQn16, + {NewQn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-15, + Qn15, NewQn15, + {Qn16, NewQn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-14, + Qn14, NewQn14, + {Qn16, Qn15, NewQn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-13, + Qn13, NewQn13, + {Qn16, Qn15, Qn14, NewQn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-12, + Qn12, NewQn12, + {Qn16, Qn15, Qn14, Qn13, NewQn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-11, + Qn11, NewQn11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + NewQn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-10, + Qn10, NewQn10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, NewQn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-9, + Qn9, NewQn9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, NewQn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-8, + Qn8, NewQn8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, NewQn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-7, + Qn7, NewQn7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, NewQn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-6, + Qn6, NewQn6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, NewQn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-5, + Qn5, NewQn5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + NewQn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-4, + Qn4, NewQn4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, NewQn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-3, + Qn3, NewQn3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, NewQn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-2, + Qn2, NewQn2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, NewQn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-1, + Qn1, NewQn1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, NewQn1}); +remove_unique_p(0, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, NewQ0} = queue_remove_unique(F, Q0), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + NewQ0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}; +?REMOVE_UNIQ_P_Qp16(1, + Qp1, NewQp1, + {NewQp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(2, + Qp2, NewQp2, + {Qp1, NewQp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(3, + Qp3, NewQp3, + {Qp1, Qp2, NewQp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(4, + Qp4, NewQp4, + {Qp1, Qp2, Qp3, NewQp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(5, + Qp5, NewQp5, + {Qp1, Qp2, Qp3, Qp4, NewQp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(6, + Qp6, NewQp6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + NewQp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(7, + Qp7, NewQp7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, NewQp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(8, + Qp8, NewQp8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, NewQp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(9, + Qp9, NewQp9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, NewQp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(10, + Qp10, NewQp10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, NewQp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(11, + Qp11, NewQp11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, NewQp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(12, + Qp12, NewQp12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + NewQp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(13, + Qp13, NewQp13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, NewQp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(14, + Qp14, NewQp14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, NewQp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(15, + Qp15, NewQp15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, NewQp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(16, + Qp16, NewQp16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, NewQp16}); +?REMOVE_UNIQ_P_Qp32(17, + Qp17, NewQp17, + {NewQp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(18, + Qp18, NewQp18, + {Qp17, NewQp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(19, + Qp19, NewQp19, + {Qp17, Qp18, NewQp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(20, + Qp20, NewQp20, + {Qp17, Qp18, Qp19, NewQp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(21, + Qp21, NewQp21, + {Qp17, Qp18, Qp19, Qp20, NewQp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(22, + Qp22, NewQp22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + NewQp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(23, + Qp23, NewQp23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, NewQp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(24, + Qp24, NewQp24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, NewQp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(25, + Qp25, NewQp25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, NewQp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(26, + Qp26, NewQp26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, NewQp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(27, + Qp27, NewQp27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, NewQp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(28, + Qp28, NewQp28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + NewQp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(29, + Qp29, NewQp29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, NewQp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(30, + Qp30, NewQp30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, NewQp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(31, + Qp31, NewQp31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, NewQp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(32, + Qp32, NewQp32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, NewQp32}); +?REMOVE_UNIQ_P_Qp48(33, + Qp33, NewQp33, + {NewQp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(34, + Qp34, NewQp34, + {Qp33, NewQp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(35, + Qp35, NewQp35, + {Qp33, Qp34, NewQp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(36, + Qp36, NewQp36, + {Qp33, Qp34, Qp35, NewQp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(37, + Qp37, NewQp37, + {Qp33, Qp34, Qp35, Qp36, NewQp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(38, + Qp38, NewQp38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + NewQp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(39, + Qp39, NewQp39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, NewQp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(40, + Qp40, NewQp40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, NewQp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(41, + Qp41, NewQp41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, NewQp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(42, + Qp42, NewQp42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, NewQp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(43, + Qp43, NewQp43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, NewQp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(44, + Qp44, NewQp44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + NewQp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(45, + Qp45, NewQp45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, NewQp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(46, + Qp46, NewQp46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, NewQp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(47, + Qp47, NewQp47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, NewQp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(48, + Qp48, NewQp48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, NewQp48}); +?REMOVE_UNIQ_P_Qp64(49, + Qp49, NewQp49, + {NewQp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(50, + Qp50, NewQp50, + {Qp49, NewQp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(51, + Qp51, NewQp51, + {Qp49, Qp50, NewQp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(52, + Qp52, NewQp52, + {Qp49, Qp50, Qp51, NewQp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(53, + Qp53, NewQp53, + {Qp49, Qp50, Qp51, Qp52, NewQp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(54, + Qp54, NewQp54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + NewQp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(55, + Qp55, NewQp55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, NewQp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(56, + Qp56, NewQp56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, NewQp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(57, + Qp57, NewQp57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, NewQp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(58, + Qp58, NewQp58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, NewQp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(59, + Qp59, NewQp59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, NewQp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(60, + Qp60, NewQp60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + NewQp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(61, + Qp61, NewQp61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, NewQp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(62, + Qp62, NewQp62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, NewQp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(63, + Qp63, NewQp63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, NewQp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(64, + Qp64, NewQp64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, NewQp64}); +?REMOVE_UNIQ_P_Qp80(65, + Qp65, NewQp65, + {NewQp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(66, + Qp66, NewQp66, + {Qp65, NewQp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(67, + Qp67, NewQp67, + {Qp65, Qp66, NewQp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(68, + Qp68, NewQp68, + {Qp65, Qp66, Qp67, NewQp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(69, + Qp69, NewQp69, + {Qp65, Qp66, Qp67, Qp68, NewQp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(70, + Qp70, NewQp70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + NewQp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(71, + Qp71, NewQp71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, NewQp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(72, + Qp72, NewQp72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, NewQp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(73, + Qp73, NewQp73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, NewQp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(74, + Qp74, NewQp74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, NewQp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(75, + Qp75, NewQp75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, NewQp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(76, + Qp76, NewQp76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + NewQp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(77, + Qp77, NewQp77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, NewQp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(78, + Qp78, NewQp78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, NewQp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(79, + Qp79, NewQp79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, NewQp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(80, + Qp80, NewQp80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, NewQp80}); +?REMOVE_UNIQ_P_Qp96(81, + Qp81, NewQp81, + {NewQp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(82, + Qp82, NewQp82, + {Qp81, NewQp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(83, + Qp83, NewQp83, + {Qp81, Qp82, NewQp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(84, + Qp84, NewQp84, + {Qp81, Qp82, Qp83, NewQp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(85, + Qp85, NewQp85, + {Qp81, Qp82, Qp83, Qp84, NewQp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(86, + Qp86, NewQp86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + NewQp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(87, + Qp87, NewQp87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, NewQp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(88, + Qp88, NewQp88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, NewQp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(89, + Qp89, NewQp89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, NewQp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(90, + Qp90, NewQp90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, NewQp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(91, + Qp91, NewQp91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, NewQp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(92, + Qp92, NewQp92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + NewQp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(93, + Qp93, NewQp93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, NewQp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(94, + Qp94, NewQp94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, NewQp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(95, + Qp95, NewQp95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, NewQp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(96, + Qp96, NewQp96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, NewQp96}); +?REMOVE_UNIQ_P_Qp112(97, + Qp97, NewQp97, + {NewQp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(98, + Qp98, NewQp98, + {Qp97, NewQp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(99, + Qp99, NewQp99, + {Qp97, Qp98, NewQp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(100, + Qp100, NewQp100, + {Qp97, Qp98, Qp99, NewQp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(101, + Qp101, NewQp101, + {Qp97, Qp98, Qp99, Qp100, NewQp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(102, + Qp102, NewQp102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + NewQp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(103, + Qp103, NewQp103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, NewQp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(104, + Qp104, NewQp104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, NewQp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(105, + Qp105, NewQp105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, NewQp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(106, + Qp106, NewQp106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, NewQp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(107, + Qp107, NewQp107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, NewQp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(108, + Qp108, NewQp108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + NewQp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(109, + Qp109, NewQp109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, NewQp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(110, + Qp110, NewQp110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, NewQp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(111, + Qp111, NewQp111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, NewQp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(112, + Qp112, NewQp112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, NewQp112}); +?REMOVE_UNIQ_P_Qp128(113, + Qp113, NewQp113, + {NewQp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(114, + Qp114, NewQp114, + {Qp113, NewQp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(115, + Qp115, NewQp115, + {Qp113, Qp114, NewQp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(116, + Qp116, NewQp116, + {Qp113, Qp114, Qp115, NewQp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(117, + Qp117, NewQp117, + {Qp113, Qp114, Qp115, Qp116, NewQp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(118, + Qp118, NewQp118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + NewQp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(119, + Qp119, NewQp119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, NewQp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(120, + Qp120, NewQp120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, NewQp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(121, + Qp121, NewQp121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, NewQp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(122, + Qp122, NewQp122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, NewQp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(123, + Qp123, NewQp123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, NewQp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(124, + Qp124, NewQp124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + NewQp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(125, + Qp125, NewQp125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, NewQp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(126, + Qp126, NewQp126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, NewQp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(127, + Qp127, NewQp127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, NewQp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(128, + Qp128, NewQp128, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, NewQp128}). + +-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_pq4())} + ], ?CLOUDI_LONG_TEST_TIMEOUT). + +-endif. + +%%------------------------------------------------------------------------- +%% @hidden +%% remove a unique value from a queue based on a binary predicate, +%% traversal order is undefined to keep it efficient (i.e., shouldn't matter) +%% (based on the implementation of queue:filter/2 +%% which is under the Apache License 2.0) +%%------------------------------------------------------------------------- + +-spec queue_remove_unique(F :: fun((any()) -> boolean()), + Q :: {list(), list()}) -> + {boolean(), {list(), list()}}. + +queue_remove_unique(Fun, {R0, F0} = Q) + when is_function(Fun, 1), is_list(R0), is_list(F0) -> + case queue_remove_unique_f(Fun, F0) of + {true, []} -> + {true, queue_r2f(R0)}; + {true, F1} -> + {true, {R0, F1}}; + {false, F1} -> + %true = F1 == F0, + case queue_remove_unique_f(Fun, R0) of % backwards + {true, []} -> + {true, queue_f2r(F1)}; + {true, R1} -> + {true, {R1, F1}}; + {false, _} -> + {false, Q} + end + end; +queue_remove_unique(Fun, Q) -> + erlang:error(badarg, [Fun,Q]). + +% Call Fun in front to back order +queue_remove_unique_f(_, [] = F) -> + {false, F}; +queue_remove_unique_f(Fun, F) -> + queue_remove_unique_f(F, [], F, Fun). + +queue_remove_unique_f([], _, F, _) -> + {false, F}; +queue_remove_unique_f([X | F0], F1, F, Fun) -> + case Fun(X) of + true -> + {true, lists:reverse(F1, F0)}; + false -> + queue_remove_unique_f(F0, [X | F1], F, Fun) + end. + +-compile({inline, [{queue_r2f,1},{queue_f2r,1}]}). + +% Move half of elements from R to F, if there are at least three +queue_r2f([]) -> + {[],[]}; +queue_r2f([_]=R) -> + {[],R}; +queue_r2f([X,Y]) -> + {[X],[Y]}; +queue_r2f(List) -> + {FF,RR} = lists:split(length(List) div 2 + 1, List), + {FF,lists:reverse(RR, [])}. + +% Move half of elements from F to R, if there are enough +queue_f2r([]) -> + {[],[]}; +queue_f2r([_]=F) -> + {F,[]}; +queue_f2r([X,Y]) -> + {[Y],[X]}; +queue_f2r(List) -> + {FF,RR} = lists:split(length(List) div 2 + 1, List), + {lists:reverse(RR, []),FF}. + diff --git a/aoc2023/build/dev/erlang/pqueue/src/pqueue_test.hrl b/aoc2023/build/dev/erlang/pqueue/src/pqueue_test.hrl new file mode 100644 index 0000000..cedffe0 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/src/pqueue_test.hrl @@ -0,0 +1,49 @@ +%-*-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: +%%% +%%%------------------------------------------------------------------------ +%%% pqueue eunit common functionality +%%% +%%% MIT License +%%% +%%% Copyright (c) 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. +%%% +%%%------------------------------------------------------------------------ + +-ifndef(_assertOk). +-define(_assertOk(Expr), ?_assertEqual(ok, Expr)). +-endif. + +-ifdef(CLOUDI_TEST_TIMEOUT). +-define(TEST_TIMEOUT, ?CLOUDI_TEST_TIMEOUT). % seconds +-else. +-define(TEST_TIMEOUT, 10). % seconds +-endif. +-ifndef(CLOUDI_LONG_TEST_TIMEOUT). +-define(CLOUDI_LONG_TEST_TIMEOUT, 60). % minutes +-endif. + +test_condition(_, 0) -> + []; +test_condition(L, LongTestTimeout) + when LongTestTimeout > 0 -> + {timeout, LongTestTimeout * 60, L}. + diff --git a/aoc2023/build/dev/erlang/pqueue/test/pqueue_proper.erl b/aoc2023/build/dev/erlang/pqueue/test/pqueue_proper.erl new file mode 100644 index 0000000..6702960 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/test/pqueue_proper.erl @@ -0,0 +1,156 @@ +-module(pqueue_proper). +-ifdef(TEST). +-include_lib("proper/include/proper.hrl"). + +-behaviour(proper_statem). + +-export([qc_pq/0, qc_pq2/0, qc_pq3/0, qc_pq4/0, correct/1]). + +-export([command/1, initial_state/0, next_state/3, postcondition/3, + precondition/2]). + +-type value() :: integer(). +-record(state, { in_queue :: [{value(), term()}] }). +-define(SERVER, queue_srv). + +priority() -> + integer(-20, 20). + +%% Selects priorities we have added +priority(InQ) -> + elements([P || {P, _} <- InQ]). + +value() -> + integer(). + +initial_state() -> + #state { in_queue = [] }. + +command(#state { in_queue = InQ }) -> + oneof([{call, ?SERVER, in, [value()]}, + {call, ?SERVER, in, [value(), priority()]}, + {call, ?SERVER, is_empty, []}, + {call, ?SERVER, is_queue, []}, + {call, ?SERVER, len, []}, + {call, ?SERVER, out, []}] ++ + [{call, ?SERVER, out, [priority(InQ)]} || InQ =/= []] ++ + [{call, ?SERVER, pout, []}, + {call, ?SERVER, to_list, []}]). + +next_state(#state { in_queue = InQ } = S, _V, {call, _, out, []}) -> + S#state { in_queue = listq_rem(InQ) }; +next_state(#state { in_queue = InQ } = S, _V, {call, _, out, [Prio]}) -> + S#state { in_queue = listq_rem(InQ, Prio) }; +next_state(#state { in_queue = InQ } = S, _V, {call, _, pout, _}) -> + S#state { in_queue = listq_rem(InQ) }; +next_state(S, _V, {call, _, to_list, _}) -> S; +next_state(S, _V, {call, _, is_queue, _}) -> S; +next_state(S, _V, {call, _, is_empty, _}) -> S; +next_state(S, _V, {call, _, len, _}) -> S; +next_state(#state { in_queue = InQ } = S, _V, {call, _, in, [Value, Prio]}) -> + S#state { in_queue = listq_insert({Prio, Value}, InQ) }; +next_state(#state { in_queue = InQ } = S, _V, {call, _, in, [Value]}) -> + S#state { in_queue = listq_insert({0, Value}, InQ) }. + +precondition(_S, _Call) -> + true. % No limitation on the things we can call at all. + +postcondition(#state { in_queue = InQ }, {call, _, out, [Prio]}, R) -> + R == listq_prio_peek(InQ, Prio); +postcondition(#state { in_queue = InQ }, {call, _, pout, _}, R) -> + R == listq_ppeek(InQ); +postcondition(#state { in_queue = InQ }, {call, _, out, _}, R) -> + R == listq_peek(InQ); +postcondition(S, {call, _, to_list, _}, R) -> + R == listq_to_list(S#state.in_queue); +postcondition(S, {call, _, len, _}, L) -> + L == listq_length(S#state.in_queue); +postcondition(_S, {call, _, is_queue, _}, true) -> true; +postcondition(S, {call, _, is_empty, _}, Res) -> + Res == (S#state.in_queue == []); +postcondition(_S, {call, _, in, _}, _) -> + true; +postcondition(_, _, _) -> + false. + +correct(M) -> + ?FORALL(Cmds, commands(?MODULE), + ?TRAPEXIT( + begin + ?SERVER:start_link(M), + {History,State,Result} = run_commands(?MODULE, Cmds), + ?SERVER:stop(), + ?WHENFAIL(io:format("History: ~w\nState: ~w\nResult: ~w\n", + [History,State,Result]), + aggregate(command_names(Cmds), Result =:= ok)) + end)). + +qc_opts() -> + [{numtests, 10000}]. + +qc_pq() -> + proper:quickcheck(pqueue_proper:correct(pqueue), qc_opts()). + +qc_pq2() -> + proper:quickcheck(pqueue_proper:correct(pqueue2), qc_opts()). + +qc_pq3() -> + proper:quickcheck(pqueue_proper:correct(pqueue3), qc_opts()). + +qc_pq4() -> + proper:quickcheck(pqueue_proper:correct(pqueue4), qc_opts()). + +%% ---------------------------------------------------------------------- + +%% A listq is a sorted list of priorities +listq_insert({P, V}, []) -> + [{P, [V]}]; +listq_insert({P, V}, [{P1, _} | _] = LQ) when P < P1 -> + [{P, [V]} | LQ]; +listq_insert({P, V}, [{P1, Vs} | Next]) when P == P1 -> + [{P, Vs ++ [V]} | Next]; +listq_insert({P, V}, [{P1, Vs} | Next]) when P > P1 -> + [{P1, Vs} | listq_insert({P, V}, Next)]. + +listq_to_list(L) -> + lists:concat( + [ Vals || {_Prio, Vals} <- L]). + +listq_length(L) -> + lists:sum( + [ length(Vs) || {_Prio, Vs} <- L]). + +listq_rem([]) -> + []; +listq_rem([{_P, [_V]} | Next]) -> + Next; +listq_rem([{P, [_V1 | Vs]} | Next]) -> + [{P, Vs} | Next]. + +listq_rem([], _P) -> + []; +listq_rem([{P, [_]} | Next], P) -> + Next; +listq_rem([{P, [_ | Vs]} | Next], P) -> + [{P, Vs} | Next]; +listq_rem([{P1, Vs} | Next], P) -> + [{P1, Vs} | listq_rem(Next, P)]. + +listq_peek([]) -> + empty; +listq_peek([{_P, [V | _]} | _]) -> + {value, V}. + +listq_prio_peek([{P, [V | _]} | _], P) -> + {value, V}; +listq_prio_peek([{_P1, _} | Next], P) -> + listq_prio_peek(Next, P); +listq_prio_peek([], _P) -> + empty. + +listq_ppeek([]) -> + empty; +listq_ppeek([{P, [V | _]} | _]) -> + {value, V, P}. + +-endif. diff --git a/aoc2023/build/dev/erlang/pqueue/test/queue_srv.erl b/aoc2023/build/dev/erlang/pqueue/test/queue_srv.erl new file mode 100644 index 0000000..7fcb0a1 --- /dev/null +++ b/aoc2023/build/dev/erlang/pqueue/test/queue_srv.erl @@ -0,0 +1,183 @@ +%%%------------------------------------------------------------------- +%%% @author Jesper Louis andersen <> +%%% @copyright (C) 2011, Jesper Louis andersen +%%% @doc +%%% +%%% @end +%%% Created : 11 Nov 2011 by Jesper Louis andersen <> +%%%------------------------------------------------------------------- +-module(queue_srv). + +-behaviour(gen_server). + +%% API +-export([start_link/1, stop/0, len/0, in/1, in/2, is_empty/0, + out/0, out/1, pout/0, + is_queue/0, to_list/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-define(SERVER, ?MODULE). + +-record(state, { mod, q }). + +%%%=================================================================== +%%% API +%%%=================================================================== + +%%-------------------------------------------------------------------- +%% @doc +%% Starts the server +%% +%% @spec start_link(Mod) -> {ok, Pid} | ignore | {error, Error} +%% @end +%%-------------------------------------------------------------------- +start_link(Mod) -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [Mod], []). + +stop() -> + gen_server:stop(?SERVER). + +call(M) -> + gen_server:call(?SERVER, M, infinity). + +in(I) -> + call({in, I}). + +in(I, P) -> + call({in, I, P}). + +len() -> + call(len). + +is_empty() -> + call(is_empty). + +is_queue() -> + call(is_queue). + +to_list() -> + call(to_list). + +out() -> + call(out). + +out(P) -> + call({out, P}). + +pout() -> + call(pout). + +%%%=================================================================== +%%% gen_server callbacks +%%%=================================================================== + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Initializes the server +%% +%% @spec init(Args) -> {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%% @end +%%-------------------------------------------------------------------- +init([Mod]) -> + {ok, #state{ mod = Mod, + q = Mod:new() }}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Handling call messages +%% +%% @spec handle_call(Request, From, State) -> +%% {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | +%% {stop, Reason, State} +%% @end +%%-------------------------------------------------------------------- +handle_call({in, Item}, _F, #state { q = Q, mod = M } = S) -> + NQ = M:in(Item, Q), + {reply, ok, S#state { q = NQ }}; +handle_call({in, Item, Prio}, _F, #state { q = Q, mod = M } = S) -> + NQ = M:in(Item, Prio, Q), + {reply, ok, S#state { q = NQ }}; +handle_call({out, P}, _F, #state { q = Q, mod = M } = S) -> + {R, NQ} = M:out(P, Q), + {reply, R, S#state { q = NQ }}; +handle_call(Ty, _F, #state { q = Q, mod = M } = S) when Ty == out; + Ty == pout -> + {R, NQ} = M:Ty(Q), + {reply, R, S#state { q = NQ }}; +handle_call(Ty, _F, #state { q = Q, mod = M } = S) when Ty == is_queue; + Ty == is_empty; + Ty == len; + Ty == to_list -> + R = M:Ty(Q), + {reply, R, S}; +handle_call(Req, From, State) -> + error_logger:info_report([{handle_call, Req, From, State}]), + Reply = ok, + {reply, Reply, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Handling cast messages +%% +%% @spec handle_cast(Msg, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% @end +%%-------------------------------------------------------------------- +handle_cast(_Msg, State) -> + {noreply, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Handling all non call/cast messages +%% +%% @spec handle_info(Info, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% @end +%%-------------------------------------------------------------------- +handle_info(_Info, State) -> + {noreply, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% This function is called by a gen_server when it is about to +%% terminate. It should be the opposite of Module:init/1 and do any +%% necessary cleaning up. When it returns, the gen_server terminates +%% with Reason. The return value is ignored. +%% +%% @spec terminate(Reason, State) -> void() +%% @end +%%-------------------------------------------------------------------- +terminate(_Reason, _State) -> + ok. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Convert process state when code is changed +%% +%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState} +%% @end +%%-------------------------------------------------------------------- +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== diff --git a/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cache b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cache Binary files differnew file mode 100644 index 0000000..bf0b1d7 --- /dev/null +++ b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cache diff --git a/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cache_meta b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cache_meta Binary files differnew file mode 100644 index 0000000..90aa893 --- /dev/null +++ b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cache_meta diff --git a/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.erl b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.erl new file mode 100644 index 0000000..2dbeac9 --- /dev/null +++ b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.erl @@ -0,0 +1,287 @@ +-module(simplifile). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([read/1, write/2, delete/1, delete_all/1, append/2, read_bits/1, write_bits/2, append_bits/2, is_directory/1, create_directory/1, read_directory/1, is_file/1, create_file/1, get_files/1, create_directory_all/1, copy_directory/2, rename_directory/2, copy_file/2, rename_file/2]). +-export_type([file_error/0]). + +-type file_error() :: eacces | + eagain | + ebadf | + ebadmsg | + ebusy | + edeadlk | + edeadlock | + edquot | + eexist | + efault | + efbig | + eftype | + eintr | + einval | + eio | + eisdir | + eloop | + emfile | + emlink | + emultihop | + enametoolong | + enfile | + enobufs | + enodev | + enolck | + enolink | + enoent | + enomem | + enospc | + enosr | + enostr | + enosys | + enotblk | + enotdir | + enotsup | + enxio | + eopnotsupp | + eoverflow | + eperm | + epipe | + erange | + erofs | + espipe | + esrch | + estale | + etxtbsy | + exdev | + not_utf8 | + unknown. + +-spec do_append(binary(), binary()) -> {ok, nil} | {error, file_error()}. +do_append(Content, Filepath) -> + _pipe = Content, + _pipe@1 = gleam_stdlib:identity(_pipe), + simplifile_erl:append_file(_pipe@1, Filepath). + +-spec do_write(binary(), binary()) -> {ok, nil} | {error, file_error()}. +do_write(Content, Filepath) -> + _pipe = Content, + _pipe@1 = gleam_stdlib:identity(_pipe), + simplifile_erl:write_file(_pipe@1, Filepath). + +-spec do_read(binary()) -> {ok, binary()} | {error, file_error()}. +do_read(Filepath) -> + case simplifile_erl:read_file(Filepath) of + {ok, Bits} -> + case gleam@bit_array:to_string(Bits) of + {ok, Str} -> + {ok, Str}; + + _ -> + {error, not_utf8} + end; + + {error, E} -> + {error, E} + end. + +-spec cast_error({ok, FJY} | {error, file_error()}) -> {ok, FJY} | + {error, file_error()}. +cast_error(Input) -> + Input. + +-spec read(binary()) -> {ok, binary()} | {error, file_error()}. +read(Filepath) -> + _pipe = do_read(Filepath), + cast_error(_pipe). + +-spec write(binary(), binary()) -> {ok, nil} | {error, file_error()}. +write(Filepath, Contents) -> + _pipe = do_write(Contents, Filepath), + cast_error(_pipe). + +-spec delete(binary()) -> {ok, nil} | {error, file_error()}. +delete(Path) -> + _pipe = simplifile_erl:recursive_delete(Path), + cast_error(_pipe). + +-spec delete_all(list(binary())) -> {ok, nil} | {error, file_error()}. +delete_all(Paths) -> + case Paths of + [] -> + {ok, nil}; + + [Path | Rest] -> + case delete(Path) of + {ok, nil} -> + delete_all(Rest); + + {error, enoent} -> + delete_all(Rest); + + E -> + E + end + end. + +-spec append(binary(), binary()) -> {ok, nil} | {error, file_error()}. +append(Filepath, Contents) -> + _pipe = do_append(Contents, Filepath), + cast_error(_pipe). + +-spec read_bits(binary()) -> {ok, bitstring()} | {error, file_error()}. +read_bits(Filepath) -> + _pipe = simplifile_erl:read_file(Filepath), + cast_error(_pipe). + +-spec write_bits(binary(), bitstring()) -> {ok, nil} | {error, file_error()}. +write_bits(Filepath, Bits) -> + _pipe = simplifile_erl:write_file(Bits, Filepath), + cast_error(_pipe). + +-spec append_bits(binary(), bitstring()) -> {ok, nil} | {error, file_error()}. +append_bits(Filepath, Bits) -> + _pipe = simplifile_erl:append_file(Bits, Filepath), + cast_error(_pipe). + +-spec is_directory(binary()) -> boolean(). +is_directory(Filepath) -> + filelib:is_dir(Filepath). + +-spec create_directory(binary()) -> {ok, nil} | {error, file_error()}. +create_directory(Filepath) -> + _pipe = simplifile_erl:make_directory(Filepath), + cast_error(_pipe). + +-spec read_directory(binary()) -> {ok, list(binary())} | {error, file_error()}. +read_directory(Path) -> + _pipe = simplifile_erl:list_directory(Path), + cast_error(_pipe). + +-spec is_file(binary()) -> boolean(). +is_file(Filepath) -> + simplifile_erl:is_file(Filepath). + +-spec create_file(binary()) -> {ok, nil} | {error, file_error()}. +create_file(Filepath) -> + case begin + _pipe = Filepath, + is_file(_pipe) + end + orelse begin + _pipe@1 = Filepath, + is_directory(_pipe@1) + end of + true -> + {error, eexist}; + + false -> + write_bits(Filepath, <<>>) + end. + +-spec do_copy_directory(binary(), binary()) -> {ok, nil} | {error, file_error()}. +do_copy_directory(Src, Dest) -> + gleam@result:'try'( + read_directory(Src), + fun(Segments) -> + _pipe = Segments, + gleam@list:each( + _pipe, + fun(Segment) -> + Src_path = <<<<Src/binary, "/"/utf8>>/binary, + Segment/binary>>, + Dest_path = <<<<Dest/binary, "/"/utf8>>/binary, + Segment/binary>>, + case {is_file(Src_path), is_directory(Src_path)} of + {true, false} -> + gleam@result:'try'( + read_bits(Src_path), + fun(Content) -> _pipe@1 = Content, + write_bits(Dest_path, _pipe@1) end + ); + + {false, true} -> + gleam@result:'try'( + create_directory(Dest_path), + fun(_) -> + do_copy_directory(Src_path, Dest_path) + end + ); + + {_, _} -> + erlang:error(#{gleam_error => panic, + message => <<"unreachable"/utf8>>, + module => <<"simplifile"/utf8>>, + function => <<"do_copy_directory"/utf8>>, + line => 341}) + end + end + ), + {ok, nil} + end + ). + +-spec get_files(binary()) -> {ok, list(binary())} | {error, file_error()}. +get_files(Directory) -> + gleam@result:'try'( + read_directory(Directory), + fun(Contents) -> + Paths = gleam@list:map( + Contents, + fun(Segment) -> + <<<<Directory/binary, "/"/utf8>>/binary, Segment/binary>> + end + ), + Files = gleam@list:filter(Paths, fun is_file/1), + case gleam@list:filter(Paths, fun is_directory/1) of + [] -> + {ok, Files}; + + Directories -> + gleam@result:'try'( + gleam@list:try_map(Directories, fun get_files/1), + fun(Nested_files) -> + {ok, + gleam@list:append( + Files, + gleam@list:flatten(Nested_files) + )} + end + ) + end + end + ). + +-spec create_directory_all(binary()) -> {ok, nil} | {error, file_error()}. +create_directory_all(Dirpath) -> + Path = case begin + _pipe = Dirpath, + gleam@string:ends_with(_pipe, <<"/"/utf8>>) + end of + true -> + Dirpath; + + false -> + <<Dirpath/binary, "/"/utf8>> + end, + _pipe@1 = simplifile_erl:create_dir_all(Path), + cast_error(_pipe@1). + +-spec copy_directory(binary(), binary()) -> {ok, nil} | {error, file_error()}. +copy_directory(Src, Dest) -> + gleam@result:'try'( + create_directory_all(Dest), + fun(_) -> do_copy_directory(Src, Dest) end + ). + +-spec rename_directory(binary(), binary()) -> {ok, nil} | {error, file_error()}. +rename_directory(Src, Dest) -> + gleam@result:'try'(copy_directory(Src, Dest), fun(_) -> delete(Src) end). + +-spec copy_file(binary(), binary()) -> {ok, nil} | {error, file_error()}. +copy_file(Src, Dest) -> + _pipe = file:copy(Src, Dest), + _pipe@1 = gleam@result:replace(_pipe, nil), + cast_error(_pipe@1). + +-spec rename_file(binary(), binary()) -> {ok, nil} | {error, file_error()}. +rename_file(Src, Dest) -> + _pipe = simplifile_erl:rename_file(Src, Dest), + cast_error(_pipe). diff --git a/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile_erl.erl b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile_erl.erl new file mode 100644 index 0000000..dac135a --- /dev/null +++ b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile_erl.erl @@ -0,0 +1,70 @@ +-module(simplifile_erl). +-export([ + read_file/1, + append_file/2, write_file/2, delete_file/1, delete_directory/1, recursive_delete/1, + list_directory/1, make_directory/1, is_file/1, create_dir_all/1, rename_file/2 +]). + +-define(is_posix_error(Error), + Error =:= eacces orelse Error =:= eagain orelse Error =:= ebadf orelse + Error =:= ebadmsg orelse Error =:= ebusy orelse Error =:= edeadlk orelse + Error =:= edeadlock orelse Error =:= edquot orelse Error =:= eexist orelse + Error =:= efault orelse Error =:= efbig orelse Error =:= eftype orelse + Error =:= eintr orelse Error =:= einval orelse Error =:= eio orelse + Error =:= eisdir orelse Error =:= eloop orelse Error =:= emfile orelse + Error =:= emlink orelse Error =:= emultihop orelse Error =:= enametoolong orelse + Error =:= enfile orelse Error =:= enobufs orelse Error =:= enodev orelse + Error =:= enolck orelse Error =:= enolink orelse Error =:= enoent orelse + Error =:= enomem orelse Error =:= enospc orelse Error =:= enosr orelse + Error =:= enostr orelse Error =:= enosys orelse Error =:= enotblk orelse + Error =:= enotdir orelse Error =:= enotsup orelse Error =:= enxio orelse + Error =:= eopnotsupp orelse Error =:= eoverflow orelse Error =:= eperm orelse + Error =:= epipe orelse Error =:= erange orelse Error =:= erofs orelse + Error =:= espipe orelse Error =:= esrch orelse Error =:= estale orelse + Error =:= etxtbsy orelse Error =:= exdev +). + +posix_result(Result) -> + case Result of + ok -> {ok, nil}; + {ok, Value} -> {ok, Value}; + {error, Reason} when ?is_posix_error(Reason) -> {error, Reason} + end. + +read_file(Filename) -> + posix_result(file:read_file(Filename)). + +write_file(Contents, Filename) -> + posix_result(file:write_file(Filename, Contents)). + +append_file(Contents, Filename) -> + posix_result(file:write_file(Filename, Contents, [append])). + +delete_file(Filename) -> + posix_result(file:delete(Filename)). + +make_directory(Dir) -> + posix_result(file:make_dir(Dir)). + +list_directory(Dir) -> + case file:list_dir(Dir) of + {ok, Filenames} -> + {ok, [list_to_binary(Filename) || Filename <- Filenames]}; + {error, Reason} when ?is_posix_error(Reason) -> + {error, Reason} + end. + +delete_directory(Dir) -> + posix_result(file:del_dir(Dir)). + +recursive_delete(Dir) -> + posix_result(file:del_dir_r(Dir)). + +is_file(Filename) -> + not (file:read_file_info(Filename) == {error, enoent}) and not filelib: is_dir(Filename). + +create_dir_all(Filename) -> + posix_result(filelib:ensure_dir(Filename)). + +rename_file(Source, Destination) -> + posix_result(file:rename(Source, Destination)). diff --git a/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile_js.mjs b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile_js.mjs new file mode 100644 index 0000000..faf4109 --- /dev/null +++ b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile_js.mjs @@ -0,0 +1,102 @@ +import fs from "node:fs" +import path from "node:path" +import { BitArray, Ok, Error as GError, toList} from "./gleam.mjs"; + +export function readBits(filepath) { + try { + const contents = fs.readFileSync(path.normalize(filepath)) + return new Ok(new BitArray(new Uint8Array(contents))) + } catch(e) { + return new GError(stringifyError(e)) + } +} + +export function writeBits(contents, filepath) { + try { + fs.writeFileSync(path.normalize(filepath), contents.buffer) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +export function appendBits(contents, filepath) { + try { + fs.appendFileSync(path.normalize(filepath), contents.buffer) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +function stringifyError(e) { + return e.code +} + +export function isFile(filepath) { + let fp = path.normalize(filepath) + return fs.existsSync(fp) && fs.lstatSync(fp).isFile(); +} + +export function isDirectory(filepath) { + let fp = path.normalize(filepath) + return fs.existsSync(fp) && fs.lstatSync(fp).isDirectory(); +} + +export function makeDirectory(filepath) { + try { + fs.mkdirSync(path.normalize(filepath)) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +export function createDirAll(filepath) { + try { + fs.mkdirSync(filepath, { recursive: true }) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +export function deleteFileOrDirRecursive(fileOrDirPath) { + try { + if (isDirectory(fileOrDirPath)) { + fs.rmSync(path.normalize(fileOrDirPath), { recursive: true }) + } else { + fs.unlinkSync(path.normalize(fileOrDirPath)) + } + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +export function listContents(filepath) { + try { + const stuff = toList(fs.readdirSync(path.normalize(filepath))) + return new Ok(stuff) + } catch(e) { + return new GError(stringifyError(e)) + } +} + +export function copyFile(srcpath, destpath) { + try { + fs.copyFileSync(path.normalize(srcpath), path.normalize(destpath)) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +export function renameFile(srcpath, destpath) { + try { + fs.renameSync(path.normalize(srcpath), path.normalize(destpath)) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +}
\ No newline at end of file diff --git a/aoc2023/build/dev/erlang/simplifile/ebin/simplifile.app b/aoc2023/build/dev/erlang/simplifile/ebin/simplifile.app new file mode 100644 index 0000000..3bb63fa --- /dev/null +++ b/aoc2023/build/dev/erlang/simplifile/ebin/simplifile.app @@ -0,0 +1,7 @@ +{application, simplifile, [ + {vsn, "1.0.0"}, + {applications, [gleam_stdlib]}, + {description, "Basic file operations that work on all targets"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/simplifile/ebin/simplifile.beam b/aoc2023/build/dev/erlang/simplifile/ebin/simplifile.beam Binary files differnew file mode 100644 index 0000000..6631cad --- /dev/null +++ b/aoc2023/build/dev/erlang/simplifile/ebin/simplifile.beam diff --git a/aoc2023/build/dev/erlang/simplifile/ebin/simplifile_erl.beam b/aoc2023/build/dev/erlang/simplifile/ebin/simplifile_erl.beam Binary files differnew file mode 100644 index 0000000..2abefda --- /dev/null +++ b/aoc2023/build/dev/erlang/simplifile/ebin/simplifile_erl.beam diff --git a/aoc2023/build/dev/erlang/snag/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/snag/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/snag/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cache b/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cache Binary files differnew file mode 100644 index 0000000..bc9c27c --- /dev/null +++ b/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cache diff --git a/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cache_meta b/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cache_meta Binary files differnew file mode 100644 index 0000000..daef1e9 --- /dev/null +++ b/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cache_meta diff --git a/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.erl b/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.erl new file mode 100644 index 0000000..92d4f80 --- /dev/null +++ b/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.erl @@ -0,0 +1,74 @@ +-module(snag). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([new/1, error/1, layer/2, context/2, pretty_print/1, line_print/1]). +-export_type([snag/0]). + +-type snag() :: {snag, binary(), list(binary())}. + +-spec new(binary()) -> snag(). +new(Issue) -> + {snag, Issue, []}. + +-spec error(binary()) -> {ok, any()} | {error, snag()}. +error(Issue) -> + {error, new(Issue)}. + +-spec layer(snag(), binary()) -> snag(). +layer(Snag, Issue) -> + {snag, Issue, [erlang:element(2, Snag) | erlang:element(3, Snag)]}. + +-spec context({ok, KFH} | {error, snag()}, binary()) -> {ok, KFH} | + {error, snag()}. +context(Result, Issue) -> + case Result of + {ok, _} -> + Result; + + {error, Snag} -> + {error, layer(Snag, Issue)} + end. + +-spec pretty_print_cause(list(binary())) -> gleam@string_builder:string_builder(). +pretty_print_cause(Cause) -> + _pipe = Cause, + _pipe@1 = gleam@list:index_map( + _pipe, + fun(Index, Line) -> + gleam@string:concat( + [<<" "/utf8>>, + gleam@int:to_string(Index), + <<": "/utf8>>, + Line, + <<"\n"/utf8>>] + ) + end + ), + gleam@string_builder:from_strings(_pipe@1). + +-spec pretty_print(snag()) -> binary(). +pretty_print(Snag) -> + Builder = gleam@string_builder:from_strings( + [<<"error: "/utf8>>, erlang:element(2, Snag), <<"\n"/utf8>>] + ), + gleam@string_builder:to_string(case erlang:element(3, Snag) of + [] -> + Builder; + + Cause -> + _pipe = Builder, + _pipe@1 = gleam@string_builder:append( + _pipe, + <<"\ncause:\n"/utf8>> + ), + gleam@string_builder:append_builder( + _pipe@1, + pretty_print_cause(Cause) + ) + end). + +-spec line_print(snag()) -> binary(). +line_print(Snag) -> + _pipe = [gleam@string:append(<<"error: "/utf8>>, erlang:element(2, Snag)) | + erlang:element(3, Snag)], + gleam@string:join(_pipe, <<" <- "/utf8>>). diff --git a/aoc2023/build/dev/erlang/snag/ebin/snag.app b/aoc2023/build/dev/erlang/snag/ebin/snag.app new file mode 100644 index 0000000..724fb97 --- /dev/null +++ b/aoc2023/build/dev/erlang/snag/ebin/snag.app @@ -0,0 +1,7 @@ +{application, snag, [ + {vsn, "0.2.1"}, + {applications, [gleam_stdlib]}, + {description, "A boilerplate-free ad-hoc error type"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/snag/ebin/snag.beam b/aoc2023/build/dev/erlang/snag/ebin/snag.beam Binary files differnew file mode 100644 index 0000000..896068a --- /dev/null +++ b/aoc2023/build/dev/erlang/snag/ebin/snag.beam diff --git a/aoc2023/build/dev/erlang/snag/include/snag_Snag.hrl b/aoc2023/build/dev/erlang/snag/include/snag_Snag.hrl new file mode 100644 index 0000000..5d6614e --- /dev/null +++ b/aoc2023/build/dev/erlang/snag/include/snag_Snag.hrl @@ -0,0 +1 @@ +-record(snag, {issue :: binary(), cause :: list(binary())}). diff --git a/aoc2023/build/dev/erlang/tom/_gleam_artefacts/gleam@@compile.erl b/aoc2023/build/dev/erlang/tom/_gleam_artefacts/gleam@@compile.erl new file mode 100644 index 0000000..543db88 --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/_gleam_artefacts/gleam@@compile.erl @@ -0,0 +1,157 @@ +#!/usr/bin/env escript + +% TODO: Don't concurrently print warnings and errors +% TODO: Some tests + +-record(arguments, {lib = "./", out = "./", modules = []}). + +main(Args) -> + #arguments{out = Out, lib = Lib, modules = Modules} = parse(Args), + IsElixirModule = fun(Module) -> + filename:extension(Module) =:= ".ex" + end, + {ElixirModules, ErlangModules} = lists:partition(IsElixirModule, Modules), + ok = configure_logging(), + ok = add_lib_to_erlang_path(Lib), + ok = filelib:ensure_dir([Out, $/]), + {ErlangOk, _ErlangBeams} = compile_erlang(ErlangModules, Out), + {ElixirOk, _ElixirBeams} = case ErlangOk of + true -> compile_elixir(ElixirModules, Out); + false -> {false, []} + end, + case ErlangOk and ElixirOk of + true -> ok; + false -> erlang:halt(1) + end. + +compile_erlang(Modules, Out) -> + Workers = start_compiler_workers(Out), + ok = producer_loop(Modules, Workers), + collect_results({true, []}). + +collect_results(Acc = {Result, Beams}) -> + receive + {compiled, Beam} -> collect_results({Result, [Beam | Beams]}); + failed -> collect_results({false, Beams}) + after 0 -> Acc + end. + +producer_loop([], 0) -> + ok; +producer_loop([], Workers) -> + receive + {work_please, _} -> producer_loop([], Workers - 1) + end; +producer_loop([Module | Modules], Workers) -> + receive + {work_please, Worker} -> + erlang:send(Worker, {module, Module}), + producer_loop(Modules, Workers) + end. + +start_compiler_workers(Out) -> + Parent = self(), + NumSchedulers = erlang:system_info(schedulers), + SpawnWorker = fun(_) -> + erlang:spawn_link(fun() -> worker_loop(Parent, Out) end) + end, + lists:foreach(SpawnWorker, lists:seq(1, NumSchedulers)), + NumSchedulers. + +worker_loop(Parent, Out) -> + Options = [report_errors, report_warnings, debug_info, {outdir, Out}], + erlang:send(Parent, {work_please, self()}), + receive + {module, Module} -> + log({compiling, Module}), + case compile:file(Module, Options) of + {ok, ModuleName} -> + Beam = filename:join(Out, ModuleName) ++ ".beam", + Message = {compiled, Beam}, + log(Message), + erlang:send(Parent, Message); + error -> + log({failed, Module}), + erlang:send(Parent, failed) + end, + worker_loop(Parent, Out) + end. + +compile_elixir(Modules, Out) -> + Error = [ + "The program elixir was not found. Is it installed?", + $\n, + "Documentation for installing Elixir can be viewed here:", + $\n, + "https://elixir-lang.org/install.html" + ], + case Modules of + [] -> {true, []}; + _ -> + log({starting, "compiler.app"}), + ok = application:start(compiler), + log({starting, "elixir.app"}), + case application:start(elixir) of + ok -> do_compile_elixir(Modules, Out); + _ -> + io:put_chars(standard_error, [Error, $\n]), + {false, []} + end + end. + +do_compile_elixir(Modules, Out) -> + ModuleBins = lists:map(fun(Module) -> + log({compiling, Module}), + list_to_binary(Module) + end, Modules), + OutBin = list_to_binary(Out), + Options = [{dest, OutBin}], + % Silence "redefining module" warnings. + % Compiled modules in the build directory are added to the code path. + % These warnings result from recompiling loaded modules. + % TODO: This line can likely be removed if/when the build directory is cleaned before every compilation. + 'Elixir.Code':compiler_options([{ignore_module_conflict, true}]), + case 'Elixir.Kernel.ParallelCompiler':compile_to_path(ModuleBins, OutBin, Options) of + {ok, ModuleAtoms, _} -> + ToBeam = fun(ModuleAtom) -> + Beam = filename:join(Out, atom_to_list(ModuleAtom)) ++ ".beam", + log({compiled, Beam}), + Beam + end, + {true, lists:map(ToBeam, ModuleAtoms)}; + {error, Errors, _} -> + % Log all filenames associated with modules that failed to compile. + % Note: The compiler prints compilation errors upon encountering them. + ErrorFiles = lists:usort([File || {File, _, _} <- Errors]), + Log = fun(File) -> + log({failed, binary_to_list(File)}) + end, + lists:foreach(Log, ErrorFiles), + {false, []}; + _ -> {false, []} + end. + +add_lib_to_erlang_path(Lib) -> + code:add_paths(filelib:wildcard([Lib, "/*/ebin"])). + +parse(Args) -> + parse(Args, #arguments{}). + +parse([], Arguments) -> + Arguments; +parse(["--lib", Lib | Rest], Arguments) -> + parse(Rest, Arguments#arguments{lib = Lib}); +parse(["--out", Out | Rest], Arguments) -> + parse(Rest, Arguments#arguments{out = Out}); +parse([Module | Rest], Arguments = #arguments{modules = Modules}) -> + parse(Rest, Arguments#arguments{modules = [Module | Modules]}). + +configure_logging() -> + Enabled = os:getenv("GLEAM_LOG") /= false, + persistent_term:put(gleam_logging_enabled, Enabled). + +log(Term) -> + case persistent_term:get(gleam_logging_enabled) of + true -> erlang:display(Term), ok; + false -> ok + end. diff --git a/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cache b/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cache Binary files differnew file mode 100644 index 0000000..c9b63ee --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cache diff --git a/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cache_meta b/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cache_meta Binary files differnew file mode 100644 index 0000000..492599b --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cache_meta diff --git a/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.erl b/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.erl new file mode 100644 index 0000000..05ab1a6 --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.erl @@ -0,0 +1,2142 @@ +-module(tom). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([get/2, get_int/2, get_float/2, get_bool/2, get_string/2, get_date/2, get_time/2, get_date_time/2, get_array/2, get_table/2, get_number/2, parse/1]). +-export_type([toml/0, date_time/0, date/0, time/0, offset/0, sign/0, parse_error/0, number_/0, get_error/0]). + +-type toml() :: {int, integer()} | + {float, float()} | + {infinity, sign()} | + {nan, sign()} | + {bool, boolean()} | + {string, binary()} | + {date, date()} | + {time, time()} | + {date_time, date_time()} | + {array, list(toml())} | + {array_of_tables, list(gleam@dict:dict(binary(), toml()))} | + {table, gleam@dict:dict(binary(), toml())} | + {inline_table, gleam@dict:dict(binary(), toml())}. + +-type date_time() :: {date_time_value, date(), time(), offset()}. + +-type date() :: {date_value, integer(), integer(), integer()}. + +-type time() :: {time_value, integer(), integer(), integer(), integer()}. + +-type offset() :: local | {offset, sign(), integer(), integer()}. + +-type sign() :: positive | negative. + +-type parse_error() :: {unexpected, binary(), binary()} | + {key_already_in_use, list(binary())}. + +-type number_() :: {number_int, integer()} | + {number_float, float()} | + {number_infinity, sign()} | + {number_nan, sign()}. + +-type get_error() :: {not_found, list(binary())} | + {wrong_type, list(binary()), binary(), binary()}. + +-spec classify(toml()) -> binary(). +classify(Toml) -> + case Toml of + {int, _} -> + <<"Int"/utf8>>; + + {float, _} -> + <<"Float"/utf8>>; + + {nan, positive} -> + <<"NaN"/utf8>>; + + {nan, negative} -> + <<"Negative NaN"/utf8>>; + + {infinity, positive} -> + <<"Infinity"/utf8>>; + + {infinity, negative} -> + <<"Negative Infinity"/utf8>>; + + {bool, _} -> + <<"Bool"/utf8>>; + + {string, _} -> + <<"String"/utf8>>; + + {date, _} -> + <<"Date"/utf8>>; + + {time, _} -> + <<"Time"/utf8>>; + + {date_time, _} -> + <<"DateTime"/utf8>>; + + {array, _} -> + <<"Array"/utf8>>; + + {array_of_tables, _} -> + <<"Array"/utf8>>; + + {table, _} -> + <<"Table"/utf8>>; + + {inline_table, _} -> + <<"Table"/utf8>> + end. + +-spec push_key({ok, LOB} | {error, get_error()}, binary()) -> {ok, LOB} | + {error, get_error()}. +push_key(Result, Key) -> + case Result of + {ok, T} -> + {ok, T}; + + {error, {not_found, Path}} -> + {error, {not_found, [Key | Path]}}; + + {error, {wrong_type, Path@1, Expected, Got}} -> + {error, {wrong_type, [Key | Path@1], Expected, Got}} + end. + +-spec get(gleam@dict:dict(binary(), toml()), list(binary())) -> {ok, toml()} | + {error, get_error()}. +get(Toml, Key) -> + case Key of + [] -> + {error, {not_found, []}}; + + [K] -> + gleam@result:replace_error(gleam@map:get(Toml, K), {not_found, [K]}); + + [K@1 | Key@1] -> + case gleam@map:get(Toml, K@1) of + {ok, {table, T}} -> + push_key(get(T, Key@1), K@1); + + {ok, Other} -> + {error, + {wrong_type, [K@1], <<"Table"/utf8>>, classify(Other)}}; + + {error, _} -> + {error, {not_found, [K@1]}} + end + end. + +-spec get_int(gleam@dict:dict(binary(), toml()), list(binary())) -> {ok, + integer()} | + {error, get_error()}. +get_int(Toml, Key) -> + case get(Toml, Key) of + {ok, {int, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Int"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_float(gleam@dict:dict(binary(), toml()), list(binary())) -> {ok, + float()} | + {error, get_error()}. +get_float(Toml, Key) -> + case get(Toml, Key) of + {ok, {float, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Float"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_bool(gleam@dict:dict(binary(), toml()), list(binary())) -> {ok, + boolean()} | + {error, get_error()}. +get_bool(Toml, Key) -> + case get(Toml, Key) of + {ok, {bool, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Bool"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_string(gleam@dict:dict(binary(), toml()), list(binary())) -> {ok, + binary()} | + {error, get_error()}. +get_string(Toml, Key) -> + case get(Toml, Key) of + {ok, {string, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"String"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_date(gleam@dict:dict(binary(), toml()), list(binary())) -> {ok, + date()} | + {error, get_error()}. +get_date(Toml, Key) -> + case get(Toml, Key) of + {ok, {date, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Date"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_time(gleam@dict:dict(binary(), toml()), list(binary())) -> {ok, + time()} | + {error, get_error()}. +get_time(Toml, Key) -> + case get(Toml, Key) of + {ok, {time, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Time"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_date_time(gleam@dict:dict(binary(), toml()), list(binary())) -> {ok, + date_time()} | + {error, get_error()}. +get_date_time(Toml, Key) -> + case get(Toml, Key) of + {ok, {date_time, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"DateTime"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_array(gleam@dict:dict(binary(), toml()), list(binary())) -> {ok, + list(toml())} | + {error, get_error()}. +get_array(Toml, Key) -> + case get(Toml, Key) of + {ok, {array, I}} -> + {ok, I}; + + {ok, {array_of_tables, I@1}} -> + {ok, gleam@list:map(I@1, fun(Field@0) -> {table, Field@0} end)}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Array"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_table(gleam@dict:dict(binary(), toml()), list(binary())) -> {ok, + gleam@dict:dict(binary(), toml())} | + {error, get_error()}. +get_table(Toml, Key) -> + case get(Toml, Key) of + {ok, {table, I}} -> + {ok, I}; + + {ok, {inline_table, I@1}} -> + {ok, I@1}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Table"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_number(gleam@dict:dict(binary(), toml()), list(binary())) -> {ok, + number_()} | + {error, get_error()}. +get_number(Toml, Key) -> + case get(Toml, Key) of + {ok, {int, X}} -> + {ok, {number_int, X}}; + + {ok, {float, X@1}} -> + {ok, {number_float, X@1}}; + + {ok, {nan, X@2}} -> + {ok, {number_nan, X@2}}; + + {ok, {infinity, X@3}} -> + {ok, {number_infinity, X@3}}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Number"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec merge(gleam@dict:dict(binary(), toml()), binary(), toml(), toml()) -> {ok, + gleam@dict:dict(binary(), toml())} | + {error, list(binary())}. +merge(Table, Key, Old, New) -> + case {Old, New} of + {{array_of_tables, Tables}, {array_of_tables, New@1}} -> + {ok, + gleam@map:insert( + Table, + Key, + {array_of_tables, gleam@list:append(New@1, Tables)} + )}; + + {_, _} -> + {error, [Key]} + end. + +-spec insert_loop(gleam@dict:dict(binary(), toml()), list(binary()), toml()) -> {ok, + gleam@dict:dict(binary(), toml())} | + {error, list(binary())}. +insert_loop(Table, Key, Value) -> + case Key of + [] -> + erlang:error(#{gleam_error => panic, + message => <<"unreachable"/utf8>>, + module => <<"tom"/utf8>>, + function => <<"insert_loop"/utf8>>, + line => 511}); + + [K] -> + case gleam@map:get(Table, K) of + {error, nil} -> + {ok, gleam@map:insert(Table, K, Value)}; + + {ok, Old} -> + merge(Table, K, Old, Value) + end; + + [K@1 | Key@1] -> + case gleam@map:get(Table, K@1) of + {error, nil} -> + case insert_loop(gleam@map:new(), Key@1, Value) of + {ok, Inner} -> + {ok, gleam@map:insert(Table, K@1, {table, Inner})}; + + {error, Path} -> + {error, [K@1 | Path]} + end; + + {ok, {array_of_tables, [Inner@1 | Rest]}} -> + case insert_loop(Inner@1, Key@1, Value) of + {ok, Inner@2} -> + {ok, + gleam@map:insert( + Table, + K@1, + {array_of_tables, [Inner@2 | Rest]} + )}; + + {error, Path@1} -> + {error, [K@1 | Path@1]} + end; + + {ok, {table, Inner@3}} -> + case insert_loop(Inner@3, Key@1, Value) of + {ok, Inner@4} -> + {ok, gleam@map:insert(Table, K@1, {table, Inner@4})}; + + {error, Path@2} -> + {error, [K@1 | Path@2]} + end; + + {ok, _} -> + {error, [K@1]} + end + end. + +-spec insert(gleam@dict:dict(binary(), toml()), list(binary()), toml()) -> {ok, + gleam@dict:dict(binary(), toml())} | + {error, parse_error()}. +insert(Table, Key, Value) -> + case insert_loop(Table, Key, Value) of + {ok, Table@1} -> + {ok, Table@1}; + + {error, Path} -> + {error, {key_already_in_use, Path}} + end. + +-spec expect_end_of_line( + list(binary()), + fun((list(binary())) -> {ok, {LQG, list(binary())}} | {error, parse_error()}) +) -> {ok, {LQG, list(binary())}} | {error, parse_error()}. +expect_end_of_line(Input, Next) -> + case Input of + [<<"\n"/utf8>> | Input@1] -> + Next(Input@1); + + [<<"\r\n"/utf8>> | Input@2] -> + Next(Input@2); + + [G | _] -> + {error, {unexpected, G, <<"\n"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"\n"/utf8>>}} + end. + +-spec parse_key_quoted(list(binary()), binary(), binary()) -> {ok, + {binary(), list(binary())}} | + {error, parse_error()}. +parse_key_quoted(Input, Close, Name) -> + case Input of + [G | Input@1] when G =:= Close -> + {ok, {Name, Input@1}}; + + [G@1 | Input@2] -> + parse_key_quoted(Input@2, Close, <<Name/binary, G@1/binary>>); + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, Close}} + end. + +-spec parse_key_bare(list(binary()), binary()) -> {ok, + {binary(), list(binary())}} | + {error, parse_error()}. +parse_key_bare(Input, Name) -> + case Input of + [<<" "/utf8>> | Input@1] when Name =/= <<""/utf8>> -> + {ok, {Name, Input@1}}; + + [<<"="/utf8>> | _] when Name =/= <<""/utf8>> -> + {ok, {Name, Input}}; + + [<<"."/utf8>> | _] when Name =/= <<""/utf8>> -> + {ok, {Name, Input}}; + + [<<"]"/utf8>> | _] when Name =/= <<""/utf8>> -> + {ok, {Name, Input}}; + + [<<","/utf8>> | _] when Name =/= <<""/utf8>> -> + {error, {unexpected, <<","/utf8>>, <<"="/utf8>>}}; + + [<<"\n"/utf8>> | _] when Name =/= <<""/utf8>> -> + {error, {unexpected, <<"\n"/utf8>>, <<"="/utf8>>}}; + + [<<"\r\n"/utf8>> | _] when Name =/= <<""/utf8>> -> + {error, {unexpected, <<"\r\n"/utf8>>, <<"="/utf8>>}}; + + [<<"\n"/utf8>> | _] -> + {error, {unexpected, <<"\n"/utf8>>, <<"key"/utf8>>}}; + + [<<"\r\n"/utf8>> | _] -> + {error, {unexpected, <<"\r\n"/utf8>>, <<"key"/utf8>>}}; + + [<<"]"/utf8>> | _] -> + {error, {unexpected, <<"]"/utf8>>, <<"key"/utf8>>}}; + + [<<","/utf8>> | _] -> + {error, {unexpected, <<","/utf8>>, <<"key"/utf8>>}}; + + [G | Input@2] -> + parse_key_bare(Input@2, <<Name/binary, G/binary>>); + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"key"/utf8>>}} + end. + +-spec skip_line_whitespace(list(binary())) -> list(binary()). +skip_line_whitespace(Input) -> + gleam@list:drop_while( + Input, + fun(G) -> (G =:= <<" "/utf8>>) orelse (G =:= <<"\t"/utf8>>) end + ). + +-spec parse_key_segment(list(binary())) -> {ok, {binary(), list(binary())}} | + {error, parse_error()}. +parse_key_segment(Input) -> + Input@1 = skip_line_whitespace(Input), + case Input@1 of + [<<"="/utf8>> | _] -> + {error, {unexpected, <<"="/utf8>>, <<"Key"/utf8>>}}; + + [<<"\n"/utf8>> | _] -> + {error, {unexpected, <<"\n"/utf8>>, <<"Key"/utf8>>}}; + + [<<"\r\n"/utf8>> | _] -> + {error, {unexpected, <<"\r\n"/utf8>>, <<"Key"/utf8>>}}; + + [<<"["/utf8>> | _] -> + {error, {unexpected, <<"["/utf8>>, <<"Key"/utf8>>}}; + + [<<"\""/utf8>> | Input@2] -> + parse_key_quoted(Input@2, <<"\""/utf8>>, <<""/utf8>>); + + [<<"'"/utf8>> | Input@3] -> + parse_key_quoted(Input@3, <<"'"/utf8>>, <<""/utf8>>); + + _ -> + parse_key_bare(Input@1, <<""/utf8>>) + end. + +-spec skip_whitespace(list(binary())) -> list(binary()). +skip_whitespace(Input) -> + case Input of + [<<" "/utf8>> | Input@1] -> + skip_whitespace(Input@1); + + [<<"\t"/utf8>> | Input@2] -> + skip_whitespace(Input@2); + + [<<"\n"/utf8>> | Input@3] -> + skip_whitespace(Input@3); + + [<<"\r\n"/utf8>> | Input@4] -> + skip_whitespace(Input@4); + + Input@5 -> + Input@5 + end. + +-spec drop_comments(list(binary()), list(binary())) -> list(binary()). +drop_comments(Input, Acc) -> + case Input of + [<<"#"/utf8>> | Input@1] -> + _pipe = Input@1, + _pipe@1 = gleam@list:drop_while( + _pipe, + fun(G) -> G /= <<"\n"/utf8>> end + ), + drop_comments(_pipe@1, Acc); + + [G@1 | Input@2] -> + drop_comments(Input@2, [G@1 | Acc]); + + [] -> + gleam@list:reverse(Acc) + end. + +-spec do( + {ok, {LQR, list(binary())}} | {error, parse_error()}, + fun((LQR, list(binary())) -> {ok, LQU} | {error, parse_error()}) +) -> {ok, LQU} | {error, parse_error()}. +do(Result, Next) -> + case Result of + {ok, {A, Input}} -> + Next(A, Input); + + {error, E} -> + {error, E} + end. + +-spec parse_key(list(binary()), list(binary())) -> {ok, + {list(binary()), list(binary())}} | + {error, parse_error()}. +parse_key(Input, Segments) -> + do( + parse_key_segment(Input), + fun(Segment, Input@1) -> + Segments@1 = [Segment | Segments], + Input@2 = skip_line_whitespace(Input@1), + case Input@2 of + [<<"."/utf8>> | Input@3] -> + parse_key(Input@3, Segments@1); + + _ -> + {ok, {gleam@list:reverse(Segments@1), Input@2}} + end + end + ). + +-spec expect( + list(binary()), + binary(), + fun((list(binary())) -> {ok, {LQZ, list(binary())}} | {error, parse_error()}) +) -> {ok, {LQZ, list(binary())}} | {error, parse_error()}. +expect(Input, Expected, Next) -> + case Input of + [G | Input@1] when G =:= Expected -> + Next(Input@1); + + [G@1 | _] -> + {error, {unexpected, G@1, Expected}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, Expected}} + end. + +-spec parse_table_header(list(binary())) -> {ok, + {list(binary()), list(binary())}} | + {error, parse_error()}. +parse_table_header(Input) -> + Input@1 = skip_line_whitespace(Input), + do( + parse_key(Input@1, []), + fun(Key, Input@2) -> + expect( + Input@2, + <<"]"/utf8>>, + fun(Input@3) -> + Input@4 = skip_line_whitespace(Input@3), + expect_end_of_line( + Input@4, + fun(Input@5) -> {ok, {Key, Input@5}} end + ) + end + ) + end + ). + +-spec parse_hex(list(binary()), integer(), sign()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_hex(Input, Number, Sign) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_hex(Input@1, Number, Sign); + + [<<"0"/utf8>> | Input@2] -> + parse_hex(Input@2, (Number * 16) + 0, Sign); + + [<<"1"/utf8>> | Input@3] -> + parse_hex(Input@3, (Number * 16) + 1, Sign); + + [<<"2"/utf8>> | Input@4] -> + parse_hex(Input@4, (Number * 16) + 2, Sign); + + [<<"3"/utf8>> | Input@5] -> + parse_hex(Input@5, (Number * 16) + 3, Sign); + + [<<"4"/utf8>> | Input@6] -> + parse_hex(Input@6, (Number * 16) + 4, Sign); + + [<<"5"/utf8>> | Input@7] -> + parse_hex(Input@7, (Number * 16) + 5, Sign); + + [<<"6"/utf8>> | Input@8] -> + parse_hex(Input@8, (Number * 16) + 6, Sign); + + [<<"7"/utf8>> | Input@9] -> + parse_hex(Input@9, (Number * 16) + 7, Sign); + + [<<"8"/utf8>> | Input@10] -> + parse_hex(Input@10, (Number * 16) + 8, Sign); + + [<<"9"/utf8>> | Input@11] -> + parse_hex(Input@11, (Number * 16) + 9, Sign); + + [<<"a"/utf8>> | Input@12] -> + parse_hex(Input@12, (Number * 16) + 10, Sign); + + [<<"b"/utf8>> | Input@13] -> + parse_hex(Input@13, (Number * 16) + 11, Sign); + + [<<"c"/utf8>> | Input@14] -> + parse_hex(Input@14, (Number * 16) + 12, Sign); + + [<<"d"/utf8>> | Input@15] -> + parse_hex(Input@15, (Number * 16) + 13, Sign); + + [<<"e"/utf8>> | Input@16] -> + parse_hex(Input@16, (Number * 16) + 14, Sign); + + [<<"f"/utf8>> | Input@17] -> + parse_hex(Input@17, (Number * 16) + 15, Sign); + + [<<"A"/utf8>> | Input@18] -> + parse_hex(Input@18, (Number * 16) + 10, Sign); + + [<<"B"/utf8>> | Input@19] -> + parse_hex(Input@19, (Number * 16) + 11, Sign); + + [<<"C"/utf8>> | Input@20] -> + parse_hex(Input@20, (Number * 16) + 12, Sign); + + [<<"D"/utf8>> | Input@21] -> + parse_hex(Input@21, (Number * 16) + 13, Sign); + + [<<"E"/utf8>> | Input@22] -> + parse_hex(Input@22, (Number * 16) + 14, Sign); + + [<<"F"/utf8>> | Input@23] -> + parse_hex(Input@23, (Number * 16) + 15, Sign); + + Input@24 -> + Number@1 = case Sign of + positive -> + Number; + + negative -> + - Number + end, + {ok, {{int, Number@1}, Input@24}} + end. + +-spec parse_octal(list(binary()), integer(), sign()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_octal(Input, Number, Sign) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_octal(Input@1, Number, Sign); + + [<<"0"/utf8>> | Input@2] -> + parse_octal(Input@2, (Number * 8) + 0, Sign); + + [<<"1"/utf8>> | Input@3] -> + parse_octal(Input@3, (Number * 8) + 1, Sign); + + [<<"2"/utf8>> | Input@4] -> + parse_octal(Input@4, (Number * 8) + 2, Sign); + + [<<"3"/utf8>> | Input@5] -> + parse_octal(Input@5, (Number * 8) + 3, Sign); + + [<<"4"/utf8>> | Input@6] -> + parse_octal(Input@6, (Number * 8) + 4, Sign); + + [<<"5"/utf8>> | Input@7] -> + parse_octal(Input@7, (Number * 8) + 5, Sign); + + [<<"6"/utf8>> | Input@8] -> + parse_octal(Input@8, (Number * 8) + 6, Sign); + + [<<"7"/utf8>> | Input@9] -> + parse_octal(Input@9, (Number * 8) + 7, Sign); + + Input@10 -> + Number@1 = case Sign of + positive -> + Number; + + negative -> + - Number + end, + {ok, {{int, Number@1}, Input@10}} + end. + +-spec parse_binary(list(binary()), integer(), sign()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_binary(Input, Number, Sign) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_binary(Input@1, Number, Sign); + + [<<"0"/utf8>> | Input@2] -> + parse_binary(Input@2, (Number * 2) + 0, Sign); + + [<<"1"/utf8>> | Input@3] -> + parse_binary(Input@3, (Number * 2) + 1, Sign); + + Input@4 -> + Number@1 = case Sign of + positive -> + Number; + + negative -> + - Number + end, + {ok, {{int, Number@1}, Input@4}} + end. + +-spec parse_exponent(list(binary()), float(), sign(), integer(), sign()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_exponent(Input, N, N_sign, Ex, Ex_sign) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_exponent(Input@1, N, N_sign, Ex, Ex_sign); + + [<<"0"/utf8>> | Input@2] -> + parse_exponent(Input@2, N, N_sign, Ex * 10, Ex_sign); + + [<<"1"/utf8>> | Input@3] -> + parse_exponent(Input@3, N, N_sign, (Ex * 10) + 1, Ex_sign); + + [<<"2"/utf8>> | Input@4] -> + parse_exponent(Input@4, N, N_sign, (Ex * 10) + 2, Ex_sign); + + [<<"3"/utf8>> | Input@5] -> + parse_exponent(Input@5, N, N_sign, (Ex * 10) + 3, Ex_sign); + + [<<"4"/utf8>> | Input@6] -> + parse_exponent(Input@6, N, N_sign, (Ex * 10) + 4, Ex_sign); + + [<<"5"/utf8>> | Input@7] -> + parse_exponent(Input@7, N, N_sign, (Ex * 10) + 5, Ex_sign); + + [<<"6"/utf8>> | Input@8] -> + parse_exponent(Input@8, N, N_sign, (Ex * 10) + 6, Ex_sign); + + [<<"7"/utf8>> | Input@9] -> + parse_exponent(Input@9, N, N_sign, (Ex * 10) + 7, Ex_sign); + + [<<"8"/utf8>> | Input@10] -> + parse_exponent(Input@10, N, N_sign, (Ex * 10) + 8, Ex_sign); + + [<<"9"/utf8>> | Input@11] -> + parse_exponent(Input@11, N, N_sign, (Ex * 10) + 9, Ex_sign); + + Input@12 -> + Number = case N_sign of + positive -> + N; + + negative -> + N * -1.0 + end, + Exponent = gleam@int:to_float(case Ex_sign of + positive -> + Ex; + + negative -> + - Ex + end), + Multiplier@1 = case gleam@float:power(10.0, Exponent) of + {ok, Multiplier} -> + Multiplier; + + {error, _} -> + 1.0 + end, + {ok, {{float, Number * Multiplier@1}, Input@12}} + end. + +-spec parse_float(list(binary()), float(), sign(), float()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_float(Input, Number, Sign, Unit) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_float(Input@1, Number, Sign, Unit); + + [<<"0"/utf8>> | Input@2] -> + parse_float(Input@2, Number, Sign, Unit * 0.1); + + [<<"1"/utf8>> | Input@3] -> + parse_float(Input@3, Number + (1.0 * Unit), Sign, Unit * 0.1); + + [<<"2"/utf8>> | Input@4] -> + parse_float(Input@4, Number + (2.0 * Unit), Sign, Unit * 0.1); + + [<<"3"/utf8>> | Input@5] -> + parse_float(Input@5, Number + (3.0 * Unit), Sign, Unit * 0.1); + + [<<"4"/utf8>> | Input@6] -> + parse_float(Input@6, Number + (4.0 * Unit), Sign, Unit * 0.1); + + [<<"5"/utf8>> | Input@7] -> + parse_float(Input@7, Number + (5.0 * Unit), Sign, Unit * 0.1); + + [<<"6"/utf8>> | Input@8] -> + parse_float(Input@8, Number + (6.0 * Unit), Sign, Unit * 0.1); + + [<<"7"/utf8>> | Input@9] -> + parse_float(Input@9, Number + (7.0 * Unit), Sign, Unit * 0.1); + + [<<"8"/utf8>> | Input@10] -> + parse_float(Input@10, Number + (8.0 * Unit), Sign, Unit * 0.1); + + [<<"9"/utf8>> | Input@11] -> + parse_float(Input@11, Number + (9.0 * Unit), Sign, Unit * 0.1); + + [<<"e"/utf8>>, <<"+"/utf8>> | Input@12] -> + parse_exponent(Input@12, Number, Sign, 0, positive); + + [<<"e"/utf8>>, <<"-"/utf8>> | Input@13] -> + parse_exponent(Input@13, Number, Sign, 0, negative); + + [<<"e"/utf8>> | Input@14] -> + parse_exponent(Input@14, Number, Sign, 0, positive); + + [<<"E"/utf8>>, <<"+"/utf8>> | Input@15] -> + parse_exponent(Input@15, Number, Sign, 0, positive); + + [<<"E"/utf8>>, <<"-"/utf8>> | Input@16] -> + parse_exponent(Input@16, Number, Sign, 0, negative); + + [<<"E"/utf8>> | Input@17] -> + parse_exponent(Input@17, Number, Sign, 0, positive); + + Input@18 -> + Number@1 = case Sign of + positive -> + Number; + + negative -> + Number * -1.0 + end, + {ok, {{float, Number@1}, Input@18}} + end. + +-spec parse_string(list(binary()), binary()) -> {ok, {toml(), list(binary())}} | + {error, parse_error()}. +parse_string(Input, String) -> + case Input of + [<<"\""/utf8>> | Input@1] -> + {ok, {{string, String}, Input@1}}; + + [<<"\\"/utf8>>, <<"t"/utf8>> | Input@2] -> + parse_string(Input@2, <<String/binary, "\t"/utf8>>); + + [<<"\\"/utf8>>, <<"n"/utf8>> | Input@3] -> + parse_string(Input@3, <<String/binary, "\n"/utf8>>); + + [<<"\\"/utf8>>, <<"r"/utf8>> | Input@4] -> + parse_string(Input@4, <<String/binary, "\r"/utf8>>); + + [<<"\\"/utf8>>, <<"\""/utf8>> | Input@5] -> + parse_string(Input@5, <<String/binary, "\""/utf8>>); + + [<<"\\"/utf8>>, <<"\\"/utf8>> | Input@6] -> + parse_string(Input@6, <<String/binary, "\\"/utf8>>); + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"\""/utf8>>}}; + + [<<"\n"/utf8>> | _] -> + {error, {unexpected, <<"\n"/utf8>>, <<"\""/utf8>>}}; + + [<<"\r\n"/utf8>> | _] -> + {error, {unexpected, <<"\r\n"/utf8>>, <<"\""/utf8>>}}; + + [G | Input@7] -> + parse_string(Input@7, <<String/binary, G/binary>>) + end. + +-spec parse_multi_line_string(list(binary()), binary()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_multi_line_string(Input, String) -> + case Input of + [<<"\""/utf8>>, <<"\""/utf8>>, <<"\""/utf8>> | Input@1] -> + {ok, {{string, String}, Input@1}}; + + [<<"\\"/utf8>>, <<"\n"/utf8>> | Input@2] -> + parse_multi_line_string(skip_whitespace(Input@2), String); + + [<<"\\"/utf8>>, <<"\r\n"/utf8>> | Input@3] -> + parse_multi_line_string(skip_whitespace(Input@3), String); + + [<<"\r\n"/utf8>> | Input@4] when String =:= <<""/utf8>> -> + parse_multi_line_string(Input@4, String); + + [<<"\n"/utf8>> | Input@5] when String =:= <<""/utf8>> -> + parse_multi_line_string(Input@5, String); + + [<<"\r\n"/utf8>> | Input@6] when String =:= <<""/utf8>> -> + parse_multi_line_string(Input@6, String); + + [<<"\\"/utf8>>, <<"t"/utf8>> | Input@7] -> + parse_multi_line_string(Input@7, <<String/binary, "\t"/utf8>>); + + [<<"\\"/utf8>>, <<"n"/utf8>> | Input@8] -> + parse_multi_line_string(Input@8, <<String/binary, "\n"/utf8>>); + + [<<"\\"/utf8>>, <<"r"/utf8>> | Input@9] -> + parse_multi_line_string(Input@9, <<String/binary, "\r"/utf8>>); + + [<<"\\"/utf8>>, <<"\""/utf8>> | Input@10] -> + parse_multi_line_string(Input@10, <<String/binary, "\""/utf8>>); + + [<<"\\"/utf8>>, <<"\\"/utf8>> | Input@11] -> + parse_multi_line_string(Input@11, <<String/binary, "\\"/utf8>>); + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"\""/utf8>>}}; + + [G | Input@12] -> + parse_multi_line_string(Input@12, <<String/binary, G/binary>>) + end. + +-spec parse_multi_line_literal_string(list(binary()), binary()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_multi_line_literal_string(Input, String) -> + case Input of + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"\""/utf8>>}}; + + [<<"'"/utf8>>, <<"'"/utf8>>, <<"'"/utf8>>, <<"'"/utf8>> | _] -> + {error, {unexpected, <<"''''"/utf8>>, <<"'''"/utf8>>}}; + + [<<"'"/utf8>>, <<"'"/utf8>>, <<"'"/utf8>> | Input@1] -> + {ok, {{string, String}, Input@1}}; + + [<<"\n"/utf8>> | Input@2] when String =:= <<""/utf8>> -> + parse_multi_line_literal_string(Input@2, String); + + [<<"\r\n"/utf8>> | Input@3] when String =:= <<""/utf8>> -> + parse_multi_line_literal_string(Input@3, String); + + [G | Input@4] -> + parse_multi_line_literal_string( + Input@4, + <<String/binary, G/binary>> + ) + end. + +-spec parse_literal_string(list(binary()), binary()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_literal_string(Input, String) -> + case Input of + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"\""/utf8>>}}; + + [<<"\n"/utf8>> | _] -> + {error, {unexpected, <<"\n"/utf8>>, <<"'"/utf8>>}}; + + [<<"\r\n"/utf8>> | _] -> + {error, {unexpected, <<"\r\n"/utf8>>, <<"'"/utf8>>}}; + + [<<"'"/utf8>> | Input@1] -> + {ok, {{string, String}, Input@1}}; + + [G | Input@2] -> + parse_literal_string(Input@2, <<String/binary, G/binary>>) + end. + +-spec parse_time_ms(list(binary()), integer(), integer()) -> {ok, + {{integer(), integer()}, list(binary())}} | + {error, parse_error()}. +parse_time_ms(Input, Seconds, Ms) -> + case Input of + [<<"0"/utf8>> | Input@1] when Ms < 100000 -> + parse_time_ms(Input@1, Seconds, (Ms * 10) + 0); + + [<<"1"/utf8>> | Input@2] when Ms < 100000 -> + parse_time_ms(Input@2, Seconds, (Ms * 10) + 1); + + [<<"2"/utf8>> | Input@3] when Ms < 100000 -> + parse_time_ms(Input@3, Seconds, (Ms * 10) + 2); + + [<<"3"/utf8>> | Input@4] when Ms < 100000 -> + parse_time_ms(Input@4, Seconds, (Ms * 10) + 3); + + [<<"4"/utf8>> | Input@5] when Ms < 100000 -> + parse_time_ms(Input@5, Seconds, (Ms * 10) + 4); + + [<<"5"/utf8>> | Input@6] when Ms < 100000 -> + parse_time_ms(Input@6, Seconds, (Ms * 10) + 5); + + [<<"6"/utf8>> | Input@7] when Ms < 100000 -> + parse_time_ms(Input@7, Seconds, (Ms * 10) + 6); + + [<<"7"/utf8>> | Input@8] when Ms < 100000 -> + parse_time_ms(Input@8, Seconds, (Ms * 10) + 7); + + [<<"8"/utf8>> | Input@9] when Ms < 100000 -> + parse_time_ms(Input@9, Seconds, (Ms * 10) + 8); + + [<<"9"/utf8>> | Input@10] when Ms < 100000 -> + parse_time_ms(Input@10, Seconds, (Ms * 10) + 9); + + _ -> + {ok, {{Seconds, Ms}, Input}} + end. + +-spec parse_number_under_60(list(binary()), binary()) -> {ok, + {integer(), list(binary())}} | + {error, parse_error()}. +parse_number_under_60(Input, Expected) -> + case Input of + [<<"0"/utf8>>, <<"0"/utf8>> | Input@1] -> + {ok, {0, Input@1}}; + + [<<"0"/utf8>>, <<"1"/utf8>> | Input@2] -> + {ok, {1, Input@2}}; + + [<<"0"/utf8>>, <<"2"/utf8>> | Input@3] -> + {ok, {2, Input@3}}; + + [<<"0"/utf8>>, <<"3"/utf8>> | Input@4] -> + {ok, {3, Input@4}}; + + [<<"0"/utf8>>, <<"4"/utf8>> | Input@5] -> + {ok, {4, Input@5}}; + + [<<"0"/utf8>>, <<"5"/utf8>> | Input@6] -> + {ok, {5, Input@6}}; + + [<<"0"/utf8>>, <<"6"/utf8>> | Input@7] -> + {ok, {6, Input@7}}; + + [<<"0"/utf8>>, <<"7"/utf8>> | Input@8] -> + {ok, {7, Input@8}}; + + [<<"0"/utf8>>, <<"8"/utf8>> | Input@9] -> + {ok, {8, Input@9}}; + + [<<"0"/utf8>>, <<"9"/utf8>> | Input@10] -> + {ok, {9, Input@10}}; + + [<<"1"/utf8>>, <<"0"/utf8>> | Input@11] -> + {ok, {10, Input@11}}; + + [<<"1"/utf8>>, <<"1"/utf8>> | Input@12] -> + {ok, {11, Input@12}}; + + [<<"1"/utf8>>, <<"2"/utf8>> | Input@13] -> + {ok, {12, Input@13}}; + + [<<"1"/utf8>>, <<"3"/utf8>> | Input@14] -> + {ok, {13, Input@14}}; + + [<<"1"/utf8>>, <<"4"/utf8>> | Input@15] -> + {ok, {14, Input@15}}; + + [<<"1"/utf8>>, <<"5"/utf8>> | Input@16] -> + {ok, {15, Input@16}}; + + [<<"1"/utf8>>, <<"6"/utf8>> | Input@17] -> + {ok, {16, Input@17}}; + + [<<"1"/utf8>>, <<"7"/utf8>> | Input@18] -> + {ok, {17, Input@18}}; + + [<<"1"/utf8>>, <<"8"/utf8>> | Input@19] -> + {ok, {18, Input@19}}; + + [<<"1"/utf8>>, <<"9"/utf8>> | Input@20] -> + {ok, {19, Input@20}}; + + [<<"2"/utf8>>, <<"0"/utf8>> | Input@21] -> + {ok, {20, Input@21}}; + + [<<"2"/utf8>>, <<"1"/utf8>> | Input@22] -> + {ok, {21, Input@22}}; + + [<<"2"/utf8>>, <<"2"/utf8>> | Input@23] -> + {ok, {22, Input@23}}; + + [<<"2"/utf8>>, <<"3"/utf8>> | Input@24] -> + {ok, {23, Input@24}}; + + [<<"2"/utf8>>, <<"4"/utf8>> | Input@25] -> + {ok, {24, Input@25}}; + + [<<"2"/utf8>>, <<"5"/utf8>> | Input@26] -> + {ok, {25, Input@26}}; + + [<<"2"/utf8>>, <<"6"/utf8>> | Input@27] -> + {ok, {26, Input@27}}; + + [<<"2"/utf8>>, <<"7"/utf8>> | Input@28] -> + {ok, {27, Input@28}}; + + [<<"2"/utf8>>, <<"8"/utf8>> | Input@29] -> + {ok, {28, Input@29}}; + + [<<"2"/utf8>>, <<"9"/utf8>> | Input@30] -> + {ok, {29, Input@30}}; + + [<<"3"/utf8>>, <<"0"/utf8>> | Input@31] -> + {ok, {30, Input@31}}; + + [<<"3"/utf8>>, <<"1"/utf8>> | Input@32] -> + {ok, {31, Input@32}}; + + [<<"3"/utf8>>, <<"2"/utf8>> | Input@33] -> + {ok, {32, Input@33}}; + + [<<"3"/utf8>>, <<"3"/utf8>> | Input@34] -> + {ok, {33, Input@34}}; + + [<<"3"/utf8>>, <<"4"/utf8>> | Input@35] -> + {ok, {34, Input@35}}; + + [<<"3"/utf8>>, <<"5"/utf8>> | Input@36] -> + {ok, {35, Input@36}}; + + [<<"3"/utf8>>, <<"6"/utf8>> | Input@37] -> + {ok, {36, Input@37}}; + + [<<"3"/utf8>>, <<"7"/utf8>> | Input@38] -> + {ok, {37, Input@38}}; + + [<<"3"/utf8>>, <<"8"/utf8>> | Input@39] -> + {ok, {38, Input@39}}; + + [<<"3"/utf8>>, <<"9"/utf8>> | Input@40] -> + {ok, {39, Input@40}}; + + [<<"4"/utf8>>, <<"0"/utf8>> | Input@41] -> + {ok, {40, Input@41}}; + + [<<"4"/utf8>>, <<"1"/utf8>> | Input@42] -> + {ok, {41, Input@42}}; + + [<<"4"/utf8>>, <<"2"/utf8>> | Input@43] -> + {ok, {42, Input@43}}; + + [<<"4"/utf8>>, <<"3"/utf8>> | Input@44] -> + {ok, {43, Input@44}}; + + [<<"4"/utf8>>, <<"4"/utf8>> | Input@45] -> + {ok, {44, Input@45}}; + + [<<"4"/utf8>>, <<"5"/utf8>> | Input@46] -> + {ok, {45, Input@46}}; + + [<<"4"/utf8>>, <<"6"/utf8>> | Input@47] -> + {ok, {46, Input@47}}; + + [<<"4"/utf8>>, <<"7"/utf8>> | Input@48] -> + {ok, {47, Input@48}}; + + [<<"4"/utf8>>, <<"8"/utf8>> | Input@49] -> + {ok, {48, Input@49}}; + + [<<"4"/utf8>>, <<"9"/utf8>> | Input@50] -> + {ok, {49, Input@50}}; + + [<<"5"/utf8>>, <<"0"/utf8>> | Input@51] -> + {ok, {50, Input@51}}; + + [<<"5"/utf8>>, <<"1"/utf8>> | Input@52] -> + {ok, {51, Input@52}}; + + [<<"5"/utf8>>, <<"2"/utf8>> | Input@53] -> + {ok, {52, Input@53}}; + + [<<"5"/utf8>>, <<"3"/utf8>> | Input@54] -> + {ok, {53, Input@54}}; + + [<<"5"/utf8>>, <<"4"/utf8>> | Input@55] -> + {ok, {54, Input@55}}; + + [<<"5"/utf8>>, <<"5"/utf8>> | Input@56] -> + {ok, {55, Input@56}}; + + [<<"5"/utf8>>, <<"6"/utf8>> | Input@57] -> + {ok, {56, Input@57}}; + + [<<"5"/utf8>>, <<"7"/utf8>> | Input@58] -> + {ok, {57, Input@58}}; + + [<<"5"/utf8>>, <<"8"/utf8>> | Input@59] -> + {ok, {58, Input@59}}; + + [<<"5"/utf8>>, <<"9"/utf8>> | Input@60] -> + {ok, {59, Input@60}}; + + [G | _] -> + {error, {unexpected, G, Expected}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, Expected}} + end. + +-spec parse_hour_minute(list(binary())) -> {ok, + {{integer(), integer()}, list(binary())}} | + {error, parse_error()}. +parse_hour_minute(Input) -> + do(case Input of + [<<"0"/utf8>>, <<"0"/utf8>>, <<":"/utf8>> | Input@1] -> + {ok, {0, Input@1}}; + + [<<"0"/utf8>>, <<"1"/utf8>>, <<":"/utf8>> | Input@2] -> + {ok, {1, Input@2}}; + + [<<"0"/utf8>>, <<"2"/utf8>>, <<":"/utf8>> | Input@3] -> + {ok, {2, Input@3}}; + + [<<"0"/utf8>>, <<"3"/utf8>>, <<":"/utf8>> | Input@4] -> + {ok, {3, Input@4}}; + + [<<"0"/utf8>>, <<"4"/utf8>>, <<":"/utf8>> | Input@5] -> + {ok, {4, Input@5}}; + + [<<"0"/utf8>>, <<"5"/utf8>>, <<":"/utf8>> | Input@6] -> + {ok, {5, Input@6}}; + + [<<"0"/utf8>>, <<"6"/utf8>>, <<":"/utf8>> | Input@7] -> + {ok, {6, Input@7}}; + + [<<"0"/utf8>>, <<"7"/utf8>>, <<":"/utf8>> | Input@8] -> + {ok, {7, Input@8}}; + + [<<"0"/utf8>>, <<"8"/utf8>>, <<":"/utf8>> | Input@9] -> + {ok, {8, Input@9}}; + + [<<"0"/utf8>>, <<"9"/utf8>>, <<":"/utf8>> | Input@10] -> + {ok, {9, Input@10}}; + + [<<"1"/utf8>>, <<"0"/utf8>>, <<":"/utf8>> | Input@11] -> + {ok, {10, Input@11}}; + + [<<"1"/utf8>>, <<"1"/utf8>>, <<":"/utf8>> | Input@12] -> + {ok, {11, Input@12}}; + + [<<"1"/utf8>>, <<"2"/utf8>>, <<":"/utf8>> | Input@13] -> + {ok, {12, Input@13}}; + + [<<"1"/utf8>>, <<"3"/utf8>>, <<":"/utf8>> | Input@14] -> + {ok, {13, Input@14}}; + + [<<"1"/utf8>>, <<"4"/utf8>>, <<":"/utf8>> | Input@15] -> + {ok, {14, Input@15}}; + + [<<"1"/utf8>>, <<"5"/utf8>>, <<":"/utf8>> | Input@16] -> + {ok, {15, Input@16}}; + + [<<"1"/utf8>>, <<"6"/utf8>>, <<":"/utf8>> | Input@17] -> + {ok, {16, Input@17}}; + + [<<"1"/utf8>>, <<"7"/utf8>>, <<":"/utf8>> | Input@18] -> + {ok, {17, Input@18}}; + + [<<"1"/utf8>>, <<"8"/utf8>>, <<":"/utf8>> | Input@19] -> + {ok, {18, Input@19}}; + + [<<"1"/utf8>>, <<"9"/utf8>>, <<":"/utf8>> | Input@20] -> + {ok, {19, Input@20}}; + + [<<"2"/utf8>>, <<"0"/utf8>>, <<":"/utf8>> | Input@21] -> + {ok, {20, Input@21}}; + + [<<"2"/utf8>>, <<"1"/utf8>>, <<":"/utf8>> | Input@22] -> + {ok, {21, Input@22}}; + + [<<"2"/utf8>>, <<"2"/utf8>>, <<":"/utf8>> | Input@23] -> + {ok, {22, Input@23}}; + + [<<"2"/utf8>>, <<"3"/utf8>>, <<":"/utf8>> | Input@24] -> + {ok, {23, Input@24}}; + + [G | _] -> + {error, {unexpected, G, <<"time"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"time"/utf8>>}} + end, fun(Hours, Input@25) -> + do( + parse_number_under_60(Input@25, <<"minutes"/utf8>>), + fun(Minutes, Input@26) -> {ok, {{Hours, Minutes}, Input@26}} end + ) + end). + +-spec parse_time_s_ms(list(binary())) -> {ok, + {{integer(), integer()}, list(binary())}} | + {error, parse_error()}. +parse_time_s_ms(Input) -> + case Input of + [<<":"/utf8>> | Input@1] -> + do( + parse_number_under_60(Input@1, <<"seconds"/utf8>>), + fun(Seconds, Input@2) -> case Input@2 of + [<<"."/utf8>> | Input@3] -> + parse_time_ms(Input@3, Seconds, 0); + + _ -> + {ok, {{Seconds, 0}, Input@2}} + end end + ); + + _ -> + {ok, {{0, 0}, Input}} + end. + +-spec parse_time_minute(list(binary()), integer()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_time_minute(Input, Hours) -> + do( + parse_number_under_60(Input, <<"minutes"/utf8>>), + fun(Minutes, Input@1) -> + do( + parse_time_s_ms(Input@1), + fun(_use0, Input@2) -> + {Seconds, Ms} = _use0, + Time = {time_value, Hours, Minutes, Seconds, Ms}, + {ok, {{time, Time}, Input@2}} + end + ) + end + ). + +-spec parse_time_value(list(binary())) -> {ok, {time(), list(binary())}} | + {error, parse_error()}. +parse_time_value(Input) -> + do( + parse_hour_minute(Input), + fun(_use0, Input@1) -> + {Hours, Minutes} = _use0, + do( + parse_time_s_ms(Input@1), + fun(_use0@1, Input@2) -> + {Seconds, Ms} = _use0@1, + Time = {time_value, Hours, Minutes, Seconds, Ms}, + {ok, {Time, Input@2}} + end + ) + end + ). + +-spec parse_offset_hours(list(binary()), sign()) -> {ok, + {offset(), list(binary())}} | + {error, parse_error()}. +parse_offset_hours(Input, Sign) -> + do( + parse_hour_minute(Input), + fun(_use0, Input@1) -> + {Hours, Minutes} = _use0, + {ok, {{offset, Sign, Hours, Minutes}, Input@1}} + end + ). + +-spec parse_offset(list(binary())) -> {ok, {offset(), list(binary())}} | + {error, parse_error()}. +parse_offset(Input) -> + case Input of + [<<"Z"/utf8>> | Input@1] -> + {ok, {{offset, positive, 0, 0}, Input@1}}; + + [<<"+"/utf8>> | Input@2] -> + parse_offset_hours(Input@2, positive); + + [<<"-"/utf8>> | Input@3] -> + parse_offset_hours(Input@3, negative); + + _ -> + {ok, {local, Input}} + end. + +-spec parse_date_end(list(binary()), integer(), integer(), integer()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_date_end(Input, Year, Month, Day) -> + Date = {date_value, Year, Month, Day}, + case Input of + [<<" "/utf8>> | Input@1] -> + do( + parse_time_value(Input@1), + fun(Time, Input@2) -> + do( + parse_offset(Input@2), + fun(Offset, Input@3) -> + {ok, + {{date_time, + {date_time_value, Date, Time, Offset}}, + Input@3}} + end + ) + end + ); + + [<<"T"/utf8>> | Input@1] -> + do( + parse_time_value(Input@1), + fun(Time, Input@2) -> + do( + parse_offset(Input@2), + fun(Offset, Input@3) -> + {ok, + {{date_time, + {date_time_value, Date, Time, Offset}}, + Input@3}} + end + ) + end + ); + + _ -> + {ok, {{date, Date}, Input}} + end. + +-spec parse_date_day(list(binary()), integer(), integer()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_date_day(Input, Year, Month) -> + case Input of + [<<"0"/utf8>>, <<"1"/utf8>> | Input@1] -> + parse_date_end(Input@1, Year, Month, 1); + + [<<"0"/utf8>>, <<"2"/utf8>> | Input@2] -> + parse_date_end(Input@2, Year, Month, 2); + + [<<"0"/utf8>>, <<"3"/utf8>> | Input@3] -> + parse_date_end(Input@3, Year, Month, 3); + + [<<"0"/utf8>>, <<"4"/utf8>> | Input@4] -> + parse_date_end(Input@4, Year, Month, 4); + + [<<"0"/utf8>>, <<"5"/utf8>> | Input@5] -> + parse_date_end(Input@5, Year, Month, 5); + + [<<"0"/utf8>>, <<"6"/utf8>> | Input@6] -> + parse_date_end(Input@6, Year, Month, 6); + + [<<"0"/utf8>>, <<"7"/utf8>> | Input@7] -> + parse_date_end(Input@7, Year, Month, 7); + + [<<"0"/utf8>>, <<"8"/utf8>> | Input@8] -> + parse_date_end(Input@8, Year, Month, 8); + + [<<"0"/utf8>>, <<"9"/utf8>> | Input@9] -> + parse_date_end(Input@9, Year, Month, 9); + + [<<"1"/utf8>>, <<"0"/utf8>> | Input@10] -> + parse_date_end(Input@10, Year, Month, 10); + + [<<"1"/utf8>>, <<"1"/utf8>> | Input@11] -> + parse_date_end(Input@11, Year, Month, 11); + + [<<"1"/utf8>>, <<"2"/utf8>> | Input@12] -> + parse_date_end(Input@12, Year, Month, 12); + + [<<"1"/utf8>>, <<"3"/utf8>> | Input@13] -> + parse_date_end(Input@13, Year, Month, 13); + + [<<"1"/utf8>>, <<"4"/utf8>> | Input@14] -> + parse_date_end(Input@14, Year, Month, 14); + + [<<"1"/utf8>>, <<"5"/utf8>> | Input@15] -> + parse_date_end(Input@15, Year, Month, 15); + + [<<"1"/utf8>>, <<"6"/utf8>> | Input@16] -> + parse_date_end(Input@16, Year, Month, 16); + + [<<"1"/utf8>>, <<"7"/utf8>> | Input@17] -> + parse_date_end(Input@17, Year, Month, 17); + + [<<"1"/utf8>>, <<"8"/utf8>> | Input@18] -> + parse_date_end(Input@18, Year, Month, 18); + + [<<"1"/utf8>>, <<"9"/utf8>> | Input@19] -> + parse_date_end(Input@19, Year, Month, 19); + + [<<"2"/utf8>>, <<"0"/utf8>> | Input@20] -> + parse_date_end(Input@20, Year, Month, 20); + + [<<"2"/utf8>>, <<"1"/utf8>> | Input@21] -> + parse_date_end(Input@21, Year, Month, 21); + + [<<"2"/utf8>>, <<"2"/utf8>> | Input@22] -> + parse_date_end(Input@22, Year, Month, 22); + + [<<"2"/utf8>>, <<"3"/utf8>> | Input@23] -> + parse_date_end(Input@23, Year, Month, 23); + + [<<"2"/utf8>>, <<"4"/utf8>> | Input@24] -> + parse_date_end(Input@24, Year, Month, 24); + + [<<"2"/utf8>>, <<"5"/utf8>> | Input@25] -> + parse_date_end(Input@25, Year, Month, 25); + + [<<"2"/utf8>>, <<"6"/utf8>> | Input@26] -> + parse_date_end(Input@26, Year, Month, 26); + + [<<"2"/utf8>>, <<"7"/utf8>> | Input@27] -> + parse_date_end(Input@27, Year, Month, 27); + + [<<"2"/utf8>>, <<"8"/utf8>> | Input@28] -> + parse_date_end(Input@28, Year, Month, 28); + + [<<"2"/utf8>>, <<"9"/utf8>> | Input@29] -> + parse_date_end(Input@29, Year, Month, 29); + + [<<"3"/utf8>>, <<"0"/utf8>> | Input@30] -> + parse_date_end(Input@30, Year, Month, 30); + + [<<"3"/utf8>>, <<"1"/utf8>> | Input@31] -> + parse_date_end(Input@31, Year, Month, 31); + + [G | _] -> + {error, {unexpected, G, <<"date day"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"date day"/utf8>>}} + end. + +-spec parse_date(list(binary()), integer()) -> {ok, {toml(), list(binary())}} | + {error, parse_error()}. +parse_date(Input, Year) -> + case Input of + [<<"0"/utf8>>, <<"1"/utf8>>, <<"-"/utf8>> | Input@1] -> + parse_date_day(Input@1, Year, 1); + + [<<"0"/utf8>>, <<"2"/utf8>>, <<"-"/utf8>> | Input@2] -> + parse_date_day(Input@2, Year, 2); + + [<<"0"/utf8>>, <<"3"/utf8>>, <<"-"/utf8>> | Input@3] -> + parse_date_day(Input@3, Year, 3); + + [<<"0"/utf8>>, <<"4"/utf8>>, <<"-"/utf8>> | Input@4] -> + parse_date_day(Input@4, Year, 4); + + [<<"0"/utf8>>, <<"5"/utf8>>, <<"-"/utf8>> | Input@5] -> + parse_date_day(Input@5, Year, 5); + + [<<"0"/utf8>>, <<"6"/utf8>>, <<"-"/utf8>> | Input@6] -> + parse_date_day(Input@6, Year, 6); + + [<<"0"/utf8>>, <<"7"/utf8>>, <<"-"/utf8>> | Input@7] -> + parse_date_day(Input@7, Year, 7); + + [<<"0"/utf8>>, <<"8"/utf8>>, <<"-"/utf8>> | Input@8] -> + parse_date_day(Input@8, Year, 8); + + [<<"0"/utf8>>, <<"9"/utf8>>, <<"-"/utf8>> | Input@9] -> + parse_date_day(Input@9, Year, 9); + + [<<"1"/utf8>>, <<"0"/utf8>>, <<"-"/utf8>> | Input@10] -> + parse_date_day(Input@10, Year, 10); + + [<<"1"/utf8>>, <<"1"/utf8>>, <<"-"/utf8>> | Input@11] -> + parse_date_day(Input@11, Year, 11); + + [<<"1"/utf8>>, <<"2"/utf8>>, <<"-"/utf8>> | Input@12] -> + parse_date_day(Input@12, Year, 12); + + [G | _] -> + {error, {unexpected, G, <<"date month"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"date month"/utf8>>}} + end. + +-spec parse_number(list(binary()), integer(), sign()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_number(Input, Number, Sign) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_number(Input@1, Number, Sign); + + [<<"0"/utf8>> | Input@2] -> + parse_number(Input@2, (Number * 10) + 0, Sign); + + [<<"1"/utf8>> | Input@3] -> + parse_number(Input@3, (Number * 10) + 1, Sign); + + [<<"2"/utf8>> | Input@4] -> + parse_number(Input@4, (Number * 10) + 2, Sign); + + [<<"3"/utf8>> | Input@5] -> + parse_number(Input@5, (Number * 10) + 3, Sign); + + [<<"4"/utf8>> | Input@6] -> + parse_number(Input@6, (Number * 10) + 4, Sign); + + [<<"5"/utf8>> | Input@7] -> + parse_number(Input@7, (Number * 10) + 5, Sign); + + [<<"6"/utf8>> | Input@8] -> + parse_number(Input@8, (Number * 10) + 6, Sign); + + [<<"7"/utf8>> | Input@9] -> + parse_number(Input@9, (Number * 10) + 7, Sign); + + [<<"8"/utf8>> | Input@10] -> + parse_number(Input@10, (Number * 10) + 8, Sign); + + [<<"9"/utf8>> | Input@11] -> + parse_number(Input@11, (Number * 10) + 9, Sign); + + [<<"-"/utf8>> | Input@12] -> + parse_date(Input@12, Number); + + [<<":"/utf8>> | Input@13] when Number < 24 -> + parse_time_minute(Input@13, Number); + + [<<"."/utf8>> | Input@14] -> + parse_float(Input@14, gleam@int:to_float(Number), Sign, 0.1); + + [<<"e"/utf8>>, <<"+"/utf8>> | Input@15] -> + parse_exponent( + Input@15, + gleam@int:to_float(Number), + Sign, + 0, + positive + ); + + [<<"e"/utf8>>, <<"-"/utf8>> | Input@16] -> + parse_exponent( + Input@16, + gleam@int:to_float(Number), + Sign, + 0, + negative + ); + + [<<"e"/utf8>> | Input@17] -> + parse_exponent( + Input@17, + gleam@int:to_float(Number), + Sign, + 0, + positive + ); + + [<<"E"/utf8>>, <<"+"/utf8>> | Input@18] -> + parse_exponent( + Input@18, + gleam@int:to_float(Number), + Sign, + 0, + positive + ); + + [<<"E"/utf8>>, <<"-"/utf8>> | Input@19] -> + parse_exponent( + Input@19, + gleam@int:to_float(Number), + Sign, + 0, + negative + ); + + [<<"E"/utf8>> | Input@20] -> + parse_exponent( + Input@20, + gleam@int:to_float(Number), + Sign, + 0, + positive + ); + + Input@21 -> + Number@1 = case Sign of + positive -> + Number; + + negative -> + - Number + end, + {ok, {{int, Number@1}, Input@21}} + end. + +-spec reverse_arrays_of_tables(toml()) -> toml(). +reverse_arrays_of_tables(Toml) -> + case Toml of + {array_of_tables, Tables} -> + {array_of_tables, reverse_arrays_of_tables_array(Tables, [])}; + + {table, Table} -> + {table, reverse_arrays_of_tables_table(Table)}; + + _ -> + Toml + end. + +-spec reverse_arrays_of_tables_table(gleam@dict:dict(binary(), toml())) -> gleam@dict:dict(binary(), toml()). +reverse_arrays_of_tables_table(Table) -> + gleam@map:map_values(Table, fun(_, V) -> reverse_arrays_of_tables(V) end). + +-spec reverse_arrays_of_tables_array( + list(gleam@dict:dict(binary(), toml())), + list(gleam@dict:dict(binary(), toml())) +) -> list(gleam@dict:dict(binary(), toml())). +reverse_arrays_of_tables_array(Array, Acc) -> + case Array of + [] -> + Acc; + + [First | Rest] -> + First@1 = reverse_arrays_of_tables_table(First), + reverse_arrays_of_tables_array(Rest, [First@1 | Acc]) + end. + +-spec parse_inline_table_property( + list(binary()), + gleam@dict:dict(binary(), toml()) +) -> {ok, {gleam@dict:dict(binary(), toml()), list(binary())}} | + {error, parse_error()}. +parse_inline_table_property(Input, Properties) -> + Input@1 = skip_whitespace(Input), + do( + parse_key(Input@1, []), + fun(Key, Input@2) -> + Input@3 = skip_line_whitespace(Input@2), + expect( + Input@3, + <<"="/utf8>>, + fun(Input@4) -> + Input@5 = skip_line_whitespace(Input@4), + do( + parse_value(Input@5), + fun(Value, Input@6) -> + case insert(Properties, Key, Value) of + {ok, Properties@1} -> + {ok, {Properties@1, Input@6}}; + + {error, E} -> + {error, E} + end + end + ) + end + ) + end + ). + +-spec parse_value(list(binary())) -> {ok, {toml(), list(binary())}} | + {error, parse_error()}. +parse_value(Input) -> + case Input of + [<<"t"/utf8>>, <<"r"/utf8>>, <<"u"/utf8>>, <<"e"/utf8>> | Input@1] -> + {ok, {{bool, true}, Input@1}}; + + [<<"f"/utf8>>, + <<"a"/utf8>>, + <<"l"/utf8>>, + <<"s"/utf8>>, + <<"e"/utf8>> | + Input@2] -> + {ok, {{bool, false}, Input@2}}; + + [<<"n"/utf8>>, <<"a"/utf8>>, <<"n"/utf8>> | Input@3] -> + {ok, {{nan, positive}, Input@3}}; + + [<<"+"/utf8>>, <<"n"/utf8>>, <<"a"/utf8>>, <<"n"/utf8>> | Input@4] -> + {ok, {{nan, positive}, Input@4}}; + + [<<"-"/utf8>>, <<"n"/utf8>>, <<"a"/utf8>>, <<"n"/utf8>> | Input@5] -> + {ok, {{nan, negative}, Input@5}}; + + [<<"i"/utf8>>, <<"n"/utf8>>, <<"f"/utf8>> | Input@6] -> + {ok, {{infinity, positive}, Input@6}}; + + [<<"+"/utf8>>, <<"i"/utf8>>, <<"n"/utf8>>, <<"f"/utf8>> | Input@7] -> + {ok, {{infinity, positive}, Input@7}}; + + [<<"-"/utf8>>, <<"i"/utf8>>, <<"n"/utf8>>, <<"f"/utf8>> | Input@8] -> + {ok, {{infinity, negative}, Input@8}}; + + [<<"["/utf8>> | Input@9] -> + parse_array(Input@9, []); + + [<<"{"/utf8>> | Input@10] -> + parse_inline_table(Input@10, gleam@map:new()); + + [<<"0"/utf8>>, <<"x"/utf8>> | Input@11] -> + parse_hex(Input@11, 0, positive); + + [<<"+"/utf8>>, <<"0"/utf8>>, <<"x"/utf8>> | Input@12] -> + parse_hex(Input@12, 0, positive); + + [<<"-"/utf8>>, <<"0"/utf8>>, <<"x"/utf8>> | Input@13] -> + parse_hex(Input@13, 0, negative); + + [<<"0"/utf8>>, <<"o"/utf8>> | Input@14] -> + parse_octal(Input@14, 0, positive); + + [<<"+"/utf8>>, <<"0"/utf8>>, <<"o"/utf8>> | Input@15] -> + parse_octal(Input@15, 0, positive); + + [<<"-"/utf8>>, <<"0"/utf8>>, <<"o"/utf8>> | Input@16] -> + parse_octal(Input@16, 0, negative); + + [<<"0"/utf8>>, <<"b"/utf8>> | Input@17] -> + parse_binary(Input@17, 0, positive); + + [<<"+"/utf8>>, <<"0"/utf8>>, <<"b"/utf8>> | Input@18] -> + parse_binary(Input@18, 0, positive); + + [<<"-"/utf8>>, <<"0"/utf8>>, <<"b"/utf8>> | Input@19] -> + parse_binary(Input@19, 0, negative); + + [<<"+"/utf8>> | Input@20] -> + parse_number(Input@20, 0, positive); + + [<<"-"/utf8>> | Input@21] -> + parse_number(Input@21, 0, negative); + + [<<"0"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"1"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"2"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"3"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"4"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"5"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"6"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"7"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"8"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"9"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"\""/utf8>>, <<"\""/utf8>>, <<"\""/utf8>> | Input@22] -> + parse_multi_line_string(Input@22, <<""/utf8>>); + + [<<"\""/utf8>> | Input@23] -> + parse_string(Input@23, <<""/utf8>>); + + [<<"'"/utf8>>, <<"'"/utf8>>, <<"'"/utf8>> | Input@24] -> + parse_multi_line_literal_string(Input@24, <<""/utf8>>); + + [<<"'"/utf8>> | Input@25] -> + parse_literal_string(Input@25, <<""/utf8>>); + + [G | _] -> + {error, {unexpected, G, <<"value"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"value"/utf8>>}} + end. + +-spec parse_inline_table(list(binary()), gleam@dict:dict(binary(), toml())) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_inline_table(Input, Properties) -> + Input@1 = skip_whitespace(Input), + case Input@1 of + [<<"}"/utf8>> | Input@2] -> + {ok, {{inline_table, Properties}, Input@2}}; + + _ -> + case parse_inline_table_property(Input@1, Properties) of + {ok, {Properties@1, Input@3}} -> + Input@4 = skip_whitespace(Input@3), + case Input@4 of + [<<"}"/utf8>> | Input@5] -> + {ok, {{inline_table, Properties@1}, Input@5}}; + + [<<","/utf8>> | Input@6] -> + Input@7 = skip_whitespace(Input@6), + parse_inline_table(Input@7, Properties@1); + + [G | _] -> + {error, {unexpected, G, <<"}"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"}"/utf8>>}} + end; + + {error, E} -> + {error, E} + end + end. + +-spec parse_key_value(list(binary()), gleam@dict:dict(binary(), toml())) -> {ok, + {gleam@dict:dict(binary(), toml()), list(binary())}} | + {error, parse_error()}. +parse_key_value(Input, Toml) -> + do( + parse_key(Input, []), + fun(Key, Input@1) -> + Input@2 = skip_line_whitespace(Input@1), + expect( + Input@2, + <<"="/utf8>>, + fun(Input@3) -> + Input@4 = skip_line_whitespace(Input@3), + do( + parse_value(Input@4), + fun(Value, Input@5) -> case insert(Toml, Key, Value) of + {ok, Toml@1} -> + {ok, {Toml@1, Input@5}}; + + {error, E} -> + {error, E} + end end + ) + end + ) + end + ). + +-spec parse_table(list(binary()), gleam@dict:dict(binary(), toml())) -> {ok, + {gleam@dict:dict(binary(), toml()), list(binary())}} | + {error, parse_error()}. +parse_table(Input, Toml) -> + Input@1 = skip_whitespace(Input), + case Input@1 of + [<<"["/utf8>> | _] -> + {ok, {Toml, Input@1}}; + + [] -> + {ok, {Toml, Input@1}}; + + _ -> + case parse_key_value(Input@1, Toml) of + {ok, {Toml@1, Input@2}} -> + case skip_line_whitespace(Input@2) of + [] -> + {ok, {Toml@1, []}}; + + [<<"\n"/utf8>> | In] -> + parse_table(In, Toml@1); + + [<<"\r\n"/utf8>> | In] -> + parse_table(In, Toml@1); + + [G | _] -> + {error, {unexpected, G, <<"\n"/utf8>>}} + end; + + E -> + E + end + end. + +-spec parse_array_of_tables(list(binary())) -> {ok, + {{list(binary()), gleam@dict:dict(binary(), toml())}, list(binary())}} | + {error, parse_error()}. +parse_array_of_tables(Input) -> + Input@1 = skip_line_whitespace(Input), + do( + parse_key(Input@1, []), + fun(Key, Input@2) -> + expect( + Input@2, + <<"]"/utf8>>, + fun(Input@3) -> + expect( + Input@3, + <<"]"/utf8>>, + fun(Input@4) -> + do( + parse_table(Input@4, gleam@map:new()), + fun(Table, Input@5) -> + {ok, {{Key, Table}, Input@5}} + end + ) + end + ) + end + ) + end + ). + +-spec parse_table_and_header(list(binary())) -> {ok, + {{list(binary()), gleam@dict:dict(binary(), toml())}, list(binary())}} | + {error, parse_error()}. +parse_table_and_header(Input) -> + do( + parse_table_header(Input), + fun(Key, Input@1) -> + do( + parse_table(Input@1, gleam@map:new()), + fun(Table, Input@2) -> {ok, {{Key, Table}, Input@2}} end + ) + end + ). + +-spec parse_tables(list(binary()), gleam@dict:dict(binary(), toml())) -> {ok, + gleam@dict:dict(binary(), toml())} | + {error, parse_error()}. +parse_tables(Input, Toml) -> + case Input of + [<<"["/utf8>>, <<"["/utf8>> | Input@1] -> + case parse_array_of_tables(Input@1) of + {error, E} -> + {error, E}; + + {ok, {{Key, Table}, Input@2}} -> + case insert(Toml, Key, {array_of_tables, [Table]}) of + {ok, Toml@1} -> + parse_tables(Input@2, Toml@1); + + {error, E@1} -> + {error, E@1} + end + end; + + [<<"["/utf8>> | Input@3] -> + case parse_table_and_header(Input@3) of + {error, E@2} -> + {error, E@2}; + + {ok, {{Key@1, Table@1}, Input@4}} -> + case insert(Toml, Key@1, {table, Table@1}) of + {ok, Toml@2} -> + parse_tables(Input@4, Toml@2); + + {error, E@3} -> + {error, E@3} + end + end; + + [G | _] -> + {error, {unexpected, G, <<"["/utf8>>}}; + + [] -> + {ok, Toml} + end. + +-spec parse(binary()) -> {ok, gleam@dict:dict(binary(), toml())} | + {error, parse_error()}. +parse(Input) -> + Input@1 = gleam@string:to_graphemes(Input), + Input@2 = drop_comments(Input@1, []), + Input@3 = skip_whitespace(Input@2), + do( + parse_table(Input@3, gleam@map:new()), + fun(Toml, Input@4) -> case parse_tables(Input@4, Toml) of + {ok, Toml@1} -> + {ok, reverse_arrays_of_tables_table(Toml@1)}; + + {error, E} -> + {error, E} + end end + ). + +-spec parse_array(list(binary()), list(toml())) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_array(Input, Elements) -> + Input@1 = skip_whitespace(Input), + case Input@1 of + [<<"]"/utf8>> | Input@2] -> + {ok, {{array, gleam@list:reverse(Elements)}, Input@2}}; + + _ -> + do( + parse_value(Input@1), + fun(Element, Input@3) -> + Elements@1 = [Element | Elements], + Input@4 = skip_whitespace(Input@3), + case Input@4 of + [<<"]"/utf8>> | Input@5] -> + {ok, + {{array, gleam@list:reverse(Elements@1)}, + Input@5}}; + + [<<","/utf8>> | Input@6] -> + Input@7 = skip_whitespace(Input@6), + parse_array(Input@7, Elements@1); + + [G | _] -> + {error, {unexpected, G, <<"]"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"]"/utf8>>}} + end + end + ) + end. diff --git a/aoc2023/build/dev/erlang/tom/ebin/tom.app b/aoc2023/build/dev/erlang/tom/ebin/tom.app new file mode 100644 index 0000000..ade9be1 --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/ebin/tom.app @@ -0,0 +1,7 @@ +{application, tom, [ + {vsn, "0.2.1"}, + {applications, [gleam_stdlib]}, + {description, "A pure Gleam TOML parser!"}, + {modules, []}, + {registered, []} +]}. diff --git a/aoc2023/build/dev/erlang/tom/ebin/tom.beam b/aoc2023/build/dev/erlang/tom/ebin/tom.beam Binary files differnew file mode 100644 index 0000000..f6a990a --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/ebin/tom.beam diff --git a/aoc2023/build/dev/erlang/tom/include/tom_DateTimeValue.hrl b/aoc2023/build/dev/erlang/tom/include/tom_DateTimeValue.hrl new file mode 100644 index 0000000..3b1e660 --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/include/tom_DateTimeValue.hrl @@ -0,0 +1,5 @@ +-record(date_time_value, { + date :: tom:date(), + time :: tom:time(), + offset :: tom:offset() +}). diff --git a/aoc2023/build/dev/erlang/tom/include/tom_DateValue.hrl b/aoc2023/build/dev/erlang/tom/include/tom_DateValue.hrl new file mode 100644 index 0000000..c41f901 --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/include/tom_DateValue.hrl @@ -0,0 +1 @@ +-record(date_value, {year :: integer(), month :: integer(), day :: integer()}). diff --git a/aoc2023/build/dev/erlang/tom/include/tom_KeyAlreadyInUse.hrl b/aoc2023/build/dev/erlang/tom/include/tom_KeyAlreadyInUse.hrl new file mode 100644 index 0000000..930df26 --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/include/tom_KeyAlreadyInUse.hrl @@ -0,0 +1 @@ +-record(key_already_in_use, {key :: list(binary())}). diff --git a/aoc2023/build/dev/erlang/tom/include/tom_NotFound.hrl b/aoc2023/build/dev/erlang/tom/include/tom_NotFound.hrl new file mode 100644 index 0000000..19c9a17 --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/include/tom_NotFound.hrl @@ -0,0 +1 @@ +-record(not_found, {key :: list(binary())}). diff --git a/aoc2023/build/dev/erlang/tom/include/tom_Offset.hrl b/aoc2023/build/dev/erlang/tom/include/tom_Offset.hrl new file mode 100644 index 0000000..a58a8e1 --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/include/tom_Offset.hrl @@ -0,0 +1,5 @@ +-record(offset, { + direction :: tom:sign(), + hours :: integer(), + minutes :: integer() +}). diff --git a/aoc2023/build/dev/erlang/tom/include/tom_TimeValue.hrl b/aoc2023/build/dev/erlang/tom/include/tom_TimeValue.hrl new file mode 100644 index 0000000..e1275de --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/include/tom_TimeValue.hrl @@ -0,0 +1,6 @@ +-record(time_value, { + hour :: integer(), + minute :: integer(), + second :: integer(), + millisecond :: integer() +}). diff --git a/aoc2023/build/dev/erlang/tom/include/tom_Unexpected.hrl b/aoc2023/build/dev/erlang/tom/include/tom_Unexpected.hrl new file mode 100644 index 0000000..ab1091c --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/include/tom_Unexpected.hrl @@ -0,0 +1 @@ +-record(unexpected, {got :: binary(), expected :: binary()}). diff --git a/aoc2023/build/dev/erlang/tom/include/tom_WrongType.hrl b/aoc2023/build/dev/erlang/tom/include/tom_WrongType.hrl new file mode 100644 index 0000000..ae57352 --- /dev/null +++ b/aoc2023/build/dev/erlang/tom/include/tom_WrongType.hrl @@ -0,0 +1,5 @@ +-record(wrong_type, { + key :: list(binary()), + expected :: binary(), + got :: binary() +}). diff --git a/aoc2023/build/dev/javascript/gleam.lock b/aoc2023/build/dev/javascript/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/dev/javascript/gleam.lock diff --git a/aoc2023/build/lsp/erlang/gleam.lock b/aoc2023/build/lsp/erlang/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam.lock diff --git a/aoc2023/build/lsp/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache b/aoc2023/build/lsp/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache Binary files differnew file mode 100644 index 0000000..d80b6f5 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache diff --git a/aoc2023/build/lsp/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache_meta b/aoc2023/build/lsp/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache_meta Binary files differnew file mode 100644 index 0000000..c59c230 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache Binary files differnew file mode 100644 index 0000000..af5064d --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache diff --git a/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_meta b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_meta Binary files differnew file mode 100644 index 0000000..ac37397 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache Binary files differnew file mode 100644 index 0000000..8b0da6a --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache diff --git a/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_meta b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_meta Binary files differnew file mode 100644 index 0000000..7612e93 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache Binary files differnew file mode 100644 index 0000000..f2dc094 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta Binary files differnew file mode 100644 index 0000000..c968106 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache Binary files differnew file mode 100644 index 0000000..ca7044f --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta Binary files differnew file mode 100644 index 0000000..738bcf2 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache Binary files differnew file mode 100644 index 0000000..77e9b13 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_meta Binary files differnew file mode 100644 index 0000000..6e3ee81 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache Binary files differnew file mode 100644 index 0000000..2a3b4ea --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_meta Binary files differnew file mode 100644 index 0000000..f2508da --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache Binary files differnew file mode 100644 index 0000000..50f4eee --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta Binary files differnew file mode 100644 index 0000000..e31207b --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache Binary files differnew file mode 100644 index 0000000..e42668c --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_meta Binary files differnew file mode 100644 index 0000000..30819f5 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache Binary files differnew file mode 100644 index 0000000..89892b0 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta Binary files differnew file mode 100644 index 0000000..1ed64d0 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache Binary files differnew file mode 100644 index 0000000..74dbf2e --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta Binary files differnew file mode 100644 index 0000000..1824e4b --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache Binary files differnew file mode 100644 index 0000000..e2bc5b0 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta Binary files differnew file mode 100644 index 0000000..5d43230 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache Binary files differnew file mode 100644 index 0000000..cb804ae --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta Binary files differnew file mode 100644 index 0000000..6d282ca --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache Binary files differnew file mode 100644 index 0000000..378413e --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta Binary files differnew file mode 100644 index 0000000..a84ec42 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache Binary files differnew file mode 100644 index 0000000..6e28b1a --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta Binary files differnew file mode 100644 index 0000000..1de48df --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache Binary files differnew file mode 100644 index 0000000..1181c6f --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta Binary files differnew file mode 100644 index 0000000..157d62a --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache Binary files differnew file mode 100644 index 0000000..8f20342 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta Binary files differnew file mode 100644 index 0000000..b063182 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache Binary files differnew file mode 100644 index 0000000..7522564 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta Binary files differnew file mode 100644 index 0000000..262f199 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache Binary files differnew file mode 100644 index 0000000..23983c9 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta Binary files differnew file mode 100644 index 0000000..d8e0f2c --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache Binary files differnew file mode 100644 index 0000000..7e30b9a --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta Binary files differnew file mode 100644 index 0000000..8431bbf --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache Binary files differnew file mode 100644 index 0000000..1dc9e66 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta Binary files differnew file mode 100644 index 0000000..0ec7fb6 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache Binary files differnew file mode 100644 index 0000000..43e7b46 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta Binary files differnew file mode 100644 index 0000000..a102823 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache Binary files differnew file mode 100644 index 0000000..4effed9 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta Binary files differnew file mode 100644 index 0000000..2c308ac --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache Binary files differnew file mode 100644 index 0000000..1c2841b --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta Binary files differnew file mode 100644 index 0000000..3031e40 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache Binary files differnew file mode 100644 index 0000000..520070a --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta Binary files differnew file mode 100644 index 0000000..b8bba7e --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache Binary files differnew file mode 100644 index 0000000..7feabe9 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta Binary files differnew file mode 100644 index 0000000..1e4a58c --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache Binary files differnew file mode 100644 index 0000000..66392d2 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_meta Binary files differnew file mode 100644 index 0000000..ecac5d1 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache Binary files differnew file mode 100644 index 0000000..1777ae2 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache diff --git a/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta Binary files differnew file mode 100644 index 0000000..0967876 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta diff --git a/aoc2023/build/lsp/erlang/gleam_version b/aoc2023/build/lsp/erlang/gleam_version new file mode 100644 index 0000000..867e524 --- /dev/null +++ b/aoc2023/build/lsp/erlang/gleam_version @@ -0,0 +1 @@ +1.2.0
\ No newline at end of file diff --git a/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cache b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cache Binary files differnew file mode 100644 index 0000000..9776f55 --- /dev/null +++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cache diff --git a/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cache_meta b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cache_meta Binary files differnew file mode 100644 index 0000000..b0ea973 --- /dev/null +++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cache_meta diff --git a/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cache b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cache Binary files differnew file mode 100644 index 0000000..b0d5297 --- /dev/null +++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cache diff --git a/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cache_meta b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cache_meta Binary files differnew file mode 100644 index 0000000..de472d6 --- /dev/null +++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cache_meta diff --git a/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache Binary files differnew file mode 100644 index 0000000..0b572cc --- /dev/null +++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache diff --git a/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache_meta b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache_meta Binary files differnew file mode 100644 index 0000000..b48a19f --- /dev/null +++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache_meta diff --git a/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache b/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache Binary files differnew file mode 100644 index 0000000..7df428a --- /dev/null +++ b/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache diff --git a/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache_meta b/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache_meta Binary files differnew file mode 100644 index 0000000..f2947eb --- /dev/null +++ b/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache_meta diff --git a/aoc2023/build/lsp/javascript/gleam.lock b/aoc2023/build/lsp/javascript/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/lsp/javascript/gleam.lock diff --git a/aoc2023/build/packages/adglent/LICENSE b/aoc2023/build/packages/adglent/LICENSE new file mode 100644 index 0000000..c7c82cc --- /dev/null +++ b/aoc2023/build/packages/adglent/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2023 John Björk + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/aoc2023/build/packages/adglent/README.md b/aoc2023/build/packages/adglent/README.md new file mode 100644 index 0000000..fcd81eb --- /dev/null +++ b/aoc2023/build/packages/adglent/README.md @@ -0,0 +1,115 @@ +# adglent + +[](https://hex.pm/packages/adglent) +[](https://hexdocs.pm/adglent/) + +## About + +`adglent` is a Gleam library which can be used to setup testing code and a template for implementing solution to [Advent of code](https://adventofcode.com/) problems. + +> NOTE: `adglent` **only** supports `erlang` target (default) for Gleam. + +## Prerequisites + +`adglent` is written in `gleam` and runs and tests solutions written in Gleam. Read more about `gleam` at [gleam.run](https://gleam.run). + +The easiest way to install `gleam` is to use `asdf`: + +1. Install `asdf` according to the instructions at the [asdf website](https://asdf-vm.com/) +2. Install the gleam asdf plugin: `asdf plugin-add gleam` +3. Install the latest `asdf install gleam latest` +4. Use the latest gleam version globally: `asdf global gleam latest` + +> HINT: `asdf` can manage multiple versions of gleam and the version can be set globally and also locally (`asdf local gleam <VERSION>`) to use a specific gleam version in a project. + +## Installation + +Start a new gleam project for your AOC soluctions with `gleam new`. In the project folder run: + +```sh +gleam add --dev adglent +``` + +## Usage + +### Initializing + +First log in to [Advent of code](https://adventofcode.com/) and copy your personal `session-cookie`. The value can be found using developer tools in the browser (in Chrome: "Application->Cookies->https://adventofcode.com->session" and copy the Cookie-value) + +```sh +gleam run -m adglent/init +``` + +Input the AOC year, you personal AOC session cookie and select if `showtime` should be used for tests (otherwise it will assume the project uses `gleeunit` as is default for `gleam new <project>`) + +> NOTE: `showtime` is an alternate gleam test-runner. It is still quite new and havn't been tested in as many project as `gleeunit`. It has a different way of formatting the test-results and also supports the possibility to run specific test-modules (which can be useful in AOC). `showtime` is a standalone project but have been embedded into `adglent`. + +### Add day + +To start working on the solution for a specific day run: + +```sh +gleam run -m adglent/day <NUM> +``` + +Where `<NUM>` is the day number of the day you want to solve a problem for. + +> Example (start solving 1st of December): +> +> ```sh +> gleam run -m adglent/day 1 +> ``` + +Adding a day will add tests in `test/day<NUM>/day<NUM>_test.gleam`and a `src/day<NUM>/solve.gleam` file where the solution can be implemented. + +Furthermore it will also download the input for the problem to `src/day<NUM>/input.txt` + +Before running the tests you need to provide one or more example. These can be found in the problem description for that day at the AOC website. + +Add an example to a part of the problem by adding examples to the `part1_examples` or `part2_examples` lists. + +> Example (input "Hello Joe!" should give answer 613411): +> +> ```gleam +> const part1_examples: List(Example(Problem1AnswerType)) = [ +> Example("Hello Joe!", "613411"), +> ] +> ``` + +The type of the answer for a part can be adjusted if needed by changing the type aliases `Problem1AnswerType` / `Problem2AnswerType`. Note that this will change the type that the `part1` / `part2` functions in `solve.gleam` expect to return. + +### Testing + +To test all days in the project use: + +```sh +gleam test +``` + +If you are using `showtime` you can test a single day by running: + +```sh +gleam test -- --modules=day<NUM>/day<NUM>_test +``` + +> Example (test solution for 1st of December): +> +> ```sh +> gleam test -- modules=day1/day1_test +> ``` + +### Get the answer + +To get the (hopefully correct) answer after the tests are ok run: + +```sh +gleam run -m day<NUM>/solve <PART> +``` + +where `<NUM>` is the day to solve and `<PART>` is the part of the problem (1 or 2) to solve. + +This will run the solver and print the answer to stdout. + +### Module documentation + +Module documentation can be found at <https://hexdocs.pm/adglent>. diff --git a/aoc2023/build/packages/adglent/gleam.toml b/aoc2023/build/packages/adglent/gleam.toml new file mode 100644 index 0000000..e1d81b8 --- /dev/null +++ b/aoc2023/build/packages/adglent/gleam.toml @@ -0,0 +1,29 @@ +name = "adglent" +version = "1.2.0" + +description = "Advent of code helper - automating setup of tests, solution template and problem input" +licences = ["Apache-2.0"] +repository = { type = "github", user = "JohnBjrk", repo = "adglent" } + +internal_modules = [ + "adglent/priv", + "adglent/priv/*", + "showtime/internal/*", +] +gleam = ">= 0.32.0" + +[dependencies] +gleam_stdlib = "~> 0.32" +simplifile = "~> 1.0" +gleam_http = "~> 3.5" +gleam_erlang = "~> 0.23.0" +gleam_otp = "~> 0.8.0" +gleam_community_ansi = "~> 1.2" +glint = "~> 0.13.0" +gap = "~> 1.0" +snag = "~> 0.2.0" +tom = "~> 0.2.0" +gleam_httpc = "~> 2.1" + +[dev-dependencies] +gleeunit = "~> 1.0" diff --git a/aoc2023/build/packages/adglent/include/adglent_Example.hrl b/aoc2023/build/packages/adglent/include/adglent_Example.hrl new file mode 100644 index 0000000..615e473 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/adglent_Example.hrl @@ -0,0 +1 @@ +-record(example, {input :: binary(), answer :: any()}). diff --git a/aoc2023/build/packages/adglent/include/priv@toml_TomGetError.hrl b/aoc2023/build/packages/adglent/include/priv@toml_TomGetError.hrl new file mode 100644 index 0000000..4cd5ddd --- /dev/null +++ b/aoc2023/build/packages/adglent/include/priv@toml_TomGetError.hrl @@ -0,0 +1 @@ +-record(tom_get_error, {error :: tom:get_error()}). diff --git a/aoc2023/build/packages/adglent/include/priv@toml_TomParseError.hrl b/aoc2023/build/packages/adglent/include/priv@toml_TomParseError.hrl new file mode 100644 index 0000000..7306934 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/priv@toml_TomParseError.hrl @@ -0,0 +1 @@ +-record(tom_parse_error, {error :: tom:parse_error()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@common_event_handler_Finished.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@common_event_handler_Finished.hrl new file mode 100644 index 0000000..7d24e52 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@common_event_handler_Finished.hrl @@ -0,0 +1 @@ +-record(finished, {num_modules :: integer()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@common_event_handler_HandlerState.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@common_event_handler_HandlerState.hrl new file mode 100644 index 0000000..2eceb23 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@common_event_handler_HandlerState.hrl @@ -0,0 +1,5 @@ +-record(handler_state, { + test_state :: showtime@internal@common@common_event_handler:test_state(), + num_done :: integer(), + events :: gleam@map:map_(binary(), gleam@map:map_(binary(), showtime@internal@common@test_suite:test_run())) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ArgList.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ArgList.hrl new file mode 100644 index 0000000..79f34f8 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ArgList.hrl @@ -0,0 +1 @@ +-record(arg_list, {arg_list :: list(gleam@dynamic:dynamic_())}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertEqual.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertEqual.hrl new file mode 100644 index 0000000..c6458ba --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertEqual.hrl @@ -0,0 +1,3 @@ +-record(assert_equal, { + details :: list(showtime@internal@common@test_result:reason_detail()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertMatch.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertMatch.hrl new file mode 100644 index 0000000..4920304 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertMatch.hrl @@ -0,0 +1,3 @@ +-record(assert_match, { + details :: list(showtime@internal@common@test_result:reason_detail()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertNotEqual.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertNotEqual.hrl new file mode 100644 index 0000000..221c15f --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertNotEqual.hrl @@ -0,0 +1,3 @@ +-record(assert_not_equal, { + details :: list(showtime@internal@common@test_result:reason_detail()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ErlangException.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ErlangException.hrl new file mode 100644 index 0000000..9a31ba8 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ErlangException.hrl @@ -0,0 +1,6 @@ +-record(erlang_exception, { + class :: showtime@internal@common@test_result:class(), + reason :: showtime@internal@common@test_result:reason(), + stacktrace :: showtime@internal@common@test_result:trace_list(), + output_buffer :: list(binary()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ErrorInfo.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ErrorInfo.hrl new file mode 100644 index 0000000..97d0802 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ErrorInfo.hrl @@ -0,0 +1,3 @@ +-record(error_info, { + error_info :: gleam@map:map_(gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Expected.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Expected.hrl new file mode 100644 index 0000000..5e40ad3 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Expected.hrl @@ -0,0 +1 @@ +-record(expected, {value :: gleam@dynamic:dynamic_()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Expression.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Expression.hrl new file mode 100644 index 0000000..7aa0c35 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Expression.hrl @@ -0,0 +1 @@ +-record(expression, {expression :: binary()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_File.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_File.hrl new file mode 100644 index 0000000..1274b74 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_File.hrl @@ -0,0 +1 @@ +-record(file, {filename :: binary()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GenericException.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GenericException.hrl new file mode 100644 index 0000000..7c33d0d --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GenericException.hrl @@ -0,0 +1 @@ +-record(generic_exception, {value :: gleam@dynamic:dynamic_()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GleamAssert.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GleamAssert.hrl new file mode 100644 index 0000000..095748c --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GleamAssert.hrl @@ -0,0 +1 @@ +-record(gleam_assert, {value :: gleam@dynamic:dynamic_(), line_no :: integer()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GleamError.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GleamError.hrl new file mode 100644 index 0000000..68e6645 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GleamError.hrl @@ -0,0 +1,3 @@ +-record(gleam_error, { + details :: showtime@internal@common@test_result:gleam_error_detail() +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Ignored.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Ignored.hrl new file mode 100644 index 0000000..87b7e2f --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Ignored.hrl @@ -0,0 +1 @@ +-record(ignored, {reason :: showtime@internal@common@test_result:ignore_reason()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_LetAssert.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_LetAssert.hrl new file mode 100644 index 0000000..5f3f60d --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_LetAssert.hrl @@ -0,0 +1,7 @@ +-record(let_assert, { + module :: binary(), + function :: binary(), + line_no :: integer(), + message :: binary(), + value :: gleam@dynamic:dynamic_() +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Line.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Line.hrl new file mode 100644 index 0000000..9807df6 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Line.hrl @@ -0,0 +1 @@ +-record(line, {line_no :: integer()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Module.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Module.hrl new file mode 100644 index 0000000..8002c0c --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Module.hrl @@ -0,0 +1 @@ +-record(module, {name :: binary()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Num.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Num.hrl new file mode 100644 index 0000000..c36efa3 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Num.hrl @@ -0,0 +1 @@ +-record(num, {arity :: integer()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Pattern.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Pattern.hrl new file mode 100644 index 0000000..6aa9c84 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Pattern.hrl @@ -0,0 +1 @@ +-record(pattern, {pattern :: binary()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ReasonLine.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ReasonLine.hrl new file mode 100644 index 0000000..b7ad1ab --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ReasonLine.hrl @@ -0,0 +1 @@ +-record(reason_line, {line_no :: integer()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TestFunctionReturn.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TestFunctionReturn.hrl new file mode 100644 index 0000000..b0bc294 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TestFunctionReturn.hrl @@ -0,0 +1,4 @@ +-record(test_function_return, { + value :: gleam@dynamic:dynamic_(), + output_buffer :: list(binary()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Trace.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Trace.hrl new file mode 100644 index 0000000..4cb007c --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Trace.hrl @@ -0,0 +1,5 @@ +-record(trace, { + function :: binary(), + arity :: showtime@internal@common@test_result:arity_(), + extra_info :: list(showtime@internal@common@test_result:extra_info()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TraceList.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TraceList.hrl new file mode 100644 index 0000000..c1aa9c5 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TraceList.hrl @@ -0,0 +1,3 @@ +-record(trace_list, { + traces :: list(showtime@internal@common@test_result:trace()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TraceModule.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TraceModule.hrl new file mode 100644 index 0000000..595362f --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TraceModule.hrl @@ -0,0 +1,6 @@ +-record(trace_module, { + module :: binary(), + function :: binary(), + arity :: showtime@internal@common@test_result:arity_(), + extra_info :: list(showtime@internal@common@test_result:extra_info()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Value.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Value.hrl new file mode 100644 index 0000000..3a4b0dd --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Value.hrl @@ -0,0 +1 @@ +-record(value, {value :: gleam@dynamic:dynamic_()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_CompletedTestRun.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_CompletedTestRun.hrl new file mode 100644 index 0000000..927a0cf --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_CompletedTestRun.hrl @@ -0,0 +1,6 @@ +-record(completed_test_run, { + test_function :: showtime@internal@common@test_suite:test_function(), + total_time :: integer(), + result :: {ok, showtime@internal@common@test_result:test_return()} | + {error, showtime@internal@common@test_result:exception()} +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTest.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTest.hrl new file mode 100644 index 0000000..13df1bf --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTest.hrl @@ -0,0 +1,6 @@ +-record(end_test, { + test_module :: showtime@internal@common@test_suite:test_module(), + test_function :: showtime@internal@common@test_suite:test_function(), + result :: {ok, showtime@internal@common@test_result:test_return()} | + {error, showtime@internal@common@test_result:exception()} +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTestRun.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTestRun.hrl new file mode 100644 index 0000000..3f78991 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTestRun.hrl @@ -0,0 +1 @@ +-record(end_test_run, {num_modules :: integer()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTestSuite.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTestSuite.hrl new file mode 100644 index 0000000..a7f37b3 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTestSuite.hrl @@ -0,0 +1,3 @@ +-record(end_test_suite, { + test_module :: showtime@internal@common@test_suite:test_module() +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_OngoingTestRun.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_OngoingTestRun.hrl new file mode 100644 index 0000000..f52e5cc --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_OngoingTestRun.hrl @@ -0,0 +1,4 @@ +-record(ongoing_test_run, { + test_function :: showtime@internal@common@test_suite:test_function(), + started_at :: integer() +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_StartTest.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_StartTest.hrl new file mode 100644 index 0000000..d532609 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_StartTest.hrl @@ -0,0 +1,4 @@ +-record(start_test, { + test_module :: showtime@internal@common@test_suite:test_module(), + test_function :: showtime@internal@common@test_suite:test_function() +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_StartTestSuite.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_StartTestSuite.hrl new file mode 100644 index 0000000..d5a03d3 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_StartTestSuite.hrl @@ -0,0 +1,3 @@ +-record(start_test_suite, { + test_module :: showtime@internal@common@test_suite:test_module() +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestFunction.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestFunction.hrl new file mode 100644 index 0000000..a783ba4 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestFunction.hrl @@ -0,0 +1 @@ +-record(test_function, {name :: binary()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestModule.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestModule.hrl new file mode 100644 index 0000000..ee9baaf --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestModule.hrl @@ -0,0 +1 @@ +-record(test_module, {name :: binary(), path :: gleam@option:option(binary())}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestSuite.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestSuite.hrl new file mode 100644 index 0000000..253a946 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestSuite.hrl @@ -0,0 +1,4 @@ +-record(test_suite, { + module :: showtime@internal@common@test_suite:test_module(), + tests :: list(showtime@internal@common@test_suite:test_function()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignLeft.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignLeft.hrl new file mode 100644 index 0000000..ca52968 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignLeft.hrl @@ -0,0 +1,4 @@ +-record(align_left, { + content :: showtime@internal@reports@table:content(), + margin :: integer() +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignLeftOverflow.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignLeftOverflow.hrl new file mode 100644 index 0000000..8d5a673 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignLeftOverflow.hrl @@ -0,0 +1,4 @@ +-record(align_left_overflow, { + content :: showtime@internal@reports@table:content(), + margin :: integer() +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignRight.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignRight.hrl new file mode 100644 index 0000000..7f7a3f0 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignRight.hrl @@ -0,0 +1,4 @@ +-record(align_right, { + content :: showtime@internal@reports@table:content(), + margin :: integer() +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignRightOverflow.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignRightOverflow.hrl new file mode 100644 index 0000000..4fc4536 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignRightOverflow.hrl @@ -0,0 +1,4 @@ +-record(align_right_overflow, { + content :: showtime@internal@reports@table:content(), + margin :: integer() +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Aligned.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Aligned.hrl new file mode 100644 index 0000000..2343dfd --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Aligned.hrl @@ -0,0 +1 @@ +-record(aligned, {content :: binary()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Content.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Content.hrl new file mode 100644 index 0000000..044891b --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Content.hrl @@ -0,0 +1 @@ +-record(content, {unstyled_text :: binary()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Separator.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Separator.hrl new file mode 100644 index 0000000..db3f822 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Separator.hrl @@ -0,0 +1 @@ +-record(separator, {char :: binary()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_StyledContent.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_StyledContent.hrl new file mode 100644 index 0000000..ed500df --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_StyledContent.hrl @@ -0,0 +1 @@ +-record(styled_content, {styled_text :: binary()}). diff --git a/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Table.hrl b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Table.hrl new file mode 100644 index 0000000..5b41bb1 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Table.hrl @@ -0,0 +1,4 @@ +-record(table, { + header :: gleam@option:option(binary()), + rows :: list(list(showtime@internal@reports@table:col())) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@tests@meta_Meta.hrl b/aoc2023/build/packages/adglent/include/showtime@tests@meta_Meta.hrl new file mode 100644 index 0000000..14184fb --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@tests@meta_Meta.hrl @@ -0,0 +1 @@ +-record(meta, {description :: binary(), tags :: list(binary())}). diff --git a/aoc2023/build/packages/adglent/include/showtime@tests@should_Eq.hrl b/aoc2023/build/packages/adglent/include/showtime@tests@should_Eq.hrl new file mode 100644 index 0000000..6ebea34 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@tests@should_Eq.hrl @@ -0,0 +1,5 @@ +-record(eq, { + a :: any(), + b :: any(), + meta :: gleam@option:option(showtime@tests@meta:meta()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@tests@should_Fail.hrl b/aoc2023/build/packages/adglent/include/showtime@tests@should_Fail.hrl new file mode 100644 index 0000000..cf06a3c --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@tests@should_Fail.hrl @@ -0,0 +1 @@ +-record(fail, {meta :: gleam@option:option(showtime@tests@meta:meta())}). diff --git a/aoc2023/build/packages/adglent/include/showtime@tests@should_IsError.hrl b/aoc2023/build/packages/adglent/include/showtime@tests@should_IsError.hrl new file mode 100644 index 0000000..e9cabf3 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@tests@should_IsError.hrl @@ -0,0 +1,4 @@ +-record(is_error, { + a :: {ok, any()} | {error, any()}, + meta :: gleam@option:option(showtime@tests@meta:meta()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@tests@should_IsOk.hrl b/aoc2023/build/packages/adglent/include/showtime@tests@should_IsOk.hrl new file mode 100644 index 0000000..37c24ca --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@tests@should_IsOk.hrl @@ -0,0 +1,4 @@ +-record(is_ok, { + a :: {ok, any()} | {error, any()}, + meta :: gleam@option:option(showtime@tests@meta:meta()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@tests@should_NotEq.hrl b/aoc2023/build/packages/adglent/include/showtime@tests@should_NotEq.hrl new file mode 100644 index 0000000..2a6bf48 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@tests@should_NotEq.hrl @@ -0,0 +1,5 @@ +-record(not_eq, { + a :: any(), + b :: any(), + meta :: gleam@option:option(showtime@tests@meta:meta()) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@tests@test_MetaShould.hrl b/aoc2023/build/packages/adglent/include/showtime@tests@test_MetaShould.hrl new file mode 100644 index 0000000..a814a93 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@tests@test_MetaShould.hrl @@ -0,0 +1,4 @@ +-record(meta_should, { + equal :: fun((any(), any()) -> nil), + not_equal :: fun((any(), any()) -> nil) +}). diff --git a/aoc2023/build/packages/adglent/include/showtime@tests@test_Test.hrl b/aoc2023/build/packages/adglent/include/showtime@tests@test_Test.hrl new file mode 100644 index 0000000..e75a0b7 --- /dev/null +++ b/aoc2023/build/packages/adglent/include/showtime@tests@test_Test.hrl @@ -0,0 +1,4 @@ +-record(test, { + meta :: showtime@tests@meta:meta(), + test_function :: fun(() -> nil) +}). diff --git a/aoc2023/build/packages/adglent/src/adglent.app.src b/aoc2023/build/packages/adglent/src/adglent.app.src new file mode 100644 index 0000000..aa44f8b --- /dev/null +++ b/aoc2023/build/packages/adglent/src/adglent.app.src @@ -0,0 +1,45 @@ +{application, adglent, [ + {vsn, "1.2.0"}, + {applications, [gap, + gleam_community_ansi, + gleam_erlang, + gleam_http, + gleam_httpc, + gleam_otp, + gleam_stdlib, + gleeunit, + glint, + simplifile, + snag, + tom]}, + {description, "Advent of code helper - automating setup of tests, solution template and problem input"}, + {modules, [adglent, + adglent@day, + adglent@init, + priv@aoc_client, + priv@errors, + priv@prompt, + priv@template, + priv@templates@solution, + priv@templates@test_main, + priv@templates@testfile_gleeunit, + priv@templates@testfile_showtime, + priv@toml, + showtime, + showtime@internal@common@cli, + showtime@internal@common@common_event_handler, + showtime@internal@common@test_result, + showtime@internal@common@test_suite, + showtime@internal@erlang@discover, + showtime@internal@erlang@event_handler, + showtime@internal@erlang@module_handler, + showtime@internal@erlang@runner, + showtime@internal@reports@compare, + showtime@internal@reports@formatter, + showtime@internal@reports@styles, + showtime@internal@reports@table, + showtime@tests@meta, + showtime@tests@should, + showtime@tests@test]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/adglent/src/adglent.erl b/aoc2023/build/packages/adglent/src/adglent.erl new file mode 100644 index 0000000..e9df2b7 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/adglent.erl @@ -0,0 +1,55 @@ +-module(adglent). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([inspect/1, get_input/1, get_test_folder/1, start_arguments/0, get_part/0]). +-export_type([example/1, problem/0, charlist/0]). + +-type example(OFF) :: {example, binary(), OFF}. + +-type problem() :: first | second. + +-type charlist() :: any(). + +-spec inspect(any()) -> binary(). +inspect(Value) -> + Inspected_value = gleam@string:inspect(Value), + case begin + _pipe = Inspected_value, + gleam@string:starts_with(_pipe, <<"\""/utf8>>) + end of + true -> + _pipe@1 = Inspected_value, + _pipe@2 = gleam@string:drop_left(_pipe@1, 1), + gleam@string:drop_right(_pipe@2, 1); + + false -> + Inspected_value + end. + +-spec get_input(binary()) -> {ok, binary()} | {error, simplifile:file_error()}. +get_input(Day) -> + simplifile:read( + <<<<"src/day"/utf8, Day/binary>>/binary, "/input.txt"/utf8>> + ). + +-spec get_test_folder(binary()) -> binary(). +get_test_folder(Day) -> + <<"test/day"/utf8, Day/binary>>. + +-spec start_arguments() -> list(binary()). +start_arguments() -> + _pipe = init:get_plain_arguments(), + gleam@list:map(_pipe, fun unicode:characters_to_binary/1). + +-spec get_part() -> {ok, problem()} | {error, nil}. +get_part() -> + case start_arguments() of + [<<"1"/utf8>>] -> + {ok, first}; + + [<<"2"/utf8>>] -> + {ok, second}; + + _ -> + {error, nil} + end. diff --git a/aoc2023/build/packages/adglent/src/adglent.gleam b/aoc2023/build/packages/adglent/src/adglent.gleam new file mode 100644 index 0000000..077d49d --- /dev/null +++ b/aoc2023/build/packages/adglent/src/adglent.gleam @@ -0,0 +1,56 @@ +import simplifile.{type FileError} +import gleam/list +import gleam/string + +pub type Example(a) { + Example(input: String, answer: a) +} + +pub fn inspect(value: a) -> String { + let inspected_value = string.inspect(value) + case + inspected_value + |> string.starts_with("\"") + { + True -> + inspected_value + |> string.drop_left(1) + |> string.drop_right(1) + False -> inspected_value + } +} + +pub fn get_input(day: String) -> Result(String, FileError) { + simplifile.read("src/day" <> day <> "/input.txt") +} + +pub fn get_test_folder(day: String) -> String { + "test/day" <> day +} + +pub type Problem { + First + Second +} + +pub fn get_part() -> Result(Problem, Nil) { + case start_arguments() { + ["1"] -> Ok(First) + ["2"] -> Ok(Second) + _ -> Error(Nil) + } +} + +pub fn start_arguments() -> List(String) { + get_start_arguments() + |> list.map(to_string) +} + +type Charlist + +/// Transform a charlist to a string +@external(erlang, "unicode", "characters_to_binary") +fn to_string(a: Charlist) -> String + +@external(erlang, "init", "get_plain_arguments") +fn get_start_arguments() -> List(Charlist) diff --git a/aoc2023/build/packages/adglent/src/adglent/day.gleam b/aoc2023/build/packages/adglent/src/adglent/day.gleam new file mode 100644 index 0000000..69e4ccc --- /dev/null +++ b/aoc2023/build/packages/adglent/src/adglent/day.gleam @@ -0,0 +1,126 @@ +import adglent +import gleam/string +import gleam/result +import priv/template +import priv/templates/testfile_gleeunit +import priv/templates/testfile_showtime +import priv/templates/solution +import priv/toml +import priv/aoc_client +import priv/errors +import simplifile + +pub fn main() { + let day = + case adglent.start_arguments() { + [day] -> Ok(day) + args -> Error("Expected day - found: " <> string.join(args, ", ")) + } + |> errors.map_error("Error when parsing command args") + |> errors.print_error + |> errors.assert_ok + + let aoc_toml = + simplifile.read("aoc.toml") + |> errors.map_error("Could not read aoc.toml") + |> errors.print_error + |> errors.assert_ok + + let aoc_toml_version = toml.get_int(aoc_toml, ["version"]) + let year = + toml.get_string(aoc_toml, ["year"]) + |> errors.map_error("Could not read \"year\" from aoc.toml") + |> errors.print_error + |> errors.assert_ok + let session = + toml.get_string(aoc_toml, ["session"]) + |> errors.map_error("Could not read \"session\" from aoc.toml") + |> errors.print_error + |> errors.assert_ok + + let showtime = case aoc_toml_version { + Ok(2) -> { + toml.get_bool(aoc_toml, ["showtime"]) + |> errors.map_error("Could not read \"showtime\" from aoc.toml") + |> errors.print_error + |> errors.assert_ok + } + _ -> + toml.get_string(aoc_toml, ["showtime"]) + |> result.map(fn(bool_string) { + case bool_string { + "True" -> True + _ -> False + } + }) + |> errors.map_error("Could not read \"showtime\" from aoc.toml") + |> errors.print_error + |> errors.assert_ok + } + + let test_folder = adglent.get_test_folder(day) + let test_file = test_folder <> "/day" <> day <> "_test.gleam" + + simplifile.create_directory_all(test_folder) + |> errors.map_error("Could not create folder \"" <> test_folder <> "\"") + |> errors.print_error + |> errors.assert_ok + + let testfile_template = case showtime { + True -> testfile_showtime.template + False -> testfile_gleeunit.template + } + + template.render(testfile_template, [#("day", day)]) + |> create_file_if_not_present(test_file) + |> errors.print_result + |> errors.assert_ok + + let solutions_folder = "src/day" <> day + let solution_file = solutions_folder <> "/solve.gleam" + + simplifile.create_directory_all(solutions_folder) + |> errors.map_error("Could not create folder \"" <> solutions_folder <> "\"") + |> errors.print_error + |> errors.assert_ok + + template.render(solution.template, [#("day", day)]) + |> create_file_if_not_present(solution_file) + |> errors.print_result + |> errors.assert_ok + + create_file_if_not_present("input.txt", solutions_folder <> "/.gitignore") + |> errors.print_result + |> errors.assert_ok + + let input = + aoc_client.get_input(year, day, session) + |> errors.map_error("Error when fetching input") + |> errors.print_error + |> errors.assert_ok + + input + |> string.trim + |> create_file_if_not_present(solutions_folder <> "/input.txt") + |> errors.print_result + |> errors.assert_ok +} + +fn create_file_if_not_present( + content: String, + path: String, +) -> Result(String, String) { + case simplifile.is_file(path) { + True -> { + Ok(path <> " already exists - skipped") + } + False -> { + use _ <- result.try( + simplifile.create_file(path) + |> errors.map_messages("Created " <> path, "Could not create " <> path), + ) + simplifile.write(content, to: path) + |> errors.map_messages("Wrote " <> path, "Could not write to " <> path) + } + } +} diff --git a/aoc2023/build/packages/adglent/src/adglent/init.gleam b/aoc2023/build/packages/adglent/src/adglent/init.gleam new file mode 100644 index 0000000..42eb833 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/adglent/init.gleam @@ -0,0 +1,110 @@ +import priv/prompt +import priv/template +import priv/templates/test_main +import priv/errors +import priv/toml +import simplifile +import gleam/string +import gleam/list +import gleam/result +import gleam/bool + +const aoc_toml_template = " +version = {{ version }} +year = \"{{ year }}\" +session = \"{{ session }}\" +showtime = {{ showtime }} +" + +pub fn main() { + let year = prompt.value("Year", "2023", False) + let session = prompt.value("Session Cookie", "", False) + let use_showtime = prompt.confirm("Use showtime", False) + + let aoc_toml_file = "aoc.toml" + let overwrite = case simplifile.create_file(aoc_toml_file) { + Ok(_) -> True + Error(simplifile.Eexist) -> + prompt.confirm("aoc.toml exits - overwrite", False) + _ -> panic as "Could not create aoc.toml" + } + case overwrite { + True -> { + template.render( + aoc_toml_template, + [ + #("version", "2"), + #("year", year), + #("session", session), + #( + "showtime", + bool.to_string(use_showtime) + |> string.lowercase, + ), + ], + ) + |> simplifile.write(to: aoc_toml_file) + |> errors.map_messages( + "aoc.toml - written", + "Error when writing aoc.toml", + ) + } + + False -> Ok("aoc.toml - skipped") + } + |> errors.print_result + + let gleam_toml = + simplifile.read("gleam.toml") + |> errors.map_error("Could not read gleam.toml") + |> errors.print_error + |> errors.assert_ok + + let name = + toml.get_string(gleam_toml, ["name"]) + |> errors.map_error("Could not read \"name\" from gleam.toml") + |> errors.print_error + |> errors.assert_ok + + let test_main_file = "test/" <> name <> "_test.gleam" + + case use_showtime { + True -> { + template.render(test_main.template, []) + |> simplifile.write(to: test_main_file) + |> errors.map_messages( + "Wrote " <> test_main_file, + "Could not write to " <> test_main_file, + ) + } + False -> Ok("Using existing (gleeunit) " <> test_main_file) + } + |> errors.print_result + |> errors.assert_ok + + case simplifile.is_file(".gitignore") { + True -> { + use gitignore <- result.try( + simplifile.read(".gitignore") + |> result.map_error(fn(err) { + "Could not read .gitignore: " <> string.inspect(err) + }), + ) + let aoc_toml_ignored = + string.split(gitignore, "\n") + |> list.find(fn(line) { line == "aoc.toml" }) + case aoc_toml_ignored { + Error(_) -> { + simplifile.append("\naoc.toml", to: ".gitignore") + |> errors.map_messages( + ".gitignore written", + "Error when writing .gitignore", + ) + } + Ok(_) -> Ok(".gitignore - skipped (already configured)") + } + } + False -> Error("Could not find .gitignore") + } + |> errors.print_result +} diff --git a/aoc2023/build/packages/adglent/src/adglent@day.erl b/aoc2023/build/packages/adglent/src/adglent@day.erl new file mode 100644 index 0000000..b80368f --- /dev/null +++ b/aoc2023/build/packages/adglent/src/adglent@day.erl @@ -0,0 +1,278 @@ +-module(adglent@day). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([main/0]). + +-spec create_file_if_not_present(binary(), binary()) -> {ok, binary()} | + {error, binary()}. +create_file_if_not_present(Content, Path) -> + case simplifile:is_file(Path) of + true -> + {ok, <<Path/binary, " already exists - skipped"/utf8>>}; + + false -> + gleam@result:'try'( + begin + _pipe = simplifile:create_file(Path), + priv@errors:map_messages( + _pipe, + <<"Created "/utf8, Path/binary>>, + <<"Could not create "/utf8, Path/binary>> + ) + end, + fun(_) -> _pipe@1 = simplifile:write(Path, Content), + priv@errors:map_messages( + _pipe@1, + <<"Wrote "/utf8, Path/binary>>, + <<"Could not write to "/utf8, Path/binary>> + ) end + ) + end. + +-spec main() -> binary(). +main() -> + Day@1 = begin + _pipe = case adglent:start_arguments() of + [Day] -> + {ok, Day}; + + Args -> + {error, + <<"Expected day - found: "/utf8, + (gleam@string:join(Args, <<", "/utf8>>))/binary>>} + end, + _pipe@1 = priv@errors:map_error( + _pipe, + <<"Error when parsing command args"/utf8>> + ), + _pipe@2 = priv@errors:print_error(_pipe@1), + priv@errors:assert_ok(_pipe@2) + end, + Aoc_toml = begin + _pipe@3 = simplifile:read(<<"aoc.toml"/utf8>>), + _pipe@4 = priv@errors:map_error( + _pipe@3, + <<"Could not read aoc.toml"/utf8>> + ), + _pipe@5 = priv@errors:print_error(_pipe@4), + priv@errors:assert_ok(_pipe@5) + end, + Aoc_toml_version = priv@toml:get_int(Aoc_toml, [<<"version"/utf8>>]), + Year = begin + _pipe@6 = priv@toml:get_string(Aoc_toml, [<<"year"/utf8>>]), + _pipe@7 = priv@errors:map_error( + _pipe@6, + <<"Could not read \"year\" from aoc.toml"/utf8>> + ), + _pipe@8 = priv@errors:print_error(_pipe@7), + priv@errors:assert_ok(_pipe@8) + end, + Session = begin + _pipe@9 = priv@toml:get_string(Aoc_toml, [<<"session"/utf8>>]), + _pipe@10 = priv@errors:map_error( + _pipe@9, + <<"Could not read \"session\" from aoc.toml"/utf8>> + ), + _pipe@11 = priv@errors:print_error(_pipe@10), + priv@errors:assert_ok(_pipe@11) + end, + Showtime = case Aoc_toml_version of + {ok, 2} -> + _pipe@12 = priv@toml:get_bool(Aoc_toml, [<<"showtime"/utf8>>]), + _pipe@13 = priv@errors:map_error( + _pipe@12, + <<"Could not read \"showtime\" from aoc.toml"/utf8>> + ), + _pipe@14 = priv@errors:print_error(_pipe@13), + priv@errors:assert_ok(_pipe@14); + + _ -> + _pipe@15 = priv@toml:get_string(Aoc_toml, [<<"showtime"/utf8>>]), + _pipe@16 = gleam@result:map( + _pipe@15, + fun(Bool_string) -> case Bool_string of + <<"True"/utf8>> -> + true; + + _ -> + false + end end + ), + _pipe@17 = priv@errors:map_error( + _pipe@16, + <<"Could not read \"showtime\" from aoc.toml"/utf8>> + ), + _pipe@18 = priv@errors:print_error(_pipe@17), + priv@errors:assert_ok(_pipe@18) + end, + Test_folder = adglent:get_test_folder(Day@1), + Test_file = <<<<<<Test_folder/binary, "/day"/utf8>>/binary, Day@1/binary>>/binary, + "_test.gleam"/utf8>>, + _pipe@19 = simplifile:create_directory_all(Test_folder), + _pipe@20 = priv@errors:map_error( + _pipe@19, + <<<<"Could not create folder \""/utf8, Test_folder/binary>>/binary, + "\""/utf8>> + ), + _pipe@21 = priv@errors:print_error(_pipe@20), + priv@errors:assert_ok(_pipe@21), + Testfile_template = case Showtime of + true -> + <<" +import gleam/list +import showtime/tests/should +import adglent.{type Example, Example} +import day{{ day }}/solve + +type Problem1AnswerType = + String + +type Problem2AnswerType = + String + +/// Add examples for part 1 here: +/// ```gleam +///const part1_examples: List(Example(Problem1AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part1_examples: List(Example(Problem1AnswerType)) = [] + +/// Add examples for part 2 here: +/// ```gleam +///const part2_examples: List(Example(Problem2AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part2_examples: List(Example(Problem2AnswerType)) = [] + +pub fn part1_test() { + part1_examples + |> should.not_equal([]) + use example <- list.map(part1_examples) + solve.part1(example.input) + |> should.equal(example.answer) +} + +pub fn part2_test() { + part2_examples + |> should.not_equal([]) + use example <- list.map(part2_examples) + solve.part2(example.input) + |> should.equal(example.answer) +} + +"/utf8>>; + + false -> + <<" +import gleam/list +import gleeunit/should +import adglent.{type Example, Example} +import day{{ day }}/solve + +type Problem1AnswerType = + String + +type Problem2AnswerType = + String + +/// Add examples for part 1 here: +/// ```gleam +///const part1_examples: List(Example(Problem1AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part1_examples: List(Example(Problem1AnswerType)) = [] + +/// Add examples for part 2 here: +/// ```gleam +///const part2_examples: List(Example(Problem2AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part2_examples: List(Example(Problem2AnswerType)) = [] + +pub fn part1_test() { + part1_examples + |> should.not_equal([]) + use example <- list.map(part1_examples) + solve.part1(example.input) + |> should.equal(example.answer) +} + +pub fn part2_test() { + part2_examples + |> should.not_equal([]) + use example <- list.map(part2_examples) + solve.part2(example.input) + |> should.equal(example.answer) +} + +"/utf8>> + end, + _pipe@22 = priv@template:render( + Testfile_template, + [{<<"day"/utf8>>, Day@1}] + ), + _pipe@23 = create_file_if_not_present(_pipe@22, Test_file), + _pipe@24 = priv@errors:print_result(_pipe@23), + priv@errors:assert_ok(_pipe@24), + Solutions_folder = <<"src/day"/utf8, Day@1/binary>>, + Solution_file = <<Solutions_folder/binary, "/solve.gleam"/utf8>>, + _pipe@25 = simplifile:create_directory_all(Solutions_folder), + _pipe@26 = priv@errors:map_error( + _pipe@25, + <<<<"Could not create folder \""/utf8, Solutions_folder/binary>>/binary, + "\""/utf8>> + ), + _pipe@27 = priv@errors:print_error(_pipe@26), + priv@errors:assert_ok(_pipe@27), + _pipe@28 = priv@template:render( + <<" +import adglent.{First, Second} +import gleam/io + +pub fn part1(input: String) { + todo as \"Implement solution to part 1\" +} + +pub fn part2(input: String) { + todo as \"Implement solution to part 2\" +} + +pub fn main() { + let assert Ok(part) = adglent.get_part() + let assert Ok(input) = adglent.get_input(\"{{ day }}\") + case part { + First -> + part1(input) + |> adglent.inspect + |> io.println + Second -> + part2(input) + |> adglent.inspect + |> io.println + } +} +"/utf8>>, + [{<<"day"/utf8>>, Day@1}] + ), + _pipe@29 = create_file_if_not_present(_pipe@28, Solution_file), + _pipe@30 = priv@errors:print_result(_pipe@29), + priv@errors:assert_ok(_pipe@30), + _pipe@31 = create_file_if_not_present( + <<"input.txt"/utf8>>, + <<Solutions_folder/binary, "/.gitignore"/utf8>> + ), + _pipe@32 = priv@errors:print_result(_pipe@31), + priv@errors:assert_ok(_pipe@32), + Input = begin + _pipe@33 = priv@aoc_client:get_input(Year, Day@1, Session), + _pipe@34 = priv@errors:map_error( + _pipe@33, + <<"Error when fetching input"/utf8>> + ), + _pipe@35 = priv@errors:print_error(_pipe@34), + priv@errors:assert_ok(_pipe@35) + end, + _pipe@36 = Input, + _pipe@37 = gleam@string:trim(_pipe@36), + _pipe@38 = create_file_if_not_present( + _pipe@37, + <<Solutions_folder/binary, "/input.txt"/utf8>> + ), + _pipe@39 = priv@errors:print_result(_pipe@38), + priv@errors:assert_ok(_pipe@39). diff --git a/aoc2023/build/packages/adglent/src/adglent@init.erl b/aoc2023/build/packages/adglent/src/adglent@init.erl new file mode 100644 index 0000000..fb28101 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/adglent@init.erl @@ -0,0 +1,142 @@ +-module(adglent@init). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([main/0]). + +-spec main() -> {ok, binary()} | {error, binary()}. +main() -> + Year = priv@prompt:value(<<"Year"/utf8>>, <<"2023"/utf8>>, false), + Session = priv@prompt:value(<<"Session Cookie"/utf8>>, <<""/utf8>>, false), + Use_showtime = priv@prompt:confirm(<<"Use showtime"/utf8>>, false), + Aoc_toml_file = <<"aoc.toml"/utf8>>, + Overwrite = case simplifile:create_file(Aoc_toml_file) of + {ok, _} -> + true; + + {error, eexist} -> + priv@prompt:confirm(<<"aoc.toml exits - overwrite"/utf8>>, false); + + _ -> + erlang:error(#{gleam_error => panic, + message => <<"Could not create aoc.toml"/utf8>>, + module => <<"adglent/init"/utf8>>, + function => <<"main"/utf8>>, + line => 29}) + end, + _pipe@3 = case Overwrite of + true -> + _pipe@1 = priv@template:render( + <<" +version = {{ version }} +year = \"{{ year }}\" +session = \"{{ session }}\" +showtime = {{ showtime }} +"/utf8>>, + [{<<"version"/utf8>>, <<"2"/utf8>>}, + {<<"year"/utf8>>, Year}, + {<<"session"/utf8>>, Session}, + {<<"showtime"/utf8>>, + begin + _pipe = gleam@bool:to_string(Use_showtime), + gleam@string:lowercase(_pipe) + end}] + ), + _pipe@2 = simplifile:write(Aoc_toml_file, _pipe@1), + priv@errors:map_messages( + _pipe@2, + <<"aoc.toml - written"/utf8>>, + <<"Error when writing aoc.toml"/utf8>> + ); + + false -> + {ok, <<"aoc.toml - skipped"/utf8>>} + end, + priv@errors:print_result(_pipe@3), + Gleam_toml = begin + _pipe@4 = simplifile:read(<<"gleam.toml"/utf8>>), + _pipe@5 = priv@errors:map_error( + _pipe@4, + <<"Could not read gleam.toml"/utf8>> + ), + _pipe@6 = priv@errors:print_error(_pipe@5), + priv@errors:assert_ok(_pipe@6) + end, + Name = begin + _pipe@7 = priv@toml:get_string(Gleam_toml, [<<"name"/utf8>>]), + _pipe@8 = priv@errors:map_error( + _pipe@7, + <<"Could not read \"name\" from gleam.toml"/utf8>> + ), + _pipe@9 = priv@errors:print_error(_pipe@8), + priv@errors:assert_ok(_pipe@9) + end, + Test_main_file = <<<<"test/"/utf8, Name/binary>>/binary, + "_test.gleam"/utf8>>, + _pipe@12 = case Use_showtime of + true -> + _pipe@10 = priv@template:render( + <<" +import showtime + +pub fn main() { + showtime.main() +} +"/utf8>>, + [] + ), + _pipe@11 = simplifile:write(Test_main_file, _pipe@10), + priv@errors:map_messages( + _pipe@11, + <<"Wrote "/utf8, Test_main_file/binary>>, + <<"Could not write to "/utf8, Test_main_file/binary>> + ); + + false -> + {ok, <<"Using existing (gleeunit) "/utf8, Test_main_file/binary>>} + end, + _pipe@13 = priv@errors:print_result(_pipe@12), + priv@errors:assert_ok(_pipe@13), + _pipe@17 = case simplifile:is_file(<<".gitignore"/utf8>>) of + true -> + gleam@result:'try'( + begin + _pipe@14 = simplifile:read(<<".gitignore"/utf8>>), + gleam@result:map_error( + _pipe@14, + fun(Err) -> + <<"Could not read .gitignore: "/utf8, + (gleam@string:inspect(Err))/binary>> + end + ) + end, + fun(Gitignore) -> + Aoc_toml_ignored = begin + _pipe@15 = gleam@string:split(Gitignore, <<"\n"/utf8>>), + gleam@list:find( + _pipe@15, + fun(Line) -> Line =:= <<"aoc.toml"/utf8>> end + ) + end, + case Aoc_toml_ignored of + {error, _} -> + _pipe@16 = simplifile:append( + <<".gitignore"/utf8>>, + <<"\naoc.toml"/utf8>> + ), + priv@errors:map_messages( + _pipe@16, + <<".gitignore written"/utf8>>, + <<"Error when writing .gitignore"/utf8>> + ); + + {ok, _} -> + {ok, + <<".gitignore - skipped (already configured)"/utf8>>} + end + end + ); + + false -> + {error, <<"Could not find .gitignore"/utf8>>} + end, + priv@errors:print_result(_pipe@17). diff --git a/aoc2023/build/packages/adglent/src/adglent_ffi.erl b/aoc2023/build/packages/adglent/src/adglent_ffi.erl new file mode 100644 index 0000000..a6a92e6 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/adglent_ffi.erl @@ -0,0 +1,12 @@ +-module(adglent_ffi). + +-export([get_line/1]). + +-spec get_line(io:prompt()) -> {ok, unicode:unicode_binary()} | {error, eof | no_data}. +get_line(Prompt) -> + case io:get_line(Prompt) of + eof -> {error, eof}; + {error, _} -> {error, no_data}; + Data when is_binary(Data) -> {ok, Data}; + Data when is_list(Data) -> {ok, unicode:characters_to_binary(Data)} + end. diff --git a/aoc2023/build/packages/adglent/src/priv/aoc_client.gleam b/aoc2023/build/packages/adglent/src/priv/aoc_client.gleam new file mode 100644 index 0000000..e18bafa --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv/aoc_client.gleam @@ -0,0 +1,37 @@ +import gleam/result.{try} +import gleam/httpc +import gleam/http/request +import gleam/int +import gleam/string + +pub fn get_input( + year: String, + day: String, + session: String, +) -> Result(String, String) { + let url = "https://adventofcode.com/" <> year <> "/day/" <> day <> "/input" + use request <- try( + request.to(url) + |> result.map_error(fn(error) { + "Could not create request for \"" <> url <> "\": " <> string.inspect( + error, + ) + }), + ) + + // Send the HTTP request to the server + use response <- try( + request + |> request.prepend_header("Accept", "application/json") + |> request.prepend_header("Cookie", "session=" <> session <> ";") + |> httpc.send + |> result.map_error(fn(error) { + "Error when requesting \"" <> url <> "\": " <> string.inspect(error) + }), + ) + + case response.status { + status if status >= 200 && status < 300 -> Ok(response.body) + status -> Error(int.to_string(status) <> " - " <> response.body) + } +} diff --git a/aoc2023/build/packages/adglent/src/priv/errors.gleam b/aoc2023/build/packages/adglent/src/priv/errors.gleam new file mode 100644 index 0000000..14c35ca --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv/errors.gleam @@ -0,0 +1,54 @@ +import gleam/result +import gleam/string +import gleam/io + +pub fn map_messages( + result: Result(a, b), + success_message: String, + error_message: String, +) -> Result(String, String) { + result + |> result.map_error(fn(error) { + "Error - " <> error_message <> ": " <> string.inspect(error) + }) + |> result.replace(success_message) +} + +pub fn map_error( + result: Result(a, b), + error_message: String, +) -> Result(a, String) { + result + |> result.map_error(fn(error) { + error_message <> ": " <> string.inspect(error) + }) +} + +pub fn print_result(result: Result(String, String)) { + result + |> result.unwrap_both + |> io.println + result +} + +pub fn print_error(result: Result(a, String)) { + result + |> result.map_error(fn(err) { + io.println(err) + err + }) +} + +pub fn assert_ok(result: Result(a, String)) { + let assert Ok(value) = + result + |> result.map_error(fn(err) { + halt(1) + err + }) + value +} + +@target(erlang) +@external(erlang, "erlang", "halt") +fn halt(a: Int) -> Nil diff --git a/aoc2023/build/packages/adglent/src/priv/prompt.gleam b/aoc2023/build/packages/adglent/src/priv/prompt.gleam new file mode 100644 index 0000000..6cee35a --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv/prompt.gleam @@ -0,0 +1,38 @@ +import gleam/result +import gleam/string + +pub fn confirm(message: String, auto_accept: Bool) -> Bool { + auto_accept || case + get_line(message <> "? (Y/N): ") + |> result.unwrap("n") + |> string.trim() + { + "Y" | "y" -> True + _ -> False + } +} + +pub fn value(message: String, default: String, auto_accept: Bool) -> String { + case get_value_of_default(message, default, auto_accept) { + "" -> default + value -> value + } +} + +fn get_value_of_default(message: String, default: String, auto_accept: Bool) { + case auto_accept { + True -> default + False -> + get_line(message <> "? (" <> default <> "): ") + |> result.unwrap("") + |> string.trim() + } +} + +pub type GetLineError { + Eof + NoData +} + +@external(erlang, "adglent_ffi", "get_line") +pub fn get_line(prompt prompt: String) -> Result(String, GetLineError) diff --git a/aoc2023/build/packages/adglent/src/priv/template.gleam b/aoc2023/build/packages/adglent/src/priv/template.gleam new file mode 100644 index 0000000..e946888 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv/template.gleam @@ -0,0 +1,18 @@ +import gleam/list +import gleam/string + +pub fn render( + template: String, + substitutions: List(#(String, String)), +) -> String { + substitutions + |> list.fold( + template, + fn(template, substitution) { + let #(name, value) = substitution + template + |> string.replace("{{ " <> name <> " }}", value) + }, + ) + |> string.trim <> "\n" +} diff --git a/aoc2023/build/packages/adglent/src/priv/templates/solution.gleam b/aoc2023/build/packages/adglent/src/priv/templates/solution.gleam new file mode 100644 index 0000000..96085c3 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv/templates/solution.gleam @@ -0,0 +1,27 @@ +pub const template = " +import adglent.{First, Second} +import gleam/io + +pub fn part1(input: String) { + todo as \"Implement solution to part 1\" +} + +pub fn part2(input: String) { + todo as \"Implement solution to part 2\" +} + +pub fn main() { + let assert Ok(part) = adglent.get_part() + let assert Ok(input) = adglent.get_input(\"{{ day }}\") + case part { + First -> + part1(input) + |> adglent.inspect + |> io.println + Second -> + part2(input) + |> adglent.inspect + |> io.println + } +} +" diff --git a/aoc2023/build/packages/adglent/src/priv/templates/test_main.gleam b/aoc2023/build/packages/adglent/src/priv/templates/test_main.gleam new file mode 100644 index 0000000..27548d3 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv/templates/test_main.gleam @@ -0,0 +1,7 @@ +pub const template = " +import showtime + +pub fn main() { + showtime.main() +} +" diff --git a/aoc2023/build/packages/adglent/src/priv/templates/testfile_gleeunit.gleam b/aoc2023/build/packages/adglent/src/priv/templates/testfile_gleeunit.gleam new file mode 100644 index 0000000..a1d56f6 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv/templates/testfile_gleeunit.gleam @@ -0,0 +1,41 @@ +pub const template = " +import gleam/list +import gleeunit/should +import adglent.{type Example, Example} +import day{{ day }}/solve + +type Problem1AnswerType = + String + +type Problem2AnswerType = + String + +/// Add examples for part 1 here: +/// ```gleam +///const part1_examples: List(Example(Problem1AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part1_examples: List(Example(Problem1AnswerType)) = [] + +/// Add examples for part 2 here: +/// ```gleam +///const part2_examples: List(Example(Problem2AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part2_examples: List(Example(Problem2AnswerType)) = [] + +pub fn part1_test() { + part1_examples + |> should.not_equal([]) + use example <- list.map(part1_examples) + solve.part1(example.input) + |> should.equal(example.answer) +} + +pub fn part2_test() { + part2_examples + |> should.not_equal([]) + use example <- list.map(part2_examples) + solve.part2(example.input) + |> should.equal(example.answer) +} + +" diff --git a/aoc2023/build/packages/adglent/src/priv/templates/testfile_showtime.gleam b/aoc2023/build/packages/adglent/src/priv/templates/testfile_showtime.gleam new file mode 100644 index 0000000..699feb2 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv/templates/testfile_showtime.gleam @@ -0,0 +1,41 @@ +pub const template = " +import gleam/list +import showtime/tests/should +import adglent.{type Example, Example} +import day{{ day }}/solve + +type Problem1AnswerType = + String + +type Problem2AnswerType = + String + +/// Add examples for part 1 here: +/// ```gleam +///const part1_examples: List(Example(Problem1AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part1_examples: List(Example(Problem1AnswerType)) = [] + +/// Add examples for part 2 here: +/// ```gleam +///const part2_examples: List(Example(Problem2AnswerType)) = [Example(\"some input\", \"\")] +/// ``` +const part2_examples: List(Example(Problem2AnswerType)) = [] + +pub fn part1_test() { + part1_examples + |> should.not_equal([]) + use example <- list.map(part1_examples) + solve.part1(example.input) + |> should.equal(example.answer) +} + +pub fn part2_test() { + part2_examples + |> should.not_equal([]) + use example <- list.map(part2_examples) + solve.part2(example.input) + |> should.equal(example.answer) +} + +" diff --git a/aoc2023/build/packages/adglent/src/priv/toml.gleam b/aoc2023/build/packages/adglent/src/priv/toml.gleam new file mode 100644 index 0000000..7042833 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv/toml.gleam @@ -0,0 +1,52 @@ +import tom +import gleam/result + +pub type TomError { + TomParseError(error: tom.ParseError) + TomGetError(error: tom.GetError) +} + +pub fn get_string( + toml_content: String, + key_path: List(String), +) -> Result(String, TomError) { + use toml <- result.try( + tom.parse(toml_content <> "\n") + |> result.map_error(TomParseError), + ) + use value <- result.try( + tom.get_string(toml, key_path) + |> result.map_error(TomGetError), + ) + Ok(value) +} + +pub fn get_bool( + toml_content: String, + key_path: List(String), +) -> Result(Bool, TomError) { + use toml <- result.try( + tom.parse(toml_content <> "\n") + |> result.map_error(TomParseError), + ) + use value <- result.try( + tom.get_bool(toml, key_path) + |> result.map_error(TomGetError), + ) + Ok(value) +} + +pub fn get_int( + toml_content: String, + key_path: List(String), +) -> Result(Int, TomError) { + use toml <- result.try( + tom.parse(toml_content <> "\n") + |> result.map_error(TomParseError), + ) + use value <- result.try( + tom.get_int(toml, key_path) + |> result.map_error(TomGetError), + ) + Ok(value) +} diff --git a/aoc2023/build/packages/adglent/src/priv@aoc_client.erl b/aoc2023/build/packages/adglent/src/priv@aoc_client.erl new file mode 100644 index 0000000..1acb9b5 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv@aoc_client.erl @@ -0,0 +1,61 @@ +-module(priv@aoc_client). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([get_input/3]). + +-spec get_input(binary(), binary(), binary()) -> {ok, binary()} | + {error, binary()}. +get_input(Year, Day, Session) -> + Url = <<<<<<<<"https://adventofcode.com/"/utf8, Year/binary>>/binary, + "/day/"/utf8>>/binary, + Day/binary>>/binary, + "/input"/utf8>>, + gleam@result:'try'( + begin + _pipe = gleam@http@request:to(Url), + gleam@result:map_error( + _pipe, + fun(Error) -> + <<<<<<"Could not create request for \""/utf8, Url/binary>>/binary, + "\": "/utf8>>/binary, + (gleam@string:inspect(Error))/binary>> + end + ) + end, + fun(Request) -> + gleam@result:'try'( + begin + _pipe@1 = Request, + _pipe@2 = gleam@http@request:prepend_header( + _pipe@1, + <<"Accept"/utf8>>, + <<"application/json"/utf8>> + ), + _pipe@3 = gleam@http@request:prepend_header( + _pipe@2, + <<"Cookie"/utf8>>, + <<<<"session="/utf8, Session/binary>>/binary, ";"/utf8>> + ), + _pipe@4 = gleam@httpc:send(_pipe@3), + gleam@result:map_error( + _pipe@4, + fun(Error@1) -> + <<<<<<"Error when requesting \""/utf8, Url/binary>>/binary, + "\": "/utf8>>/binary, + (gleam@string:inspect(Error@1))/binary>> + end + ) + end, + fun(Response) -> case erlang:element(2, Response) of + Status when (Status >= 200) andalso (Status < 300) -> + {ok, erlang:element(4, Response)}; + + Status@1 -> + {error, + <<<<(gleam@int:to_string(Status@1))/binary, + " - "/utf8>>/binary, + (erlang:element(4, Response))/binary>>} + end end + ) + end + ). diff --git a/aoc2023/build/packages/adglent/src/priv@errors.erl b/aoc2023/build/packages/adglent/src/priv@errors.erl new file mode 100644 index 0000000..978c675 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv@errors.erl @@ -0,0 +1,74 @@ +-module(priv@errors). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([map_messages/3, map_error/2, print_result/1, print_error/1, assert_ok/1]). + +-spec map_messages({ok, any()} | {error, any()}, binary(), binary()) -> {ok, + binary()} | + {error, binary()}. +map_messages(Result, Success_message, Error_message) -> + _pipe = Result, + _pipe@1 = gleam@result:map_error( + _pipe, + fun(Error) -> + <<<<<<"Error - "/utf8, Error_message/binary>>/binary, ": "/utf8>>/binary, + (gleam@string:inspect(Error))/binary>> + end + ), + gleam@result:replace(_pipe@1, Success_message). + +-spec map_error({ok, NIB} | {error, any()}, binary()) -> {ok, NIB} | + {error, binary()}. +map_error(Result, Error_message) -> + _pipe = Result, + gleam@result:map_error( + _pipe, + fun(Error) -> + <<<<Error_message/binary, ": "/utf8>>/binary, + (gleam@string:inspect(Error))/binary>> + end + ). + +-spec print_result({ok, binary()} | {error, binary()}) -> {ok, binary()} | + {error, binary()}. +print_result(Result) -> + _pipe = Result, + _pipe@1 = gleam@result:unwrap_both(_pipe), + gleam@io:println(_pipe@1), + Result. + +-spec print_error({ok, NIK} | {error, binary()}) -> {ok, NIK} | + {error, binary()}. +print_error(Result) -> + _pipe = Result, + gleam@result:map_error( + _pipe, + fun(Err) -> + gleam@io:println(Err), + Err + end + ). + +-spec assert_ok({ok, NIO} | {error, binary()}) -> NIO. +assert_ok(Result) -> + _assert_subject = begin + _pipe = Result, + gleam@result:map_error( + _pipe, + fun(Err) -> + erlang:halt(1), + Err + end + ) + end, + {ok, Value} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"priv/errors"/utf8>>, + function => <<"assert_ok"/utf8>>, + line => 43}) + end, + Value. diff --git a/aoc2023/build/packages/adglent/src/priv@prompt.erl b/aoc2023/build/packages/adglent/src/priv@prompt.erl new file mode 100644 index 0000000..0277f14 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv@prompt.erl @@ -0,0 +1,53 @@ +-module(priv@prompt). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([get_line/1, confirm/2, value/3]). +-export_type([get_line_error/0]). + +-type get_line_error() :: eof | no_data. + +-spec get_line(binary()) -> {ok, binary()} | {error, get_line_error()}. +get_line(Prompt) -> + adglent_ffi:get_line(Prompt). + +-spec confirm(binary(), boolean()) -> boolean(). +confirm(Message, Auto_accept) -> + Auto_accept orelse case begin + _pipe = adglent_ffi:get_line(<<Message/binary, "? (Y/N): "/utf8>>), + _pipe@1 = gleam@result:unwrap(_pipe, <<"n"/utf8>>), + gleam@string:trim(_pipe@1) + end of + <<"Y"/utf8>> -> + true; + + <<"y"/utf8>> -> + true; + + _ -> + false + end. + +-spec get_value_of_default(binary(), binary(), boolean()) -> binary(). +get_value_of_default(Message, Default, Auto_accept) -> + case Auto_accept of + true -> + Default; + + false -> + _pipe = adglent_ffi:get_line( + <<<<<<Message/binary, "? ("/utf8>>/binary, Default/binary>>/binary, + "): "/utf8>> + ), + _pipe@1 = gleam@result:unwrap(_pipe, <<""/utf8>>), + gleam@string:trim(_pipe@1) + end. + +-spec value(binary(), binary(), boolean()) -> binary(). +value(Message, Default, Auto_accept) -> + case get_value_of_default(Message, Default, Auto_accept) of + <<""/utf8>> -> + Default; + + Value -> + Value + end. diff --git a/aoc2023/build/packages/adglent/src/priv@template.erl b/aoc2023/build/packages/adglent/src/priv@template.erl new file mode 100644 index 0000000..6a5d0bf --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv@template.erl @@ -0,0 +1,25 @@ +-module(priv@template). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([render/2]). + +-spec render(binary(), list({binary(), binary()})) -> binary(). +render(Template, Substitutions) -> + <<(begin + _pipe = Substitutions, + _pipe@2 = gleam@list:fold( + _pipe, + Template, + fun(Template@1, Substitution) -> + {Name, Value} = Substitution, + _pipe@1 = Template@1, + gleam@string:replace( + _pipe@1, + <<<<"{{ "/utf8, Name/binary>>/binary, " }}"/utf8>>, + Value + ) + end + ), + gleam@string:trim(_pipe@2) + end)/binary, + "\n"/utf8>>. diff --git a/aoc2023/build/packages/adglent/src/priv@templates@solution.erl b/aoc2023/build/packages/adglent/src/priv@templates@solution.erl new file mode 100644 index 0000000..7e36387 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv@templates@solution.erl @@ -0,0 +1 @@ +-module(priv@templates@solution). diff --git a/aoc2023/build/packages/adglent/src/priv@templates@test_main.erl b/aoc2023/build/packages/adglent/src/priv@templates@test_main.erl new file mode 100644 index 0000000..ca6b127 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv@templates@test_main.erl @@ -0,0 +1 @@ +-module(priv@templates@test_main). diff --git a/aoc2023/build/packages/adglent/src/priv@templates@testfile_gleeunit.erl b/aoc2023/build/packages/adglent/src/priv@templates@testfile_gleeunit.erl new file mode 100644 index 0000000..2f5a41e --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv@templates@testfile_gleeunit.erl @@ -0,0 +1 @@ +-module(priv@templates@testfile_gleeunit). diff --git a/aoc2023/build/packages/adglent/src/priv@templates@testfile_showtime.erl b/aoc2023/build/packages/adglent/src/priv@templates@testfile_showtime.erl new file mode 100644 index 0000000..bbbc8b2 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv@templates@testfile_showtime.erl @@ -0,0 +1 @@ +-module(priv@templates@testfile_showtime). diff --git a/aoc2023/build/packages/adglent/src/priv@toml.erl b/aoc2023/build/packages/adglent/src/priv@toml.erl new file mode 100644 index 0000000..6c41fbf --- /dev/null +++ b/aoc2023/build/packages/adglent/src/priv@toml.erl @@ -0,0 +1,83 @@ +-module(priv@toml). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([get_string/2, get_bool/2, get_int/2]). +-export_type([tom_error/0]). + +-type tom_error() :: {tom_parse_error, tom:parse_error()} | + {tom_get_error, tom:get_error()}. + +-spec get_string(binary(), list(binary())) -> {ok, binary()} | + {error, tom_error()}. +get_string(Toml_content, Key_path) -> + gleam@result:'try'( + begin + _pipe = tom:parse(<<Toml_content/binary, "\n"/utf8>>), + gleam@result:map_error( + _pipe, + fun(Field@0) -> {tom_parse_error, Field@0} end + ) + end, + fun(Toml) -> + gleam@result:'try'( + begin + _pipe@1 = tom:get_string(Toml, Key_path), + gleam@result:map_error( + _pipe@1, + fun(Field@0) -> {tom_get_error, Field@0} end + ) + end, + fun(Value) -> {ok, Value} end + ) + end + ). + +-spec get_bool(binary(), list(binary())) -> {ok, boolean()} | + {error, tom_error()}. +get_bool(Toml_content, Key_path) -> + gleam@result:'try'( + begin + _pipe = tom:parse(<<Toml_content/binary, "\n"/utf8>>), + gleam@result:map_error( + _pipe, + fun(Field@0) -> {tom_parse_error, Field@0} end + ) + end, + fun(Toml) -> + gleam@result:'try'( + begin + _pipe@1 = tom:get_bool(Toml, Key_path), + gleam@result:map_error( + _pipe@1, + fun(Field@0) -> {tom_get_error, Field@0} end + ) + end, + fun(Value) -> {ok, Value} end + ) + end + ). + +-spec get_int(binary(), list(binary())) -> {ok, integer()} | + {error, tom_error()}. +get_int(Toml_content, Key_path) -> + gleam@result:'try'( + begin + _pipe = tom:parse(<<Toml_content/binary, "\n"/utf8>>), + gleam@result:map_error( + _pipe, + fun(Field@0) -> {tom_parse_error, Field@0} end + ) + end, + fun(Toml) -> + gleam@result:'try'( + begin + _pipe@1 = tom:get_int(Toml, Key_path), + gleam@result:map_error( + _pipe@1, + fun(Field@0) -> {tom_get_error, Field@0} end + ) + end, + fun(Value) -> {ok, Value} end + ) + end + ). diff --git a/aoc2023/build/packages/adglent/src/showtime.erl b/aoc2023/build/packages/adglent/src/showtime.erl new file mode 100644 index 0000000..721bad4 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime.erl @@ -0,0 +1,155 @@ +-module(showtime). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([main/0]). + +-spec mk_runner( + fun((gleam@option:option(list(binary())), list(binary()), showtime@internal@common@cli:capture()) -> OBY), + glint:command_input() +) -> OBY. +mk_runner(Func, Command) -> + _assert_subject = begin + _pipe = erlang:element(3, Command), + _pipe@1 = glint@flag:get_strings(_pipe, <<"modules"/utf8>>), + gleam@result:map(_pipe@1, fun(Modules) -> case Modules of + [] -> + none; + + Modules@1 -> + {some, Modules@1} + end end) + end, + {ok, Module_list} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime"/utf8>>, + function => <<"mk_runner"/utf8>>, + line => 91}) + end, + _assert_subject@1 = begin + _pipe@2 = erlang:element(3, Command), + glint@flag:get_strings(_pipe@2, <<"ignore"/utf8>>) + end, + {ok, Ignore_tags} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"showtime"/utf8>>, + function => <<"mk_runner"/utf8>>, + line => 100}) + end, + _assert_subject@2 = begin + _pipe@3 = erlang:element(3, Command), + _pipe@4 = glint@flag:get_string(_pipe@3, <<"capture"/utf8>>), + _pipe@5 = gleam@result:map( + _pipe@4, + fun(Arg) -> gleam@string:lowercase(Arg) end + ), + gleam@result:map(_pipe@5, fun(Arg@1) -> case Arg@1 of + <<"no"/utf8>> -> + no; + + <<"yes"/utf8>> -> + yes; + + <<"mixed"/utf8>> -> + mixed + end end) + end, + {ok, Capture_output} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"showtime"/utf8>>, + function => <<"mk_runner"/utf8>>, + line => 104}) + end, + Func(Module_list, Ignore_tags, Capture_output). + +-spec start_with_args( + list(binary()), + fun((gleam@option:option(list(binary())), list(binary()), showtime@internal@common@cli:capture()) -> any()) +) -> nil. +start_with_args(Args, Func) -> + Modules_flag = begin + _pipe = glint@flag:string_list(), + _pipe@1 = glint@flag:default(_pipe, []), + glint@flag:description( + _pipe@1, + <<"Run only tests in the modules in this list"/utf8>> + ) + end, + Ignore_flag = begin + _pipe@2 = glint@flag:string_list(), + _pipe@3 = glint@flag:default(_pipe@2, []), + glint@flag:description( + _pipe@3, + <<"Ignore tests that are have tags matching a tag in this list"/utf8>> + ) + end, + Capture_flag = begin + _pipe@4 = glint@flag:string(), + _pipe@5 = glint@flag:default(_pipe@4, <<"no"/utf8>>), + _pipe@6 = glint@flag:constraint( + _pipe@5, + glint@flag@constraint:one_of( + [<<"yes"/utf8>>, <<"no"/utf8>>, <<"mixed"/utf8>>] + ) + ), + glint@flag:description( + _pipe@6, + <<"Capture output: no (default) - output when tests are run, yes - output is captured and shown in report, mixed - output when run and in report"/utf8>> + ) + end, + _pipe@7 = glint:new(), + _pipe@12 = glint:add( + _pipe@7, + [], + begin + _pipe@8 = glint:command( + fun(_capture) -> mk_runner(Func, _capture) end + ), + _pipe@9 = glint:flag(_pipe@8, <<"modules"/utf8>>, Modules_flag), + _pipe@10 = glint:flag(_pipe@9, <<"ignore"/utf8>>, Ignore_flag), + _pipe@11 = glint:flag(_pipe@10, <<"capture"/utf8>>, Capture_flag), + glint:description(_pipe@11, <<"Runs test"/utf8>>) + end + ), + _pipe@13 = glint:with_pretty_help(_pipe@12, glint:default_pretty_help()), + glint:run(_pipe@13, Args). + +-spec main() -> nil. +main() -> + start_with_args( + gleam@erlang:start_arguments(), + fun(Module_list, Ignore_tags, Capture) -> + Test_event_handler = showtime@internal@erlang@event_handler:start(), + Test_module_handler = showtime@internal@erlang@module_handler:start( + Test_event_handler, + fun showtime@internal@erlang@discover:collect_test_functions/1, + fun showtime@internal@erlang@runner:run_test_suite/4, + Ignore_tags, + Capture + ), + Test_event_handler(start_test_run), + Modules = showtime@internal@erlang@discover:collect_modules( + Test_module_handler, + Module_list + ), + Test_event_handler( + {end_test_run, + begin + _pipe = Modules, + gleam@list:length(_pipe) + end} + ), + nil + end + ). diff --git a/aoc2023/build/packages/adglent/src/showtime.gleam b/aoc2023/build/packages/adglent/src/showtime.gleam new file mode 100644 index 0000000..f0401c9 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime.gleam @@ -0,0 +1,116 @@ +import glint.{type CommandInput, flag} +import glint/flag +import glint/flag/constraint.{one_of} +import gleam/result +import gleam/string +import showtime/internal/common/cli.{Mixed, No, Yes} +@target(erlang) +import gleam/list +@target(erlang) +import gleam/option.{None, Some} +@target(erlang) +import gleam/erlang.{start_arguments} +@target(erlang) +import showtime/internal/common/test_suite.{EndTestRun, StartTestRun} +@target(erlang) +import showtime/internal/erlang/event_handler +@target(erlang) +import showtime/internal/erlang/module_handler +@target(erlang) +import showtime/internal/erlang/runner +@target(erlang) +import showtime/internal/erlang/discover.{ + collect_modules, collect_test_functions, +} + +// @target(javascript) +// import gleam/io + +@target(erlang) +pub fn main() { + use module_list, ignore_tags, capture <- start_with_args(start_arguments()) + // Start event handler which will collect test-results and eventually + // print test report + let test_event_handler = event_handler.start() + // Start module handler which receives msg about modules to test and + // runs the test-suite for the module + let test_module_handler = + module_handler.start( + test_event_handler, + collect_test_functions, + runner.run_test_suite, + ignore_tags, + capture, + ) + + test_event_handler(StartTestRun) + // Collect modules and notify the module handler to start the test-suites + let modules = collect_modules(test_module_handler, module_list) + test_event_handler(EndTestRun( + modules + |> list.length(), + )) + Nil +} + +fn start_with_args(args, func) { + let modules_flag = + flag.string_list() + |> flag.default([]) + |> flag.description("Run only tests in the modules in this list") + + let ignore_flag = + flag.string_list() + |> flag.default([]) + |> flag.description( + "Ignore tests that are have tags matching a tag in this list", + ) + + let capture_flag = + flag.string() + |> flag.default("no") + |> flag.constraint(one_of(["yes", "no", "mixed"])) + |> flag.description( + "Capture output: no (default) - output when tests are run, yes - output is captured and shown in report, mixed - output when run and in report", + ) + + glint.new() + |> glint.add( + at: [], + do: glint.command(mk_runner(func, _)) + |> glint.flag("modules", modules_flag) + |> glint.flag("ignore", ignore_flag) + |> glint.flag("capture", capture_flag) + |> glint.description("Runs test"), + ) + |> glint.with_pretty_help(glint.default_pretty_help()) + |> glint.run(args) +} + +fn mk_runner(func, command: CommandInput) { + let assert Ok(module_list) = + command.flags + |> flag.get_strings("modules") + |> result.map(fn(modules) { + case modules { + [] -> None + modules -> Some(modules) + } + }) + let assert Ok(ignore_tags) = + command.flags + |> flag.get_strings("ignore") + + let assert Ok(capture_output) = + command.flags + |> flag.get_string("capture") + |> result.map(fn(arg) { string.lowercase(arg) }) + |> result.map(fn(arg) { + case arg { + "no" -> No + "yes" -> Yes + "mixed" -> Mixed + } + }) + func(module_list, ignore_tags, capture_output) +} diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/common/cli.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/common/cli.gleam new file mode 100644 index 0000000..1c03211 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/common/cli.gleam @@ -0,0 +1,5 @@ +pub type Capture { + Yes + No + Mixed +} diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/common/common_event_handler.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/common/common_event_handler.gleam new file mode 100644 index 0000000..b90af14 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/common/common_event_handler.gleam @@ -0,0 +1,101 @@ +import gleam/map.{type Map} +import showtime/internal/common/test_suite.{ + type TestEvent, type TestRun, CompletedTestRun, EndTest, EndTestRun, + EndTestSuite, OngoingTestRun, StartTest, StartTestRun, StartTestSuite, +} + +pub type TestState { + NotStarted + Running + Finished(num_modules: Int) +} + +pub type HandlerState { + HandlerState( + test_state: TestState, + num_done: Int, + events: Map(String, Map(String, TestRun)), + ) +} + +// This is the common event-handler (shared between erlang/JS targets) +// The main strategy is to collect the test-results in a map of maps: +// module_name -> +// test_name -> test_result +// It will also keep track of if it is running (i.e. did it receive the EndTestRun) +// so that the caller can determine when to print test-results +pub fn handle_event( + msg: TestEvent, + system_time: fn() -> Int, + state: HandlerState, +) { + let test_state = state.test_state + let num_done = state.num_done + let events = state.events + let #(updated_test_state, updated_num_done, updated_events) = case msg { + StartTestRun -> #(Running, num_done, events) + StartTestSuite(module) -> { + let maybe_module_events = map.get(events, module.name) + let new_events = case maybe_module_events { + Ok(_) -> events + Error(_) -> + events + |> map.insert(module.name, map.new()) + } + #(test_state, num_done, new_events) + } + StartTest(module, test) -> { + let current_time = system_time() + let maybe_module_events = map.get(events, module.name) + let new_events = case maybe_module_events { + Ok(module_events) -> { + let maybe_test_event = map.get(module_events, test.name) + case maybe_test_event { + Error(_) -> + events + |> map.insert( + module.name, + module_events + |> map.insert(test.name, OngoingTestRun(test, current_time)), + ) + Ok(_) -> events + } + } + Error(_) -> events + } + #(test_state, num_done, new_events) + } + EndTest(module, test, result) -> { + let current_time = system_time() + let maybe_module_events = map.get(events, module.name) + let new_events = case maybe_module_events { + Ok(module_events) -> { + let maybe_test_run = + module_events + |> map.get(test.name) + let updated_module_events = case maybe_test_run { + Ok(OngoingTestRun(test_function, started_at)) -> + module_events + |> map.insert( + test.name, + CompletedTestRun( + test_function, + current_time - started_at, + result, + ), + ) + Error(_) -> module_events + } + events + |> map.insert(module.name, updated_module_events) + } + Error(_) -> events + } + #(test_state, num_done, new_events) + } + EndTestSuite(_) -> #(test_state, num_done + 1, events) + EndTestRun(num_modules) -> #(Finished(num_modules), num_done, events) + _ -> #(Running, num_done, events) + } + HandlerState(updated_test_state, updated_num_done, updated_events) +} diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/common/test_result.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/common/test_result.gleam new file mode 100644 index 0000000..a1d6bd9 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/common/test_result.gleam @@ -0,0 +1,119 @@ +import gleam/dynamic.{type Dynamic} +import gleam/map.{type Map} + +// These are all the types used for test-results +// NOTE: These are heavily used in the erlang/js ffi:s +// so any changes here are likely to break the ffi:s unless +// the corresponding change is introduced there +// +// Futhermore this has some erlang related names that should +// probably be cleaned up, but it is used by both the ffi:s + +// Currently only one reason, but could be possible to support +// more reasons in the future +pub type IgnoreReason { + Ignore +} + +// This is the return value from running the test-function +// or ignored if the test was ignored +pub type TestReturn { + TestFunctionReturn(value: Dynamic, output_buffer: List(String)) + Ignored(reason: IgnoreReason) +} + +// All data about an exception in the test function is captured +// in this type. +// This is also where the data about the assertions will end up (in reason) +pub type Exception { + ErlangException( + class: Class, + reason: Reason, + stacktrace: TraceList, + output_buffer: List(String), + ) +} + +// Alias for the test-result which is either a TestResult (passed test, ignored or a test-definition) +// or an Exception (failed test) +pub type TestResult = + Result(TestReturn, Exception) + +// Reason is either an assert equal (which is if the error was produced by gleeunit should) +// TODO: Add other asserts +// or it is a gleam error meaning that is was produced by showtime should +// TODO: Rename GleamError to ShowtimeError +pub type Reason { + AssertEqual(details: List(ReasonDetail)) + AssertNotEqual(details: List(ReasonDetail)) + AssertMatch(details: List(ReasonDetail)) + GleamError(details: GleamErrorDetail) + GleamAssert(value: Dynamic, line_no: Int) + GenericException(value: Dynamic) +} + +// ReasonDetail is the union-type used in erlang-exceptions where the reason +// is a list of such details +pub type ReasonDetail { + Module(name: String) + ReasonLine(line_no: Int) + Expression(expression: String) + Expected(value: Dynamic) + Value(value: Dynamic) + Pattern(pattern: String) +} + +// Gleam error detail is produced by showtime should and will hold all the information +// about the assertion (both expected and got) +pub type GleamErrorDetail { + LetAssert( + module: String, + function: String, + line_no: Int, + message: String, + value: Dynamic, + ) +} + +// Class is a part of standard erlang exceptions, but also used on js-side +// TODO: Extend to include a JS specific constructor +pub type Class { + ErlangError + Exit + Throw +} + +// The trace list is part of the standard erlang exception, but is also +// emulated on js-side. +// TODO: Maybe we need a js-version that contain some js-specific trace-elements +pub type TraceList { + TraceList(traces: List(Trace)) +} + +// Trace are the elements in the trace list in an erlang exception +// TODO: Maybe add a js-specific trace (since arity is not really a js attribute) +pub type Trace { + Trace(function: String, arity: Arity, extra_info: List(ExtraInfo)) + TraceModule( + module: String, + function: String, + arity: Arity, + extra_info: List(ExtraInfo), + ) +} + +// Extra info holds information about the file and line +// as well as some dynamic data in a map +// This is currently not used in the reporter +pub type ExtraInfo { + ErrorInfo(error_info: Map(Dynamic, Dynamic)) + File(filename: String) + Line(line_no: Int) +} + +// Arity is the erlang type for arity +// Can be either a number, or a list of arguments +pub type Arity { + Num(arity: Int) + ArgList(arg_list: List(Dynamic)) +} diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/common/test_suite.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/common/test_suite.gleam new file mode 100644 index 0000000..eb58d64 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/common/test_suite.gleam @@ -0,0 +1,63 @@ +import gleam/option.{type Option} +import showtime/internal/common/test_result.{type TestResult} +import showtime/internal/common/cli.{type Capture} + +// The state (and result) of a test function +pub type TestRun { + OngoingTestRun(test_function: TestFunction, started_at: Int) + CompletedTestRun( + test_function: TestFunction, + total_time: Int, + result: TestResult, + ) +} + +// A test module (found by discovery) +pub type TestModule { + TestModule(name: String, path: Option(String)) +} + +// A test function +pub type TestFunction { + TestFunction(name: String) +} + +// A test suite is a test module together with the test functions +// that were collected from that module +pub type TestSuite { + TestSuite(module: TestModule, tests: List(TestFunction)) +} + +// Test event for the event handler +pub type TestEvent { + StartTestRun + StartTestSuite(test_module: TestModule) + StartTest(test_module: TestModule, test_function: TestFunction) + EndTest( + test_module: TestModule, + test_function: TestFunction, + result: TestResult, + ) + EndTestSuite(test_module: TestModule) + EndTestRun(num_modules: Int) +} + +// Interface for the module handler +pub type TestModuleHandler = + fn(TestModule) -> Nil + +// Interface for the event handler +pub type TestEventHandler = + fn(TestEvent) -> Nil + +// Interface for the module collector +pub type ModuleCollector = + fn(TestModuleHandler) -> List(TestModule) + +// Interface for the function collector +pub type TestFunctionCollector = + fn(TestModule) -> TestSuite + +// Interface for the test runner +pub type TestRunner = + fn(TestSuite, TestEventHandler, List(String), Capture) -> Nil diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/erlang/discover.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/erlang/discover.gleam new file mode 100644 index 0000000..ecb752d --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/erlang/discover.gleam @@ -0,0 +1,167 @@ +@target(erlang) +import gleam/io +@target(erlang) +import gleam/dynamic.{type Dynamic} +@target(erlang) +import gleam/list +@target(erlang) +import gleam/string +@target(erlang) +import gleam/int +@target(erlang) +import gleam/option.{type Option, None, Some} +@target(erlang) +import gleam/erlang/atom.{type Atom} +@target(erlang) +import showtime/internal/common/test_suite.{ + type TestModule, type TestModuleHandler, type TestSuite, TestFunction, + TestModule, TestSuite, +} +import simplifile + +// Module collector for erlang +// Will search the test folder for files ending with _test and notify +// the module handler about each module it finds +@target(erlang) +pub fn collect_modules( + test_module_handler: TestModuleHandler, + only_modules: Option(List(String)), +) -> List(TestModule) { + collect_modules_in_folder("./test", test_module_handler, only_modules) +} + +@target(erlang) +fn collect_modules_in_folder( + path: String, + test_module_handler: TestModuleHandler, + only_modules: Option(List(String)), +) { + let module_prefix = get_module_prefix(path) + let assert Ok(files) = simplifile.read_directory(path) + let test_modules_in_folder = + files + |> list.filter(string.ends_with(_, "_test.gleam")) + |> list.filter_map(fn(test_module_file) { + let module_name = + module_prefix <> { + test_module_file + |> string.replace(".gleam", "") + } + case only_modules { + Some(only_modules_list) -> { + let module_in_list = + only_modules_list + |> list.any(fn(only_module_name) { + only_module_name == module_name + |> string.replace("@", "/") + }) + case module_in_list { + True -> { + let test_module = TestModule(module_name, Some(test_module_file)) + test_module_handler(test_module) + Ok(test_module) + } + + False -> Error(Nil) + } + } + None -> { + let test_module = TestModule(module_name, Some(test_module_file)) + test_module_handler(test_module) + Ok(test_module) + } + } + }) + let test_modules_in_subfolders = + files + |> list.map(fn(filename) { path <> "/" <> filename }) + |> list.filter(fn(file) { simplifile.is_directory(file) }) + |> list.fold( + [], + fn(modules, subfolder) { + modules + |> list.append(collect_modules_in_folder( + subfolder, + test_module_handler, + only_modules, + )) + }, + ) + test_modules_in_folder + |> list.append(test_modules_in_subfolders) +} + +@target(erlang) +fn get_module_prefix(path) { + let path_without_test = + path + |> string.replace("./test", "") + + let path_without_leading_slash = case + string.starts_with(path_without_test, "/") + { + True -> string.drop_left(path_without_test, 1) + False -> path_without_test + } + let module_prefix = + path_without_leading_slash + |> string.replace("/", "@") + case string.length(module_prefix) { + 0 -> module_prefix + _ -> module_prefix <> "@" + } +} + +// Test function collector for erlang +// Uses erlang `apply` to run `module_info` for the test module +// and collects all the exports ending with _test into a `TestSuite` +@target(erlang) +pub fn collect_test_functions(module: TestModule) -> TestSuite { + let test_functions: List(#(Atom, Int)) = + apply( + atom.create_from_string(module.name), + atom.create_from_string("module_info"), + [dynamic.from(atom.create_from_string("exports"))], + ) + |> dynamic.unsafe_coerce() + + let test_functions_filtered = + test_functions + |> list.map(fn(entry) { + let assert #(name, arity) = entry + #( + name + |> atom.to_string(), + arity, + ) + }) + |> list.filter_map(fn(entry) { + let assert #(name, arity) = entry + case string.ends_with(name, "_test") { + True -> + case arity { + 0 -> Ok(name) + _ -> { + io.println( + "WARNING: function \"" <> name <> "\" has arity: " <> int.to_string( + arity, + ) <> " - cannot be used as test (needs to be 0)", + ) + Error("Wrong arity") + } + } + False -> Error("Non matching name") + } + }) + |> list.filter(string.ends_with(_, "_test")) + |> list.map(fn(function_name) { TestFunction(function_name) }) + TestSuite(module, test_functions_filtered) +} + +@target(erlang) +@external(erlang, "erlang", "apply") +fn apply( + module module: Atom, + function function: Atom, + args args: List(Dynamic), +) -> Dynamic diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/erlang/event_handler.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/erlang/event_handler.gleam new file mode 100644 index 0000000..62a9caf --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/erlang/event_handler.gleam @@ -0,0 +1,91 @@ +@target(erlang) +import gleam/io +@target(erlang) +import gleam/otp/actor.{Continue, Stop} +@target(erlang) +import gleam/erlang/process.{type Subject, Normal} +@target(erlang) +import gleam/map +@target(erlang) +import showtime/internal/common/test_suite.{type TestEvent, EndTestRun} +@target(erlang) +import showtime/internal/common/common_event_handler.{ + Finished, HandlerState, NotStarted, handle_event, +} +@target(erlang) +import showtime/internal/reports/formatter.{create_test_report} +@target(erlang) +import gleam/erlang.{Millisecond} +@target(erlang) +import gleam/option.{None} + +@target(erlang) +type EventHandlerMessage { + EventHandlerMessage(test_event: TestEvent, reply_to: Subject(Int)) +} + +// Starts an actor that receives test events and forwards the to the event handler +// When handler updates the state to `Finished` the actor will wait until handler +// reports that all modules are done and the stop +@target(erlang) +pub fn start() { + let assert Ok(subject) = + actor.start( + #(NotStarted, 0, map.new()), + fn(msg: EventHandlerMessage, state) { + let EventHandlerMessage(test_event, reply_to) = msg + let #(test_state, num_done, events) = state + let updated_state = + handle_event( + test_event, + system_time, + HandlerState(test_state, num_done, events), + ) + case updated_state { + HandlerState(Finished(num_modules), num_done, events) if num_done == num_modules -> { + let #(test_report, num_failed) = create_test_report(events) + io.println(test_report) + process.send(reply_to, num_failed) + Stop(Normal) + } + HandlerState(test_state, num_done, events) -> + Continue(#(test_state, num_done, events), None) + } + }, + ) + let parent_subject = process.new_subject() + + let selector = + process.new_selector() + |> process.selecting(parent_subject, fn(x) { x }) + + // Returns a callback that can receive test events + fn(test_event: TestEvent) { + case test_event { + EndTestRun(..) -> { + // When EndTestRun has been received the callback will wait until the + // actor has stopped + // TODO: Use a timeout? + process.send(subject, EventHandlerMessage(test_event, parent_subject)) + let num_failed = process.select_forever(selector) + case num_failed > 0 { + True -> halt(1) + False -> halt(0) + } + } + + // Normally just send the test event to the actor + _ -> + process.send(subject, EventHandlerMessage(test_event, parent_subject)) + } + } +} + +@target(erlang) +@external(erlang, "erlang", "halt") +fn halt(a: Int) -> Nil + +@target(erlang) +fn system_time() { + erlang.system_time(Millisecond) +} diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/erlang/module_handler.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/erlang/module_handler.gleam new file mode 100644 index 0000000..88cc251 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/erlang/module_handler.gleam @@ -0,0 +1,43 @@ +@target(erlang) +import gleam/otp/actor.{Continue} +@target(erlang) +import gleam/erlang/process +@target(erlang) +import showtime/internal/common/test_suite.{ + type TestEventHandler, type TestFunctionCollector, type TestModule, + type TestRunner, EndTestSuite, StartTestSuite, +} +@target(erlang) +import showtime/internal/common/cli.{type Capture} +@target(erlang) +import gleam/option.{None} + +@target(erlang) +pub fn start( + test_event_handler: TestEventHandler, + test_function_collector: TestFunctionCollector, + run_test_suite: TestRunner, + ignore_tags: List(String), + capture: Capture, +) { + let assert Ok(subject) = + actor.start( + Nil, + fn(module: TestModule, state) { + process.start( + fn() { + let test_suite = test_function_collector(module) + test_event_handler(StartTestSuite(module)) + run_test_suite(test_suite, test_event_handler, ignore_tags, capture) + test_event_handler(EndTestSuite(module)) + }, + False, + ) + Continue(state, None) + }, + ) + fn(test_module: TestModule) { + process.send(subject, test_module) + Nil + } +} diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/erlang/runner.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/erlang/runner.gleam new file mode 100644 index 0000000..ebbf426 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/erlang/runner.gleam @@ -0,0 +1,59 @@ +@target(erlang) +import gleam/list +@target(erlang) +import gleam/erlang/atom.{type Atom} +@target(erlang) +import showtime/internal/common/test_suite.{ + type TestEventHandler, type TestSuite, EndTest, StartTest, +} +@target(erlang) +import showtime/internal/common/test_result.{type TestResult} +@target(erlang) +import showtime/internal/common/cli.{type Capture} + +// Runs all tests in a test suite +@target(erlang) +pub fn run_test_suite( + test_suite: TestSuite, + test_event_handler: TestEventHandler, + ignore_tags: List(String), + capture: Capture, +) { + test_suite.tests + |> list.each(fn(test) { + test_event_handler(StartTest(test_suite.module, test)) + let result = + run_test(test_suite.module.name, test.name, ignore_tags, capture) + test_event_handler(EndTest(test_suite.module, test, result)) + }) +} + +// Wrapper around the ffi function that converts names to atoms +@target(erlang) +pub fn run_test( + module_name: String, + test_name: String, + ignore_tags: List(String), + capture: Capture, +) -> TestResult { + let result = + run_test_ffi( + atom.create_from_string(module_name), + atom.create_from_string(test_name), + ignore_tags, + capture, + ) + result +} + +// Calls ffi for running a test function +// The ffi will take care of mapping the result and exception to the data-types +// used in gleam +@target(erlang) +@external(erlang, "showtime_ffi", "run_test") +fn run_test_ffi( + module module: Atom, + function function: Atom, + ignore_tags ignore_tags: List(String), + capture capture: Capture, +) -> TestResult diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/reports/compare.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/reports/compare.gleam new file mode 100644 index 0000000..5ccddee --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/reports/compare.gleam @@ -0,0 +1,42 @@ +import gleam/dynamic.{type Dynamic} +import gleam/string +import showtime/internal/reports/styles.{expected_highlight, got_highlight} +import gap.{compare_lists, compare_strings} +import gap/styling.{from_comparison, highlight, to_styled_comparison} + +pub fn compare(expected: Dynamic, got: Dynamic) -> #(String, String) { + let expected_as_list = + expected + |> dynamic.list(dynamic.dynamic) + let got_as_list = + got + |> dynamic.list(dynamic.dynamic) + let expected_as_string = + expected + |> dynamic.string() + let got_as_string = + got + |> dynamic.string() + case expected_as_list, got_as_list, expected_as_string, got_as_string { + Ok(expected_list), Ok(got_list), _, _ -> { + let comparison = + compare_lists(expected_list, got_list) + |> from_comparison() + |> highlight(expected_highlight, got_highlight, fn(item) { item }) + |> to_styled_comparison() + #(comparison.first, comparison.second) + } + _, _, Ok(expected_string), Ok(got_string) -> { + let comparison = + compare_strings(expected_string, got_string) + |> from_comparison() + |> highlight(expected_highlight, got_highlight, fn(item) { item }) + |> to_styled_comparison() + #(comparison.first, comparison.second) + } + _, _, _, _ -> #( + expected_highlight(string.inspect(expected)), + got_highlight(string.inspect(got)), + ) + } +} diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/reports/formatter.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/reports/formatter.gleam new file mode 100644 index 0000000..8c1a6ac --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/reports/formatter.gleam @@ -0,0 +1,480 @@ +import gleam/io +import gleam/int +import gleam/list +import gleam/string +import gleam/option.{type Option, None, Some} +import gleam/map.{type Map} +import gleam/dynamic.{type Dynamic} +import showtime/internal/common/test_result.{ + type GleamErrorDetail, type ReasonDetail, type Trace, AssertEqual, AssertMatch, + AssertNotEqual, Expected, Expression, GenericException, GleamAssert, + GleamError, Ignored, LetAssert, Pattern, Trace, TraceModule, Value, +} +import showtime/internal/common/test_suite.{type TestRun, CompletedTestRun} +import showtime/tests/should.{type Assertion, Eq, Fail, IsError, IsOk, NotEq} +import showtime/internal/reports/styles.{ + error_style, expected_highlight, failed_style, function_style, got_highlight, + heading_style, ignored_style, not_style, passed_style, stacktrace_style, +} +import showtime/internal/reports/compare.{compare} +import showtime/internal/reports/table.{ + AlignLeft, AlignLeftOverflow, AlignRight, Content, Separator, StyledContent, + Table, align_table, to_string, +} +import showtime/tests/meta.{type Meta} + +type GleeUnitAssertionType { + GleeUnitAssertEqual(message: String) + GleeUnitAssertNotEqual(message: String) + GleeUnitAssertMatch(message: String) +} + +type ModuleAndTest { + ModuleAndTestRun(module_name: String, test_run: TestRun) +} + +type UnifiedError { + UnifiedError( + meta: Option(Meta), + reason: String, + message: String, + expected: String, + got: String, + line: Option(Int), + stacktrace: List(Trace), + ) +} + +pub fn create_test_report(test_results: Map(String, Map(String, TestRun))) { + let all_test_runs = + test_results + |> map.values() + |> list.flat_map(map.values) + let failed_test_runs = + test_results + |> map.to_list() + |> list.flat_map(fn(entry) { + let #(module_name, test_module_results) = entry + test_module_results + |> map.values() + |> list.filter_map(fn(test_run) { + case test_run { + CompletedTestRun(_test_function, _, result) -> + case result { + Error(_) -> Ok(ModuleAndTestRun(module_name, test_run)) + Ok(Ignored(_)) -> Error(Nil) + Ok(_) -> Error(Nil) + } + _ -> { + test_run + |> io.debug() + Error(Nil) + } + } + }) + }) + + let ignored_test_runs = + test_results + |> map.to_list() + |> list.flat_map(fn(entry) { + let #(module_name, test_module_results) = entry + test_module_results + |> map.values() + |> list.filter_map(fn(test_run) { + case test_run { + CompletedTestRun(test_function, _, result) -> + case result { + Ok(Ignored(reason)) -> + Ok(#(module_name <> "." <> test_function.name, reason)) + _ -> Error(Nil) + } + _ -> Error(Nil) + } + }) + }) + + let failed_tests_report = + failed_test_runs + |> list.filter_map(fn(module_and_test_run) { + case module_and_test_run.test_run { + CompletedTestRun(test_function, _total_time, result) -> + case result { + Error(exception) -> + case exception.reason { + AssertEqual(reason_details) -> + Ok(format_reason( + erlang_error_to_unified( + reason_details, + GleeUnitAssertEqual("Assert equal"), + exception.stacktrace.traces, + ), + module_and_test_run.module_name, + test_function.name, + exception.output_buffer, + )) + AssertNotEqual(reason_details) -> + Ok(format_reason( + erlang_error_to_unified( + reason_details, + GleeUnitAssertNotEqual("Assert not equal"), + exception.stacktrace.traces, + ), + module_and_test_run.module_name, + test_function.name, + exception.output_buffer, + )) + AssertMatch(reason_details) -> + Ok(format_reason( + erlang_error_to_unified( + reason_details, + GleeUnitAssertMatch("Assert match"), + exception.stacktrace.traces, + ), + module_and_test_run.module_name, + test_function.name, + exception.output_buffer, + )) + GleamError(reason) -> + Ok(format_reason( + gleam_error_to_unified(reason, exception.stacktrace.traces), + module_and_test_run.module_name, + test_function.name, + exception.output_buffer, + )) + // GleamAssert(value) -> Error(Nil) + GleamAssert(value, line_no) -> + Ok(format_reason( + UnifiedError( + None, + "gleam assert", + "Assert failed", + "Patterns should match", + error_style(string.inspect(value)), + Some(line_no), + exception.stacktrace.traces, + ), + module_and_test_run.module_name, + test_function.name, + exception.output_buffer, + )) + GenericException(value) -> + Ok(format_reason( + UnifiedError( + None, + "generic exception", + "Test function threw an exception", + "Exception in test function", + error_style(string.inspect(value)), + None, + exception.stacktrace.traces, + ), + module_and_test_run.module_name, + test_function.name, + exception.output_buffer, + )) + other -> { + io.println("Other: " <> string.inspect(other)) + panic + Error(Nil) + } + } + _ -> Error(Nil) + } + _ -> Error(Nil) + } + }) + |> list.fold([], fn(rows, test_rows) { list.append(rows, test_rows) }) + + let all_test_execution_time_reports = + all_test_runs + |> list.filter_map(fn(test_run) { + case test_run { + CompletedTestRun(test_function, total_time, _) -> + Ok(test_function.name <> ": " <> int.to_string(total_time) <> " ms") + _ -> Error(Nil) + } + }) + let _execution_times_report = + all_test_execution_time_reports + |> string.join("\n") + + let all_tests_count = + all_test_runs + |> list.length() + let ignored_tests_count = + ignored_test_runs + |> list.length() + let failed_tests_count = + failed_test_runs + |> list.length() + + let passed = + passed_style( + int.to_string(all_tests_count - failed_tests_count - ignored_tests_count) <> " passed", + ) + let failed = failed_style(int.to_string(failed_tests_count) <> " failed") + let ignored = case ignored_tests_count { + 0 -> "" + _ -> ", " <> ignored_style(int.to_string(ignored_tests_count) <> " ignored") + } + + let failed_tests_table = + Table(None, failed_tests_report) + |> align_table() + |> to_string() + + let test_report = + "\n" <> failed_tests_table <> "\n" <> passed <> ", " <> failed <> ignored + #(test_report, failed_tests_count) +} + +fn erlang_error_to_unified( + error_details: List(ReasonDetail), + assertion_type: GleeUnitAssertionType, + stacktrace: List(Trace), +) { + error_details + |> list.fold( + UnifiedError( + None, + "not_set", + assertion_type.message, + "", + "", + None, + stacktrace, + ), + fn(unified, reason) { + case reason { + Expression(expression) -> UnifiedError(..unified, reason: expression) + Expected(value) -> + case assertion_type { + GleeUnitAssertEqual(_messaged) -> + UnifiedError( + ..unified, + expected: expected_highlight(string.inspect(value)), + ) + _ -> unified + } + Value(value) -> + case assertion_type { + GleeUnitAssertNotEqual(_message) -> + UnifiedError( + ..unified, + expected: not_style("not ") <> string.inspect(value), + got: got_highlight(string.inspect(value)), + ) + _ -> + UnifiedError(..unified, got: got_highlight(string.inspect(value))) + } + Pattern(pattern) -> + case pattern { + "{ ok , _ }" -> + UnifiedError(..unified, expected: expected_highlight("Ok(_)")) + "{ error , _ }" -> + UnifiedError(..unified, expected: expected_highlight("Error(_)")) + _ -> unified + } + _ -> unified + } + }, + ) +} + +fn gleam_error_to_unified( + gleam_error: GleamErrorDetail, + stacktrace: List(Trace), +) -> UnifiedError { + case gleam_error { + LetAssert(_module, _function, _line_no, _message, value) -> { + let result: Result(Dynamic, Assertion(Dynamic, Dynamic)) = + dynamic.unsafe_coerce(value) + let assert Error(assertion) = result + case assertion { + Eq(got, expected, meta) -> { + let #(expected, got) = compare(expected, got) + UnifiedError( + meta, + "assert", + "Assert equal", + expected, + got, + None, + stacktrace, + ) + } + NotEq(got, expected, meta) -> + UnifiedError( + meta, + "assert", + "Assert not equal", + not_style("not ") <> string.inspect(expected), + string.inspect(got), + None, + stacktrace, + ) + IsOk(got, meta) -> + UnifiedError( + meta, + "assert", + "Assert is Ok", + expected_highlight("Ok(_)"), + got_highlight(string.inspect(got)), + None, + stacktrace, + ) + IsError(got, meta) -> + UnifiedError( + meta, + "assert", + "Assert is Ok", + expected_highlight("Error(_)"), + got_highlight(string.inspect(got)), + None, + stacktrace, + ) + Fail(meta) -> + UnifiedError( + meta, + "assert", + "Assert is Ok", + got_highlight("should.fail()"), + got_highlight("N/A - test always expected to fail"), + None, + stacktrace, + ) + } + } + } +} + +fn format_reason( + error: UnifiedError, + module: String, + function: String, + output_buffer: List(String), +) { + let meta = case error.meta { + Some(meta) -> + Some([ + AlignRight(StyledContent(heading_style("Description")), 2), + Separator(": "), + AlignLeft(Content(meta.description), 0), + ]) + + None -> None + } + + let stacktrace = + error.stacktrace + |> list.map(fn(trace) { + case trace { + Trace(function, _, _) if function == "" -> "(anonymous)" + TraceModule(module, function, _, _) if function == "" -> + module <> "." <> "(anonymous)" + Trace(function, _, _) -> function + TraceModule(module, function, _, _) -> module <> "." <> function + } + }) + let stacktrace_rows = case stacktrace { + [] -> [] + [first, ..rest] -> { + let first_row = + Some([ + AlignRight(StyledContent(heading_style("Stacktrace")), 2), + Separator(": "), + AlignLeft(StyledContent(stacktrace_style(first)), 0), + ]) + let rest_rows = + rest + |> list.map(fn(row) { + Some([ + AlignRight(Content(""), 2), + Separator(" "), + AlignLeft(StyledContent(stacktrace_style(row)), 0), + ]) + }) + [first_row, ..rest_rows] + } + } + + let output_rows = case + output_buffer + |> list.reverse() + |> list.map(fn(row) { string.trim_right(row) }) + { + [] -> [] + [first, ..rest] -> { + let first_row = + Some([ + AlignRight(StyledContent(heading_style("Output")), 2), + Separator(": "), + AlignLeftOverflow(StyledContent(stacktrace_style(first)), 0), + ]) + let rest_rows = + rest + |> list.map(fn(row) { + Some([ + AlignRight(Content(""), 2), + Separator(" "), + AlignLeftOverflow(StyledContent(stacktrace_style(row)), 0), + ]) + }) + [first_row, ..rest_rows] + } + } + + let line = + error.line + |> option.map(fn(line) { ":" <> int.to_string(line) }) + |> option.unwrap("") + + let arrow = + string.join( + list.repeat( + "-", + string.length(module) + 1 + { + string.length(function) + string.length(line) + } / 2, + ), + "", + ) <> "⌄" + let standard_table_rows = [ + Some([ + AlignRight(StyledContent(error_style("Failed")), 2), + Separator(": "), + AlignLeft(Content(arrow), 0), + ]), + Some([ + AlignRight(StyledContent(heading_style("Test")), 2), + Separator(": "), + AlignLeft( + StyledContent(module <> "." <> function_style(function <> line)), + 0, + ), + ]), + meta, + Some([ + AlignRight(StyledContent(heading_style("Expected")), 2), + Separator(": "), + AlignLeftOverflow(StyledContent(error.expected), 0), + ]), + Some([ + AlignRight(StyledContent(heading_style("Got")), 2), + Separator(": "), + AlignLeftOverflow(StyledContent(error.got), 0), + ]), + ] + standard_table_rows + |> list.append(stacktrace_rows) + |> list.append(output_rows) + |> list.append([ + Some([ + AlignRight(Content(""), 0), + AlignRight(Content(""), 0), + AlignRight(Content(""), 0), + ]), + ]) + |> list.filter_map(fn(row) { option.to_result(row, Nil) }) +} diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/reports/styles.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/reports/styles.gleam new file mode 100644 index 0000000..b051dd3 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/reports/styles.gleam @@ -0,0 +1,84 @@ +import gleam_community/ansi +import gleam/list +import gleam/string +import gleam/bit_array + +pub fn passed_style(text) { + bold_green(text) +} + +pub fn failed_style(text) { + bold_red(text) +} + +pub fn ignored_style(text) { + bold_yellow(text) +} + +pub fn error_style(text) { + bold_red(text) +} + +pub fn expected_highlight(text) { + bold_green(text) +} + +pub fn got_highlight(text) { + bold_red(text) +} + +pub fn not_style(text) { + ansi.bold(text) +} + +pub fn module_style(text: String) { + ansi.cyan(text) +} + +pub fn heading_style(text: String) { + ansi.cyan(text) +} + +pub fn function_style(text: String) { + bold_cyan(text) +} + +pub fn stacktrace_style(text: String) { + text +} + +fn bold_red(text: String) { + ansi.bold(ansi.red(text)) +} + +fn bold_green(text) { + ansi.bold(ansi.green(text)) +} + +fn bold_yellow(text) { + ansi.bold(ansi.yellow(text)) +} + +fn bold_cyan(text) { + ansi.bold(ansi.cyan(text)) +} + +pub fn strip_style(text) { + let #(new_text, _) = + text + |> string.to_graphemes() + |> list.fold( + #("", False), + fn(acc, char) { + let #(str, removing) = acc + let bit_char = bit_array.from_string(char) + case bit_char, removing { + <<0x1b>>, _ -> #(str, True) + <<0x6d>>, True -> #(str, False) + _, True -> #(str, True) + _, False -> #(str <> char, False) + } + }, + ) + new_text +} diff --git a/aoc2023/build/packages/adglent/src/showtime/internal/reports/table.gleam b/aoc2023/build/packages/adglent/src/showtime/internal/reports/table.gleam new file mode 100644 index 0000000..f8bc00c --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/internal/reports/table.gleam @@ -0,0 +1,148 @@ +import gleam/list +import gleam/string +import gleam/int +import gleam/option.{type Option} +import showtime/internal/reports/styles.{strip_style} + +pub type Content { + Content(unstyled_text: String) + StyledContent(styled_text: String) +} + +pub type Col { + AlignRight(content: Content, margin: Int) + AlignLeft(content: Content, margin: Int) + AlignRightOverflow(content: Content, margin: Int) + AlignLeftOverflow(content: Content, margin: Int) + Separator(char: String) + Aligned(content: String) +} + +pub type Table { + Table(header: Option(String), rows: List(List(Col))) +} + +pub fn to_string(table: Table) -> String { + let rows = + table.rows + |> list.map(fn(row) { + row + |> list.filter_map(fn(col) { + case col { + Separator(char) -> Ok(char) + Aligned(content) -> Ok(content) + _ -> Error(Nil) + } + }) + |> string.join("") + }) + |> string.join("\n") + let header = + table.header + |> option.map(fn(header) { header <> "\n" }) + |> option.unwrap("") + header <> rows +} + +pub fn align_table(table: Table) -> Table { + let cols = + table.rows + |> list.transpose() + let col_width = + cols + |> list.map(fn(col) { + col + |> list.map(fn(content) { + case content { + AlignRight(Content(unstyled), _) -> unstyled + AlignRight(StyledContent(styled), _) -> strip_style(styled) + AlignLeft(Content(unstyled), _) -> unstyled + AlignLeft(StyledContent(styled), _) -> strip_style(styled) + AlignLeftOverflow(_, _) -> "" + AlignRightOverflow(_, _) -> "" + Separator(char) -> char + Aligned(content) -> content + } + }) + |> list.fold(0, fn(max, str) { int.max(max, string.length(str)) }) + }) + let aligned_col = + cols + |> list.zip(col_width) + |> list.map(fn(col_and_width) { + let #(col, width) = col_and_width + col + |> list.map(fn(content) { + case content { + AlignRight(Content(unstyled), margin) -> + Aligned(pad_left( + unstyled, + width + margin - string.length(unstyled), + " ", + )) + AlignRight(StyledContent(styled), margin) -> + Aligned(pad_left( + styled, + width + margin - string.length(strip_style(styled)), + " ", + )) + AlignRightOverflow(Content(unstyled), margin) -> + Aligned(pad_left( + unstyled, + width + margin - string.length(unstyled), + " ", + )) + AlignRightOverflow(StyledContent(styled), margin) -> + Aligned(pad_left( + styled, + width + margin - string.length(strip_style(styled)), + " ", + )) + AlignLeft(Content(unstyled), margin) -> + Aligned(pad_right( + unstyled, + width + margin - string.length(unstyled), + " ", + )) + AlignLeft(StyledContent(styled), margin) -> + Aligned(pad_right( + styled, + width + margin - string.length(strip_style(styled)), + " ", + )) + AlignLeftOverflow(Content(unstyled), margin) -> + Aligned(pad_right( + unstyled, + width + margin - string.length(unstyled), + " ", + )) + AlignLeftOverflow(StyledContent(styled), margin) -> + Aligned(pad_right( + styled, + width + margin - string.length(strip_style(styled)), + " ", + )) + Separator(char) -> Separator(char) + Aligned(content) -> Aligned(content) + } + }) + }) + let aligned_rows = + aligned_col + |> list.transpose() + Table(..table, rows: aligned_rows) +} + +fn pad_left(str: String, num: Int, char: String) { + let padding = + list.repeat(char, num) + |> string.join("") + padding <> str +} + +fn pad_right(str: String, num: Int, char: String) { + let padding = + list.repeat(char, num) + |> string.join("") + str <> padding +} diff --git a/aoc2023/build/packages/adglent/src/showtime/tests/meta.gleam b/aoc2023/build/packages/adglent/src/showtime/tests/meta.gleam new file mode 100644 index 0000000..cbba414 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/tests/meta.gleam @@ -0,0 +1,3 @@ +pub type Meta { + Meta(description: String, tags: List(String)) +} diff --git a/aoc2023/build/packages/adglent/src/showtime/tests/should.gleam b/aoc2023/build/packages/adglent/src/showtime/tests/should.gleam new file mode 100644 index 0000000..71578c7 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/tests/should.gleam @@ -0,0 +1,113 @@ +import gleam/option.{type Option, None, Some} +import showtime/tests/meta.{type Meta} + +pub type Assertion(t, e) { + Eq(a: t, b: t, meta: Option(Meta)) + NotEq(a: t, b: t, meta: Option(Meta)) + IsOk(a: Result(t, e), meta: Option(Meta)) + IsError(a: Result(t, e), meta: Option(Meta)) + Fail(meta: Option(Meta)) +} + +pub fn equal(a: t, b: t) { + evaluate(Eq(a, b, None)) +} + +pub fn equal_meta(a: t, b: t, meta: Meta) { + evaluate(Eq(a, b, Some(meta))) +} + +pub fn not_equal(a: t, b: t) { + evaluate(NotEq(a, b, None)) +} + +pub fn not_equal_meta(a: t, b: t, meta: Meta) { + evaluate(NotEq(a, b, Some(meta))) +} + +pub fn be_ok(a: Result(o, e)) { + evaluate(IsOk(a, None)) + let assert Ok(value) = a + value +} + +pub fn be_ok_meta(a: Result(o, e), meta: Meta) { + evaluate(IsOk(a, Some(meta))) +} + +pub fn be_error(a: Result(o, e)) { + evaluate(IsError(a, None)) + let assert Error(value) = a + value +} + +pub fn be_error_meta(a: Result(o, e), meta: Meta) { + evaluate(IsError(a, Some(meta))) +} + +pub fn fail() { + evaluate(Fail(None)) +} + +pub fn fail_meta(meta: Meta) { + evaluate(Fail(Some(meta))) +} + +pub fn be_true(a: Bool) { + a + |> equal(True) +} + +pub fn be_true_meta(a: Bool, meta: Meta) { + a + |> equal_meta(True, meta) +} + +pub fn be_false(a: Bool) { + a + |> equal(False) +} + +pub fn be_false_meta(a: Bool, meta: Meta) { + a + |> equal_meta(False, meta) +} + +@external(erlang, "showtime_ffi", "gleam_error") +fn gleam_error(value: Result(Nil, Assertion(a, b))) -> Nil + +pub fn evaluate(assertion) -> Nil { + case assertion { + Eq(a, b, _meta) -> + case a == b { + True -> Nil + False -> { + gleam_error(Error(assertion)) + } + } + NotEq(a, b, _meta) -> + case a != b { + True -> Nil + False -> { + gleam_error(Error(assertion)) + } + } + IsOk(a, _meta) -> + case a { + Ok(_) -> Nil + Error(_) -> { + gleam_error(Error(assertion)) + } + } + IsError(a, _meta) -> + case a { + Error(_) -> Nil + Ok(_) -> { + gleam_error(Error(assertion)) + } + } + Fail(_meta) -> { + gleam_error(Error(assertion)) + } + } +} diff --git a/aoc2023/build/packages/adglent/src/showtime/tests/test.gleam b/aoc2023/build/packages/adglent/src/showtime/tests/test.gleam new file mode 100644 index 0000000..730f943 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime/tests/test.gleam @@ -0,0 +1,57 @@ +import showtime/tests/should +import showtime/tests/meta.{type Meta} +import gleam/io + +pub type Test { + Test(meta: Meta, test_function: fn() -> Nil) +} + +pub type MetaShould(t) { + MetaShould(equal: fn(t, t) -> Nil, not_equal: fn(t, t) -> Nil) +} + +pub fn test(meta: Meta, test_function: fn(Meta) -> Nil) { + Test(meta, fn() { test_function(meta) }) +} + +pub fn with_meta(meta: Meta, test_function: fn(MetaShould(a)) -> Nil) { + Test( + meta, + fn() { + test_function(MetaShould( + fn(a, b) { equal(a, b, meta) }, + fn(a, b) { not_equal(a, b, meta) }, + )) + }, + ) +} + +pub fn equal(a: t, b: t, meta: Meta) { + io.debug(a) + io.debug(b) + should.equal_meta(a, b, meta) +} + +pub fn not_equal(a: t, b: t, meta: Meta) { + should.equal_meta(a, b, meta) +} + +pub fn be_ok(a: Result(o, e), meta: Meta) { + should.be_ok_meta(a, meta) +} + +pub fn be_error(a: Result(o, e), meta: Meta) { + should.be_error_meta(a, meta) +} + +pub fn fail(meta: Meta) { + should.fail_meta(meta) +} + +pub fn be_true(a: Bool, meta: Meta) { + should.be_true_meta(a, meta) +} + +pub fn be_false(a: Bool, meta: Meta) { + should.be_false_meta(a, meta) +} diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@common@cli.erl b/aoc2023/build/packages/adglent/src/showtime@internal@common@cli.erl new file mode 100644 index 0000000..f2d2396 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@common@cli.erl @@ -0,0 +1,8 @@ +-module(showtime@internal@common@cli). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export_type([capture/0]). + +-type capture() :: yes | no | mixed. + + diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@common@common_event_handler.erl b/aoc2023/build/packages/adglent/src/showtime@internal@common@common_event_handler.erl new file mode 100644 index 0000000..b0a6d7a --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@common@common_event_handler.erl @@ -0,0 +1,131 @@ +-module(showtime@internal@common@common_event_handler). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([handle_event/3]). +-export_type([test_state/0, handler_state/0]). + +-type test_state() :: not_started | running | {finished, integer()}. + +-type handler_state() :: {handler_state, + test_state(), + integer(), + gleam@map:map_(binary(), gleam@map:map_(binary(), showtime@internal@common@test_suite:test_run()))}. + +-spec handle_event( + showtime@internal@common@test_suite:test_event(), + fun(() -> integer()), + handler_state() +) -> handler_state(). +handle_event(Msg, System_time, State) -> + Test_state = erlang:element(2, State), + Num_done = erlang:element(3, State), + Events = erlang:element(4, State), + {Updated_test_state, Updated_num_done, Updated_events} = case Msg of + start_test_run -> + {running, Num_done, Events}; + + {start_test_suite, Module} -> + Maybe_module_events = gleam@map:get( + Events, + erlang:element(2, Module) + ), + New_events = case Maybe_module_events of + {ok, _} -> + Events; + + {error, _} -> + _pipe = Events, + gleam@map:insert( + _pipe, + erlang:element(2, Module), + gleam@map:new() + ) + end, + {Test_state, Num_done, New_events}; + + {start_test, Module@1, Test} -> + Current_time = System_time(), + Maybe_module_events@1 = gleam@map:get( + Events, + erlang:element(2, Module@1) + ), + New_events@1 = case Maybe_module_events@1 of + {ok, Module_events} -> + Maybe_test_event = gleam@map:get( + Module_events, + erlang:element(2, Test) + ), + case Maybe_test_event of + {error, _} -> + _pipe@1 = Events, + gleam@map:insert( + _pipe@1, + erlang:element(2, Module@1), + begin + _pipe@2 = Module_events, + gleam@map:insert( + _pipe@2, + erlang:element(2, Test), + {ongoing_test_run, Test, Current_time} + ) + end + ); + + {ok, _} -> + Events + end; + + {error, _} -> + Events + end, + {Test_state, Num_done, New_events@1}; + + {end_test, Module@2, Test@1, Result} -> + Current_time@1 = System_time(), + Maybe_module_events@2 = gleam@map:get( + Events, + erlang:element(2, Module@2) + ), + New_events@2 = case Maybe_module_events@2 of + {ok, Module_events@1} -> + Maybe_test_run = begin + _pipe@3 = Module_events@1, + gleam@map:get(_pipe@3, erlang:element(2, Test@1)) + end, + Updated_module_events = case Maybe_test_run of + {ok, {ongoing_test_run, Test_function, Started_at}} -> + _pipe@4 = Module_events@1, + gleam@map:insert( + _pipe@4, + erlang:element(2, Test@1), + {completed_test_run, + Test_function, + Current_time@1 - Started_at, + Result} + ); + + {error, _} -> + Module_events@1 + end, + _pipe@5 = Events, + gleam@map:insert( + _pipe@5, + erlang:element(2, Module@2), + Updated_module_events + ); + + {error, _} -> + Events + end, + {Test_state, Num_done, New_events@2}; + + {end_test_suite, _} -> + {Test_state, Num_done + 1, Events}; + + {end_test_run, Num_modules} -> + {{finished, Num_modules}, Num_done, Events}; + + _ -> + {running, Num_done, Events} + end, + {handler_state, Updated_test_state, Updated_num_done, Updated_events}. diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@common@test_result.erl b/aoc2023/build/packages/adglent/src/showtime@internal@common@test_result.erl new file mode 100644 index 0000000..b7b73be --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@common@test_result.erl @@ -0,0 +1,54 @@ +-module(showtime@internal@common@test_result). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export_type([ignore_reason/0, test_return/0, exception/0, reason/0, reason_detail/0, gleam_error_detail/0, class/0, trace_list/0, trace/0, extra_info/0, arity_/0]). + +-type ignore_reason() :: ignore. + +-type test_return() :: {test_function_return, + gleam@dynamic:dynamic_(), + list(binary())} | + {ignored, ignore_reason()}. + +-type exception() :: {erlang_exception, + class(), + reason(), + trace_list(), + list(binary())}. + +-type reason() :: {assert_equal, list(reason_detail())} | + {assert_not_equal, list(reason_detail())} | + {assert_match, list(reason_detail())} | + {gleam_error, gleam_error_detail()} | + {gleam_assert, gleam@dynamic:dynamic_(), integer()} | + {generic_exception, gleam@dynamic:dynamic_()}. + +-type reason_detail() :: {module, binary()} | + {reason_line, integer()} | + {expression, binary()} | + {expected, gleam@dynamic:dynamic_()} | + {value, gleam@dynamic:dynamic_()} | + {pattern, binary()}. + +-type gleam_error_detail() :: {let_assert, + binary(), + binary(), + integer(), + binary(), + gleam@dynamic:dynamic_()}. + +-type class() :: erlang_error | exit | throw. + +-type trace_list() :: {trace_list, list(trace())}. + +-type trace() :: {trace, binary(), arity_(), list(extra_info())} | + {trace_module, binary(), binary(), arity_(), list(extra_info())}. + +-type extra_info() :: {error_info, + gleam@map:map_(gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_())} | + {file, binary()} | + {line, integer()}. + +-type arity_() :: {num, integer()} | {arg_list, list(gleam@dynamic:dynamic_())}. + + diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@common@test_suite.erl b/aoc2023/build/packages/adglent/src/showtime@internal@common@test_suite.erl new file mode 100644 index 0000000..6a56de8 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@common@test_suite.erl @@ -0,0 +1,30 @@ +-module(showtime@internal@common@test_suite). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export_type([test_run/0, test_module/0, test_function/0, test_suite/0, test_event/0]). + +-type test_run() :: {ongoing_test_run, test_function(), integer()} | + {completed_test_run, + test_function(), + integer(), + {ok, showtime@internal@common@test_result:test_return()} | + {error, showtime@internal@common@test_result:exception()}}. + +-type test_module() :: {test_module, binary(), gleam@option:option(binary())}. + +-type test_function() :: {test_function, binary()}. + +-type test_suite() :: {test_suite, test_module(), list(test_function())}. + +-type test_event() :: start_test_run | + {start_test_suite, test_module()} | + {start_test, test_module(), test_function()} | + {end_test, + test_module(), + test_function(), + {ok, showtime@internal@common@test_result:test_return()} | + {error, showtime@internal@common@test_result:exception()}} | + {end_test_suite, test_module()} | + {end_test_run, integer()}. + + diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@erlang@discover.erl b/aoc2023/build/packages/adglent/src/showtime@internal@erlang@discover.erl new file mode 100644 index 0000000..f0548aa --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@erlang@discover.erl @@ -0,0 +1,230 @@ +-module(showtime@internal@erlang@discover). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([collect_modules/2, collect_test_functions/1]). + +-spec get_module_prefix(binary()) -> binary(). +get_module_prefix(Path) -> + Path_without_test = begin + _pipe = Path, + gleam@string:replace(_pipe, <<"./test"/utf8>>, <<""/utf8>>) + end, + Path_without_leading_slash = case gleam@string:starts_with( + Path_without_test, + <<"/"/utf8>> + ) of + true -> + gleam@string:drop_left(Path_without_test, 1); + + false -> + Path_without_test + end, + Module_prefix = begin + _pipe@1 = Path_without_leading_slash, + gleam@string:replace(_pipe@1, <<"/"/utf8>>, <<"@"/utf8>>) + end, + case gleam@string:length(Module_prefix) of + 0 -> + Module_prefix; + + _ -> + <<Module_prefix/binary, "@"/utf8>> + end. + +-spec collect_modules_in_folder( + binary(), + fun((showtime@internal@common@test_suite:test_module()) -> nil), + gleam@option:option(list(binary())) +) -> list(showtime@internal@common@test_suite:test_module()). +collect_modules_in_folder(Path, Test_module_handler, Only_modules) -> + Module_prefix = get_module_prefix(Path), + _assert_subject = simplifile:read_directory(Path), + {ok, Files} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/internal/erlang/discover"/utf8>>, + function => <<"collect_modules_in_folder"/utf8>>, + line => 40}) + end, + Test_modules_in_folder = begin + _pipe = Files, + _pipe@1 = gleam@list:filter( + _pipe, + fun(_capture) -> + gleam@string:ends_with(_capture, <<"_test.gleam"/utf8>>) + end + ), + gleam@list:filter_map( + _pipe@1, + fun(Test_module_file) -> + Module_name = <<Module_prefix/binary, + (begin + _pipe@2 = Test_module_file, + gleam@string:replace( + _pipe@2, + <<".gleam"/utf8>>, + <<""/utf8>> + ) + end)/binary>>, + case Only_modules of + {some, Only_modules_list} -> + Module_in_list = begin + _pipe@3 = Only_modules_list, + gleam@list:any( + _pipe@3, + fun(Only_module_name) -> + Only_module_name =:= begin + _pipe@4 = Module_name, + gleam@string:replace( + _pipe@4, + <<"@"/utf8>>, + <<"/"/utf8>> + ) + end + end + ) + end, + case Module_in_list of + true -> + Test_module = {test_module, + Module_name, + {some, Test_module_file}}, + Test_module_handler(Test_module), + {ok, Test_module}; + + false -> + {error, nil} + end; + + none -> + Test_module@1 = {test_module, + Module_name, + {some, Test_module_file}}, + Test_module_handler(Test_module@1), + {ok, Test_module@1} + end + end + ) + end, + Test_modules_in_subfolders = begin + _pipe@5 = Files, + _pipe@6 = gleam@list:map( + _pipe@5, + fun(Filename) -> + <<<<Path/binary, "/"/utf8>>/binary, Filename/binary>> + end + ), + _pipe@7 = gleam@list:filter( + _pipe@6, + fun(File) -> simplifile:is_directory(File) end + ), + gleam@list:fold( + _pipe@7, + [], + fun(Modules, Subfolder) -> _pipe@8 = Modules, + gleam@list:append( + _pipe@8, + collect_modules_in_folder( + Subfolder, + Test_module_handler, + Only_modules + ) + ) end + ) + end, + _pipe@9 = Test_modules_in_folder, + gleam@list:append(_pipe@9, Test_modules_in_subfolders). + +-spec collect_modules( + fun((showtime@internal@common@test_suite:test_module()) -> nil), + gleam@option:option(list(binary())) +) -> list(showtime@internal@common@test_suite:test_module()). +collect_modules(Test_module_handler, Only_modules) -> + collect_modules_in_folder( + <<"./test"/utf8>>, + Test_module_handler, + Only_modules + ). + +-spec collect_test_functions(showtime@internal@common@test_suite:test_module()) -> showtime@internal@common@test_suite:test_suite(). +collect_test_functions(Module) -> + Test_functions = begin + _pipe = erlang:apply( + erlang:binary_to_atom(erlang:element(2, Module)), + erlang:binary_to_atom(<<"module_info"/utf8>>), + [gleam@dynamic:from(erlang:binary_to_atom(<<"exports"/utf8>>))] + ), + gleam@dynamic:unsafe_coerce(_pipe) + end, + Test_functions_filtered = begin + _pipe@1 = Test_functions, + _pipe@3 = gleam@list:map( + _pipe@1, + fun(Entry) -> + {Name, Arity} = case Entry of + {_, _} -> Entry; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/internal/erlang/discover"/utf8>>, + function => <<"collect_test_functions"/utf8>>, + line => 131}) + end, + {begin + _pipe@2 = Name, + erlang:atom_to_binary(_pipe@2) + end, + Arity} + end + ), + _pipe@4 = gleam@list:filter_map( + _pipe@3, + fun(Entry@1) -> + {Name@1, Arity@1} = case Entry@1 of + {_, _} -> Entry@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"showtime/internal/erlang/discover"/utf8>>, + function => <<"collect_test_functions"/utf8>>, + line => 139}) + end, + case gleam@string:ends_with(Name@1, <<"_test"/utf8>>) of + true -> + case Arity@1 of + 0 -> + {ok, Name@1}; + + _ -> + gleam@io:println( + <<<<<<<<"WARNING: function \""/utf8, + Name@1/binary>>/binary, + "\" has arity: "/utf8>>/binary, + (gleam@int:to_string(Arity@1))/binary>>/binary, + " - cannot be used as test (needs to be 0)"/utf8>> + ), + {error, <<"Wrong arity"/utf8>>} + end; + + false -> + {error, <<"Non matching name"/utf8>>} + end + end + ), + _pipe@5 = gleam@list:filter( + _pipe@4, + fun(_capture) -> + gleam@string:ends_with(_capture, <<"_test"/utf8>>) + end + ), + gleam@list:map( + _pipe@5, + fun(Function_name) -> {test_function, Function_name} end + ) + end, + {test_suite, Module, Test_functions_filtered}. diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@erlang@event_handler.erl b/aoc2023/build/packages/adglent/src/showtime@internal@erlang@event_handler.erl new file mode 100644 index 0000000..d72ce2c --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@erlang@event_handler.erl @@ -0,0 +1,76 @@ +-module(showtime@internal@erlang@event_handler). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([start/0]). +-export_type([event_handler_message/0]). + +-type event_handler_message() :: {event_handler_message, + showtime@internal@common@test_suite:test_event(), + gleam@erlang@process:subject(integer())}. + +-spec system_time() -> integer(). +system_time() -> + os:system_time(millisecond). + +-spec start() -> fun((showtime@internal@common@test_suite:test_event()) -> nil). +start() -> + _assert_subject = gleam@otp@actor:start( + {not_started, 0, gleam@map:new()}, + fun(Msg, State) -> + {event_handler_message, Test_event, Reply_to} = Msg, + {Test_state, Num_done, Events} = State, + Updated_state = showtime@internal@common@common_event_handler:handle_event( + Test_event, + fun system_time/0, + {handler_state, Test_state, Num_done, Events} + ), + case Updated_state of + {handler_state, {finished, Num_modules}, Num_done@1, Events@1} when Num_done@1 =:= Num_modules -> + {Test_report, Num_failed} = showtime@internal@reports@formatter:create_test_report( + Events@1 + ), + gleam@io:println(Test_report), + gleam@erlang@process:send(Reply_to, Num_failed), + {stop, normal}; + + {handler_state, Test_state@1, Num_done@2, Events@2} -> + {continue, {Test_state@1, Num_done@2, Events@2}, none} + end + end + ), + {ok, Subject} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/internal/erlang/event_handler"/utf8>>, + function => <<"start"/utf8>>, + line => 32}) + end, + Parent_subject = gleam@erlang@process:new_subject(), + Selector = begin + _pipe = gleam_erlang_ffi:new_selector(), + gleam@erlang@process:selecting(_pipe, Parent_subject, fun(X) -> X end) + end, + fun(Test_event@1) -> case Test_event@1 of + {end_test_run, _} -> + gleam@erlang@process:send( + Subject, + {event_handler_message, Test_event@1, Parent_subject} + ), + Num_failed@1 = gleam_erlang_ffi:select(Selector), + case Num_failed@1 > 0 of + true -> + erlang:halt(1); + + false -> + erlang:halt(0) + end; + + _ -> + gleam@erlang@process:send( + Subject, + {event_handler_message, Test_event@1, Parent_subject} + ) + end end. diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@erlang@module_handler.erl b/aoc2023/build/packages/adglent/src/showtime@internal@erlang@module_handler.erl new file mode 100644 index 0000000..a6959f5 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@erlang@module_handler.erl @@ -0,0 +1,53 @@ +-module(showtime@internal@erlang@module_handler). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([start/5]). + +-spec start( + fun((showtime@internal@common@test_suite:test_event()) -> nil), + fun((showtime@internal@common@test_suite:test_module()) -> showtime@internal@common@test_suite:test_suite()), + fun((showtime@internal@common@test_suite:test_suite(), fun((showtime@internal@common@test_suite:test_event()) -> nil), list(binary()), showtime@internal@common@cli:capture()) -> nil), + list(binary()), + showtime@internal@common@cli:capture() +) -> fun((showtime@internal@common@test_suite:test_module()) -> nil). +start( + Test_event_handler, + Test_function_collector, + Run_test_suite, + Ignore_tags, + Capture +) -> + _assert_subject = gleam@otp@actor:start( + nil, + fun(Module, State) -> + gleam@erlang@process:start( + fun() -> + Test_suite = Test_function_collector(Module), + Test_event_handler({start_test_suite, Module}), + Run_test_suite( + Test_suite, + Test_event_handler, + Ignore_tags, + Capture + ), + Test_event_handler({end_test_suite, Module}) + end, + false + ), + {continue, State, none} + end + ), + {ok, Subject} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/internal/erlang/module_handler"/utf8>>, + function => <<"start"/utf8>>, + line => 23}) + end, + fun(Test_module) -> + gleam@erlang@process:send(Subject, Test_module), + nil + end. diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@erlang@runner.erl b/aoc2023/build/packages/adglent/src/showtime@internal@erlang@runner.erl new file mode 100644 index 0000000..702fb75 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@erlang@runner.erl @@ -0,0 +1,46 @@ +-module(showtime@internal@erlang@runner). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([run_test/4, run_test_suite/4]). + +-spec run_test( + binary(), + binary(), + list(binary()), + showtime@internal@common@cli:capture() +) -> {ok, showtime@internal@common@test_result:test_return()} | + {error, showtime@internal@common@test_result:exception()}. +run_test(Module_name, Test_name, Ignore_tags, Capture) -> + Result = showtime_ffi:run_test( + erlang:binary_to_atom(Module_name), + erlang:binary_to_atom(Test_name), + Ignore_tags, + Capture + ), + Result. + +-spec run_test_suite( + showtime@internal@common@test_suite:test_suite(), + fun((showtime@internal@common@test_suite:test_event()) -> nil), + list(binary()), + showtime@internal@common@cli:capture() +) -> nil. +run_test_suite(Test_suite, Test_event_handler, Ignore_tags, Capture) -> + _pipe = erlang:element(3, Test_suite), + gleam@list:each( + _pipe, + fun(Test) -> + Test_event_handler( + {start_test, erlang:element(2, Test_suite), Test} + ), + Result = run_test( + erlang:element(2, erlang:element(2, Test_suite)), + erlang:element(2, Test), + Ignore_tags, + Capture + ), + Test_event_handler( + {end_test, erlang:element(2, Test_suite), Test, Result} + ) + end + ). diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@reports@compare.erl b/aoc2023/build/packages/adglent/src/showtime@internal@reports@compare.erl new file mode 100644 index 0000000..d2969b2 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@reports@compare.erl @@ -0,0 +1,61 @@ +-module(showtime@internal@reports@compare). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([compare/2]). + +-spec compare(gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> {binary(), + binary()}. +compare(Expected, Got) -> + Expected_as_list = begin + _pipe = Expected, + (gleam@dynamic:list(fun gleam@dynamic:dynamic/1))(_pipe) + end, + Got_as_list = begin + _pipe@1 = Got, + (gleam@dynamic:list(fun gleam@dynamic:dynamic/1))(_pipe@1) + end, + Expected_as_string = begin + _pipe@2 = Expected, + gleam@dynamic:string(_pipe@2) + end, + Got_as_string = begin + _pipe@3 = Got, + gleam@dynamic:string(_pipe@3) + end, + case {Expected_as_list, Got_as_list, Expected_as_string, Got_as_string} of + {{ok, Expected_list}, {ok, Got_list}, _, _} -> + Comparison = begin + _pipe@4 = gap:compare_lists(Expected_list, Got_list), + _pipe@5 = gap@styling:from_comparison(_pipe@4), + _pipe@6 = gap@styling:highlight( + _pipe@5, + fun showtime@internal@reports@styles:expected_highlight/1, + fun showtime@internal@reports@styles:got_highlight/1, + fun(Item) -> Item end + ), + gap@styling:to_styled_comparison(_pipe@6) + end, + {erlang:element(2, Comparison), erlang:element(3, Comparison)}; + + {_, _, {ok, Expected_string}, {ok, Got_string}} -> + Comparison@1 = begin + _pipe@7 = gap:compare_strings(Expected_string, Got_string), + _pipe@8 = gap@styling:from_comparison(_pipe@7), + _pipe@9 = gap@styling:highlight( + _pipe@8, + fun showtime@internal@reports@styles:expected_highlight/1, + fun showtime@internal@reports@styles:got_highlight/1, + fun(Item@1) -> Item@1 end + ), + gap@styling:to_styled_comparison(_pipe@9) + end, + {erlang:element(2, Comparison@1), erlang:element(3, Comparison@1)}; + + {_, _, _, _} -> + {showtime@internal@reports@styles:expected_highlight( + gleam@string:inspect(Expected) + ), + showtime@internal@reports@styles:got_highlight( + gleam@string:inspect(Got) + )} + end. diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@reports@formatter.erl b/aoc2023/build/packages/adglent/src/showtime@internal@reports@formatter.erl new file mode 100644 index 0000000..faea091 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@reports@formatter.erl @@ -0,0 +1,749 @@ +-module(showtime@internal@reports@formatter). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([create_test_report/1]). +-export_type([glee_unit_assertion_type/0, module_and_test/0, unified_error/0]). + +-type glee_unit_assertion_type() :: {glee_unit_assert_equal, binary()} | + {glee_unit_assert_not_equal, binary()} | + {glee_unit_assert_match, binary()}. + +-type module_and_test() :: {module_and_test_run, + binary(), + showtime@internal@common@test_suite:test_run()}. + +-type unified_error() :: {unified_error, + gleam@option:option(showtime@tests@meta:meta()), + binary(), + binary(), + binary(), + binary(), + gleam@option:option(integer()), + list(showtime@internal@common@test_result:trace())}. + +-spec erlang_error_to_unified( + list(showtime@internal@common@test_result:reason_detail()), + glee_unit_assertion_type(), + list(showtime@internal@common@test_result:trace()) +) -> unified_error(). +erlang_error_to_unified(Error_details, Assertion_type, Stacktrace) -> + _pipe = Error_details, + gleam@list:fold( + _pipe, + {unified_error, + none, + <<"not_set"/utf8>>, + erlang:element(2, Assertion_type), + <<""/utf8>>, + <<""/utf8>>, + none, + Stacktrace}, + fun(Unified, Reason) -> case Reason of + {expression, Expression} -> + erlang:setelement(3, Unified, Expression); + + {expected, Value} -> + case Assertion_type of + {glee_unit_assert_equal, _} -> + erlang:setelement( + 5, + Unified, + showtime@internal@reports@styles:expected_highlight( + gleam@string:inspect(Value) + ) + ); + + _ -> + Unified + end; + + {value, Value@1} -> + case Assertion_type of + {glee_unit_assert_not_equal, _} -> + erlang:setelement( + 6, + erlang:setelement( + 5, + Unified, + <<(showtime@internal@reports@styles:not_style( + <<"not "/utf8>> + ))/binary, + (gleam@string:inspect(Value@1))/binary>> + ), + showtime@internal@reports@styles:got_highlight( + gleam@string:inspect(Value@1) + ) + ); + + _ -> + erlang:setelement( + 6, + Unified, + showtime@internal@reports@styles:got_highlight( + gleam@string:inspect(Value@1) + ) + ) + end; + + {pattern, Pattern} -> + case Pattern of + <<"{ ok , _ }"/utf8>> -> + erlang:setelement( + 5, + Unified, + showtime@internal@reports@styles:expected_highlight( + <<"Ok(_)"/utf8>> + ) + ); + + <<"{ error , _ }"/utf8>> -> + erlang:setelement( + 5, + Unified, + showtime@internal@reports@styles:expected_highlight( + <<"Error(_)"/utf8>> + ) + ); + + _ -> + Unified + end; + + _ -> + Unified + end end + ). + +-spec gleam_error_to_unified( + showtime@internal@common@test_result:gleam_error_detail(), + list(showtime@internal@common@test_result:trace()) +) -> unified_error(). +gleam_error_to_unified(Gleam_error, Stacktrace) -> + case Gleam_error of + {let_assert, _, _, _, _, Value} -> + Result = gleam@dynamic:unsafe_coerce(Value), + {error, Assertion} = case Result of + {error, _} -> Result; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/internal/reports/formatter"/utf8>>, + function => <<"gleam_error_to_unified"/utf8>>, + line => 293}) + end, + case Assertion of + {eq, Got, Expected, Meta} -> + {Expected@1, Got@1} = showtime@internal@reports@compare:compare( + Expected, + Got + ), + {unified_error, + Meta, + <<"assert"/utf8>>, + <<"Assert equal"/utf8>>, + Expected@1, + Got@1, + none, + Stacktrace}; + + {not_eq, Got@2, Expected@2, Meta@1} -> + {unified_error, + Meta@1, + <<"assert"/utf8>>, + <<"Assert not equal"/utf8>>, + <<(showtime@internal@reports@styles:not_style( + <<"not "/utf8>> + ))/binary, + (gleam@string:inspect(Expected@2))/binary>>, + gleam@string:inspect(Got@2), + none, + Stacktrace}; + + {is_ok, Got@3, Meta@2} -> + {unified_error, + Meta@2, + <<"assert"/utf8>>, + <<"Assert is Ok"/utf8>>, + showtime@internal@reports@styles:expected_highlight( + <<"Ok(_)"/utf8>> + ), + showtime@internal@reports@styles:got_highlight( + gleam@string:inspect(Got@3) + ), + none, + Stacktrace}; + + {is_error, Got@4, Meta@3} -> + {unified_error, + Meta@3, + <<"assert"/utf8>>, + <<"Assert is Ok"/utf8>>, + showtime@internal@reports@styles:expected_highlight( + <<"Error(_)"/utf8>> + ), + showtime@internal@reports@styles:got_highlight( + gleam@string:inspect(Got@4) + ), + none, + Stacktrace}; + + {fail, Meta@4} -> + {unified_error, + Meta@4, + <<"assert"/utf8>>, + <<"Assert is Ok"/utf8>>, + showtime@internal@reports@styles:got_highlight( + <<"should.fail()"/utf8>> + ), + showtime@internal@reports@styles:got_highlight( + <<"N/A - test always expected to fail"/utf8>> + ), + none, + Stacktrace} + end + end. + +-spec format_reason(unified_error(), binary(), binary(), list(binary())) -> list(list(showtime@internal@reports@table:col())). +format_reason(Error, Module, Function, Output_buffer) -> + Meta@1 = case erlang:element(2, Error) of + {some, Meta} -> + {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Description"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left, {content, erlang:element(2, Meta)}, 0}]}; + + none -> + none + end, + Stacktrace = begin + _pipe = erlang:element(8, Error), + gleam@list:map(_pipe, fun(Trace) -> case Trace of + {trace, Function@1, _, _} when Function@1 =:= <<""/utf8>> -> + <<"(anonymous)"/utf8>>; + + {trace_module, Module@1, Function@2, _, _} when Function@2 =:= <<""/utf8>> -> + <<<<Module@1/binary, "."/utf8>>/binary, + "(anonymous)"/utf8>>; + + {trace, Function@3, _, _} -> + Function@3; + + {trace_module, Module@2, Function@4, _, _} -> + <<<<Module@2/binary, "."/utf8>>/binary, + Function@4/binary>> + end end) + end, + Stacktrace_rows = case Stacktrace of + [] -> + []; + + [First | Rest] -> + First_row = {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Stacktrace"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left, + {styled_content, + showtime@internal@reports@styles:stacktrace_style( + First + )}, + 0}]}, + Rest_rows = begin + _pipe@1 = Rest, + gleam@list:map( + _pipe@1, + fun(Row) -> + {some, + [{align_right, {content, <<""/utf8>>}, 2}, + {separator, <<" "/utf8>>}, + {align_left, + {styled_content, + showtime@internal@reports@styles:stacktrace_style( + Row + )}, + 0}]} + end + ) + end, + [First_row | Rest_rows] + end, + Output_rows = case begin + _pipe@2 = Output_buffer, + _pipe@3 = gleam@list:reverse(_pipe@2), + gleam@list:map( + _pipe@3, + fun(Row@1) -> gleam@string:trim_right(Row@1) end + ) + end of + [] -> + []; + + [First@1 | Rest@1] -> + First_row@1 = {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Output"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left_overflow, + {styled_content, + showtime@internal@reports@styles:stacktrace_style( + First@1 + )}, + 0}]}, + Rest_rows@1 = begin + _pipe@4 = Rest@1, + gleam@list:map( + _pipe@4, + fun(Row@2) -> + {some, + [{align_right, {content, <<""/utf8>>}, 2}, + {separator, <<" "/utf8>>}, + {align_left_overflow, + {styled_content, + showtime@internal@reports@styles:stacktrace_style( + Row@2 + )}, + 0}]} + end + ) + end, + [First_row@1 | Rest_rows@1] + end, + Line@1 = begin + _pipe@5 = erlang:element(7, Error), + _pipe@6 = gleam@option:map( + _pipe@5, + fun(Line) -> <<":"/utf8, (gleam@int:to_string(Line))/binary>> end + ), + gleam@option:unwrap(_pipe@6, <<""/utf8>>) + end, + Arrow = <<(gleam@string:join( + gleam@list:repeat( + <<"-"/utf8>>, + (gleam@string:length(Module) + 1) + ((gleam@string:length( + Function + ) + + gleam@string:length(Line@1)) + div 2) + ), + <<""/utf8>> + ))/binary, + "⌄"/utf8>>, + Standard_table_rows = [{some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:error_style( + <<"Failed"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left, {content, Arrow}, 0}]}, + {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Test"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left, + {styled_content, + <<<<Module/binary, "."/utf8>>/binary, + (showtime@internal@reports@styles:function_style( + <<Function/binary, Line@1/binary>> + ))/binary>>}, + 0}]}, + Meta@1, + {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Expected"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left_overflow, + {styled_content, erlang:element(5, Error)}, + 0}]}, + {some, + [{align_right, + {styled_content, + showtime@internal@reports@styles:heading_style( + <<"Got"/utf8>> + )}, + 2}, + {separator, <<": "/utf8>>}, + {align_left_overflow, + {styled_content, erlang:element(6, Error)}, + 0}]}], + _pipe@7 = Standard_table_rows, + _pipe@8 = gleam@list:append(_pipe@7, Stacktrace_rows), + _pipe@9 = gleam@list:append(_pipe@8, Output_rows), + _pipe@10 = gleam@list:append( + _pipe@9, + [{some, + [{align_right, {content, <<""/utf8>>}, 0}, + {align_right, {content, <<""/utf8>>}, 0}, + {align_right, {content, <<""/utf8>>}, 0}]}] + ), + gleam@list:filter_map( + _pipe@10, + fun(Row@3) -> gleam@option:to_result(Row@3, nil) end + ). + +-spec create_test_report( + gleam@map:map_(binary(), gleam@map:map_(binary(), showtime@internal@common@test_suite:test_run())) +) -> {binary(), integer()}. +create_test_report(Test_results) -> + All_test_runs = begin + _pipe = Test_results, + _pipe@1 = gleam@map:values(_pipe), + gleam@list:flat_map(_pipe@1, fun gleam@map:values/1) + end, + Failed_test_runs = begin + _pipe@2 = Test_results, + _pipe@3 = gleam@map:to_list(_pipe@2), + gleam@list:flat_map( + _pipe@3, + fun(Entry) -> + {Module_name, Test_module_results} = Entry, + _pipe@4 = Test_module_results, + _pipe@5 = gleam@map:values(_pipe@4), + gleam@list:filter_map(_pipe@5, fun(Test_run) -> case Test_run of + {completed_test_run, _, _, Result} -> + case Result of + {error, _} -> + {ok, + {module_and_test_run, + Module_name, + Test_run}}; + + {ok, {ignored, _}} -> + {error, nil}; + + {ok, _} -> + {error, nil} + end; + + _ -> + _pipe@6 = Test_run, + gleam@io:debug(_pipe@6), + {error, nil} + end end) + end + ) + end, + Ignored_test_runs = begin + _pipe@7 = Test_results, + _pipe@8 = gleam@map:to_list(_pipe@7), + gleam@list:flat_map( + _pipe@8, + fun(Entry@1) -> + {Module_name@1, Test_module_results@1} = Entry@1, + _pipe@9 = Test_module_results@1, + _pipe@10 = gleam@map:values(_pipe@9), + gleam@list:filter_map( + _pipe@10, + fun(Test_run@1) -> case Test_run@1 of + {completed_test_run, Test_function, _, Result@1} -> + case Result@1 of + {ok, {ignored, Reason}} -> + {ok, + {<<<<Module_name@1/binary, + "."/utf8>>/binary, + (erlang:element( + 2, + Test_function + ))/binary>>, + Reason}}; + + _ -> + {error, nil} + end; + + _ -> + {error, nil} + end end + ) + end + ) + end, + Failed_tests_report = begin + _pipe@11 = Failed_test_runs, + _pipe@12 = gleam@list:filter_map( + _pipe@11, + fun(Module_and_test_run) -> + case erlang:element(3, Module_and_test_run) of + {completed_test_run, Test_function@1, _, Result@2} -> + case Result@2 of + {error, Exception} -> + case erlang:element(3, Exception) of + {assert_equal, Reason_details} -> + {ok, + format_reason( + erlang_error_to_unified( + Reason_details, + {glee_unit_assert_equal, + <<"Assert equal"/utf8>>}, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + ) + ), + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + {assert_not_equal, Reason_details@1} -> + {ok, + format_reason( + erlang_error_to_unified( + Reason_details@1, + {glee_unit_assert_not_equal, + <<"Assert not equal"/utf8>>}, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + ) + ), + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + {assert_match, Reason_details@2} -> + {ok, + format_reason( + erlang_error_to_unified( + Reason_details@2, + {glee_unit_assert_match, + <<"Assert match"/utf8>>}, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + ) + ), + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + {gleam_error, Reason@1} -> + {ok, + format_reason( + gleam_error_to_unified( + Reason@1, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + ) + ), + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + {gleam_assert, Value, Line_no} -> + {ok, + format_reason( + {unified_error, + none, + <<"gleam assert"/utf8>>, + <<"Assert failed"/utf8>>, + <<"Patterns should match"/utf8>>, + showtime@internal@reports@styles:error_style( + gleam@string:inspect( + Value + ) + ), + {some, Line_no}, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + )}, + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + {generic_exception, Value@1} -> + {ok, + format_reason( + {unified_error, + none, + <<"generic exception"/utf8>>, + <<"Test function threw an exception"/utf8>>, + <<"Exception in test function"/utf8>>, + showtime@internal@reports@styles:error_style( + gleam@string:inspect( + Value@1 + ) + ), + none, + erlang:element( + 2, + erlang:element( + 4, + Exception + ) + )}, + erlang:element( + 2, + Module_and_test_run + ), + erlang:element( + 2, + Test_function@1 + ), + erlang:element(5, Exception) + )}; + + Other -> + gleam@io:println( + <<"Other: "/utf8, + (gleam@string:inspect(Other))/binary>> + ), + erlang:error(#{gleam_error => panic, + message => <<"panic expression evaluated"/utf8>>, + module => <<"showtime/internal/reports/formatter"/utf8>>, + function => <<"create_test_report"/utf8>>, + line => 178}), + {error, nil} + end; + + _ -> + {error, nil} + end; + + _ -> + {error, nil} + end + end + ), + gleam@list:fold( + _pipe@12, + [], + fun(Rows, Test_rows) -> gleam@list:append(Rows, Test_rows) end + ) + end, + All_test_execution_time_reports = begin + _pipe@13 = All_test_runs, + gleam@list:filter_map(_pipe@13, fun(Test_run@2) -> case Test_run@2 of + {completed_test_run, Test_function@2, Total_time, _} -> + {ok, + <<<<<<(erlang:element(2, Test_function@2))/binary, + ": "/utf8>>/binary, + (gleam@int:to_string(Total_time))/binary>>/binary, + " ms"/utf8>>}; + + _ -> + {error, nil} + end end) + end, + _ = begin + _pipe@14 = All_test_execution_time_reports, + gleam@string:join(_pipe@14, <<"\n"/utf8>>) + end, + All_tests_count = begin + _pipe@15 = All_test_runs, + gleam@list:length(_pipe@15) + end, + Ignored_tests_count = begin + _pipe@16 = Ignored_test_runs, + gleam@list:length(_pipe@16) + end, + Failed_tests_count = begin + _pipe@17 = Failed_test_runs, + gleam@list:length(_pipe@17) + end, + Passed = showtime@internal@reports@styles:passed_style( + <<(gleam@int:to_string( + (All_tests_count - Failed_tests_count) - Ignored_tests_count + ))/binary, + " passed"/utf8>> + ), + Failed = showtime@internal@reports@styles:failed_style( + <<(gleam@int:to_string(Failed_tests_count))/binary, " failed"/utf8>> + ), + Ignored = case Ignored_tests_count of + 0 -> + <<""/utf8>>; + + _ -> + <<", "/utf8, + (showtime@internal@reports@styles:ignored_style( + <<(gleam@int:to_string(Ignored_tests_count))/binary, + " ignored"/utf8>> + ))/binary>> + end, + Failed_tests_table = begin + _pipe@18 = {table, none, Failed_tests_report}, + _pipe@19 = showtime@internal@reports@table:align_table(_pipe@18), + showtime@internal@reports@table:to_string(_pipe@19) + end, + Test_report = <<<<<<<<<<<<"\n"/utf8, Failed_tests_table/binary>>/binary, + "\n"/utf8>>/binary, + Passed/binary>>/binary, + ", "/utf8>>/binary, + Failed/binary>>/binary, + Ignored/binary>>, + {Test_report, Failed_tests_count}. diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@reports@styles.erl b/aoc2023/build/packages/adglent/src/showtime@internal@reports@styles.erl new file mode 100644 index 0000000..ec6230c --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@reports@styles.erl @@ -0,0 +1,93 @@ +-module(showtime@internal@reports@styles). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([not_style/1, module_style/1, heading_style/1, stacktrace_style/1, failed_style/1, error_style/1, got_highlight/1, passed_style/1, expected_highlight/1, ignored_style/1, function_style/1, strip_style/1]). + +-spec not_style(binary()) -> binary(). +not_style(Text) -> + gleam_community@ansi:bold(Text). + +-spec module_style(binary()) -> binary(). +module_style(Text) -> + gleam_community@ansi:cyan(Text). + +-spec heading_style(binary()) -> binary(). +heading_style(Text) -> + gleam_community@ansi:cyan(Text). + +-spec stacktrace_style(binary()) -> binary(). +stacktrace_style(Text) -> + Text. + +-spec bold_red(binary()) -> binary(). +bold_red(Text) -> + gleam_community@ansi:bold(gleam_community@ansi:red(Text)). + +-spec failed_style(binary()) -> binary(). +failed_style(Text) -> + bold_red(Text). + +-spec error_style(binary()) -> binary(). +error_style(Text) -> + bold_red(Text). + +-spec got_highlight(binary()) -> binary(). +got_highlight(Text) -> + bold_red(Text). + +-spec bold_green(binary()) -> binary(). +bold_green(Text) -> + gleam_community@ansi:bold(gleam_community@ansi:green(Text)). + +-spec passed_style(binary()) -> binary(). +passed_style(Text) -> + bold_green(Text). + +-spec expected_highlight(binary()) -> binary(). +expected_highlight(Text) -> + bold_green(Text). + +-spec bold_yellow(binary()) -> binary(). +bold_yellow(Text) -> + gleam_community@ansi:bold(gleam_community@ansi:yellow(Text)). + +-spec ignored_style(binary()) -> binary(). +ignored_style(Text) -> + bold_yellow(Text). + +-spec bold_cyan(binary()) -> binary(). +bold_cyan(Text) -> + gleam_community@ansi:bold(gleam_community@ansi:cyan(Text)). + +-spec function_style(binary()) -> binary(). +function_style(Text) -> + bold_cyan(Text). + +-spec strip_style(binary()) -> binary(). +strip_style(Text) -> + {New_text, _} = begin + _pipe = Text, + _pipe@1 = gleam@string:to_graphemes(_pipe), + gleam@list:fold( + _pipe@1, + {<<""/utf8>>, false}, + fun(Acc, Char) -> + {Str, Removing} = Acc, + Bit_char = gleam_stdlib:identity(Char), + case {Bit_char, Removing} of + {<<16#1b>>, _} -> + {Str, true}; + + {<<16#6d>>, true} -> + {Str, false}; + + {_, true} -> + {Str, true}; + + {_, false} -> + {<<Str/binary, Char/binary>>, false} + end + end + ) + end, + New_text. diff --git a/aoc2023/build/packages/adglent/src/showtime@internal@reports@table.erl b/aoc2023/build/packages/adglent/src/showtime@internal@reports@table.erl new file mode 100644 index 0000000..35dbba3 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@internal@reports@table.erl @@ -0,0 +1,229 @@ +-module(showtime@internal@reports@table). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([to_string/1, align_table/1]). +-export_type([content/0, col/0, table/0]). + +-type content() :: {content, binary()} | {styled_content, binary()}. + +-type col() :: {align_right, content(), integer()} | + {align_left, content(), integer()} | + {align_right_overflow, content(), integer()} | + {align_left_overflow, content(), integer()} | + {separator, binary()} | + {aligned, binary()}. + +-type table() :: {table, gleam@option:option(binary()), list(list(col()))}. + +-spec to_string(table()) -> binary(). +to_string(Table) -> + Rows = begin + _pipe = erlang:element(3, Table), + _pipe@3 = gleam@list:map(_pipe, fun(Row) -> _pipe@1 = Row, + _pipe@2 = gleam@list:filter_map(_pipe@1, fun(Col) -> case Col of + {separator, Char} -> + {ok, Char}; + + {aligned, Content} -> + {ok, Content}; + + _ -> + {error, nil} + end end), + gleam@string:join(_pipe@2, <<""/utf8>>) end), + gleam@string:join(_pipe@3, <<"\n"/utf8>>) + end, + Header@1 = begin + _pipe@4 = erlang:element(2, Table), + _pipe@5 = gleam@option:map( + _pipe@4, + fun(Header) -> <<Header/binary, "\n"/utf8>> end + ), + gleam@option:unwrap(_pipe@5, <<""/utf8>>) + end, + <<Header@1/binary, Rows/binary>>. + +-spec pad_left(binary(), integer(), binary()) -> binary(). +pad_left(Str, Num, Char) -> + Padding = begin + _pipe = gleam@list:repeat(Char, Num), + gleam@string:join(_pipe, <<""/utf8>>) + end, + <<Padding/binary, Str/binary>>. + +-spec pad_right(binary(), integer(), binary()) -> binary(). +pad_right(Str, Num, Char) -> + Padding = begin + _pipe = gleam@list:repeat(Char, Num), + gleam@string:join(_pipe, <<""/utf8>>) + end, + <<Str/binary, Padding/binary>>. + +-spec align_table(table()) -> table(). +align_table(Table) -> + Cols = begin + _pipe = erlang:element(3, Table), + gleam@list:transpose(_pipe) + end, + Col_width = begin + _pipe@1 = Cols, + gleam@list:map(_pipe@1, fun(Col) -> _pipe@2 = Col, + _pipe@3 = gleam@list:map( + _pipe@2, + fun(Content) -> case Content of + {align_right, {content, Unstyled}, _} -> + Unstyled; + + {align_right, {styled_content, Styled}, _} -> + showtime@internal@reports@styles:strip_style( + Styled + ); + + {align_left, {content, Unstyled@1}, _} -> + Unstyled@1; + + {align_left, {styled_content, Styled@1}, _} -> + showtime@internal@reports@styles:strip_style( + Styled@1 + ); + + {align_left_overflow, _, _} -> + <<""/utf8>>; + + {align_right_overflow, _, _} -> + <<""/utf8>>; + + {separator, Char} -> + Char; + + {aligned, Content@1} -> + Content@1 + end end + ), + gleam@list:fold( + _pipe@3, + 0, + fun(Max, Str) -> + gleam@int:max(Max, gleam@string:length(Str)) + end + ) end) + end, + Aligned_col = begin + _pipe@4 = Cols, + _pipe@5 = gleam@list:zip(_pipe@4, Col_width), + gleam@list:map( + _pipe@5, + fun(Col_and_width) -> + {Col@1, Width} = Col_and_width, + _pipe@6 = Col@1, + gleam@list:map(_pipe@6, fun(Content@2) -> case Content@2 of + {align_right, {content, Unstyled@2}, Margin} -> + {aligned, + pad_left( + Unstyled@2, + (Width + Margin) - gleam@string:length( + Unstyled@2 + ), + <<" "/utf8>> + )}; + + {align_right, {styled_content, Styled@2}, Margin@1} -> + {aligned, + pad_left( + Styled@2, + (Width + Margin@1) - gleam@string:length( + showtime@internal@reports@styles:strip_style( + Styled@2 + ) + ), + <<" "/utf8>> + )}; + + {align_right_overflow, + {content, Unstyled@3}, + Margin@2} -> + {aligned, + pad_left( + Unstyled@3, + (Width + Margin@2) - gleam@string:length( + Unstyled@3 + ), + <<" "/utf8>> + )}; + + {align_right_overflow, + {styled_content, Styled@3}, + Margin@3} -> + {aligned, + pad_left( + Styled@3, + (Width + Margin@3) - gleam@string:length( + showtime@internal@reports@styles:strip_style( + Styled@3 + ) + ), + <<" "/utf8>> + )}; + + {align_left, {content, Unstyled@4}, Margin@4} -> + {aligned, + pad_right( + Unstyled@4, + (Width + Margin@4) - gleam@string:length( + Unstyled@4 + ), + <<" "/utf8>> + )}; + + {align_left, {styled_content, Styled@4}, Margin@5} -> + {aligned, + pad_right( + Styled@4, + (Width + Margin@5) - gleam@string:length( + showtime@internal@reports@styles:strip_style( + Styled@4 + ) + ), + <<" "/utf8>> + )}; + + {align_left_overflow, + {content, Unstyled@5}, + Margin@6} -> + {aligned, + pad_right( + Unstyled@5, + (Width + Margin@6) - gleam@string:length( + Unstyled@5 + ), + <<" "/utf8>> + )}; + + {align_left_overflow, + {styled_content, Styled@5}, + Margin@7} -> + {aligned, + pad_right( + Styled@5, + (Width + Margin@7) - gleam@string:length( + showtime@internal@reports@styles:strip_style( + Styled@5 + ) + ), + <<" "/utf8>> + )}; + + {separator, Char@1} -> + {separator, Char@1}; + + {aligned, Content@3} -> + {aligned, Content@3} + end end) + end + ) + end, + Aligned_rows = begin + _pipe@7 = Aligned_col, + gleam@list:transpose(_pipe@7) + end, + erlang:setelement(3, Table, Aligned_rows). diff --git a/aoc2023/build/packages/adglent/src/showtime@tests@meta.erl b/aoc2023/build/packages/adglent/src/showtime@tests@meta.erl new file mode 100644 index 0000000..c975467 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@tests@meta.erl @@ -0,0 +1,8 @@ +-module(showtime@tests@meta). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export_type([meta/0]). + +-type meta() :: {meta, binary(), list(binary())}. + + diff --git a/aoc2023/build/packages/adglent/src/showtime@tests@should.erl b/aoc2023/build/packages/adglent/src/showtime@tests@should.erl new file mode 100644 index 0000000..29906b4 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@tests@should.erl @@ -0,0 +1,143 @@ +-module(showtime@tests@should). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([evaluate/1, equal/2, equal_meta/3, not_equal/2, not_equal_meta/3, be_ok/1, be_ok_meta/2, be_error/1, be_error_meta/2, fail/0, fail_meta/1, be_true/1, be_true_meta/2, be_false/1, be_false_meta/2]). +-export_type([assertion/2]). + +-type assertion(MXP, MXQ) :: {eq, + MXP, + MXP, + gleam@option:option(showtime@tests@meta:meta())} | + {not_eq, MXP, MXP, gleam@option:option(showtime@tests@meta:meta())} | + {is_ok, + {ok, MXP} | {error, MXQ}, + gleam@option:option(showtime@tests@meta:meta())} | + {is_error, + {ok, MXP} | {error, MXQ}, + gleam@option:option(showtime@tests@meta:meta())} | + {fail, gleam@option:option(showtime@tests@meta:meta())}. + +-spec evaluate(assertion(any(), any())) -> nil. +evaluate(Assertion) -> + case Assertion of + {eq, A, B, _} -> + case A =:= B of + true -> + nil; + + false -> + showtime_ffi:gleam_error({error, Assertion}) + end; + + {not_eq, A@1, B@1, _} -> + case A@1 /= B@1 of + true -> + nil; + + false -> + showtime_ffi:gleam_error({error, Assertion}) + end; + + {is_ok, A@2, _} -> + case A@2 of + {ok, _} -> + nil; + + {error, _} -> + showtime_ffi:gleam_error({error, Assertion}) + end; + + {is_error, A@3, _} -> + case A@3 of + {error, _} -> + nil; + + {ok, _} -> + showtime_ffi:gleam_error({error, Assertion}) + end; + + {fail, _} -> + showtime_ffi:gleam_error({error, Assertion}) + end. + +-spec equal(MXR, MXR) -> nil. +equal(A, B) -> + evaluate({eq, A, B, none}). + +-spec equal_meta(MXT, MXT, showtime@tests@meta:meta()) -> nil. +equal_meta(A, B, Meta) -> + evaluate({eq, A, B, {some, Meta}}). + +-spec not_equal(MXV, MXV) -> nil. +not_equal(A, B) -> + evaluate({not_eq, A, B, none}). + +-spec not_equal_meta(MXX, MXX, showtime@tests@meta:meta()) -> nil. +not_equal_meta(A, B, Meta) -> + evaluate({not_eq, A, B, {some, Meta}}). + +-spec be_ok({ok, MXZ} | {error, any()}) -> MXZ. +be_ok(A) -> + evaluate({is_ok, A, none}), + {ok, Value} = case A of + {ok, _} -> A; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/tests/should"/utf8>>, + function => <<"be_ok"/utf8>>, + line => 30}) + end, + Value. + +-spec be_ok_meta({ok, any()} | {error, any()}, showtime@tests@meta:meta()) -> nil. +be_ok_meta(A, Meta) -> + evaluate({is_ok, A, {some, Meta}}). + +-spec be_error({ok, any()} | {error, MYK}) -> MYK. +be_error(A) -> + evaluate({is_error, A, none}), + {error, Value} = case A of + {error, _} -> A; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"showtime/tests/should"/utf8>>, + function => <<"be_error"/utf8>>, + line => 40}) + end, + Value. + +-spec be_error_meta({ok, any()} | {error, any()}, showtime@tests@meta:meta()) -> nil. +be_error_meta(A, Meta) -> + evaluate({is_error, A, {some, Meta}}). + +-spec fail() -> nil. +fail() -> + evaluate({fail, none}). + +-spec fail_meta(showtime@tests@meta:meta()) -> nil. +fail_meta(Meta) -> + evaluate({fail, {some, Meta}}). + +-spec be_true(boolean()) -> nil. +be_true(A) -> + _pipe = A, + equal(_pipe, true). + +-spec be_true_meta(boolean(), showtime@tests@meta:meta()) -> nil. +be_true_meta(A, Meta) -> + _pipe = A, + equal_meta(_pipe, true, Meta). + +-spec be_false(boolean()) -> nil. +be_false(A) -> + _pipe = A, + equal(_pipe, false). + +-spec be_false_meta(boolean(), showtime@tests@meta:meta()) -> nil. +be_false_meta(A, Meta) -> + _pipe = A, + equal_meta(_pipe, false, Meta). diff --git a/aoc2023/build/packages/adglent/src/showtime@tests@test.erl b/aoc2023/build/packages/adglent/src/showtime@tests@test.erl new file mode 100644 index 0000000..2f23b9f --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime@tests@test.erl @@ -0,0 +1,57 @@ +-module(showtime@tests@test). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([test/2, equal/3, not_equal/3, with_meta/2, be_ok/2, be_error/2, fail/1, be_true/2, be_false/2]). +-export_type([test/0, meta_should/1]). + +-type test() :: {test, showtime@tests@meta:meta(), fun(() -> nil)}. + +-type meta_should(NDO) :: {meta_should, + fun((NDO, NDO) -> nil), + fun((NDO, NDO) -> nil)}. + +-spec test(showtime@tests@meta:meta(), fun((showtime@tests@meta:meta()) -> nil)) -> test(). +test(Meta, Test_function) -> + {test, Meta, fun() -> Test_function(Meta) end}. + +-spec equal(NDT, NDT, showtime@tests@meta:meta()) -> nil. +equal(A, B, Meta) -> + gleam@io:debug(A), + gleam@io:debug(B), + showtime@tests@should:equal_meta(A, B, Meta). + +-spec not_equal(NDV, NDV, showtime@tests@meta:meta()) -> nil. +not_equal(A, B, Meta) -> + showtime@tests@should:equal_meta(A, B, Meta). + +-spec with_meta(showtime@tests@meta:meta(), fun((meta_should(any())) -> nil)) -> test(). +with_meta(Meta, Test_function) -> + {test, + Meta, + fun() -> + Test_function( + {meta_should, + fun(A, B) -> equal(A, B, Meta) end, + fun(A@1, B@1) -> not_equal(A@1, B@1, Meta) end} + ) + end}. + +-spec be_ok({ok, any()} | {error, any()}, showtime@tests@meta:meta()) -> nil. +be_ok(A, Meta) -> + showtime@tests@should:be_ok_meta(A, Meta). + +-spec be_error({ok, any()} | {error, any()}, showtime@tests@meta:meta()) -> nil. +be_error(A, Meta) -> + showtime@tests@should:be_error_meta(A, Meta). + +-spec fail(showtime@tests@meta:meta()) -> nil. +fail(Meta) -> + showtime@tests@should:fail_meta(Meta). + +-spec be_true(boolean(), showtime@tests@meta:meta()) -> nil. +be_true(A, Meta) -> + showtime@tests@should:be_true_meta(A, Meta). + +-spec be_false(boolean(), showtime@tests@meta:meta()) -> nil. +be_false(A, Meta) -> + showtime@tests@should:be_false_meta(A, Meta). diff --git a/aoc2023/build/packages/adglent/src/showtime_ffi.erl b/aoc2023/build/packages/adglent/src/showtime_ffi.erl new file mode 100644 index 0000000..3259623 --- /dev/null +++ b/aoc2023/build/packages/adglent/src/showtime_ffi.erl @@ -0,0 +1,187 @@ +-module(showtime_ffi). + +-export([run_test/4, functions/0, capture_output/1, gleam_error/1]). + +gleam_error(Value) -> + erlang:error(#{ + gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => Value, + module => <<"this/is/not/used"/utf8>>, + function => <<"gleam_error"/utf8>>, + % Not used + line => 0 + }). + +start_output_capture(Capture) -> + OldGroupLeader = group_leader(), + CapturePid = spawn(showtime_ffi, capture_output, [{[], {OldGroupLeader, Capture}}]), + group_leader(CapturePid, self()), + {CapturePid, OldGroupLeader}. + +stop_output_capture({CapturePid, OldGroupLeader}) -> + group_leader(OldGroupLeader, self()), + CapturePid ! {capture_done, self()}, + receive + Buffer -> + Buffer + end. + +capture_output({Buffer, {OldGroupLeader, Capture}}) -> + receive + {io_request, From, ReplyAs, {put_chars, unicode, BitString}} -> + case Capture of + yes -> + From ! {io_reply, ReplyAs, ok}, + capture_output({[BitString | Buffer], {OldGroupLeader, Capture}}); + mixed -> + OldGroupLeader ! {io_request, From, ReplyAs, {put_chars, unicode, BitString}}, + capture_output({[BitString | Buffer], {OldGroupLeader, Capture}}); + no -> + OldGroupLeader ! {io_request, From, ReplyAs, {put_chars, unicode, BitString}}, + capture_output({Buffer, {OldGroupLeader, Capture}}) + end; + {capture_done, SenderPid} -> + SenderPid ! Buffer; + OtherMessage -> + OldGroupLeader ! OtherMessage, + capture_output({Buffer, {OldGroupLeader, Capture}}) + end. + +run_test(Module, Function, IgnoreTags, Capture) -> + OutputCapture = start_output_capture(Capture), + try + Result = apply(Module, Function, []), + {ResultType, FinalResult} = + case Result of + {test, {meta, _Description, Tags}, TestFun} -> + case + lists:any( + fun(Tag) -> + lists:any(fun(IgnoreTag) -> IgnoreTag == Tag end, IgnoreTags) + end, + Tags + ) + of + true -> + {ignored, ignore}; + false -> + {test_function_return, TestFun()} + end; + DirectResult -> + {test_function_return, DirectResult} + end, + OutputCaptureBuffer = stop_output_capture(OutputCapture), + case ResultType of + ignored -> {ok, {ResultType, FinalResult}}; + _ -> {ok, {ResultType, FinalResult, OutputCaptureBuffer}} + end + catch + Class:Reason:Stacktrace -> + GleamReason = + case Reason of + {Assertion, ReasonList} -> + ErlangReasonList = + lists:map( + fun(ReasonDetail) -> + case ReasonDetail of + {line, LineNo} -> + {reason_line, LineNo}; + {expression, List} -> + {expression, list_to_binary(List)}; + {module, ModuleAtom} -> + {module, atom_to_binary(ModuleAtom)}; + {pattern, Pattern} -> + {pattern, list_to_binary(Pattern)}; + Other -> + Other + end + end, + ReasonList + ), + GleamAssertionType = + case Assertion of + assertEqual -> + assert_equal; + assertNotEqual -> + assert_not_equal; + assertMatch -> + assert_match; + OtherAssertionType -> + OtherAssertionType + end, + {GleamAssertionType, ErlangReasonList}; + #{ + function := GleamFunction, + gleam_error := GleamError, + line := Line, + message := Message, + module := GleamModule, + value := Value + } -> + case Value of + {error, {OkValue, _, _, _}} when OkValue == not_eq; OkValue == eq -> + {gleam_error, + {GleamError, GleamModule, GleamFunction, Line, Message, Value}}; + {error, {OkValue, _, _}} when OkValue == is_ok; OkValue == is_error -> + {gleam_error, + {GleamError, GleamModule, GleamFunction, Line, Message, Value}}; + {error, {OkValue, _}} when OkValue == fail -> + {gleam_error, + {GleamError, GleamModule, GleamFunction, Line, Message, Value}}; + _ -> + {gleam_assert, Value, Line} + end; + OtherReason -> + {generic_exception, OtherReason} + end, + GleamClass = + case Class of + error -> + erlang_error; + Other -> + Other + end, + GleamTraceList = + lists:map( + fun(Trace) -> + case Trace of + {ModuleName, FunctionName, Arity, ExtraInfoList} -> + {trace_module, atom_to_binary(ModuleName), + atom_to_binary(FunctionName), map_arity(Arity), + map_extra_info_list(ExtraInfoList)}; + {FunctionName, Arity, ExtraInfoList} -> + {trace, atom_to_binary(FunctionName), map_arity(Arity), + map_extra_info_list(ExtraInfoList)} + end + end, + Stacktrace + ), + OutputCaptureBufferCatch = stop_output_capture(OutputCapture), + {error, + {erlang_exception, GleamClass, GleamReason, {trace_list, GleamTraceList}, + OutputCaptureBufferCatch}} + end. + +map_extra_info_list(ExtraInfoList) -> + lists:map( + fun(ExtraInfo) -> + case ExtraInfo of + {file, FileNameList} -> {file, list_to_binary(FileNameList)}; + Other -> Other + end + end, + ExtraInfoList + ). + +map_arity(Arity) -> + if + is_list(Arity) -> + {arg_list, Arity}; + is_integer(Arity) -> + {num, Arity} + end. + +functions() -> + Funs = module_info(exports), + Funs. diff --git a/aoc2023/build/packages/gap/LICENSE b/aoc2023/build/packages/gap/LICENSE new file mode 100644 index 0000000..d1cec9b --- /dev/null +++ b/aoc2023/build/packages/gap/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 John Björk + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
\ No newline at end of file diff --git a/aoc2023/build/packages/gap/README.md b/aoc2023/build/packages/gap/README.md new file mode 100644 index 0000000..3e02686 --- /dev/null +++ b/aoc2023/build/packages/gap/README.md @@ -0,0 +1,202 @@ +# gap + +[](https://hex.pm/packages/gap) +[](https://hexdocs.pm/gap/) + +A Gleam library for comparing strings/lists and producing a textual (styled) representation of the differences. + +A typical styled output from the comparison can look like this: + +<img src="https://github.com/JohnBjrk/gap/blob/main/static/example_diff_lucy.png?raw=true" alt="Image of two strings with highlighted differences" width="400vw"> + +## Installation + +If available on Hex this package can be added to your Gleam project: + +```sh +gleam add gap +``` + +Documentation can be found at <https://hexdocs.pm/gap>. + +## Usage + +# Introduction + +Gap implements string/list comparison by finding the longest common subsequence. The result of the comparison are two sequences +(one for each of the compared strings/lists) consisting of subsequences that are annotated as matching or non-matching. + +For example comparing the strings in the example above will look as follows: + +```gleam +let comparison = +compare_strings( + "lucy in the sky with diamonds", + "lucy is the shy with diagrams", +) +|> io.debug() +// StringComparison( +// [ +// Match(["l", "u", "c", "y", " ", "i"]), +// NoMatch(["n"]), +// Match([" ", "t", "h", "e", " ", "s"]), +// NoMatch(["k"]), +// Match(["y", " ", "w", "i", "t", "h", " ", "d", "i", "a", "m"]), +// NoMatch(["o", "n", "d"]), +// Match(["s"]), +// ], +// [ +// Match(["l", "u", "c", "y", " ", "i"]), +// NoMatch(["s", " "]), +// Match([" ", "t", "h", "e", " ", "s"]), +// NoMatch(["h"]), +// Match(["y", " ", "w", "i", "t", "h", " ", "d", "i"]), +// NoMatch(["a", "g", "r"]), +// Match(["a", "m", "s"]), +// ], +// ) +``` + +## Styling + +This is useful information but a bit overwhelming to look at (specially for longer string) so the library +has some built in functions to display the differences using colors instead. + +Using the same example again we can style the result and print it to the console + +```gleam +let comparison = +compare_strings( + "lucy in the sky with diamonds", + "lucy is the shy with diagrams", +) +|> to_styled() +io.println(comparison.first) +io.println(comparison.second) +``` + +This will give us something similar to the output above. + +## Comparing list + +It is also possible to compare lists with elements of arbitrary types. + +```gleam +pub type Warning { + Please + Mind + The(what: String) +} + +compare_lists([Mind, The("Gap")], [Please, Mind, The("What")]) +|> io.debug() +// ListComparison( +// [Match([Mind]), NoMatch([The("Gap")])], +// [NoMatch([Please]), Match([Mind]), NoMatch([The("What")])], +// ) +``` + +## Customize styling + +The visual representation of the comparison can be customized. To do this use a `Styling` created from +the comparison that should be styled. This example uses [gleam_community/ansi](https://hexdocs.pm/gleam_community_ansi/index.html) +to highlight the non-matches in different colors. + +```gleam +let comparison = +compare_strings( + "Strings are made of smaller things", + "Things are maybe smaller string", +) +|> from_comparison() +|> highlight( + fn(first) { ansi.cyan(first) }, + fn(second) { ansi.magenta(second) }, + fn(matching) { matching }, +) +|> to_styled_comparison() +io.println(comparison.first) +io.println(comparison.second) +``` + +This will output something similar to this + +<img src="https://github.com/JohnBjrk/gap/blob/main/static/example_diff_things.png?raw=true" alt="Image of two strings with highlighted differences" width="400vw"> + +### Serialization + +Furthermore it is also possible to customize the styling by changing the way that the comparison is serialized. An easy way to do +this is to use the utility function `mk_generic_serializer` which creates a serializer which some specific separator and a hook +for surrounding the result with some content. Here is a somewhat contrived example + +```gleam +let comparison = +compare_lists(["one", "two", "three"], ["two", "two", "tree"]) +|> from_comparison() +|> highlight( + fn(first) { first <> " was not found in other" }, + fn(second) { second <> " was not found in other" }, +) +|> serialize(mk_generic_serializer( + ", and ", + fn(result) { "Comparing the lists gave the following result: " <> result }, +)) +|> to_styled_comparison() +io.println(comparison.first) +io.println(comparison.second) +// Comparing the lists gave the following result: "one" was not found in other, and "two" was found in other, and "three" was not found in other +// Comparing the lists gave the following result: "two" was not found in other, and "two" was found in other, and "tree" was not found in other +``` + +### Custom serialization + +Serializers can of course have a custom implementation. The following example utilizes this together with custom highlighters, +creating a patch-like output (this is not exactly the same as patch-format since that shows the changes in relation to the original - to do +that both lists of matching/non-matching lines would need to be processed together) + +```gleam +let comparison = +compare_lists( + [ + "pub type Gap = List(EmptyString)", "", "pub type Traveler {", + " OnTrain", " OverGap(gap: Gap)", " OnPlatform", "}", + ], + [ + "pub type Traveler {", " OnTrain", " OverGap(gap: String)", + " OnPlatform", "}", + ], +) +|> from_comparison() +|> highlight( + fn(first) { "+" <> first }, + fn(second) { "-" <> second }, + fn(matching) { " " <> matching }, +) +|> serialize(fn(part) { + case part { + Part(acc, lines, highlight) -> + acc <> { + lines + |> list.map(fn(line) { highlight(line) }) + |> string.join("\n") + } <> "\n" + All(result) -> result + } +}) +|> to_styled_comparison() +io.println(comparison.first) +io.println(comparison.second) +// +pub type Gap = List(EmptyString) +// + +// pub type Traveler { +// OnTrain +// + OverGap(gap: Gap) +// OnPlatform +// } +// +// pub type Traveler { +// OnTrain +// - OverGap(gap: String) +// OnPlatform +// } +``` diff --git a/aoc2023/build/packages/gap/gleam.toml b/aoc2023/build/packages/gap/gleam.toml new file mode 100644 index 0000000..ec35329 --- /dev/null +++ b/aoc2023/build/packages/gap/gleam.toml @@ -0,0 +1,18 @@ +name = "gap" +gleam = ">= 0.32.2" +version = "1.0.1" +description = "A Gleam library for comparing strings/lists and producing a textual (styled) representation of the differences." + +# Fill out these fields if you intend to generate HTML documentation or publish +# your project to the Hex package manager. +# +licences = ["Apache-2.0"] +repository = { type = "github", user = "JohnBjrk", repo = "gap" } +# links = [{ title = "Website", href = "https://gleam.run" }] + +[dependencies] +gleam_stdlib = "~> 0.32" +gleam_community_ansi = "~> 1.2" + +[dev-dependencies] +gleeunit = "~> 1.0" diff --git a/aoc2023/build/packages/gap/include/gap@comparison_ListComparison.hrl b/aoc2023/build/packages/gap/include/gap@comparison_ListComparison.hrl new file mode 100644 index 0000000..5e4b20d --- /dev/null +++ b/aoc2023/build/packages/gap/include/gap@comparison_ListComparison.hrl @@ -0,0 +1,4 @@ +-record(list_comparison, { + first :: list(gap@comparison:match(list(any()))), + second :: list(gap@comparison:match(list(any()))) +}). diff --git a/aoc2023/build/packages/gap/include/gap@comparison_Match.hrl b/aoc2023/build/packages/gap/include/gap@comparison_Match.hrl new file mode 100644 index 0000000..f1225dd --- /dev/null +++ b/aoc2023/build/packages/gap/include/gap@comparison_Match.hrl @@ -0,0 +1 @@ +-record(match, {item :: any()}). diff --git a/aoc2023/build/packages/gap/include/gap@comparison_NoMatch.hrl b/aoc2023/build/packages/gap/include/gap@comparison_NoMatch.hrl new file mode 100644 index 0000000..742783b --- /dev/null +++ b/aoc2023/build/packages/gap/include/gap@comparison_NoMatch.hrl @@ -0,0 +1 @@ +-record(no_match, {item :: any()}). diff --git a/aoc2023/build/packages/gap/include/gap@comparison_StringComparison.hrl b/aoc2023/build/packages/gap/include/gap@comparison_StringComparison.hrl new file mode 100644 index 0000000..c0b1a75 --- /dev/null +++ b/aoc2023/build/packages/gap/include/gap@comparison_StringComparison.hrl @@ -0,0 +1,4 @@ +-record(string_comparison, { + first :: list(gap@comparison:match(list(binary()))), + second :: list(gap@comparison:match(list(binary()))) +}). diff --git a/aoc2023/build/packages/gap/include/gap@styled_comparison_StyledComparison.hrl b/aoc2023/build/packages/gap/include/gap@styled_comparison_StyledComparison.hrl new file mode 100644 index 0000000..0e7c64a --- /dev/null +++ b/aoc2023/build/packages/gap/include/gap@styled_comparison_StyledComparison.hrl @@ -0,0 +1 @@ +-record(styled_comparison, {first :: binary(), second :: binary()}). diff --git a/aoc2023/build/packages/gap/include/gap@styling_All.hrl b/aoc2023/build/packages/gap/include/gap@styling_All.hrl new file mode 100644 index 0000000..c11a9a6 --- /dev/null +++ b/aoc2023/build/packages/gap/include/gap@styling_All.hrl @@ -0,0 +1 @@ +-record(all, {all :: binary()}). diff --git a/aoc2023/build/packages/gap/include/gap@styling_Highlighters.hrl b/aoc2023/build/packages/gap/include/gap@styling_Highlighters.hrl new file mode 100644 index 0000000..6e073b3 --- /dev/null +++ b/aoc2023/build/packages/gap/include/gap@styling_Highlighters.hrl @@ -0,0 +1,5 @@ +-record(highlighters, { + first :: fun((binary()) -> binary()), + second :: fun((binary()) -> binary()), + matching :: fun((binary()) -> binary()) +}). diff --git a/aoc2023/build/packages/gap/include/gap@styling_Part.hrl b/aoc2023/build/packages/gap/include/gap@styling_Part.hrl new file mode 100644 index 0000000..db45796 --- /dev/null +++ b/aoc2023/build/packages/gap/include/gap@styling_Part.hrl @@ -0,0 +1,5 @@ +-record(part, { + acc :: binary(), + part :: list(any()), + highlight :: fun((binary()) -> binary()) +}). diff --git a/aoc2023/build/packages/gap/include/gap@styling_Styling.hrl b/aoc2023/build/packages/gap/include/gap@styling_Styling.hrl new file mode 100644 index 0000000..a7341c6 --- /dev/null +++ b/aoc2023/build/packages/gap/include/gap@styling_Styling.hrl @@ -0,0 +1,5 @@ +-record(styling, { + comparison :: gap@comparison:comparison(any()), + serializer :: gleam@option:option(fun((gap@styling:part(any())) -> binary())), + highlight :: gleam@option:option(gap@styling:highlighters()) +}). diff --git a/aoc2023/build/packages/gap/src/gap.app.src b/aoc2023/build/packages/gap/src/gap.app.src new file mode 100644 index 0000000..1abc7df --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap.app.src @@ -0,0 +1,13 @@ +{application, gap, [ + {vsn, "1.0.1"}, + {applications, [gleam_community_ansi, + gleam_stdlib, + gleeunit]}, + {description, "A Gleam library for comparing strings/lists and producing a textual (styled) representation of the differences."}, + {modules, [gap, + gap@comparison, + gap@myers, + gap@styled_comparison, + gap@styling]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/gap/src/gap.erl b/aoc2023/build/packages/gap/src/gap.erl new file mode 100644 index 0000000..827e5ce --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap.erl @@ -0,0 +1,538 @@ +-module(gap). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([to_styled/1, compare_strings_with_algorithm/3, compare_lists_with_algorithm/3, myers/2, compare_lists/2, compare_strings/2, lcs/2]). +-export_type([score/1]). + +-type score(GAM) :: {score, integer(), gleam@option:option(GAM)}. + +-spec to_styled(gap@comparison:comparison(any())) -> gap@styled_comparison:styled_comparison(). +to_styled(Comparison) -> + _pipe = Comparison, + _pipe@1 = gap@styling:from_comparison(_pipe), + _pipe@2 = gap@styling:highlight( + _pipe@1, + fun gap@styling:first_highlight_default/1, + fun gap@styling:second_highlight_default/1, + fun gap@styling:no_highlight/1 + ), + gap@styling:to_styled_comparison(_pipe@2). + +-spec compare_strings_with_algorithm( + binary(), + binary(), + fun((list(binary()), list(binary())) -> gap@comparison:comparison(binary())) +) -> gap@comparison:comparison(binary()). +compare_strings_with_algorithm(First, Second, Algorithm) -> + Comparison = Algorithm( + gleam@string:to_graphemes(First), + gleam@string:to_graphemes(Second) + ), + case Comparison of + {list_comparison, First@1, Second@1} -> + {string_comparison, First@1, Second@1}; + + {string_comparison, First@2, Second@2} -> + {string_comparison, First@2, Second@2} + end. + +-spec compare_lists_with_algorithm( + list(GBB), + list(GBB), + fun((list(GBB), list(GBB)) -> gap@comparison:comparison(GBB)) +) -> gap@comparison:comparison(GBB). +compare_lists_with_algorithm(First_sequence, Second_sequence, Algorithm) -> + Algorithm(First_sequence, Second_sequence). + +-spec myers(list(GBG), list(GBG)) -> gap@comparison:comparison(GBG). +myers(First_sequence, Second_sequence) -> + Edits = gap@myers:difference(First_sequence, Second_sequence), + _pipe = Edits, + _pipe@1 = gleam@list:reverse(_pipe), + gleam@list:fold( + _pipe@1, + {list_comparison, [], []}, + fun(Comparison, Edit) -> case Comparison of + {list_comparison, First, Second} -> + case Edit of + {eq, Segment} -> + {list_comparison, + [{match, Segment} | First], + [{match, Segment} | Second]}; + + {ins, Segment@1} -> + {list_comparison, + First, + [{no_match, Segment@1} | Second]}; + + {del, Segment@2} -> + {list_comparison, + [{no_match, Segment@2} | First], + Second} + end; + + {string_comparison, _, _} -> + Comparison + end end + ). + +-spec compare_lists(list(GAX), list(GAX)) -> gap@comparison:comparison(GAX). +compare_lists(First_sequence, Second_sequence) -> + myers(First_sequence, Second_sequence). + +-spec compare_strings(binary(), binary()) -> gap@comparison:comparison(binary()). +compare_strings(First, Second) -> + Comparison = compare_lists( + gleam@string:to_graphemes(First), + gleam@string:to_graphemes(Second) + ), + case Comparison of + {list_comparison, First@1, Second@1} -> + {string_comparison, First@1, Second@1}; + + {string_comparison, First@2, Second@2} -> + {string_comparison, First@2, Second@2} + end. + +-spec prepend_and_merge( + list(gap@comparison:match(list(GBO))), + gap@comparison:match(list(GBO)) +) -> list(gap@comparison:match(list(GBO))). +prepend_and_merge(Matches, Match) -> + case {Matches, Match} of + {[], _} -> + [Match]; + + {[{match, First_match} | Rest], {match, _}} -> + [{match, + begin + _pipe = erlang:element(2, Match), + gleam@list:append(_pipe, First_match) + end} | + Rest]; + + {[{no_match, First_match@1} | Rest@1], {no_match, _}} -> + [{no_match, + begin + _pipe@1 = erlang:element(2, Match), + gleam@list:append(_pipe@1, First_match@1) + end} | + Rest@1]; + + {Matches@1, Match@1} -> + [Match@1 | Matches@1] + end. + +-spec append_and_merge( + list(gap@comparison:match(list(GBX))), + gap@comparison:match(list(GBX)) +) -> list(gap@comparison:match(list(GBX))). +append_and_merge(Matches, Match) -> + _pipe@3 = case {begin + _pipe = Matches, + gleam@list:reverse(_pipe) + end, + Match} of + {[], _} -> + [Match]; + + {[{match, First_match} | Rest], {match, _}} -> + [{match, + begin + _pipe@1 = First_match, + gleam@list:append(_pipe@1, erlang:element(2, Match)) + end} | + Rest]; + + {[{no_match, First_match@1} | Rest@1], {no_match, _}} -> + [{no_match, + begin + _pipe@2 = First_match@1, + gleam@list:append(_pipe@2, erlang:element(2, Match)) + end} | + Rest@1]; + + {Matches@1, Match@1} -> + [Match@1 | Matches@1] + end, + gleam@list:reverse(_pipe@3). + +-spec collect_matches( + gleam@map:map_(GFY, any()), + list(GCH), + fun((GFY) -> integer()) +) -> list(gap@comparison:match(list(GCH))). +collect_matches(Tracking, Str, Extract_fun) -> + Matching_indexes = begin + _pipe = gleam@map:keys(Tracking), + _pipe@1 = gleam@list:map(_pipe, Extract_fun), + gleam@set:from_list(_pipe@1) + end, + Matches = begin + _pipe@2 = Str, + gleam@list:index_map( + _pipe@2, + fun(Index, Item) -> + case gleam@set:contains(Matching_indexes, Index) of + true -> + {match, Item}; + + false -> + {no_match, Item} + end + end + ) + end, + _pipe@3 = Matches, + _pipe@4 = gleam@list:chunk(_pipe@3, fun(Match) -> case Match of + {match, _} -> + true; + + {no_match, _} -> + false + end end), + gleam@list:map(_pipe@4, fun(Match_list) -> case Match_list of + [{match, _} | _] -> + {match, + gleam@list:filter_map( + Match_list, + fun(Match@1) -> case Match@1 of + {match, Item@1} -> + {ok, Item@1}; + + {no_match, _} -> + {error, nil} + end end + )}; + + [{no_match, _} | _] -> + {no_match, + gleam@list:filter_map( + Match_list, + fun(Match@2) -> case Match@2 of + {no_match, Item@2} -> + {ok, Item@2}; + + {match, _} -> + {error, nil} + end end + )} + end end). + +-spec back_track( + gleam@map:map_({integer(), integer()}, score(GCL)), + integer(), + integer(), + list({{integer(), integer()}, GCL}) +) -> list({{integer(), integer()}, GCL}). +back_track(Diff_map, First_index, Second_index, Stack) -> + case (First_index =:= 0) orelse (Second_index =:= 0) of + true -> + This_score = begin + _pipe = gleam@map:get(Diff_map, {First_index, Second_index}), + gleam@result:unwrap(_pipe, {score, 0, none}) + end, + case This_score of + {score, _, {some, Item}} -> + [{{First_index, Second_index}, Item} | Stack]; + + _ -> + case {First_index, Second_index} of + {0, A} when A > 0 -> + back_track( + Diff_map, + First_index, + Second_index - 1, + Stack + ); + + {A@1, 0} when A@1 > 0 -> + back_track( + Diff_map, + First_index - 1, + Second_index, + Stack + ); + + {0, 0} -> + Stack; + + {_, _} -> + back_track( + Diff_map, + First_index - 1, + Second_index, + Stack + ) + end + end; + + false -> + This_score@1 = begin + _pipe@1 = gleam@map:get(Diff_map, {First_index, Second_index}), + gleam@result:unwrap(_pipe@1, {score, 0, none}) + end, + case This_score@1 of + {score, _, {some, Item@1}} -> + back_track( + Diff_map, + First_index - 1, + Second_index - 1, + [{{First_index, Second_index}, Item@1} | Stack] + ); + + {score, _, none} -> + Up = begin + _pipe@2 = gleam@map:get( + Diff_map, + {First_index, Second_index - 1} + ), + gleam@result:unwrap(_pipe@2, {score, 0, none}) + end, + Back = begin + _pipe@3 = gleam@map:get( + Diff_map, + {First_index - 1, Second_index} + ), + gleam@result:unwrap(_pipe@3, {score, 0, none}) + end, + case gleam@int:compare( + erlang:element(2, Up), + erlang:element(2, Back) + ) of + gt -> + back_track( + Diff_map, + First_index, + Second_index - 1, + Stack + ); + + lt -> + back_track( + Diff_map, + First_index - 1, + Second_index, + Stack + ); + + eq -> + case {First_index, Second_index} of + {0, A@2} when A@2 > 0 -> + back_track( + Diff_map, + First_index, + Second_index - 1, + Stack + ); + + {A@3, 0} when A@3 > 0 -> + back_track( + Diff_map, + First_index - 1, + Second_index, + Stack + ); + + {0, 0} -> + Stack; + + {_, _} -> + back_track( + Diff_map, + First_index - 1, + Second_index, + Stack + ) + end + end + end + end. + +-spec build_diff_map( + GCR, + integer(), + GCR, + integer(), + gleam@map:map_({integer(), integer()}, score(GCR)) +) -> gleam@map:map_({integer(), integer()}, score(GCR)). +build_diff_map(First_item, First_index, Second_item, Second_index, Diff_map) -> + Prev_score = begin + _pipe = gleam@map:get(Diff_map, {First_index - 1, Second_index - 1}), + gleam@result:unwrap(_pipe, {score, 0, none}) + end, + Derived_score_up = begin + _pipe@1 = Diff_map, + _pipe@2 = gleam@map:get(_pipe@1, {First_index, Second_index - 1}), + gleam@result:unwrap(_pipe@2, {score, 0, none}) + end, + Derived_score_back = begin + _pipe@3 = Diff_map, + _pipe@4 = gleam@map:get(_pipe@3, {First_index - 1, Second_index}), + gleam@result:unwrap(_pipe@4, {score, 0, none}) + end, + Derived_score = gleam@int:max( + erlang:element(2, Derived_score_up), + erlang:element(2, Derived_score_back) + ), + This_score = case First_item =:= Second_item of + true -> + {score, erlang:element(2, Prev_score) + 1, {some, First_item}}; + + false -> + {score, Derived_score, none} + end, + _pipe@5 = Diff_map, + gleam@map:insert(_pipe@5, {First_index, Second_index}, This_score). + +-spec lcs(list(GBK), list(GBK)) -> gap@comparison:comparison(GBK). +lcs(First_sequence, Second_sequence) -> + Leading_matches = begin + _pipe = gleam@list:zip(First_sequence, Second_sequence), + _pipe@1 = gleam@list:take_while( + _pipe, + fun(Pair) -> erlang:element(1, Pair) =:= erlang:element(2, Pair) end + ), + gleam@list:map(_pipe@1, fun gleam@pair:first/1) + end, + Num_leading_matches = gleam@list:length(Leading_matches), + Trailing_matches = begin + _pipe@2 = gleam@list:zip( + gleam@list:reverse(First_sequence), + gleam@list:reverse(Second_sequence) + ), + _pipe@3 = gleam@list:take_while( + _pipe@2, + fun(Pair@1) -> + erlang:element(1, Pair@1) =:= erlang:element(2, Pair@1) + end + ), + _pipe@4 = gleam@list:map(_pipe@3, fun gleam@pair:first/1), + gleam@list:reverse(_pipe@4) + end, + Num_trailing_matches = gleam@list:length(Trailing_matches), + First_sequence_to_diff = begin + _pipe@5 = First_sequence, + _pipe@6 = gleam@list:drop(_pipe@5, Num_leading_matches), + gleam@list:take( + _pipe@6, + (gleam@list:length(First_sequence) - Num_leading_matches) - Num_trailing_matches + ) + end, + Second_sequence_to_diff = begin + _pipe@7 = Second_sequence, + _pipe@8 = gleam@list:drop(_pipe@7, Num_leading_matches), + gleam@list:take( + _pipe@8, + (gleam@list:length(Second_sequence) - Num_leading_matches) - Num_trailing_matches + ) + end, + Diff_map@2 = begin + _pipe@9 = Second_sequence_to_diff, + gleam@list:index_fold( + _pipe@9, + gleam@map:new(), + fun(Diff_map, Item_second, Index_second) -> + _pipe@10 = First_sequence_to_diff, + gleam@list:index_fold( + _pipe@10, + Diff_map, + fun(Diff_map@1, Item_first, Index_first) -> + build_diff_map( + Item_first, + Index_first, + Item_second, + Index_second, + Diff_map@1 + ) + end + ) + end + ) + end, + {First_segments@1, Second_segments@1} = case {First_sequence_to_diff, + Second_sequence_to_diff} of + {[], []} -> + {[], []}; + + {First_matching, []} -> + {[{no_match, First_matching}], []}; + + {[], Second_matching} -> + {[], [{no_match, Second_matching}]}; + + {First_sequence_to_diff@1, Second_sequence_to_diff@1} -> + Tracking = begin + _pipe@11 = back_track( + Diff_map@2, + gleam@list:length(First_sequence_to_diff@1) - 1, + gleam@list:length(Second_sequence_to_diff@1) - 1, + [] + ), + gleam@map:from_list(_pipe@11) + end, + First_segments = collect_matches( + Tracking, + First_sequence_to_diff@1, + fun(Key) -> + {First, _} = Key, + First + end + ), + Second_segments = collect_matches( + Tracking, + Second_sequence_to_diff@1, + fun(Key@1) -> + {_, Second} = Key@1, + Second + end + ), + {First_segments, Second_segments} + end, + {First_segments_with_leading_trailing, + Second_segments_with_leading_trailing} = case {Leading_matches, + Trailing_matches} of + {[], []} -> + {First_segments@1, Second_segments@1}; + + {[], Trailing_matches@1} -> + {begin + _pipe@12 = First_segments@1, + append_and_merge(_pipe@12, {match, Trailing_matches@1}) + end, + begin + _pipe@13 = Second_segments@1, + append_and_merge(_pipe@13, {match, Trailing_matches@1}) + end}; + + {Leading_matches@1, []} -> + {begin + _pipe@14 = First_segments@1, + prepend_and_merge(_pipe@14, {match, Leading_matches@1}) + end, + begin + _pipe@15 = Second_segments@1, + prepend_and_merge(_pipe@15, {match, Leading_matches@1}) + end}; + + {Leading_matches@2, Trailing_matches@2} -> + {begin + _pipe@16 = First_segments@1, + _pipe@17 = prepend_and_merge( + _pipe@16, + {match, Leading_matches@2} + ), + append_and_merge(_pipe@17, {match, Trailing_matches@2}) + end, + begin + _pipe@18 = Second_segments@1, + _pipe@19 = prepend_and_merge( + _pipe@18, + {match, Leading_matches@2} + ), + append_and_merge(_pipe@19, {match, Trailing_matches@2}) + end} + end, + {list_comparison, + First_segments_with_leading_trailing, + Second_segments_with_leading_trailing}. diff --git a/aoc2023/build/packages/gap/src/gap.gleam b/aoc2023/build/packages/gap/src/gap.gleam new file mode 100644 index 0000000..7eb0e7f --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap.gleam @@ -0,0 +1,438 @@ +import gleam/string +import gleam/list +import gleam/pair +import gleam/map.{type Map} +import gleam/result +import gleam/option.{type Option, None, Some} +import gleam/int +import gleam/order.{Eq, Gt, Lt} +import gleam/set +import gap/comparison.{ + type Comparison, type Match, type Segments, ListComparison, Match, NoMatch, + StringComparison, +} +import gap/styled_comparison.{type StyledComparison} +import gap/styling.{ + first_highlight_default, from_comparison, highlight, no_highlight, + second_highlight_default, to_styled_comparison, +} +import gap/myers.{type Edit, Del, Eq as MyerEq, Ins} + +type MatchedItem(a) = + #(#(Int, Int), a) + +type Score(a) { + Score(value: Int, item: Option(a)) +} + +type DiffMap(a) = + Map(#(Int, Int), Score(a)) + +/// Creates a `StyledComparison` from `Comparison` using default values for +/// highting and serialization. +/// +/// ## Example +/// +/// ```gleam +/// > compare_strings("abc", "abe") |> to_styled() +/// ``` +/// This will return a `StyledComparison(first, second)` where "c" in `first` is green +/// and "e" in `second` is red. +pub fn to_styled(comparison: Comparison(a)) -> StyledComparison { + comparison + |> from_comparison() + |> highlight(first_highlight_default, second_highlight_default, no_highlight) + |> to_styled_comparison() +} + +/// Compare two string and return a `StringComparison` which will be styled as string +/// when passed to `to_styled` +/// +/// Will use the default `myers` algorithm +pub fn compare_strings(first: String, second: String) -> Comparison(String) { + let comparison = + compare_lists(string.to_graphemes(first), string.to_graphemes(second)) + case comparison { + ListComparison(first, second) -> StringComparison(first, second) + StringComparison(first, second) -> StringComparison(first, second) + } +} + +/// Compare two string and return a `StringComparison` which will be styled as string +/// when passed to `to_styled` +/// +/// Algorithm can be used to select either `myers` or the legacy `lcs` algorithm +pub fn compare_strings_with_algorithm( + first: String, + second: String, + algorithm, +) -> Comparison(String) { + let comparison = + algorithm(string.to_graphemes(first), string.to_graphemes(second)) + case comparison { + ListComparison(first, second) -> StringComparison(first, second) + StringComparison(first, second) -> StringComparison(first, second) + } +} + +/// Compare two lists and return a `ListComparison` which will be styled as list +/// when passed to `to_styled` +/// +/// Will use the default `myers` algorithm +pub fn compare_lists( + first_sequence: List(a), + second_sequence: List(a), +) -> Comparison(a) { + myers(first_sequence, second_sequence) +} + +/// Compare two lists and return a `ListComparison` which will be styled as list +/// when passed to `to_styled` +/// +/// Algorithm can be used to select either `myers` or the legacy `lcs` algorithm +pub fn compare_lists_with_algorithm( + first_sequence: List(a), + second_sequence: List(a), + algorithm, +) -> Comparison(a) { + algorithm(first_sequence, second_sequence) +} + +/// An adapter for the the `myers` algorithm. +/// Intended to be use as an argument to `compare_strings_with_algorithm` or +/// `compare_lists_with_algorithm` +pub fn myers(first_sequence: List(a), second_sequence: List(a)) -> Comparison(a) { + let edits = myers.difference(first_sequence, second_sequence) + edits + |> list.reverse() + |> list.fold( + ListComparison([], []), + fn(comparison: Comparison(a), edit: Edit(a)) { + case comparison { + ListComparison(first, second) -> { + case edit { + MyerEq(segment) -> + ListComparison( + [Match(segment), ..first], + [Match(segment), ..second], + ) + Ins(segment) -> ListComparison(first, [NoMatch(segment), ..second]) + Del(segment) -> ListComparison([NoMatch(segment), ..first], second) + } + } + StringComparison(..) -> comparison + } + }, + ) +} + +/// An adapter for the the `lcs` (longest common subsequence) algorithm. +/// Intended to be use as an argument to `compare_strings_with_algorithm` or +/// `compare_lists_with_algorithm` +pub fn lcs(first_sequence: List(a), second_sequence: List(a)) -> Comparison(a) { + let leading_matches = + list.zip(first_sequence, second_sequence) + |> list.take_while(fn(pair) { pair.0 == pair.1 }) + |> list.map(pair.first) + let num_leading_matches = list.length(leading_matches) + let trailing_matches = + list.zip(list.reverse(first_sequence), list.reverse(second_sequence)) + |> list.take_while(fn(pair) { pair.0 == pair.1 }) + |> list.map(pair.first) + |> list.reverse() + let num_trailing_matches = list.length(trailing_matches) + let first_sequence_to_diff = + first_sequence + |> list.drop(num_leading_matches) + |> list.take( + list.length(first_sequence) - num_leading_matches - num_trailing_matches, + ) + let second_sequence_to_diff = + second_sequence + |> list.drop(num_leading_matches) + |> list.take( + list.length(second_sequence) - num_leading_matches - num_trailing_matches, + ) + + let diff_map = + second_sequence_to_diff + |> list.index_fold( + map.new(), + fn(diff_map, item_second, index_second) { + first_sequence_to_diff + |> list.index_fold( + diff_map, + fn(diff_map, item_first, index_first) { + build_diff_map( + item_first, + index_first, + item_second, + index_second, + diff_map, + ) + }, + ) + }, + ) + let #(first_segments, second_segments) = case + first_sequence_to_diff, + second_sequence_to_diff + { + [], [] -> #([], []) + first_matching, [] -> #([NoMatch(first_matching)], []) + [], second_matching -> #([], [NoMatch(second_matching)]) + first_sequence_to_diff, second_sequence_to_diff -> { + let tracking = + back_track( + diff_map, + list.length(first_sequence_to_diff) - 1, + list.length(second_sequence_to_diff) - 1, + [], + ) + |> map.from_list() + + let first_segments = + collect_matches( + tracking, + first_sequence_to_diff, + fn(key) { + let #(first, _) = key + first + }, + ) + let second_segments = + collect_matches( + tracking, + second_sequence_to_diff, + fn(key) { + let #(_, second) = key + second + }, + ) + #(first_segments, second_segments) + } + } + + let #( + first_segments_with_leading_trailing, + second_segments_with_leading_trailing, + ) = case leading_matches, trailing_matches { + [], [] -> #(first_segments, second_segments) + [], trailing_matches -> #( + first_segments + |> append_and_merge(Match(trailing_matches)), + second_segments + |> append_and_merge(Match(trailing_matches)), + ) + leading_matches, [] -> #( + first_segments + |> prepend_and_merge(Match(leading_matches)), + second_segments + |> prepend_and_merge(Match(leading_matches)), + ) + leading_matches, trailing_matches -> #( + first_segments + |> prepend_and_merge(Match(leading_matches)) + |> append_and_merge(Match(trailing_matches)), + second_segments + |> prepend_and_merge(Match(leading_matches)) + |> append_and_merge(Match(trailing_matches)), + ) + } + + ListComparison( + first_segments_with_leading_trailing, + second_segments_with_leading_trailing, + ) +} + +fn prepend_and_merge( + matches: List(Match(List(a))), + match: Match(List(a)), +) -> List(Match(List(a))) { + case matches, match { + [], _ -> [match] + [Match(first_match), ..rest], Match(_) -> [ + Match( + match.item + |> list.append(first_match), + ), + ..rest + ] + [NoMatch(first_match), ..rest], NoMatch(_) -> [ + NoMatch( + match.item + |> list.append(first_match), + ), + ..rest + ] + matches, match -> [match, ..matches] + } +} + +fn append_and_merge( + matches: List(Match(List(a))), + match: Match(List(a)), +) -> List(Match(List(a))) { + case + matches + |> list.reverse(), + match + { + [], _ -> [match] + [Match(first_match), ..rest], Match(_) -> [ + Match( + first_match + |> list.append(match.item), + ), + ..rest + ] + [NoMatch(first_match), ..rest], NoMatch(_) -> [ + NoMatch( + first_match + |> list.append(match.item), + ), + ..rest + ] + matches, match -> [match, ..matches] + } + |> list.reverse() +} + +fn collect_matches(tracking, str: List(a), extract_fun) -> Segments(a) { + let matching_indexes = + map.keys(tracking) + |> list.map(extract_fun) + |> set.from_list() + + let matches = + str + |> list.index_map(fn(index, item) { + case set.contains(matching_indexes, index) { + True -> Match(item) + False -> NoMatch(item) + } + }) + + matches + |> list.chunk(fn(match) { + case match { + Match(_) -> True + NoMatch(_) -> False + } + }) + |> list.map(fn(match_list) { + case match_list { + [Match(_), ..] -> + Match(list.filter_map( + match_list, + fn(match) { + case match { + Match(item) -> Ok(item) + NoMatch(_) -> Error(Nil) + } + }, + )) + [NoMatch(_), ..] -> + NoMatch(list.filter_map( + match_list, + fn(match) { + case match { + NoMatch(item) -> Ok(item) + Match(_) -> Error(Nil) + } + }, + )) + } + }) +} + +fn back_track( + diff_map: DiffMap(a), + first_index: Int, + second_index: Int, + stack: List(MatchedItem(a)), +) -> List(MatchedItem(a)) { + case first_index == 0 || second_index == 0 { + True -> { + let this_score = + map.get(diff_map, #(first_index, second_index)) + |> result.unwrap(Score(0, None)) + case this_score { + Score(_, Some(item)) -> [#(#(first_index, second_index), item), ..stack] + _ -> + case first_index, second_index { + 0, a if a > 0 -> + back_track(diff_map, first_index, second_index - 1, stack) + a, 0 if a > 0 -> + back_track(diff_map, first_index - 1, second_index, stack) + 0, 0 -> stack + _, _ -> back_track(diff_map, first_index - 1, second_index, stack) + } + } + } + False -> { + let this_score = + map.get(diff_map, #(first_index, second_index)) + |> result.unwrap(Score(0, None)) + case this_score { + Score(_, Some(item)) -> + back_track( + diff_map, + first_index - 1, + second_index - 1, + [#(#(first_index, second_index), item), ..stack], + ) + Score(_, None) -> { + let up = + map.get(diff_map, #(first_index, second_index - 1)) + |> result.unwrap(Score(0, None)) + let back = + map.get(diff_map, #(first_index - 1, second_index)) + |> result.unwrap(Score(0, None)) + case int.compare(up.value, back.value) { + Gt -> back_track(diff_map, first_index, second_index - 1, stack) + Lt -> back_track(diff_map, first_index - 1, second_index, stack) + Eq -> + case first_index, second_index { + 0, a if a > 0 -> + back_track(diff_map, first_index, second_index - 1, stack) + a, 0 if a > 0 -> + back_track(diff_map, first_index - 1, second_index, stack) + 0, 0 -> stack + _, _ -> + back_track(diff_map, first_index - 1, second_index, stack) + } + } + } + } + } + } +} + +fn build_diff_map( + first_item: a, + first_index: Int, + second_item: a, + second_index: Int, + diff_map: DiffMap(a), +) -> DiffMap(a) { + let prev_score = + map.get(diff_map, #(first_index - 1, second_index - 1)) + |> result.unwrap(Score(0, None)) + let derived_score_up = + diff_map + |> map.get(#(first_index, second_index - 1)) + |> result.unwrap(Score(0, None)) + let derived_score_back = + diff_map + |> map.get(#(first_index - 1, second_index)) + |> result.unwrap(Score(0, None)) + let derived_score = int.max(derived_score_up.value, derived_score_back.value) + let this_score = case first_item == second_item { + True -> Score(prev_score.value + 1, Some(first_item)) + False -> Score(derived_score, None) + } + diff_map + |> map.insert(#(first_index, second_index), this_score) +} diff --git a/aoc2023/build/packages/gap/src/gap/comparison.gleam b/aoc2023/build/packages/gap/src/gap/comparison.gleam new file mode 100644 index 0000000..da30c29 --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap/comparison.gleam @@ -0,0 +1,22 @@ +/// Comparison of two strings or lists +/// +/// The comparison consists of two lists of matched segments. The segments represent +/// a sequence of succeeding matches or non-matches (up until the next match/non-match) +/// +/// For lists the elements in the segment will be same as the elements in the list, and +/// for strings the elements will be the graphemes of the string +pub type Comparison(a) { + ListComparison(first: Segments(a), second: Segments(a)) + StringComparison(first: Segments(String), second: Segments(String)) +} + +/// Indicating that the item has a matching (`Match`) or no matching (`NoMatch`) item in the +/// other string/list +pub type Match(a) { + Match(item: a) + NoMatch(item: a) +} + +/// List of segments of succeeding matches / non-matches +pub type Segments(a) = + List(Match(List(a))) diff --git a/aoc2023/build/packages/gap/src/gap/myers.gleam b/aoc2023/build/packages/gap/src/gap/myers.gleam new file mode 100644 index 0000000..f0b8ddc --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap/myers.gleam @@ -0,0 +1,122 @@ +import gleam/list + +pub type Edit(a) { + Eq(List(a)) + Del(List(a)) + Ins(List(a)) +} + +type Path(a) { + Path(x: Int, y: Int, list1: List(a), list2: List(a), edits: List(Edit(a))) +} + +type Status(a) { + Done(edits: List(Edit(a))) + Next(paths: List(Path(a))) + Cont(path: Path(a)) +} + +/// The algorithm is outlined in the +/// "An O(ND) Difference Algorithm and Its Variations" paper by E. Myers. +/// +/// Adapted from the implementation of "myers_difference" in Elixirs List module +pub fn difference(list1: List(a), list2: List(a)) -> List(Edit(a)) { + let path = Path(0, 0, list1, list2, []) + find_script(0, list.length(list1) + list.length(list2), [path]) +} + +fn find_script(envelope: Int, max: Int, paths: List(Path(a))) { + case envelope > max { + True -> [] + False -> { + case each_diagonal(-envelope, envelope, paths, []) { + Done(edits) -> compact_reverse(edits, []) + Next(paths) -> find_script(envelope + 1, max, paths) + _ -> panic as "Didn't expect a Cont here" + } + } + } +} + +fn compact_reverse(edits: List(Edit(a)), acc: List(Edit(a))) -> List(Edit(a)) { + case edits, acc { + [], acc -> acc + [Eq(elem), ..rest], [Eq(result), ..acc_rest] -> + compact_reverse(rest, [Eq(list.flatten([elem, result])), ..acc_rest]) + [Del(elem), ..rest], [Del(result), ..acc_rest] -> + compact_reverse(rest, [Del(list.flatten([elem, result])), ..acc_rest]) + [Ins(elem), ..rest], [Ins(result), ..acc_rest] -> + compact_reverse(rest, [Ins(list.flatten([elem, result])), ..acc_rest]) + [Eq(elem), ..rest], acc -> compact_reverse(rest, [Eq(elem), ..acc]) + [Del(elem), ..rest], acc -> compact_reverse(rest, [Del(elem), ..acc]) + [Ins(elem), ..rest], acc -> compact_reverse(rest, [Ins(elem), ..acc]) + } +} + +fn each_diagonal( + diag: Int, + limit: Int, + paths: List(Path(a)), + next_paths: List(Path(a)), +) -> Status(a) { + case diag > limit { + True -> Next(list.reverse(next_paths)) + False -> { + let #(path, rest) = proceed_path(diag, limit, paths) + case follow_snake(path) { + Cont(path) -> each_diagonal(diag + 2, limit, rest, [path, ..next_paths]) + other -> other + } + } + } +} + +fn proceed_path( + diag: Int, + limit: Int, + paths: List(Path(a)), +) -> #(Path(a), List(Path(a))) { + let neg_limit = -limit + case diag, limit, paths { + 0, 0, [path] -> #(path, []) + diag, _limit, [path, ..] as paths if diag == neg_limit -> #( + move_down(path), + paths, + ) + diag, limit, [path, ..] as paths if diag == limit -> #( + move_right(path), + paths, + ) + _diag, _limit, [path1, path2, ..rest] -> { + case path1.y > path2.y { + True -> #(move_right(path1), [path2, ..rest]) + False -> #(move_down(path2), [path2, ..rest]) + } + } + } +} + +fn move_right(path: Path(a)) -> Path(a) { + case path { + Path(x, y, list1, [elem, ..rest], edits) -> + Path(x + 1, y, list1, rest, [Ins([elem]), ..edits]) + Path(x, y, list1, [], edits) -> Path(x + 1, y, list1, [], edits) + } +} + +fn move_down(path: Path(a)) -> Path(a) { + case path { + Path(x, y, [elem, ..rest], list2, edits) -> + Path(x, y + 1, rest, list2, [Del([elem]), ..edits]) + Path(x, y, [], list2, edits) -> Path(x, y + 1, [], list2, edits) + } +} + +fn follow_snake(path: Path(a)) -> Status(a) { + case path { + Path(x, y, [elem1, ..rest1], [elem2, ..rest2], edits) if elem1 == elem2 -> + follow_snake(Path(x + 1, y + 1, rest1, rest2, [Eq([elem1]), ..edits])) + Path(_x, _y, [], [], edits) -> Done(edits) + _ -> Cont(path) + } +} diff --git a/aoc2023/build/packages/gap/src/gap/styled_comparison.gleam b/aoc2023/build/packages/gap/src/gap/styled_comparison.gleam new file mode 100644 index 0000000..7103c2e --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap/styled_comparison.gleam @@ -0,0 +1,4 @@ +/// A comparison where the parts have been styled (serialized and highlighted) +pub type StyledComparison { + StyledComparison(first: String, second: String) +} diff --git a/aoc2023/build/packages/gap/src/gap/styling.gleam b/aoc2023/build/packages/gap/src/gap/styling.gleam new file mode 100644 index 0000000..623ae8a --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap/styling.gleam @@ -0,0 +1,233 @@ +import gleam/option.{type Option, None, Some} +import gleam/list +import gleam/string +import gleam_community/ansi +import gap/comparison.{ + type Comparison, type Segments, ListComparison, Match, NoMatch, + StringComparison, +} +import gap/styled_comparison.{type StyledComparison, StyledComparison} + +/// The `Highlighter`takes a string representation of the item that was not matching +/// and should return a string representation that can be used to visually indicate that +/// it is a non-matching item. +/// +/// The default implementation of the highlighters uses the +/// [gleam_community/ansi](https://hexdocs.pm/gleam_community_ansi/index.html) library +/// to set a different color for the item, but any type if indication can be used as long +/// as it returns a valid string +pub type Highlighter = + fn(String) -> String + +/// `Part` is used to indicate to a custom serializer if it should produce a serialization +/// based on a segment with items or the final string that contains already serialized segments +pub type Part(a) { + /// `acc` the already serialized part of the result, `part` is the current segment that should be serialized and appended and `highlighter` is the `Highlighter` that can be used to indicate non-matching items + Part(acc: String, part: List(a), highlight: Highlighter) + /// `all` is a string representing all serialized segments. This can be useful if some string should be prepended/appended to the final result + All(all: String) +} + +/// A `Serializer`can be used to create string representation of the comparison results +/// +/// See [serialize](#serialize) for adding custom serializers and [mk_generic_serializer](#mk_generic_serializer) +pub type Serializer(a) = + fn(Part(a)) -> String + +/// Highlighters to use for indicating matches / non-matches +/// +/// `first` is used to highlight non-matches in the first string/list +/// `second` is used to highlight non-matches in the second string/list +/// `matching` is used to highlight matches in the both strings/lists +pub type Highlighters { + Highlighters(first: Highlighter, second: Highlighter, matching: Highlighter) +} + +/// Styling of a `Comparison` +/// +/// See [from_comparison](#from_comparison) +pub opaque type Styling(a) { + Styling( + comparison: Comparison(a), + serializer: Option(Serializer(a)), + highlight: Option(Highlighters), + ) +} + +/// Create a new `Styling` from a `Comparison` +/// +/// The `Styling` can be customized by adding highlighters and a serializer +/// See [highlight](#highlight) and [serialize](#serialize) +pub fn from_comparison(comparison: Comparison(a)) -> Styling(a) { + Styling(comparison, None, None) +} + +/// Add highlighters to the `Styling` +/// +/// The highlighters are used to mark the matching/non-matching items in the +/// first/second list/string +pub fn highlight( + styling: Styling(a), + first: Highlighter, + second: Highlighter, + matching: Highlighter, +) -> Styling(a) { + Styling(..styling, highlight: Some(Highlighters(first, second, matching))) +} + +/// Add a serializer to the `Styling` +/// +/// The serializer is used to create string representation of the items in the segments of the `Comparison` +/// See [Part](#part) for details +/// +/// > **NOTE:** `StringComparison` will always use the default string serializer (concatenating the graphemes). +/// > If there is a need for custom serialization of `StringComparison` convert the string to a list of +/// > graphemes and treat it as a `ListComparison` +pub fn serialize(styling: Styling(a), serializer: Serializer(a)) -> Styling(a) { + Styling(..styling, serializer: Some(serializer)) +} + +/// Creates a styled comparison using either custom highlighters/serializer if they where added or default +/// highlighters and/or serializer +pub fn to_styled_comparison(styling: Styling(a)) -> StyledComparison { + let highlight = + styling.highlight + |> option.unwrap(Highlighters( + first_highlight_default, + second_highlight_default, + no_highlight, + )) + case styling.comparison { + StringComparison(first, second) -> + to_strings( + first, + second, + // NOTE: Using string serializer here because otherwise we need to have a specific string serializer on the styling + string_serializer, + highlight.first, + highlight.second, + highlight.matching, + ) + ListComparison(first, second) -> + to_strings( + first, + second, + option.unwrap(styling.serializer, generic_serializer), + highlight.first, + highlight.second, + highlight.matching, + ) + } +} + +/// Default highlighter for the first string/list in the comparison +pub fn first_highlight_default(string: String) -> String { + case string { + " " -> + string + |> ansi.underline() + |> ansi.bold() + |> ansi.green() + + _ -> + string + |> ansi.green() + |> ansi.bold() + } +} + +/// Default highlighter for the second string/list in the comparison +pub fn second_highlight_default(string: String) -> String { + case string { + " " -> + string + |> ansi.underline() + |> ansi.bold() + |> ansi.red() + + _ -> + string + |> ansi.red() + |> ansi.bold() + } +} + +/// Default highlighter used for matching items +pub fn no_highlight(string: String) -> String { + string +} + +fn string_serializer(part: Part(String)) -> String { + case part { + Part(acc, sequence, highlight) -> + acc <> { + sequence + |> list.map(highlight) + |> string.join("") + } + All(string) -> string + } +} + +fn generic_serializer(part: Part(a)) -> String { + mk_generic_serializer(", ", fn(all) { "[" <> all <> "]" })(part) +} + +/// Creates a generic serializer that uses `separator` between all items and calls +/// `around` for possibility to prepend/append strings to the final result +pub fn mk_generic_serializer(separator: String, around: fn(String) -> String) { + fn(part) { + case part { + Part(acc, sequence, highlight) -> { + let segment_separator = case acc { + "" -> "" + _ -> separator + } + acc <> segment_separator <> { + sequence + |> list.map(string.inspect) + |> list.map(highlight) + |> string.join(separator) + } + } + All(string) -> around(string) + } + } +} + +fn to_strings( + first: Segments(a), + second: Segments(a), + serializer: Serializer(a), + first_highlight: Highlighter, + second_highlight: Highlighter, + no_highlight: Highlighter, +) -> StyledComparison { + let first_styled = + first + |> list.fold( + "", + fn(str, match) { + case match { + Match(item) -> serializer(Part(str, item, no_highlight)) + NoMatch(item) -> serializer(Part(str, item, first_highlight)) + } + }, + ) + let second_styled = + second + |> list.fold( + "", + fn(str, match) { + case match { + Match(item) -> serializer(Part(str, item, no_highlight)) + NoMatch(item) -> serializer(Part(str, item, second_highlight)) + } + }, + ) + + StyledComparison( + serializer(All(first_styled)), + serializer(All(second_styled)), + ) +} diff --git a/aoc2023/build/packages/gap/src/gap@comparison.erl b/aoc2023/build/packages/gap/src/gap@comparison.erl new file mode 100644 index 0000000..36bd1c3 --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap@comparison.erl @@ -0,0 +1,15 @@ +-module(gap@comparison). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export_type([comparison/1, match/1]). + +-type comparison(FQT) :: {list_comparison, + list(match(list(FQT))), + list(match(list(FQT)))} | + {string_comparison, + list(match(list(binary()))), + list(match(list(binary())))}. + +-type match(FQU) :: {match, FQU} | {no_match, FQU}. + + diff --git a/aoc2023/build/packages/gap/src/gap@myers.erl b/aoc2023/build/packages/gap/src/gap@myers.erl new file mode 100644 index 0000000..6a8ad35 --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap@myers.erl @@ -0,0 +1,156 @@ +-module(gap@myers). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([difference/2]). +-export_type([edit/1, path/1, status/1]). + +-type edit(FUV) :: {eq, list(FUV)} | {del, list(FUV)} | {ins, list(FUV)}. + +-type path(FUW) :: {path, + integer(), + integer(), + list(FUW), + list(FUW), + list(edit(FUW))}. + +-type status(FUX) :: {done, list(edit(FUX))} | + {next, list(path(FUX))} | + {cont, path(FUX)}. + +-spec compact_reverse(list(edit(FVH)), list(edit(FVH))) -> list(edit(FVH)). +compact_reverse(Edits, Acc) -> + case {Edits, Acc} of + {[], Acc@1} -> + Acc@1; + + {[{eq, Elem} | Rest], [{eq, Result} | Acc_rest]} -> + compact_reverse( + Rest, + [{eq, gleam@list:flatten([Elem, Result])} | Acc_rest] + ); + + {[{del, Elem@1} | Rest@1], [{del, Result@1} | Acc_rest@1]} -> + compact_reverse( + Rest@1, + [{del, gleam@list:flatten([Elem@1, Result@1])} | Acc_rest@1] + ); + + {[{ins, Elem@2} | Rest@2], [{ins, Result@2} | Acc_rest@2]} -> + compact_reverse( + Rest@2, + [{ins, gleam@list:flatten([Elem@2, Result@2])} | Acc_rest@2] + ); + + {[{eq, Elem@3} | Rest@3], Acc@2} -> + compact_reverse(Rest@3, [{eq, Elem@3} | Acc@2]); + + {[{del, Elem@4} | Rest@4], Acc@3} -> + compact_reverse(Rest@4, [{del, Elem@4} | Acc@3]); + + {[{ins, Elem@5} | Rest@5], Acc@4} -> + compact_reverse(Rest@5, [{ins, Elem@5} | Acc@4]) + end. + +-spec move_right(path(FWA)) -> path(FWA). +move_right(Path) -> + case Path of + {path, X, Y, List1, [Elem | Rest], Edits} -> + {path, X + 1, Y, List1, Rest, [{ins, [Elem]} | Edits]}; + + {path, X@1, Y@1, List1@1, [], Edits@1} -> + {path, X@1 + 1, Y@1, List1@1, [], Edits@1} + end. + +-spec move_down(path(FWD)) -> path(FWD). +move_down(Path) -> + case Path of + {path, X, Y, [Elem | Rest], List2, Edits} -> + {path, X, Y + 1, Rest, List2, [{del, [Elem]} | Edits]}; + + {path, X@1, Y@1, [], List2@1, Edits@1} -> + {path, X@1, Y@1 + 1, [], List2@1, Edits@1} + end. + +-spec proceed_path(integer(), integer(), list(path(FVU))) -> {path(FVU), + list(path(FVU))}. +proceed_path(Diag, Limit, Paths) -> + Neg_limit = - Limit, + case {Diag, Limit, Paths} of + {0, 0, [Path]} -> + {Path, []}; + + {Diag@1, _, [Path@1 | _] = Paths@1} when Diag@1 =:= Neg_limit -> + {move_down(Path@1), Paths@1}; + + {Diag@2, Limit@1, [Path@2 | _] = Paths@2} when Diag@2 =:= Limit@1 -> + {move_right(Path@2), Paths@2}; + + {_, _, [Path1, Path2 | Rest]} -> + case erlang:element(3, Path1) > erlang:element(3, Path2) of + true -> + {move_right(Path1), [Path2 | Rest]}; + + false -> + {move_down(Path2), [Path2 | Rest]} + end + end. + +-spec follow_snake(path(FWG)) -> status(FWG). +follow_snake(Path) -> + case Path of + {path, X, Y, [Elem1 | Rest1], [Elem2 | Rest2], Edits} when Elem1 =:= Elem2 -> + follow_snake( + {path, X + 1, Y + 1, Rest1, Rest2, [{eq, [Elem1]} | Edits]} + ); + + {path, _, _, [], [], Edits@1} -> + {done, Edits@1}; + + _ -> + {cont, Path} + end. + +-spec each_diagonal(integer(), integer(), list(path(FVO)), list(path(FVO))) -> status(FVO). +each_diagonal(Diag, Limit, Paths, Next_paths) -> + case Diag > Limit of + true -> + {next, gleam@list:reverse(Next_paths)}; + + false -> + {Path, Rest} = proceed_path(Diag, Limit, Paths), + case follow_snake(Path) of + {cont, Path@1} -> + each_diagonal(Diag + 2, Limit, Rest, [Path@1 | Next_paths]); + + Other -> + Other + end + end. + +-spec find_script(integer(), integer(), list(path(FVD))) -> list(edit(FVD)). +find_script(Envelope, Max, Paths) -> + case Envelope > Max of + true -> + []; + + false -> + case each_diagonal(- Envelope, Envelope, Paths, []) of + {done, Edits} -> + compact_reverse(Edits, []); + + {next, Paths@1} -> + find_script(Envelope + 1, Max, Paths@1); + + _ -> + erlang:error(#{gleam_error => panic, + message => <<"Didn't expect a Cont here"/utf8>>, + module => <<"gap/myers"/utf8>>, + function => <<"find_script"/utf8>>, + line => 35}) + end + end. + +-spec difference(list(FUY), list(FUY)) -> list(edit(FUY)). +difference(List1, List2) -> + Path = {path, 0, 0, List1, List2, []}, + find_script(0, gleam@list:length(List1) + gleam@list:length(List2), [Path]). diff --git a/aoc2023/build/packages/gap/src/gap@styled_comparison.erl b/aoc2023/build/packages/gap/src/gap@styled_comparison.erl new file mode 100644 index 0000000..14cc390 --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap@styled_comparison.erl @@ -0,0 +1,8 @@ +-module(gap@styled_comparison). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export_type([styled_comparison/0]). + +-type styled_comparison() :: {styled_comparison, binary(), binary()}. + + diff --git a/aoc2023/build/packages/gap/src/gap@styling.erl b/aoc2023/build/packages/gap/src/gap@styling.erl new file mode 100644 index 0000000..ba226c3 --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap@styling.erl @@ -0,0 +1,202 @@ +-module(gap@styling). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([from_comparison/1, highlight/4, serialize/2, first_highlight_default/1, second_highlight_default/1, no_highlight/1, mk_generic_serializer/2, to_styled_comparison/1]). +-export_type([part/1, highlighters/0, styling/1]). + +-type part(FRE) :: {part, binary(), list(FRE), fun((binary()) -> binary())} | + {all, binary()}. + +-type highlighters() :: {highlighters, + fun((binary()) -> binary()), + fun((binary()) -> binary()), + fun((binary()) -> binary())}. + +-opaque styling(FRF) :: {styling, + gap@comparison:comparison(FRF), + gleam@option:option(fun((part(FRF)) -> binary())), + gleam@option:option(highlighters())}. + +-spec from_comparison(gap@comparison:comparison(FRI)) -> styling(FRI). +from_comparison(Comparison) -> + {styling, Comparison, none, none}. + +-spec highlight( + styling(FRL), + fun((binary()) -> binary()), + fun((binary()) -> binary()), + fun((binary()) -> binary()) +) -> styling(FRL). +highlight(Styling, First, Second, Matching) -> + erlang:setelement( + 4, + Styling, + {some, {highlighters, First, Second, Matching}} + ). + +-spec serialize(styling(FRO), fun((part(FRO)) -> binary())) -> styling(FRO). +serialize(Styling, Serializer) -> + erlang:setelement(3, Styling, {some, Serializer}). + +-spec first_highlight_default(binary()) -> binary(). +first_highlight_default(String) -> + case String of + <<" "/utf8>> -> + _pipe = String, + _pipe@1 = gleam_community@ansi:underline(_pipe), + _pipe@2 = gleam_community@ansi:bold(_pipe@1), + gleam_community@ansi:green(_pipe@2); + + _ -> + _pipe@3 = String, + _pipe@4 = gleam_community@ansi:green(_pipe@3), + gleam_community@ansi:bold(_pipe@4) + end. + +-spec second_highlight_default(binary()) -> binary(). +second_highlight_default(String) -> + case String of + <<" "/utf8>> -> + _pipe = String, + _pipe@1 = gleam_community@ansi:underline(_pipe), + _pipe@2 = gleam_community@ansi:bold(_pipe@1), + gleam_community@ansi:red(_pipe@2); + + _ -> + _pipe@3 = String, + _pipe@4 = gleam_community@ansi:red(_pipe@3), + gleam_community@ansi:bold(_pipe@4) + end. + +-spec no_highlight(binary()) -> binary(). +no_highlight(String) -> + String. + +-spec string_serializer(part(binary())) -> binary(). +string_serializer(Part) -> + case Part of + {part, Acc, Sequence, Highlight} -> + <<Acc/binary, + (begin + _pipe = Sequence, + _pipe@1 = gleam@list:map(_pipe, Highlight), + gleam@string:join(_pipe@1, <<""/utf8>>) + end)/binary>>; + + {all, String} -> + String + end. + +-spec mk_generic_serializer(binary(), fun((binary()) -> binary())) -> fun((part(any())) -> binary()). +mk_generic_serializer(Separator, Around) -> + fun(Part) -> case Part of + {part, Acc, Sequence, Highlight} -> + Segment_separator = case Acc of + <<""/utf8>> -> + <<""/utf8>>; + + _ -> + Separator + end, + <<<<Acc/binary, Segment_separator/binary>>/binary, + (begin + _pipe = Sequence, + _pipe@1 = gleam@list:map( + _pipe, + fun gleam@string:inspect/1 + ), + _pipe@2 = gleam@list:map(_pipe@1, Highlight), + gleam@string:join(_pipe@2, Separator) + end)/binary>>; + + {all, String} -> + Around(String) + end end. + +-spec generic_serializer(part(any())) -> binary(). +generic_serializer(Part) -> + (mk_generic_serializer( + <<", "/utf8>>, + fun(All) -> <<<<"["/utf8, All/binary>>/binary, "]"/utf8>> end + ))(Part). + +-spec to_strings( + list(gap@comparison:match(list(FRY))), + list(gap@comparison:match(list(FRY))), + fun((part(FRY)) -> binary()), + fun((binary()) -> binary()), + fun((binary()) -> binary()), + fun((binary()) -> binary()) +) -> gap@styled_comparison:styled_comparison(). +to_strings( + First, + Second, + Serializer, + First_highlight, + Second_highlight, + No_highlight +) -> + First_styled = begin + _pipe = First, + gleam@list:fold(_pipe, <<""/utf8>>, fun(Str, Match) -> case Match of + {match, Item} -> + Serializer({part, Str, Item, No_highlight}); + + {no_match, Item@1} -> + Serializer({part, Str, Item@1, First_highlight}) + end end) + end, + Second_styled = begin + _pipe@1 = Second, + gleam@list:fold( + _pipe@1, + <<""/utf8>>, + fun(Str@1, Match@1) -> case Match@1 of + {match, Item@2} -> + Serializer({part, Str@1, Item@2, No_highlight}); + + {no_match, Item@3} -> + Serializer({part, Str@1, Item@3, Second_highlight}) + end end + ) + end, + {styled_comparison, + Serializer({all, First_styled}), + Serializer({all, Second_styled})}. + +-spec to_styled_comparison(styling(any())) -> gap@styled_comparison:styled_comparison(). +to_styled_comparison(Styling) -> + Highlight = begin + _pipe = erlang:element(4, Styling), + gleam@option:unwrap( + _pipe, + {highlighters, + fun first_highlight_default/1, + fun second_highlight_default/1, + fun no_highlight/1} + ) + end, + case erlang:element(2, Styling) of + {string_comparison, First, Second} -> + to_strings( + First, + Second, + fun string_serializer/1, + erlang:element(2, Highlight), + erlang:element(3, Highlight), + erlang:element(4, Highlight) + ); + + {list_comparison, First@1, Second@1} -> + to_strings( + First@1, + Second@1, + gleam@option:unwrap( + erlang:element(3, Styling), + fun generic_serializer/1 + ), + erlang:element(2, Highlight), + erlang:element(3, Highlight), + erlang:element(4, Highlight) + ) + end. diff --git a/aoc2023/build/packages/gap/src/gap_ffi.mjs b/aoc2023/build/packages/gap/src/gap_ffi.mjs new file mode 100644 index 0000000..235c80b --- /dev/null +++ b/aoc2023/build/packages/gap/src/gap_ffi.mjs @@ -0,0 +1,431 @@ +import { + Error, + List, + Ok, + inspect, + toList, + makeError, + isEqual, +} from "./gleam.mjs"; +import * as $option from "../gleam_stdlib/gleam/option.mjs"; + +const HASHCODE_CACHE = new WeakMap(); +const Nil = undefined; + +class MutableMap { + static #hashcode_cache = new WeakMap(); + + static hash(value) { + let existing = this.#hashcode_cache.get(value); + if (existing) { + return existing; + } else if (value instanceof Object) { + let hashcode = inspect(value); + HASHCODE_CACHE.set(value, hashcode); + return hashcode; + } else { + return value.toString(); + } + } + + constructor() { + this.entries = new globalThis.Map(); + } + + get size() { + return this.entries.size; + } + + inspect() { + let entries = [...this.entries.values()] + .map((pair) => inspect(pair)) + .join(", "); + return `map.from_list([${entries}])`; + } + + toList() { + return List.fromArray([...this.entries.values()]); + } + + insert(k, v) { + this.entries.set(MutableMap.hash(k), [k, v]); + return this; + } + + delete(k) { + this.entries.delete(MutableMap.hash(k)); + return this; + } + + get(key) { + let code = MutableMap.hash(key); + if (this.entries.has(code)) { + return new Ok(this.entries.get(code)[1]); + } else { + return new Error(Nil); + } + } +} + +export function new_mutable_map() { + return new MutableMap(); +} + +export function mutable_map_size(map) { + return map.size; +} + +export function mutable_map_to_list(map) { + return map.toList(); +} + +export function mutable_map_remove(k, map) { + return map.delete(k); +} + +export function mutable_map_get(map, key) { + return map.get(key); +} + +export function mutable_map_insert(key, value, map) { + return map.insert(key, value); +} + +// From map.mjs + +export function size(map) { + return mutable_map_size(map); +} + +export function to_list(map) { + return mutable_map_to_list(map); +} + +export function new$() { + return new_mutable_map(); +} + +export function get(from, get) { + return mutable_map_get(from, get); +} + +function do_has_key(key, map) { + return !isEqual(get(map, key), new Error(undefined)); +} + +export function has_key(map, key) { + return do_has_key(key, map); +} + +export function insert(map, key, value) { + return mutable_map_insert(key, value, map); +} + +function insert_pair(map, pair) { + return insert(map, pair[0], pair[1]); +} + +export function update(map, key, fun) { + let _pipe = map; + let _pipe$1 = get(_pipe, key); + let _pipe$2 = $option.from_result(_pipe$1); + let _pipe$3 = fun(_pipe$2); + return ((_capture) => { + return insert(map, key, _capture); + })(_pipe$3); +} + +export function delete$(map, key) { + return mutable_map_remove(key, map); +} + +function fold_list_of_pair(loop$list, loop$initial) { + while (true) { + let list = loop$list; + let initial = loop$initial; + if (list.hasLength(0)) { + return initial; + } else if (list.atLeastLength(1)) { + let x = list.head; + let rest = list.tail; + loop$list = rest; + loop$initial = insert(initial, x[0], x[1]); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 98, + "fold_list_of_pair", + "No case clause matched", + { values: [list] } + ); + } + } +} + +function do_from_list(list) { + return fold_list_of_pair(list, new$()); +} + +export function from_list(list) { + return do_from_list(list); +} + +function do_fold(loop$list, loop$initial, loop$fun) { + while (true) { + let list = loop$list; + let initial = loop$initial; + let fun = loop$fun; + if (list.hasLength(0)) { + return initial; + } else if (list.atLeastLength(1)) { + let k = list.head[0]; + let v = list.head[1]; + let tail = list.tail; + loop$list = tail; + loop$initial = fun(initial, k, v); + loop$fun = fun; + } else { + throw makeError( + "case_no_match", + "gleam/map", + 558, + "do_fold", + "No case clause matched", + { values: [list] } + ); + } + } +} + +export function fold(map, initial, fun) { + let _pipe = map; + let _pipe$1 = to_list(_pipe); + return do_fold(_pipe$1, initial, fun); +} + +function do_map_values(f, map) { + let f$1 = (map, k, v) => { + return insert(map, k, f(k, v)); + }; + let _pipe = map; + return fold(_pipe, new$(), f$1); +} + +export function map_values(map, fun) { + return do_map_values(fun, map); +} + +function do_filter(f, map) { + let insert$1 = (map, k, v) => { + let $ = f(k, v); + if ($) { + return insert(map, k, v); + } else { + return map; + } + }; + let _pipe = map; + return fold(_pipe, new$(), insert$1); +} + +export function filter(map, property) { + return do_filter(property, map); +} + +function do_keys_acc(loop$list, loop$acc) { + while (true) { + let list = loop$list; + let acc = loop$acc; + if (list.hasLength(0)) { + return reverse_and_concat(acc, toList([])); + } else if (list.atLeastLength(1)) { + let x = list.head; + let xs = list.tail; + loop$list = xs; + loop$acc = toList([x[0]], acc); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 276, + "do_keys_acc", + "No case clause matched", + { values: [list] } + ); + } + } +} + +function do_keys(map) { + let list_of_pairs = (() => { + let _pipe = map; + return to_list(_pipe); + })(); + return do_keys_acc(list_of_pairs, toList([])); +} + +export function keys(map) { + return do_keys(map); +} + +function reverse_and_concat(loop$remaining, loop$accumulator) { + while (true) { + let remaining = loop$remaining; + let accumulator = loop$accumulator; + if (remaining.hasLength(0)) { + return accumulator; + } else if (remaining.atLeastLength(1)) { + let item = remaining.head; + let rest = remaining.tail; + loop$remaining = rest; + loop$accumulator = toList([item], accumulator); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 269, + "reverse_and_concat", + "No case clause matched", + { values: [remaining] } + ); + } + } +} + +function do_values_acc(loop$list, loop$acc) { + while (true) { + let list = loop$list; + let acc = loop$acc; + if (list.hasLength(0)) { + return reverse_and_concat(acc, toList([])); + } else if (list.atLeastLength(1)) { + let x = list.head; + let xs = list.tail; + loop$list = xs; + loop$acc = toList([x[1]], acc); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 314, + "do_values_acc", + "No case clause matched", + { values: [list] } + ); + } + } +} + +function do_values(map) { + let list_of_pairs = (() => { + let _pipe = map; + return to_list(_pipe); + })(); + return do_values_acc(list_of_pairs, toList([])); +} + +export function values(map) { + return do_values(map); +} + +function insert_taken(loop$map, loop$desired_keys, loop$acc) { + while (true) { + let map = loop$map; + let desired_keys = loop$desired_keys; + let acc = loop$acc; + let insert$1 = (taken, key) => { + let $ = get(map, key); + if ($.isOk()) { + let value = $[0]; + return insert(taken, key, value); + } else { + return taken; + } + }; + if (desired_keys.hasLength(0)) { + return acc; + } else if (desired_keys.atLeastLength(1)) { + let x = desired_keys.head; + let xs = desired_keys.tail; + loop$map = map; + loop$desired_keys = xs; + loop$acc = insert$1(acc, x); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 411, + "insert_taken", + "No case clause matched", + { values: [desired_keys] } + ); + } + } +} + +function do_take(desired_keys, map) { + return insert_taken(map, desired_keys, new$()); +} + +export function take(map, desired_keys) { + return do_take(desired_keys, map); +} + +function fold_inserts(loop$new_entries, loop$map) { + while (true) { + let new_entries = loop$new_entries; + let map = loop$map; + if (new_entries.hasLength(0)) { + return map; + } else if (new_entries.atLeastLength(1)) { + let x = new_entries.head; + let xs = new_entries.tail; + loop$new_entries = xs; + loop$map = insert_pair(map, x); + } else { + throw makeError( + "case_no_match", + "gleam/map", + 451, + "fold_inserts", + "No case clause matched", + { values: [new_entries] } + ); + } + } +} + +function do_merge(map, new_entries) { + let _pipe = new_entries; + let _pipe$1 = to_list(_pipe); + return fold_inserts(_pipe$1, map); +} + +export function merge(map, new_entries) { + return do_merge(map, new_entries); +} + +export function drop(loop$map, loop$disallowed_keys) { + while (true) { + let map = loop$map; + let disallowed_keys = loop$disallowed_keys; + if (disallowed_keys.hasLength(0)) { + return map; + } else if (disallowed_keys.atLeastLength(1)) { + let x = disallowed_keys.head; + let xs = disallowed_keys.tail; + loop$map = delete$(map, x); + loop$disallowed_keys = xs; + } else { + throw makeError( + "case_no_match", + "gleam/map", + 514, + "drop", + "No case clause matched", + { values: [disallowed_keys] } + ); + } + } +} diff --git a/aoc2023/build/packages/gleam.lock b/aoc2023/build/packages/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/packages/gleam.lock diff --git a/aoc2023/build/packages/gleam_community_ansi/LICENCE b/aoc2023/build/packages/gleam_community_ansi/LICENCE new file mode 100644 index 0000000..a84f0ec --- /dev/null +++ b/aoc2023/build/packages/gleam_community_ansi/LICENCE @@ -0,0 +1,190 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2023 Gleam Community Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
\ No newline at end of file diff --git a/aoc2023/build/packages/gleam_community_ansi/README.md b/aoc2023/build/packages/gleam_community_ansi/README.md new file mode 100644 index 0000000..90ab0d5 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_ansi/README.md @@ -0,0 +1,72 @@ +# gleam-community/ansi + +Format text with ANSI escape sequences. + +[](https://hex.pm/packages/gleam_community_ansi) +[](https://hexdocs.pm/gleam_community_ansi/) + +✨ This project is written in _pure Gleam_ so you can use it anywhere Gleam runs: +Erlang, Elixir, Node, Deno, even [some browsers](https://bit.ly/devtools-console-ansi-support)! + +--- + +## Quickstart + +```gleam +import gleam/io +import gleam_community/ansi + +pub fn main() { + let greeting = "Hello, " <> ansi.pink("world") <> "!" + + greeting + |> ansi.bg_white + |> io.println +} + +``` + +## Installation + +`gleam_community` packages are published to [hex.pm](https://hex.pm/packages/gleam_community_ansi) +with the prefix `gleam_community_`. You can add them to your Gleam projects directly: + +```sh +gleam add gleam_community_ansi +``` + +The docs can be found over at [hexdocs.pm](https://hexdocs.pm/gleam_community_ansi). + +## ANSI-what? + +ANSI escape sequences date back to the 70s as a standard way to format text on +various video text terminals. Since then they have been adopted by many software +terminal emulators and platforms, including some Web browsers, and are a simple +way to format text without platform-specific APIs. + +The point of this package is to abstract the specific codes away and give you an +easy-to-understand API for formatting and colouring terminal text. Still, here is +a quick couple of examples of what's happening under the hood. + +You can copy these examples straight into your terminal to see them in action! + +- Colour text yellow: + + ```shell + $ echo "\e[33mhello" + ``` + +- Colour the background pink: + + ```shell + $ echo "\e[45mhello" + ``` + +- Render text italic: + + ```shell + $ echo "\e[3mhello\e[23m" + ``` + +As you can see, the escape sequences are a bit obscure. Sure, you could hard code +them, or you could use this package! diff --git a/aoc2023/build/packages/gleam_community_ansi/gleam.toml b/aoc2023/build/packages/gleam_community_ansi/gleam.toml new file mode 100644 index 0000000..5da1f7e --- /dev/null +++ b/aoc2023/build/packages/gleam_community_ansi/gleam.toml @@ -0,0 +1,13 @@ +name = "gleam_community_ansi" +version = "1.2.0" +licences = ["Apache-2.0"] +description = "ANSI colours, formatting, and control codes" +repository = { type = "github", user = "gleam-community", repo = "ansi" } +gleam = ">= 0.32.0" + +[dependencies] +gleam_stdlib = "~> 0.32" +gleam_community_colour = "~> 1.2" + +[dev-dependencies] +gleeunit = "~> 0.11" diff --git a/aoc2023/build/packages/gleam_community_ansi/src/gleam_community/ansi.gleam b/aoc2023/build/packages/gleam_community_ansi/src/gleam_community/ansi.gleam new file mode 100644 index 0000000..a542dda --- /dev/null +++ b/aoc2023/build/packages/gleam_community_ansi/src/gleam_community/ansi.gleam @@ -0,0 +1,2317 @@ +//// +//// - **Text style** +//// - [`bold`](#bold) +//// - [`italic`](#italic) +//// - [`underline`](#underline) +//// - [`strikethrough`](#strikethrough) +//// - [`inverse`](#inverse) +//// - [`dim`](#dim) +//// - [`hidden`](#hidden) +//// - [`reset`](#reset) +//// - **Text colour** +//// - [`black`](#black) +//// - [`red`](#red) +//// - [`green`](#green) +//// - [`yellow`](#yellow) +//// - [`blue`](#blue) +//// - [`magenta`](#magenta) +//// - [`cyan`](#cyan) +//// - [`white`](#white) +//// - [`pink`](#pink) +//// - [`grey`](#grey) +//// - [`gray`](#gray) +//// - [`bright_black`](#bright_black) +//// - [`bright_red`](#bright_red) +//// - [`bright_green`](#bright_green) +//// - [`bright_yellow`](#bright_yellow) +//// - [`bright_blue`](#bright_blue) +//// - [`bright_magenta`](#bright_magenta) +//// - [`bright_cyan`](#bright_cyan) +//// - [`bright_white`](#bright_white) +//// - [`hex`](#hex) +//// - [`colour`](#colour) +//// - [`color`](#color) +//// - **Background colour** +//// - [`bg_black`](#bg_black) +//// - [`bg_red`](#bg_red) +//// - [`bg_green`](#bg_green) +//// - [`bg_yellow`](#bg_yellow) +//// - [`bg_blue`](#bg_blue) +//// - [`bg_magenta`](#bg_magenta) +//// - [`bg_cyan`](#bg_cyan) +//// - [`bg_white`](#bg_white) +//// - [`bg_pink`](#bg_pink) +//// - [`bg_bright_black`](#bg_bright_black) +//// - [`bg_bright_red`](#bg_bright_red) +//// - [`bg_bright_green`](#bg_bright_green) +//// - [`bg_bright_yellow`](#bg_bright_yellow) +//// - [`bg_bright_blue`](#bg_bright_blue) +//// - [`bg_bright_magenta`](#bg_bright_magenta) +//// - [`bg_bright_cyan`](#bg_bright_cyan) +//// - [`bg_bright_white`](#bg_bright_white) +//// - [`bg_hex`](#bg_hex) +//// - [`bg_colour`](#bg_colour) +//// - [`bg_color`](#bg_color) +//// +//// --- +//// +//// This package was heavily inspired by the `colours` module in the Deno standard +//// library. The original source code can be found +//// <a href="https://deno.land/std@0.167.0/fmt/colours.ts">here</a>. +//// +//// <details> +//// <summary>The license of that package is produced below:</summary> +//// +//// +//// > MIT License +//// +//// > Copyright 2018-2022 the Deno authors. +//// +//// > 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. +//// </details> +//// + +// Just in case we decide in the future to no longer include the above reference +// and license, this package was initially a port of the Deno `colours` module: +// +// https://deno.land/std@0.167.0/fmt/colours.ts +// + +// This seems like a really handy reference if/when we want to expand this beyond +// formatting escape sequences: +// +// https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 +// + +// IMPORTS -------------------------------------------------------------------- + +import gleam/int +import gleam/list +import gleam/string +import gleam_community/colour.{type Colour} as gc_colour + +// CONSTS --------------------------------------------------------------------- + +const asci_escape_character = "" + +// TYPES ---------------------------------------------------------------------- + +type Code { + Code(open: String, close: String, regexp: String) +} + +// UTILITY -------------------------------------------------------------------- + +/// Builds colour code +fn code(open: List(Int), close: Int) -> Code { + let close_str = int.to_string(close) + let open_strs = list.map(open, int.to_string) + + Code( + open: asci_escape_character <> "[" <> string.join(open_strs, ";") <> "m", + close: asci_escape_character <> "[" <> close_str <> "m", + regexp: asci_escape_character <> "[" <> close_str <> "m", + ) +} + +/// Applies colour and background based on colour code and its associated text +fn run(text: String, code: Code) -> String { + code.open <> string.replace(text, code.regexp, code.open) <> code.close +} + +// STYLES --------------------------------------------------------------------- + +/// Reset the text modified +pub fn reset(text: String) -> String { + run(text, code([0], 0)) +} + +/// Style the given text bold. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bold("lucy") +/// // => "\x1B[1mlucy\x1B[22m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[22m"` added to the string. This is the escape code +/// for the "default" bold/dim style of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// style, it will use both the outter style and the inner style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.dim("Isn't " <> ansi.bold("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be dim but the text "fun?" will be +/// both underlined, *and* bold! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bold(text: String) -> String { + run(text, code([1], 22)) +} + +/// Style the given text's colour to be dimmer. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.dim("lucy") +/// // => "\x1B[2mlucy\x1B[22m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[22m"` added to the string. This is the escape code +/// for the "default" bold/dim style of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// style, it will use both the outter style and the inner style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.dim("Isn't " <> ansi.bold("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be dim but the text "fun?" will be +/// both underlined, *and* bold! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn dim(text: String) -> String { + run(text, code([2], 22)) +} + +/// Style the given text italic. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.italic("lucy") +/// // => "\x1B[3mlucy\x1B[23m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[23m"` added to the string. This is the escape code +/// for the "default" italic style of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// style, it will use both the outter style and the inner style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.underline("Isn't " <> ansi.bold("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be underlined but the text "fun?" will be +/// both underlined, *and* bold! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn italic(text: String) -> String { + run(text, code([3], 23)) +} + +/// Style the given text's colour to be dimmer. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.underline("lucy") +/// // => "\x1B[4mlucy\x1B[24m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[24m"` added to the string. This is the escape code +/// for the "default" underline style of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// style, it will use both the outter style and the inner style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.dim("Isn't " <> ansi.bold("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be dim but the text "fun?" will be +/// both underlined, *and* bold! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn underline(text: String) -> String { + run(text, code([4], 24)) +} + +/// Inverse the given text's colour, and background colour. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.inverse("lucy") +/// // => "\x1B[7mlucy\x1B[27m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[27m"` added to the string. This is the escape code +/// for the "default" inverse style of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// style, it will use both the outter style and the inner style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.dim("Isn't " <> ansi.bold("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be dim but the text "fun?" will be +/// both underlined, *and* bold! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn inverse(text: String) -> String { + run(text, code([7], 27)) +} + +/// Style the given text to be hidden. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.hidden("lucy") +/// // => "\x1B[8mlucy\x1B[28m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[28m"` added to the string. This is the escape code +/// for the "default" hidden style of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// style, it will use both the outter style and the inner style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.dim("Isn't " <> ansi.bold("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be dim but the text "fun?" will be +/// both underlined, *and* bold! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn hidden(text: String) -> String { + run(text, code([8], 28)) +} + +/// Style the given text to be striked through. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.strikethrough("lucy") +/// // => "\x1B[9mlucy\x1B[29m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[29m"` added to the string. This is the escape code +/// for the "default" strikethrough style of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// style, it will use both the outter style and the inner style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.dim("Isn't " <> ansi.bold("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be dim but the text "fun?" will be +/// both underlined, *and* bold! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn strikethrough(text: String) -> String { + run(text, code([9], 29)) +} + +// FOREGROUND ----------------------------------------------------------------- + +/// Colour the given text black. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.black("lucy") +/// // => "\x1B[30mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn black(text: String) -> String { + run(text, code([30], 39)) +} + +/// Colour the given text red. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.red("lucy") +/// // => "\x1B[31mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn red(text: String) -> String { + run(text, code([31], 39)) +} + +/// Colour the given text green. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.green("lucy") +/// // => "\x1B[32mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn green(text: String) -> String { + run(text, code([32], 39)) +} + +/// Colour the given text yellow. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("lucy") +/// // => "\x1B[33mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn yellow(text: String) -> String { + run(text, code([33], 39)) +} + +/// Colour the given text blue. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.blue("lucy") +/// // => "\x1B[34mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn blue(text: String) -> String { + run(text, code([34], 39)) +} + +/// Colour the given text magenta. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.magenta("lucy") +/// // => "\x1B[35mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn magenta(text: String) -> String { + run(text, code([35], 39)) +} + +/// Colour the given text cyan. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.cyan("lucy") +/// // => "\x1B[36mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn cyan(text: String) -> String { + run(text, code([36], 39)) +} + +/// Colour the given text white. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.white("lucy") +/// // => "\x1B[37mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn white(text: String) -> String { + run(text, code([37], 39)) +} + +/// Colour the given text gray. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.gray("lucy") +/// // => "\x1B[90mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn grey(text: String) -> String { + bright_black(text) +} + +/// This is an alias for [`grey`](#grey) for those who prefer the American English +/// spelling. +/// +pub fn gray(text: String) -> String { + bright_black(text) +} + +/// Colour the given text bright black. This should increase the luminosity of +/// the base colour, but some terminals will interpret this as bold instead. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bright_black("lucy") +/// // => "\x1B[90mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bright_black(text: String) -> String { + run(text, code([90], 39)) +} + +/// Colour the given text bright red. This should increase the luminosity of +/// the base colour, but some terminals will interpret this as bold instead. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bright_red("lucy") +/// // => "\x1B[91mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bright_red(text: String) -> String { + run(text, code([91], 39)) +} + +/// Colour the given text bright green. This should increase the luminosity of +/// the base colour, but some terminals will interpret this as bold instead. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// ansi.bright_green("lucy") +/// // => "\x1B[92mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href=""> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bright_green(text: String) -> String { + run(text, code([92], 39)) +} + +/// Colour the given text bright yellow. This should increase the luminosity of +/// the base colour, but some terminals will interpret this as bold instead. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// ansi.bright_yellow("lucy") +/// // => "\x1B[93mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href=""> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bright_yellow(text: String) -> String { + run(text, code([93], 39)) +} + +/// Colour the given text bright blue. This should increase the luminosity of +/// the base colour, but some terminals will interpret this as bold instead. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// ansi.bright_blue("lucy") +/// // => "\x1B[94mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href=""> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bright_blue(text: String) -> String { + run(text, code([94], 39)) +} + +/// Colour the given text bright gremagentaen. This should increase the luminosity +/// of the base colour, but some terminals will interpret this as bold instead. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// ansi.bright_magenta("lucy") +/// // => "\x1B[95mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href=""> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bright_magenta(text: String) -> String { + run(text, code([95], 39)) +} + +/// Colour the given text bright cyan. This should increase the luminosity of +/// the base colour, but some terminals will interpret this as bold instead. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// ansi.bright_cyan("lucy") +/// // => "\x1B[96mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href=""> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bright_cyan(text: String) -> String { + run(text, code([96], 39)) +} + +/// Colour the given text bright white. This should increase the luminosity of +/// the base colour, but some terminals will interpret this as bold instead. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// ansi.bright_white("lucy") +/// // => "\x1B[97mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href=""> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bright_white(text: String) -> String { + run(text, code([97], 39)) +} + +/// Colour the given text pink. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.pink("lucy") +/// // => "\x1B[38;2;255;175;243mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[39m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn pink(text: String) -> String { + hex(text, 0xffaff3) +} + +/// Colour the given text the given colour represented by a hex `Int`. +/// +/// The given hex Int can be any valid [shorthand hexadecimal form](https://en.wikipedia.org/wiki/Web_colors#Shorthand_hexadecimal_form). +/// +/// ❗️ Note that if supplied hex Int is less than 0 or larger than 0xfffff the +/// colour will be set to black and white respectively. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.hex("lucy", 0xffaff3) +/// // => "\x1B[38;2;255;175;243mlucy\x1B[39m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn hex(text: String, colour: Int) -> String { + let colour = int.clamp(colour, max: 0xffffff, min: 0x0) + run( + text, + code( + [ + 38, + 2, + int.bitwise_shift_right(colour, 16) + |> int.bitwise_and(0xff), + int.bitwise_shift_right(colour, 8) + |> int.bitwise_and(0xff), + int.bitwise_and(colour, 0xff), + ], + 39, + ), + ) +} + +/// Colour the given text the given colour represented by a `Colour`. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// import gleam_community/colour.{Colour} +/// +/// fn example() { +/// let pink = colour.from_hsl(0.8583, 1.0, 0,84) +/// ansi.colour("lucy", pink) +/// // => "\x1B[48;2;255;175;243mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn colour(text: String, colour: Colour) -> String { + let hex_colour = gc_colour.to_rgb_hex(colour) + hex(text, hex_colour) +} + +/// This is an alias for [`colour`](#colour) for those who prefer the American English +/// spelling. +/// +pub fn color(text: String, color: Colour) -> String { + colour(text, color) +} + +// BACKGROUND ----------------------------------------------------------------- + +/// Colour the given text's background black. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_black("lucy") +/// // => "\x1B[40mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_black(text: String) -> String { + run(text, code([40], 49)) +} + +/// Colour the given text's background red. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_red("lucy") +/// // => "\x1B[41mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_red(text: String) -> String { + run(text, code([41], 49)) +} + +/// Colour the given text's background green. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_green("lucy") +/// // => "\x1B[42mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_green(text: String) -> String { + run(text, code([42], 49)) +} + +/// Colour the given text's background yellow. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_yellow("lucy") +/// // => "\x1B[43mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_yellow(text: String) -> String { + run(text, code([43], 49)) +} + +/// Colour the given text's background blue. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_blue("lucy") +/// // => "\x1B[44mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_blue(text: String) -> String { + run(text, code([44], 49)) +} + +/// Colour the given text's background magenta. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_magenta("lucy") +/// // => "\x1B[45mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_magenta(text: String) -> String { + run(text, code([45], 49)) +} + +/// Colour the given text's background cyan. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_cyan("lucy") +/// // => "\x1B[46mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_cyan(text: String) -> String { + run(text, code([46], 49)) +} + +/// Colour the given text's background white. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_white("lucy") +/// // => "\x1B[47mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_white(text: String) -> String { + run(text, code([47], 49)) +} + +/// Colour the given text's background bright black. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_bright_black("lucy") +/// // => "\x1B[100mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_bright_black(text: String) -> String { + run(text, code([100], 49)) +} + +/// Colour the given text's background bright red. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_bright_red("lucy") +/// // => "\x1B[101mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_bright_red(text: String) -> String { + run(text, code([101], 49)) +} + +/// Colour the given text's background bright green. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_bright_green("lucy") +/// // => "\x1B[102mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_bright_green(text: String) -> String { + run(text, code([102], 49)) +} + +/// Colour the given text's background bright yellow. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_bright_yellow("lucy") +/// // => "\x1B[103mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_bright_yellow(text: String) -> String { + run(text, code([103], 49)) +} + +/// Colour the given text's background bright blue. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_bright_blue("lucy") +/// // => "\x1B[104mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_bright_blue(text: String) -> String { + run(text, code([104], 49)) +} + +/// Colour the given text's background bright magenta. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_bright_magenta("lucy") +/// // => "\x1B[105mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_bright_magenta(text: String) -> String { + run(text, code([105], 49)) +} + +/// Colour the given text's background bright cyan. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_bright_cyan("lucy") +/// // => "\x1B[106mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_bright_cyan(text: String) -> String { + run(text, code([106], 49)) +} + +/// Colour the given text's background bright white. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_bright_white("lucy") +/// // => "\x1B[107mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_bright_white(text: String) -> String { + run(text, code([107], 49)) +} + +/// Colour the given text's background pink. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.bg_pink("lucy") +/// // => "\x1B[48;2;255;175;243mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_pink(text: String) -> String { + bg_hex(text, 0xffaff3) +} + +/// Colour the given text's background the given colour represented by a hex `Int`. +/// +/// The given hex Int can be any valid [shorthand hexadecimal form](https://en.wikipedia.org/wiki/Web_colors#Shorthand_hexadecimal_form). +/// +/// ❗️ Note that if supplied hex Int is less than 0 or larger than 0xfffff the +/// colour will be set to black and white respectively. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.hex("lucy", 0xffaff3) +/// // => "\x1B[48;2;255;175;243mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_hex(text: String, colour: Int) -> String { + run( + text, + code( + [ + 48, + 2, + int.bitwise_shift_right(colour, 16) + |> int.bitwise_and(0xff), + int.bitwise_shift_right(colour, 8) + |> int.bitwise_and(0xff), + int.bitwise_and(colour, 0xff), + ], + 49, + ), + ) +} + +/// Colour the given text's background with the given colour represented by a `Colour`. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// import gleam_community/ansi +/// import gleam_community/colour.{Colour} +/// +/// fn example() { +/// let pink = colour.from_hsl(0.8583, 1.0, 0,84) +/// ansi.bg_colour("lucy", pink) +/// // => "\x1B[48;2;255;175;243mlucy\x1B[49m" +/// } +/// ``` +/// +/// ❗️ Note the trailing `"\x1B[49m"` added to the string. This is the escape code +/// for the "default" colour of the terminal. This means text you write after +/// this will revert back to default. +/// +/// ✨ `gleam_community/ansi` is smart about nested styles; instead of using the default +/// colour, it will use the colour of the outter style. +/// +/// ```gleam +/// import gleam_community/ansi +/// +/// fn example() { +/// ansi.yellow("Isn't " <> ansi.pink("Gleam") <> " fun?") +/// } +/// ``` +/// +/// In this example, the text "Gleam" will be pink but the text "fun?" will be +/// yellow, *not* the default colour! +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/ansi/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn bg_colour(text: String, colour: Colour) -> String { + let hex_colour = gc_colour.to_rgb_hex(colour) + bg_hex(text, hex_colour) +} + +/// This is an alias for [`bg_colour`](#bg_colour) for those who prefer the American English +/// spelling. +/// +pub fn bg_color(text: String, colour: Colour) -> String { + bg_colour(text, colour) +} diff --git a/aoc2023/build/packages/gleam_community_ansi/src/gleam_community@ansi.erl b/aoc2023/build/packages/gleam_community_ansi/src/gleam_community@ansi.erl new file mode 100644 index 0000000..8b7a4c9 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_ansi/src/gleam_community@ansi.erl @@ -0,0 +1,263 @@ +-module(gleam_community@ansi). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([reset/1, bold/1, dim/1, italic/1, underline/1, inverse/1, hidden/1, strikethrough/1, black/1, red/1, green/1, yellow/1, blue/1, magenta/1, cyan/1, white/1, bright_black/1, grey/1, gray/1, bright_red/1, bright_green/1, bright_yellow/1, bright_blue/1, bright_magenta/1, bright_cyan/1, bright_white/1, hex/2, pink/1, colour/2, color/2, bg_black/1, bg_red/1, bg_green/1, bg_yellow/1, bg_blue/1, bg_magenta/1, bg_cyan/1, bg_white/1, bg_bright_black/1, bg_bright_red/1, bg_bright_green/1, bg_bright_yellow/1, bg_bright_blue/1, bg_bright_magenta/1, bg_bright_cyan/1, bg_bright_white/1, bg_hex/2, bg_pink/1, bg_colour/2, bg_color/2]). +-export_type([code/0]). + +-type code() :: {code, binary(), binary(), binary()}. + +-spec code(list(integer()), integer()) -> code(). +code(Open, Close) -> + Close_str = gleam@int:to_string(Close), + Open_strs = gleam@list:map(Open, fun gleam@int:to_string/1), + {code, + <<<<<<""/utf8, "["/utf8>>/binary, + (gleam@string:join(Open_strs, <<";"/utf8>>))/binary>>/binary, + "m"/utf8>>, + <<<<<<""/utf8, "["/utf8>>/binary, Close_str/binary>>/binary, "m"/utf8>>, + <<<<<<""/utf8, "["/utf8>>/binary, Close_str/binary>>/binary, "m"/utf8>>}. + +-spec run(binary(), code()) -> binary(). +run(Text, Code) -> + <<<<(erlang:element(2, Code))/binary, + (gleam@string:replace( + Text, + erlang:element(4, Code), + erlang:element(2, Code) + ))/binary>>/binary, + (erlang:element(3, Code))/binary>>. + +-spec reset(binary()) -> binary(). +reset(Text) -> + run(Text, code([0], 0)). + +-spec bold(binary()) -> binary(). +bold(Text) -> + run(Text, code([1], 22)). + +-spec dim(binary()) -> binary(). +dim(Text) -> + run(Text, code([2], 22)). + +-spec italic(binary()) -> binary(). +italic(Text) -> + run(Text, code([3], 23)). + +-spec underline(binary()) -> binary(). +underline(Text) -> + run(Text, code([4], 24)). + +-spec inverse(binary()) -> binary(). +inverse(Text) -> + run(Text, code([7], 27)). + +-spec hidden(binary()) -> binary(). +hidden(Text) -> + run(Text, code([8], 28)). + +-spec strikethrough(binary()) -> binary(). +strikethrough(Text) -> + run(Text, code([9], 29)). + +-spec black(binary()) -> binary(). +black(Text) -> + run(Text, code([30], 39)). + +-spec red(binary()) -> binary(). +red(Text) -> + run(Text, code([31], 39)). + +-spec green(binary()) -> binary(). +green(Text) -> + run(Text, code([32], 39)). + +-spec yellow(binary()) -> binary(). +yellow(Text) -> + run(Text, code([33], 39)). + +-spec blue(binary()) -> binary(). +blue(Text) -> + run(Text, code([34], 39)). + +-spec magenta(binary()) -> binary(). +magenta(Text) -> + run(Text, code([35], 39)). + +-spec cyan(binary()) -> binary(). +cyan(Text) -> + run(Text, code([36], 39)). + +-spec white(binary()) -> binary(). +white(Text) -> + run(Text, code([37], 39)). + +-spec bright_black(binary()) -> binary(). +bright_black(Text) -> + run(Text, code([90], 39)). + +-spec grey(binary()) -> binary(). +grey(Text) -> + bright_black(Text). + +-spec gray(binary()) -> binary(). +gray(Text) -> + bright_black(Text). + +-spec bright_red(binary()) -> binary(). +bright_red(Text) -> + run(Text, code([91], 39)). + +-spec bright_green(binary()) -> binary(). +bright_green(Text) -> + run(Text, code([92], 39)). + +-spec bright_yellow(binary()) -> binary(). +bright_yellow(Text) -> + run(Text, code([93], 39)). + +-spec bright_blue(binary()) -> binary(). +bright_blue(Text) -> + run(Text, code([94], 39)). + +-spec bright_magenta(binary()) -> binary(). +bright_magenta(Text) -> + run(Text, code([95], 39)). + +-spec bright_cyan(binary()) -> binary(). +bright_cyan(Text) -> + run(Text, code([96], 39)). + +-spec bright_white(binary()) -> binary(). +bright_white(Text) -> + run(Text, code([97], 39)). + +-spec hex(binary(), integer()) -> binary(). +hex(Text, Colour) -> + Colour@1 = gleam@int:clamp(Colour, 16#0, 16#ffffff), + run( + Text, + code( + [38, + 2, + begin + _pipe = erlang:'bsr'(Colour@1, 16), + erlang:'band'(_pipe, 16#ff) + end, + begin + _pipe@1 = erlang:'bsr'(Colour@1, 8), + erlang:'band'(_pipe@1, 16#ff) + end, + erlang:'band'(Colour@1, 16#ff)], + 39 + ) + ). + +-spec pink(binary()) -> binary(). +pink(Text) -> + hex(Text, 16#ffaff3). + +-spec colour(binary(), gleam_community@colour:colour()) -> binary(). +colour(Text, Colour) -> + Hex_colour = gleam_community@colour:to_rgb_hex(Colour), + hex(Text, Hex_colour). + +-spec color(binary(), gleam_community@colour:colour()) -> binary(). +color(Text, Color) -> + colour(Text, Color). + +-spec bg_black(binary()) -> binary(). +bg_black(Text) -> + run(Text, code([40], 49)). + +-spec bg_red(binary()) -> binary(). +bg_red(Text) -> + run(Text, code([41], 49)). + +-spec bg_green(binary()) -> binary(). +bg_green(Text) -> + run(Text, code([42], 49)). + +-spec bg_yellow(binary()) -> binary(). +bg_yellow(Text) -> + run(Text, code([43], 49)). + +-spec bg_blue(binary()) -> binary(). +bg_blue(Text) -> + run(Text, code([44], 49)). + +-spec bg_magenta(binary()) -> binary(). +bg_magenta(Text) -> + run(Text, code([45], 49)). + +-spec bg_cyan(binary()) -> binary(). +bg_cyan(Text) -> + run(Text, code([46], 49)). + +-spec bg_white(binary()) -> binary(). +bg_white(Text) -> + run(Text, code([47], 49)). + +-spec bg_bright_black(binary()) -> binary(). +bg_bright_black(Text) -> + run(Text, code([100], 49)). + +-spec bg_bright_red(binary()) -> binary(). +bg_bright_red(Text) -> + run(Text, code([101], 49)). + +-spec bg_bright_green(binary()) -> binary(). +bg_bright_green(Text) -> + run(Text, code([102], 49)). + +-spec bg_bright_yellow(binary()) -> binary(). +bg_bright_yellow(Text) -> + run(Text, code([103], 49)). + +-spec bg_bright_blue(binary()) -> binary(). +bg_bright_blue(Text) -> + run(Text, code([104], 49)). + +-spec bg_bright_magenta(binary()) -> binary(). +bg_bright_magenta(Text) -> + run(Text, code([105], 49)). + +-spec bg_bright_cyan(binary()) -> binary(). +bg_bright_cyan(Text) -> + run(Text, code([106], 49)). + +-spec bg_bright_white(binary()) -> binary(). +bg_bright_white(Text) -> + run(Text, code([107], 49)). + +-spec bg_hex(binary(), integer()) -> binary(). +bg_hex(Text, Colour) -> + run( + Text, + code( + [48, + 2, + begin + _pipe = erlang:'bsr'(Colour, 16), + erlang:'band'(_pipe, 16#ff) + end, + begin + _pipe@1 = erlang:'bsr'(Colour, 8), + erlang:'band'(_pipe@1, 16#ff) + end, + erlang:'band'(Colour, 16#ff)], + 49 + ) + ). + +-spec bg_pink(binary()) -> binary(). +bg_pink(Text) -> + bg_hex(Text, 16#ffaff3). + +-spec bg_colour(binary(), gleam_community@colour:colour()) -> binary(). +bg_colour(Text, Colour) -> + Hex_colour = gleam_community@colour:to_rgb_hex(Colour), + bg_hex(Text, Hex_colour). + +-spec bg_color(binary(), gleam_community@colour:colour()) -> binary(). +bg_color(Text, Colour) -> + bg_colour(Text, Colour). diff --git a/aoc2023/build/packages/gleam_community_ansi/src/gleam_community_ansi.app.src b/aoc2023/build/packages/gleam_community_ansi/src/gleam_community_ansi.app.src new file mode 100644 index 0000000..dfcfdc3 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_ansi/src/gleam_community_ansi.app.src @@ -0,0 +1,9 @@ +{application, gleam_community_ansi, [ + {vsn, "1.2.0"}, + {applications, [gleam_community_colour, + gleam_stdlib, + gleeunit]}, + {description, "ANSI colours, formatting, and control codes"}, + {modules, [gleam_community@ansi]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/gleam_community_colour/LICENCE b/aoc2023/build/packages/gleam_community_colour/LICENCE new file mode 100644 index 0000000..a84f0ec --- /dev/null +++ b/aoc2023/build/packages/gleam_community_colour/LICENCE @@ -0,0 +1,190 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2023 Gleam Community Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
\ No newline at end of file diff --git a/aoc2023/build/packages/gleam_community_colour/README.md b/aoc2023/build/packages/gleam_community_colour/README.md new file mode 100644 index 0000000..0eccdd7 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_colour/README.md @@ -0,0 +1,36 @@ +# gleam-community/colour + +A package for a standard Colour type, conversions, and other utilities. + +[](https://hex.pm/packages/gleam_community_colour) +[](https://hexdocs.pm/gleam_community_colour/) + +✨ This project is written in pure Gleam so you can use it anywhere Gleam runs: Erlang, Elixir, Node, Deno, and the browser! + +--- + +## Quickstart + +```gleam +import gleam_community/colour +import gleam_community/colour/accessibility + +pub fn main() { + let foreground = colour.from_hsl(h: 0.858, s: 1.0, l: 0.843) + + let background_options = [colour.light_grey, colour.dark_grey] + + let background = accessibility.maximum_contrast(foreground, background_options) +} +``` + +## Installation + +`gleam_community` packages are published to [hex.pm](https://hex.pm/packages/gleam_community_colour) +with the prefix `gleam_community_`. You can add them to your Gleam projects directly: + +```sh +gleam add gleam_community_colour +``` + +The docs can be found over at [hexdocs.pm](https://hexdocs.pm/gleam_community_colour). diff --git a/aoc2023/build/packages/gleam_community_colour/gleam.toml b/aoc2023/build/packages/gleam_community_colour/gleam.toml new file mode 100644 index 0000000..07a81bf --- /dev/null +++ b/aoc2023/build/packages/gleam_community_colour/gleam.toml @@ -0,0 +1,11 @@ +name = "gleam_community_colour" +version = "1.2.0" +licences = ["Apache-2.0"] +description = "Colour types, conversions, and other utilities" +repository = { type = "github", user = "gleam-community", repo = "colour" } + +[dependencies] +gleam_stdlib = "~> 0.32" + +[dev-dependencies] +gleeunit = "~> 0.11" diff --git a/aoc2023/build/packages/gleam_community_colour/include/gleam_community@colour_Hsla.hrl b/aoc2023/build/packages/gleam_community_colour/include/gleam_community@colour_Hsla.hrl new file mode 100644 index 0000000..06116df --- /dev/null +++ b/aoc2023/build/packages/gleam_community_colour/include/gleam_community@colour_Hsla.hrl @@ -0,0 +1 @@ +-record(hsla, {h :: float(), s :: float(), l :: float(), a :: float()}). diff --git a/aoc2023/build/packages/gleam_community_colour/include/gleam_community@colour_Rgba.hrl b/aoc2023/build/packages/gleam_community_colour/include/gleam_community@colour_Rgba.hrl new file mode 100644 index 0000000..fff139e --- /dev/null +++ b/aoc2023/build/packages/gleam_community_colour/include/gleam_community@colour_Rgba.hrl @@ -0,0 +1 @@ +-record(rgba, {r :: float(), g :: float(), b :: float(), a :: float()}). diff --git a/aoc2023/build/packages/gleam_community_colour/src/gleam_community/colour.gleam b/aoc2023/build/packages/gleam_community_colour/src/gleam_community/colour.gleam new file mode 100644 index 0000000..1f5872f --- /dev/null +++ b/aoc2023/build/packages/gleam_community_colour/src/gleam_community/colour.gleam @@ -0,0 +1,1126 @@ +//// +//// - **Types** +//// - [`Colour`](#Colour) +//// - [`Color`](#Color) +//// - **Constructors** +//// - [`from_rgb255`](#from_rgb255) +//// - [`from_rgb`](#from_rgb) +//// - [`from_rgba`](#from_rgba) +//// - [`from_hsl`](#from_hsl) +//// - [`from_hsla`](#from_hsla) +//// - [`from_rgb_hex`](#from_rgb_hex) +//// - [`from_rgba_hex`](#from_rgba_hex) +//// - [`from_rgb_hex_string`](#from_rgb_hex_string) +//// - [`from_rgba_hex_string`](#from_rgba_hex_string) +//// - **Conversions** +//// - [`to_rgba`](#to_rgba) +//// - [`to_hsla`](#hsla) +//// - [`to_css_rgba_string`](#to_css_rgba_string) +//// - [`to_rgba_hex_string`](#to_rgba_hex_string) +//// - [`to_rgb_hex_string`](#to_rgb_hex_string) +//// - [`to_rgba_hex`](#to_rgba_hex) +//// - [`to_rgb_hex`](#to_rgb_hex) +//// - **Colours** +//// - [`light_red`](#light_red) +//// - [`red`](#red) +//// - [`dark_red`](#dark_red) +//// - [`light_orange`](#light_orange) +//// - [`orange`](#orange) +//// - [`dark_orange`](#dark_orange) +//// - [`light_yellow`](#light_yellow) +//// - [`yellow`](#yellow) +//// - [`dark_yellow`](#dark_yellow) +//// - [`light_green`](#light_green) +//// - [`green`](#green) +//// - [`dark_green`](#dark_green) +//// - [`light_blue`](#light_blue) +//// - [`blue`](#blue) +//// - [`dark_blue`](#dark_blue) +//// - [`light_purple`](#light_purple) +//// - [`purple`](#purple) +//// - [`dark_purple`](#dark_purple) +//// - [`light_brown`](#light_brown) +//// - [`brown`](#brown) +//// - [`dark_brown`](#dark_brown) +//// - [`black`](#black) +//// - [`white`](#white) +//// - [`light_grey`](#light_grey) +//// - [`grey`](#grey) +//// - [`dark_grey`](#dark_grey) +//// - [`light_gray`](#light_gray) +//// - [`gray`](#gray) +//// - [`dark_gray`](#dark_gray) +//// - [`light_charcoal`](#light_charcoal) +//// - [`charcoal`](#charcoal) +//// - [`dark_charcoal`](#dark_charcoal) +//// - [`pink`](#pink) +//// +//// --- +//// +//// This package was heavily inspired by the `elm-color` module. +//// The original source code can be found +//// <a href="https://github.com/avh4/elm-color/">here</a>. +//// +//// <details> +//// <summary>The license of that package is produced below:</summary> +//// +//// +//// > MIT License +//// +//// > Copyright 2018 Aaron VonderHaar +//// +//// > Redistribution and use in source and binary forms, with or without modification, +//// are permitted provided that the following conditions are met: +//// +//// 1. Redistributions of source code must retain the above copyright notice, +//// this list of conditions and the following disclaimer. +//// +//// 2. Redistributions in binary form must reproduce the above copyright notice, +//// this list of conditions and the following disclaimer in the documentation +//// and/or other materials provided with the distribution. +//// +//// 3. Neither the name of the copyright holder nor the names of its contributors +//// may be used to endorse or promote products derived from this software without +//// specific prior written permission. +//// +//// > THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +//// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +//// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +//// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +//// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +//// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +//// +//// > The above copyright notice and this permission notice shall be included in all +//// copies or substantial portions of the Software. +//// </details> +//// + +// Just in case we decide in the future to no longer include the above reference +// and license, this package was initially a port of the `elm-color` module: +// +// https://github.com/avh4/elm-color/ +// + +// IMPORTS -------------------------------------------------------------------- + +import gleam/int +import gleam/float +import gleam/result +import gleam/string +import gleam/list + +// TYPES ---------------------------------------------------------------------- + +/// A representation of a colour that can be converted to RGBA or HSLA format. +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// </br> +/// +pub opaque type Colour { + Rgba(r: Float, g: Float, b: Float, a: Float) + Hsla(h: Float, s: Float, l: Float, a: Float) +} + +/// Type alias for `Colour` +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// </br> +/// +pub type Color = + Colour + +// UTILITY -------------------------------------------------------------------- + +fn valid_colour_value(c: Float) -> Result(Float, Nil) { + case c >. 1.0 || c <. 0.0 { + True -> Error(Nil) + False -> Ok(c) + } +} + +fn hue_to_rgb(hue: Float, m1: Float, m2: Float) -> Float { + let h = case hue { + _ if hue <. 0.0 -> hue +. 1.0 + _ if hue >. 1.0 -> hue -. 1.0 + _ -> hue + } + + let h_t_6 = h *. 6.0 + let h_t_2 = h *. 2.0 + let h_t_3 = h *. 3.0 + + case h { + _ if h_t_6 <. 1.0 -> m1 +. { m2 -. m1 } *. h *. 6.0 + _ if h_t_2 <. 1.0 -> m2 + _ if h_t_3 <. 2.0 -> m1 +. { m2 -. m1 } *. { 2.0 /. 3.0 -. h } *. 6.0 + _ -> m1 + } +} + +fn hex_string_to_int(hex_string: String) -> Result(Int, Nil) { + let hex = case hex_string { + "#" <> hex_number -> hex_number + "0x" <> hex_number -> hex_number + _ -> hex_string + } + + hex + |> string.lowercase() + |> string.to_graphemes() + |> list.reverse() + |> list.index_fold( + Ok(0), + fn(total, char, index) { + case total { + Error(Nil) -> Error(Nil) + Ok(v) -> { + use num <- result.then(case char { + "a" -> Ok(10) + "b" -> Ok(11) + "c" -> Ok(12) + "d" -> Ok(13) + "e" -> Ok(14) + "f" -> Ok(15) + _ -> int.parse(char) + }) + use base <- result.then(int.power(16, int.to_float(index))) + Ok(v + float.round(int.to_float(num) *. base)) + } + } + }, + ) +} + +fn hsla_to_rgba( + h: Float, + s: Float, + l: Float, + a: Float, +) -> #(Float, Float, Float, Float) { + let m2 = case l <=. 0.5 { + True -> l *. { s +. 1.0 } + False -> l +. s -. l *. s + } + + let m1 = l *. 2.0 -. m2 + + let r = hue_to_rgb(h +. 1.0 /. 3.0, m1, m2) + let g = hue_to_rgb(h, m1, m2) + let b = hue_to_rgb(h -. 1.0 /. 3.0, m1, m2) + + #(r, g, b, a) +} + +fn rgba_to_hsla( + r: Float, + g: Float, + b: Float, + a: Float, +) -> #(Float, Float, Float, Float) { + let min_colour = float.min(r, float.min(g, b)) + + let max_colour = float.max(r, float.max(g, b)) + + let h1 = case True { + _ if max_colour == r -> float.divide(g -. b, max_colour -. min_colour) + _ if max_colour == g -> + float.divide(b -. r, max_colour -. min_colour) + |> result.then(fn(d) { Ok(2.0 +. d) }) + _ -> + float.divide(r -. g, max_colour -. min_colour) + |> result.then(fn(d) { Ok(4.0 +. d) }) + } + + let h2 = case h1 { + Ok(v) -> Ok(v *. { 1.0 /. 6.0 }) + _ -> h1 + } + + let h3 = case h2 { + Ok(v) if v <. 0.0 -> v +. 1.0 + Ok(v) -> v + _ -> 0.0 + } + + let l = { min_colour +. max_colour } /. 2.0 + + let s = case True { + _ if min_colour == max_colour -> 0.0 + _ if l <. 0.5 -> + { max_colour -. min_colour } /. { max_colour +. min_colour } + _ -> { max_colour -. min_colour } /. { 2.0 -. max_colour -. min_colour } + } + + #(h3, s, l, a) +} + +// CONSTRUCTORS --------------------------------------------------------------- + +/// Returns a `Result(Colour)` created from the given 8 bit RGB values. +/// +/// Returns `Error(Nil)` if the supplied RGB values are greater than 255 or less than 0. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_rgb255(255, 0, 0) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn from_rgb255(r red: Int, g green: Int, b blue: Int) -> Result(Colour, Nil) { + use r <- result.then( + red + |> int.to_float() + |> float.divide(255.0) + |> result.then(valid_colour_value), + ) + + use g <- result.then( + green + |> int.to_float() + |> float.divide(255.0) + |> result.then(valid_colour_value), + ) + + use b <- result.then( + blue + |> int.to_float() + |> float.divide(255.0) + |> result.then(valid_colour_value), + ) + + Ok(Rgba(r: r, g: g, b: b, a: 1.0)) +} + +/// Returns `Result(Colour)` created from the given RGB values. +/// +/// If the supplied RGB values are greater than 1.0 or less than 0.0 returns `Error(Nil)` +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_rgb(1.0, 0.0, 0.0) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn from_rgb( + r red: Float, + g green: Float, + b blue: Float, +) -> Result(Colour, Nil) { + use r <- result.then(valid_colour_value(red)) + use g <- result.then(valid_colour_value(green)) + use b <- result.then(valid_colour_value(blue)) + + Ok(Rgba(r: r, g: g, b: b, a: 1.0)) +} + +/// Returns `Result(Colour)` created from the given RGBA values. +/// +/// Returns `Error(Nil)` if the supplied RGBA values are greater than 1.0 or less than 0.0. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red_half_opacity) = from_rbga(1.0, 0.0, 0.0, 0.5) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn from_rgba( + r red: Float, + g green: Float, + b blue: Float, + a alpha: Float, +) -> Result(Colour, Nil) { + use r <- result.then(valid_colour_value(red)) + use g <- result.then(valid_colour_value(green)) + use b <- result.then(valid_colour_value(blue)) + use a <- result.then(valid_colour_value(alpha)) + + Ok(Rgba(r: r, g: g, b: b, a: a)) +} + +/// Returns `Result(Colour)` created from the given HSLA values. +/// +/// Returns `Error(Nil)`f the supplied HSLA values are greater than 1.0 or less than 0.0. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red_half_opacity) = from_hsla(0.0, 1.0, 0.5, 0.5) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn from_hsla( + h hue: Float, + s saturation: Float, + l lightness: Float, + a alpha: Float, +) -> Result(Colour, Nil) { + use h <- result.then(valid_colour_value(hue)) + use s <- result.then(valid_colour_value(saturation)) + use l <- result.then(valid_colour_value(lightness)) + use a <- result.then(valid_colour_value(alpha)) + + Ok(Hsla(h: h, s: s, l: l, a: a)) +} + +/// Returns `Result(Colour)` created from the given HSL values. +/// +/// Returns `Error(Nil)` if the supplied HSL values are greater than 1.0 or less than 0.0. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_hsla(0.0, 1.0, 0.5) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn from_hsl( + h hue: Float, + s saturation: Float, + l lightness: Float, +) -> Result(Colour, Nil) { + from_hsla(hue, saturation, lightness, 1.0) +} + +/// Returns a `Result(Colour)` created from the given hex `Int`. +/// +/// Returns `Error(Nil)` if the supplied hex `Int is greater than 0xffffff or less than 0x0. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_rgb_hex(0xff0000) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn from_rgb_hex(hex: Int) -> Result(Colour, Nil) { + case hex > 0xffffff || hex < 0 { + True -> Error(Nil) + False -> { + let r = + int.bitwise_shift_right(hex, 16) + |> int.bitwise_and(0xff) + let g = + int.bitwise_shift_right(hex, 8) + |> int.bitwise_and(0xff) + let b = int.bitwise_and(hex, 0xff) + from_rgb255(r, g, b) + } + } +} + +/// Returns a `Result(Colour)` created from the given RGB hex `String`. +/// +/// Returns `Error(Nil)` if the supplied hex `String` is invalid, or greater than `"#ffffff" or less than `"#0"` +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_rgb_hex_string("#ff0000") +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn from_rgb_hex_string(hex_string: String) -> Result(Colour, Nil) { + use hex_int <- result.then(hex_string_to_int(hex_string)) + + from_rgb_hex(hex_int) +} + +/// Returns a `Result(Colour)` created from the given RGBA hex `String`. +/// +/// Returns `Error(Nil)` if the supplied hex `String` is invalid, or greater than `"#ffffffff" or less than `"#0"` +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red_half_opacity) = from_rgba_hex_string("#ff00007f") +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn from_rgba_hex_string(hex_string: String) -> Result(Colour, Nil) { + use hex_int <- result.then(hex_string_to_int(hex_string)) + + from_rgba_hex(hex_int) +} + +/// Returns a `Result(Colour)` created from the given hex `Int`. +/// +/// Returns `Error(Nil)` if the supplied hex `Int is greater than 0xffffffff or less than 0x0. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red_half_opacity) = from_rgba_hex(0xff00007f) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn from_rgba_hex(hex: Int) -> Result(Colour, Nil) { + case hex > 0xffffffff || hex < 0 { + True -> Error(Nil) + False -> { + // This won't fail because we are always dividing by 255.0 + let assert Ok(r) = + int.bitwise_shift_right(hex, 24) + |> int.bitwise_and(0xff) + |> int.to_float() + |> float.divide(255.0) + // This won't fail because we are always dividing by 255.0 + let assert Ok(g) = + int.bitwise_shift_right(hex, 16) + |> int.bitwise_and(0xff) + |> int.to_float() + |> float.divide(255.0) + // This won't fail because we are always dividing by 255.0 + let assert Ok(b) = + int.bitwise_shift_right(hex, 8) + |> int.bitwise_and(0xff) + |> int.to_float() + |> float.divide(255.0) + // This won't fail because we are always dividing by 255.0 + let assert Ok(a) = + int.bitwise_and(hex, 0xff) + |> int.to_float() + |> float.divide(255.0) + from_rgba(r, g, b, a) + } + } +} + +// CONVERSIONS ---------------------------------------------------------------- + +/// Returns `#(Float, Float, Float, Float)` representing the given `Colour`'s +/// R, G, B, and A values respectively. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_rgb255(255, 0, 0) +/// let #(r, g, b, a) = to_rgba(red) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn to_rgba(colour: Colour) -> #(Float, Float, Float, Float) { + case colour { + Rgba(r, g, b, a) -> #(r, g, b, a) + Hsla(h, s, l, a) -> hsla_to_rgba(h, s, l, a) + } +} + +/// Returns `#(Float, Float, Float, Float)` representing the given `Colour`'s +/// H, S, L, and A values respectively. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_rgb255(255, 0, 0) +/// let #(h, s, l, a) = to_hsla(red) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn to_hsla(colour: Colour) -> #(Float, Float, Float, Float) { + case colour { + Hsla(h, s, l, a) -> #(h, s, l, a) + Rgba(r, g, b, a) -> rgba_to_hsla(r, g, b, a) + } +} + +/// Returns an rgba formatted CSS `String` created from the given `Colour`. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_rgb255(255, 0, 0) +/// let css_red = to_css_rgba_string(red) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn to_css_rgba_string(colour: Colour) -> String { + let #(r, g, b, a) = to_rgba(colour) + + let percent = fn(x: Float) -> Float { + // This won't fail because we are always dividing by 100.0 + let assert Ok(p) = + x + |> float.multiply(10_000.0) + |> float.round() + |> int.to_float() + |> float.divide(100.0) + + p + } + + let round_to = fn(x: Float) -> Float { + // This won't fail because we are always dividing by 1000.0 + let assert Ok(r) = + x + |> float.multiply(1000.0) + |> float.round() + |> int.to_float() + |> float.divide(1000.0) + + r + } + + string.join( + [ + "rgba(", + float.to_string(percent(r)) <> "%,", + float.to_string(percent(g)) <> "%,", + float.to_string(percent(b)) <> "%,", + float.to_string(round_to(a)), + ")", + ], + "", + ) +} + +/// Returns an rgba hex formatted `String` created from the given `Colour`. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_rgba(1.0, 0.0, 0.0, 1.0) +/// let red_hex = to_rgba_hex_string(red) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn to_rgba_hex_string(colour: Colour) -> String { + to_rgba_hex(colour) + |> int.to_base16() +} + +/// Returns an rgb hex formatted `String` created from the given `Colour`. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_rgba(255, 0, 0) +/// let red_hex = to_rgb_hex_string(red) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn to_rgb_hex_string(colour: Colour) -> String { + to_rgb_hex(colour) + |> int.to_base16() +} + +/// Returns an hex `Int` created from the given `Colour`. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_rgba(1.0, 0.0, 0.0, 1.0) +/// let red_hex_int = to_rgba_hex(red) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn to_rgba_hex(colour: Colour) -> Int { + let #(r, g, b, a) = to_rgba(colour) + + let red = + r *. 255.0 + |> float.round() + |> int.bitwise_shift_left(24) + + let green = + g *. 255.0 + |> float.round() + |> int.bitwise_shift_left(16) + + let blue = + b *. 255.0 + |> float.round() + |> int.bitwise_shift_left(8) + + let alpha = + a *. 255.0 + |> float.round() + + red + green + blue + alpha +} + +/// Returns a rgb hex `Int` created from the given `Colour`. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// assert Ok(red) = from_rgba(255, 0, 0) +/// let red_hex_int = to_rgb_hex(red) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn to_rgb_hex(colour: Colour) -> Int { + let #(r, g, b, _) = to_rgba(colour) + + let red = + r *. 255.0 + |> float.round() + |> int.bitwise_shift_left(16) + + let green = + g *. 255.0 + |> float.round() + |> int.bitwise_shift_left(8) + + let blue = + b *. 255.0 + |> float.round() + + red + green + blue +} + +// COLOURS -------------------------------------------------------------------- + +/// A `Colour` reprsenting the colour RGBA(239, 41, 41, 1.0) +pub const light_red = Rgba( + r: 0.9372549019607843, + g: 0.1607843137254902, + b: 0.1607843137254902, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(204, 0, 0, 1.0) +pub const red = Rgba(r: 0.8, g: 0.0, b: 0.0, a: 1.0) + +/// A `Colour` reprsenting the colour RGBA(164, 0, 0, 1.0) +pub const dark_red = Rgba(r: 0.6431372549019608, g: 0.0, b: 0.0, a: 1.0) + +/// A `Colour` reprsenting the colour RGBA(252, 175, 62, 1.0) +pub const light_orange = Rgba( + r: 0.9882352941176471, + g: 0.6862745098039216, + b: 0.24313725490196078, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(245, 121, 0, 1.0) +pub const orange = Rgba( + r: 0.9607843137254902, + g: 0.4745098039215686, + b: 0.0, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(206, 92, 0, 1.0) +pub const dark_orange = Rgba( + r: 0.807843137254902, + g: 0.3607843137254902, + b: 0.0, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(255, 233, 79, 1.0) +pub const light_yellow = Rgba( + r: 1.0, + g: 0.9137254901960784, + b: 0.30980392156862746, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(237, 212, 0, 1.0) +pub const yellow = Rgba( + r: 0.9294117647058824, + g: 0.8313725490196079, + b: 0.0, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(196, 160, 0, 1.0) +pub const dark_yellow = Rgba( + r: 0.7686274509803922, + g: 0.6274509803921569, + b: 0.0, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(138, 226, 52, 1.0) +pub const light_green = Rgba( + r: 0.5411764705882353, + g: 0.8862745098039215, + b: 0.20392156862745098, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(115, 210, 22, 1.0) +pub const green = Rgba( + r: 0.45098039215686275, + g: 0.8235294117647058, + b: 0.08627450980392157, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(78, 154, 6, 1.0) +pub const dark_green = Rgba( + r: 0.3058823529411765, + g: 0.6039215686274509, + b: 0.023529411764705882, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(114, 159, 207, 1.0) +pub const light_blue = Rgba( + r: 0.4470588235294118, + g: 0.6235294117647059, + b: 0.8117647058823529, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(52, 101, 164, 1.0) +pub const blue = Rgba( + r: 0.20392156862745098, + g: 0.396078431372549, + b: 0.6431372549019608, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(32, 74, 135, 1.0) +pub const dark_blue = Rgba( + r: 0.12549019607843137, + g: 0.2901960784313726, + b: 0.5294117647058824, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(173, 127, 168, 1.0) +pub const light_purple = Rgba( + r: 0.6784313725490196, + g: 0.4980392156862745, + b: 0.6588235294117647, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(117, 80, 123, 1.0) +pub const purple = Rgba( + r: 0.4588235294117647, + g: 0.3137254901960784, + b: 0.4823529411764706, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(92, 53, 102, 1.0) +pub const dark_purple = Rgba( + r: 0.3607843137254902, + g: 0.20784313725490197, + b: 0.4, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(233, 185, 110, 1.0) +pub const light_brown = Rgba( + r: 0.9137254901960784, + g: 0.7254901960784313, + b: 0.43137254901960786, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(193, 125, 17, 1.0) +pub const brown = Rgba( + r: 0.7568627450980392, + g: 0.49019607843137253, + b: 0.06666666666666667, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(143, 89, 2, 1.0) +pub const dark_brown = Rgba( + r: 0.5607843137254902, + g: 0.34901960784313724, + b: 0.00784313725490196, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(0, 0, 0, 1.0) +pub const black = Rgba(r: 0.0, g: 0.0, b: 0.0, a: 1.0) + +/// A `Colour` reprsenting the colour RGBA(255, 255, 255, 1.0) +pub const white = Rgba(r: 1.0, g: 1.0, b: 1.0, a: 1.0) + +/// A `Colour` reprsenting the colour RGBA(238, 238, 236, 1.0) +pub const light_grey = Rgba( + r: 0.9333333333333333, + g: 0.9333333333333333, + b: 0.9254901960784314, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(211, 215, 207, 1.0) +pub const grey = Rgba( + r: 0.8274509803921568, + g: 0.8431372549019608, + b: 0.8117647058823529, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(186, 189, 182, 1.0) +pub const dark_grey = Rgba( + r: 0.7294117647058823, + g: 0.7411764705882353, + b: 0.7137254901960784, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(238, 238, 236, 1.0) +pub const light_gray = Rgba( + r: 0.9333333333333333, + g: 0.9333333333333333, + b: 0.9254901960784314, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(211, 215, 207, 1.0) +pub const gray = Rgba( + r: 0.8274509803921568, + g: 0.8431372549019608, + b: 0.8117647058823529, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(186, 189, 182, 1.0) +pub const dark_gray = Rgba( + r: 0.7294117647058823, + g: 0.7411764705882353, + b: 0.7137254901960784, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(136, 138, 133, 1.0) +pub const light_charcoal = Rgba( + r: 0.5333333333333333, + g: 0.5411764705882353, + b: 0.5215686274509804, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(85, 87, 83, 1.0) +pub const charcoal = Rgba( + r: 0.3333333333333333, + g: 0.3411764705882353, + b: 0.3254901960784314, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(46, 52, 54, 1.0) +pub const dark_charcoal = Rgba( + r: 0.1803921568627451, + g: 0.20392156862745098, + b: 0.21176470588235294, + a: 1.0, +) + +/// A `Colour` reprsenting the colour RGBA(255, 175, 243, 1.0) +pub const pink = Rgba( + r: 1.0, + g: 0.6862745098039216, + b: 0.9529411764705882, + a: 1.0, +) diff --git a/aoc2023/build/packages/gleam_community_colour/src/gleam_community/colour/accessibility.gleam b/aoc2023/build/packages/gleam_community_colour/src/gleam_community/colour/accessibility.gleam new file mode 100644 index 0000000..54f75e4 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_colour/src/gleam_community/colour/accessibility.gleam @@ -0,0 +1,173 @@ +//// +//// - **Accessibility** +//// - [`luminance`](#luminance) +//// - [`contrast_ratio`](#contrast_ratio) +//// - [`maximum_contrast`](#maximum_contrast) +//// +//// --- +//// +//// This package was heavily inspired by the `elm-color-extra` module. +//// The original source code can be found +//// <a href="https://github.com/noahzgordon/elm-color-extra">here</a>. +//// +//// <details> +//// <summary>The license of that package is produced below:</summary> +//// +//// +//// > MIT License +//// +//// > Copyright (c) 2016 Andreas Köberle +//// +//// > 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. +//// +//// </details> +//// + +// Just in case we decide in the future to no longer include the above reference +// and license, this package was initially a port of the `elm-color-extra` module: +// +// https://github.com/noahzgordon/elm-color-extra +// + +// IMPORTS -------------------------------------------------------------------- + +import gleam/float +import gleam/list +import gleam_community/colour.{type Colour} + +// UTILITIES ------------------------------------------------------------------ + +fn intensity(colour_value: Float) -> Float { + // Calculation taken from https://www.w3.org/TR/WCAG20/#relativeluminancedef + case True { + _ if colour_value <=. 0.03928 -> colour_value /. 12.92 + _ -> { + // Is this guaranteed to be `OK`? + let assert Ok(i) = float.power({ colour_value +. 0.055 } /. 1.055, 2.4) + i + } + } +} + +// ACCESSIBILITY -------------------------------------------------------------- + +/// Returns the relative brightness of the given `Colour` as a `Float` between +/// 0.0, and 1.0 with 0.0 being the darkest possible colour and 1.0 being the lightest. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// luminance(colour.white) // 1.0 +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn luminance(colour: Colour) -> Float { + // Calculation taken from https://www.w3.org/TR/WCAG20/#relativeluminancedef + let #(r, g, b, _) = colour.to_rgba(colour) + + let r_intensity = intensity(r) + let g_intensity = intensity(g) + let b_intensity = intensity(b) + + 0.2126 *. r_intensity +. 0.7152 *. g_intensity +. 0.0722 *. b_intensity +} + +/// Returns the contrast between two `Colour` values as a `Float` between 1.0, +/// and 21.0 with 1.0 being no contrast and, 21.0 being the highest possible contrast. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// contrast_ratio(between: colour.white, and: colour.black) // 21.0 +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn contrast_ratio(between colour_a: Colour, and colour_b: Colour) -> Float { + // Calculation taken from https://www.w3.org/TR/WCAG20/#contrast-ratiodef + let luminance_a = luminance(colour_a) +. 0.05 + let luminance_b = luminance(colour_b) +. 0.05 + + case luminance_a >. luminance_b { + True -> luminance_a /. luminance_b + False -> luminance_b /. luminance_a + } +} + +/// Returns the `Colour` with the highest contrast between the base `Colour`, +/// and and the other provided `Colour` values. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// ```gleam +/// fn example() { +/// maximum_contrast( +/// colour.yellow, +/// [colour.white, colour.dark_blue, colour.green], +/// ) +/// } +/// ``` +/// </details> +/// +/// <div style="position: relative;"> +/// <a style="position: absolute; left: 0;" href="https://github.com/gleam-community/colour/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// <a style="position: absolute; right: 0;" href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn maximum_contrast( + base: Colour, + colours: List(Colour), +) -> Result(Colour, Nil) { + colours + |> list.sort(fn(colour_a, colour_b) { + let contrast_a = contrast_ratio(base, colour_a) + let contrast_b = contrast_ratio(base, colour_b) + + float.compare(contrast_b, contrast_a) + }) + |> list.first() +} diff --git a/aoc2023/build/packages/gleam_community_colour/src/gleam_community@colour.erl b/aoc2023/build/packages/gleam_community_colour/src/gleam_community@colour.erl new file mode 100644 index 0000000..21e4c81 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_colour/src/gleam_community@colour.erl @@ -0,0 +1,511 @@ +-module(gleam_community@colour). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([from_rgb255/3, from_rgb/3, from_rgba/4, from_hsla/4, from_hsl/3, from_rgb_hex/1, from_rgb_hex_string/1, from_rgba_hex/1, from_rgba_hex_string/1, to_rgba/1, to_hsla/1, to_css_rgba_string/1, to_rgba_hex/1, to_rgba_hex_string/1, to_rgb_hex/1, to_rgb_hex_string/1]). +-export_type([colour/0]). + +-opaque colour() :: {rgba, float(), float(), float(), float()} | + {hsla, float(), float(), float(), float()}. + +-spec valid_colour_value(float()) -> {ok, float()} | {error, nil}. +valid_colour_value(C) -> + case (C > 1.0) orelse (C < +0.0) of + true -> + {error, nil}; + + false -> + {ok, C} + end. + +-spec hue_to_rgb(float(), float(), float()) -> float(). +hue_to_rgb(Hue, M1, M2) -> + H = case Hue of + _ when Hue < +0.0 -> + Hue + 1.0; + + _ when Hue > 1.0 -> + Hue - 1.0; + + _ -> + Hue + end, + H_t_6 = H * 6.0, + H_t_2 = H * 2.0, + H_t_3 = H * 3.0, + case H of + _ when H_t_6 < 1.0 -> + M1 + (((M2 - M1) * H) * 6.0); + + _ when H_t_2 < 1.0 -> + M2; + + _ when H_t_3 < 2.0 -> + M1 + (((M2 - M1) * ((2.0 / 3.0) - H)) * 6.0); + + _ -> + M1 + end. + +-spec hex_string_to_int(binary()) -> {ok, integer()} | {error, nil}. +hex_string_to_int(Hex_string) -> + Hex = case Hex_string of + <<"#"/utf8, Hex_number/binary>> -> + Hex_number; + + <<"0x"/utf8, Hex_number@1/binary>> -> + Hex_number@1; + + _ -> + Hex_string + end, + _pipe = Hex, + _pipe@1 = gleam@string:lowercase(_pipe), + _pipe@2 = gleam@string:to_graphemes(_pipe@1), + _pipe@3 = gleam@list:reverse(_pipe@2), + gleam@list:index_fold( + _pipe@3, + {ok, 0}, + fun(Total, Char, Index) -> case Total of + {error, nil} -> + {error, nil}; + + {ok, V} -> + gleam@result:then(case Char of + <<"a"/utf8>> -> + {ok, 10}; + + <<"b"/utf8>> -> + {ok, 11}; + + <<"c"/utf8>> -> + {ok, 12}; + + <<"d"/utf8>> -> + {ok, 13}; + + <<"e"/utf8>> -> + {ok, 14}; + + <<"f"/utf8>> -> + {ok, 15}; + + _ -> + gleam@int:parse(Char) + end, fun(Num) -> + gleam@result:then( + gleam@int:power(16, gleam@int:to_float(Index)), + fun(Base) -> + {ok, + V + gleam@float:round( + gleam@int:to_float(Num) * Base + )} + end + ) + end) + end end + ). + +-spec hsla_to_rgba(float(), float(), float(), float()) -> {float(), + float(), + float(), + float()}. +hsla_to_rgba(H, S, L, A) -> + M2 = case L =< 0.5 of + true -> + L * (S + 1.0); + + false -> + (L + S) - (L * S) + end, + M1 = (L * 2.0) - M2, + R = hue_to_rgb(H + (1.0 / 3.0), M1, M2), + G = hue_to_rgb(H, M1, M2), + B = hue_to_rgb(H - (1.0 / 3.0), M1, M2), + {R, G, B, A}. + +-spec rgba_to_hsla(float(), float(), float(), float()) -> {float(), + float(), + float(), + float()}. +rgba_to_hsla(R, G, B, A) -> + Min_colour = gleam@float:min(R, gleam@float:min(G, B)), + Max_colour = gleam@float:max(R, gleam@float:max(G, B)), + H1 = case true of + _ when Max_colour =:= R -> + gleam@float:divide(G - B, Max_colour - Min_colour); + + _ when Max_colour =:= G -> + _pipe = gleam@float:divide(B - R, Max_colour - Min_colour), + gleam@result:then(_pipe, fun(D) -> {ok, 2.0 + D} end); + + _ -> + _pipe@1 = gleam@float:divide(R - G, Max_colour - Min_colour), + gleam@result:then(_pipe@1, fun(D@1) -> {ok, 4.0 + D@1} end) + end, + H2 = case H1 of + {ok, V} -> + {ok, V * (1.0 / 6.0)}; + + _ -> + H1 + end, + H3 = case H2 of + {ok, V@1} when V@1 < +0.0 -> + V@1 + 1.0; + + {ok, V@2} -> + V@2; + + _ -> + +0.0 + end, + L = (Min_colour + Max_colour) / 2.0, + S = case true of + _ when Min_colour =:= Max_colour -> + +0.0; + + _ when L < 0.5 -> + case (Max_colour + Min_colour) of + 0.0 -> 0.0; + Gleam@denominator -> (Max_colour - Min_colour) / Gleam@denominator + end; + + _ -> + case ((2.0 - Max_colour) - Min_colour) of + 0.0 -> 0.0; + Gleam@denominator@1 -> (Max_colour - Min_colour) / Gleam@denominator@1 + end + end, + {H3, S, L, A}. + +-spec from_rgb255(integer(), integer(), integer()) -> {ok, colour()} | + {error, nil}. +from_rgb255(Red, Green, Blue) -> + gleam@result:then( + begin + _pipe = Red, + _pipe@1 = gleam@int:to_float(_pipe), + _pipe@2 = gleam@float:divide(_pipe@1, 255.0), + gleam@result:then(_pipe@2, fun valid_colour_value/1) + end, + fun(R) -> + gleam@result:then( + begin + _pipe@3 = Green, + _pipe@4 = gleam@int:to_float(_pipe@3), + _pipe@5 = gleam@float:divide(_pipe@4, 255.0), + gleam@result:then(_pipe@5, fun valid_colour_value/1) + end, + fun(G) -> + gleam@result:then( + begin + _pipe@6 = Blue, + _pipe@7 = gleam@int:to_float(_pipe@6), + _pipe@8 = gleam@float:divide(_pipe@7, 255.0), + gleam@result:then(_pipe@8, fun valid_colour_value/1) + end, + fun(B) -> {ok, {rgba, R, G, B, 1.0}} end + ) + end + ) + end + ). + +-spec from_rgb(float(), float(), float()) -> {ok, colour()} | {error, nil}. +from_rgb(Red, Green, Blue) -> + gleam@result:then( + valid_colour_value(Red), + fun(R) -> + gleam@result:then( + valid_colour_value(Green), + fun(G) -> + gleam@result:then( + valid_colour_value(Blue), + fun(B) -> {ok, {rgba, R, G, B, 1.0}} end + ) + end + ) + end + ). + +-spec from_rgba(float(), float(), float(), float()) -> {ok, colour()} | + {error, nil}. +from_rgba(Red, Green, Blue, Alpha) -> + gleam@result:then( + valid_colour_value(Red), + fun(R) -> + gleam@result:then( + valid_colour_value(Green), + fun(G) -> + gleam@result:then( + valid_colour_value(Blue), + fun(B) -> + gleam@result:then( + valid_colour_value(Alpha), + fun(A) -> {ok, {rgba, R, G, B, A}} end + ) + end + ) + end + ) + end + ). + +-spec from_hsla(float(), float(), float(), float()) -> {ok, colour()} | + {error, nil}. +from_hsla(Hue, Saturation, Lightness, Alpha) -> + gleam@result:then( + valid_colour_value(Hue), + fun(H) -> + gleam@result:then( + valid_colour_value(Saturation), + fun(S) -> + gleam@result:then( + valid_colour_value(Lightness), + fun(L) -> + gleam@result:then( + valid_colour_value(Alpha), + fun(A) -> {ok, {hsla, H, S, L, A}} end + ) + end + ) + end + ) + end + ). + +-spec from_hsl(float(), float(), float()) -> {ok, colour()} | {error, nil}. +from_hsl(Hue, Saturation, Lightness) -> + from_hsla(Hue, Saturation, Lightness, 1.0). + +-spec from_rgb_hex(integer()) -> {ok, colour()} | {error, nil}. +from_rgb_hex(Hex) -> + case (Hex > 16#ffffff) orelse (Hex < 0) of + true -> + {error, nil}; + + false -> + R = begin + _pipe = erlang:'bsr'(Hex, 16), + erlang:'band'(_pipe, 16#ff) + end, + G = begin + _pipe@1 = erlang:'bsr'(Hex, 8), + erlang:'band'(_pipe@1, 16#ff) + end, + B = erlang:'band'(Hex, 16#ff), + from_rgb255(R, G, B) + end. + +-spec from_rgb_hex_string(binary()) -> {ok, colour()} | {error, nil}. +from_rgb_hex_string(Hex_string) -> + gleam@result:then( + hex_string_to_int(Hex_string), + fun(Hex_int) -> from_rgb_hex(Hex_int) end + ). + +-spec from_rgba_hex(integer()) -> {ok, colour()} | {error, nil}. +from_rgba_hex(Hex) -> + case (Hex > 16#ffffffff) orelse (Hex < 0) of + true -> + {error, nil}; + + false -> + _assert_subject = begin + _pipe = erlang:'bsr'(Hex, 24), + _pipe@1 = erlang:'band'(_pipe, 16#ff), + _pipe@2 = gleam@int:to_float(_pipe@1), + gleam@float:divide(_pipe@2, 255.0) + end, + {ok, R} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/colour"/utf8>>, + function => <<"from_rgba_hex"/utf8>>, + line => 588}) + end, + _assert_subject@1 = begin + _pipe@3 = erlang:'bsr'(Hex, 16), + _pipe@4 = erlang:'band'(_pipe@3, 16#ff), + _pipe@5 = gleam@int:to_float(_pipe@4), + gleam@float:divide(_pipe@5, 255.0) + end, + {ok, G} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/colour"/utf8>>, + function => <<"from_rgba_hex"/utf8>>, + line => 594}) + end, + _assert_subject@2 = begin + _pipe@6 = erlang:'bsr'(Hex, 8), + _pipe@7 = erlang:'band'(_pipe@6, 16#ff), + _pipe@8 = gleam@int:to_float(_pipe@7), + gleam@float:divide(_pipe@8, 255.0) + end, + {ok, B} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"gleam_community/colour"/utf8>>, + function => <<"from_rgba_hex"/utf8>>, + line => 600}) + end, + _assert_subject@3 = begin + _pipe@9 = erlang:'band'(Hex, 16#ff), + _pipe@10 = gleam@int:to_float(_pipe@9), + gleam@float:divide(_pipe@10, 255.0) + end, + {ok, A} = case _assert_subject@3 of + {ok, _} -> _assert_subject@3; + _assert_fail@3 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@3, + module => <<"gleam_community/colour"/utf8>>, + function => <<"from_rgba_hex"/utf8>>, + line => 606}) + end, + from_rgba(R, G, B, A) + end. + +-spec from_rgba_hex_string(binary()) -> {ok, colour()} | {error, nil}. +from_rgba_hex_string(Hex_string) -> + gleam@result:then( + hex_string_to_int(Hex_string), + fun(Hex_int) -> from_rgba_hex(Hex_int) end + ). + +-spec to_rgba(colour()) -> {float(), float(), float(), float()}. +to_rgba(Colour) -> + case Colour of + {rgba, R, G, B, A} -> + {R, G, B, A}; + + {hsla, H, S, L, A@1} -> + hsla_to_rgba(H, S, L, A@1) + end. + +-spec to_hsla(colour()) -> {float(), float(), float(), float()}. +to_hsla(Colour) -> + case Colour of + {hsla, H, S, L, A} -> + {H, S, L, A}; + + {rgba, R, G, B, A@1} -> + rgba_to_hsla(R, G, B, A@1) + end. + +-spec to_css_rgba_string(colour()) -> binary(). +to_css_rgba_string(Colour) -> + {R, G, B, A} = to_rgba(Colour), + Percent = fun(X) -> + _assert_subject = begin + _pipe = X, + _pipe@1 = gleam@float:multiply(_pipe, 10000.0), + _pipe@2 = gleam@float:round(_pipe@1), + _pipe@3 = gleam@int:to_float(_pipe@2), + gleam@float:divide(_pipe@3, 100.0) + end, + {ok, P} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/colour"/utf8>>, + function => <<"to_css_rgba_string"/utf8>>, + line => 704}) + end, + P + end, + Round_to = fun(X@1) -> + _assert_subject@1 = begin + _pipe@4 = X@1, + _pipe@5 = gleam@float:multiply(_pipe@4, 1000.0), + _pipe@6 = gleam@float:round(_pipe@5), + _pipe@7 = gleam@int:to_float(_pipe@6), + gleam@float:divide(_pipe@7, 1000.0) + end, + {ok, R@1} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/colour"/utf8>>, + function => <<"to_css_rgba_string"/utf8>>, + line => 716}) + end, + R@1 + end, + gleam@string:join( + [<<"rgba("/utf8>>, + <<(gleam@float:to_string(Percent(R)))/binary, "%,"/utf8>>, + <<(gleam@float:to_string(Percent(G)))/binary, "%,"/utf8>>, + <<(gleam@float:to_string(Percent(B)))/binary, "%,"/utf8>>, + gleam@float:to_string(Round_to(A)), + <<")"/utf8>>], + <<""/utf8>> + ). + +-spec to_rgba_hex(colour()) -> integer(). +to_rgba_hex(Colour) -> + {R, G, B, A} = to_rgba(Colour), + Red = begin + _pipe = R * 255.0, + _pipe@1 = gleam@float:round(_pipe), + erlang:'bsl'(_pipe@1, 24) + end, + Green = begin + _pipe@2 = G * 255.0, + _pipe@3 = gleam@float:round(_pipe@2), + erlang:'bsl'(_pipe@3, 16) + end, + Blue = begin + _pipe@4 = B * 255.0, + _pipe@5 = gleam@float:round(_pipe@4), + erlang:'bsl'(_pipe@5, 8) + end, + Alpha = begin + _pipe@6 = A * 255.0, + gleam@float:round(_pipe@6) + end, + ((Red + Green) + Blue) + Alpha. + +-spec to_rgba_hex_string(colour()) -> binary(). +to_rgba_hex_string(Colour) -> + _pipe = to_rgba_hex(Colour), + gleam@int:to_base16(_pipe). + +-spec to_rgb_hex(colour()) -> integer(). +to_rgb_hex(Colour) -> + {R, G, B, _} = to_rgba(Colour), + Red = begin + _pipe = R * 255.0, + _pipe@1 = gleam@float:round(_pipe), + erlang:'bsl'(_pipe@1, 16) + end, + Green = begin + _pipe@2 = G * 255.0, + _pipe@3 = gleam@float:round(_pipe@2), + erlang:'bsl'(_pipe@3, 8) + end, + Blue = begin + _pipe@4 = B * 255.0, + gleam@float:round(_pipe@4) + end, + (Red + Green) + Blue. + +-spec to_rgb_hex_string(colour()) -> binary(). +to_rgb_hex_string(Colour) -> + _pipe = to_rgb_hex(Colour), + gleam@int:to_base16(_pipe). diff --git a/aoc2023/build/packages/gleam_community_colour/src/gleam_community@colour@accessibility.erl b/aoc2023/build/packages/gleam_community_colour/src/gleam_community@colour@accessibility.erl new file mode 100644 index 0000000..64d37bf --- /dev/null +++ b/aoc2023/build/packages/gleam_community_colour/src/gleam_community@colour@accessibility.erl @@ -0,0 +1,73 @@ +-module(gleam_community@colour@accessibility). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([luminance/1, contrast_ratio/2, maximum_contrast/2]). + +-spec intensity(float()) -> float(). +intensity(Colour_value) -> + case true of + _ when Colour_value =< 0.03928 -> + Colour_value / 12.92; + + _ -> + _assert_subject = gleam@float:power( + (Colour_value + 0.055) / 1.055, + 2.4 + ), + {ok, I} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/colour/accessibility"/utf8>>, + function => <<"intensity"/utf8>>, + line => 62}) + end, + I + end. + +-spec luminance(gleam_community@colour:colour()) -> float(). +luminance(Colour) -> + {R, G, B, _} = gleam_community@colour:to_rgba(Colour), + R_intensity = intensity(R), + G_intensity = intensity(G), + B_intensity = intensity(B), + ((0.2126 * R_intensity) + (0.7152 * G_intensity)) + (0.0722 * B_intensity). + +-spec contrast_ratio( + gleam_community@colour:colour(), + gleam_community@colour:colour() +) -> float(). +contrast_ratio(Colour_a, Colour_b) -> + Luminance_a = luminance(Colour_a) + 0.05, + Luminance_b = luminance(Colour_b) + 0.05, + case Luminance_a > Luminance_b of + true -> + case Luminance_b of + 0.0 -> 0.0; + Gleam@denominator -> Luminance_a / Gleam@denominator + end; + + false -> + case Luminance_a of + 0.0 -> 0.0; + Gleam@denominator@1 -> Luminance_b / Gleam@denominator@1 + end + end. + +-spec maximum_contrast( + gleam_community@colour:colour(), + list(gleam_community@colour:colour()) +) -> {ok, gleam_community@colour:colour()} | {error, nil}. +maximum_contrast(Base, Colours) -> + _pipe = Colours, + _pipe@1 = gleam@list:sort( + _pipe, + fun(Colour_a, Colour_b) -> + Contrast_a = contrast_ratio(Base, Colour_a), + Contrast_b = contrast_ratio(Base, Colour_b), + gleam@float:compare(Contrast_b, Contrast_a) + end + ), + gleam@list:first(_pipe@1). diff --git a/aoc2023/build/packages/gleam_community_colour/src/gleam_community_colour.app.src b/aoc2023/build/packages/gleam_community_colour/src/gleam_community_colour.app.src new file mode 100644 index 0000000..a327650 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_colour/src/gleam_community_colour.app.src @@ -0,0 +1,9 @@ +{application, gleam_community_colour, [ + {vsn, "1.2.0"}, + {applications, [gleam_stdlib, + gleeunit]}, + {description, "Colour types, conversions, and other utilities"}, + {modules, [gleam_community@colour, + gleam_community@colour@accessibility]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/gleam_community_maths/LICENCE b/aoc2023/build/packages/gleam_community_maths/LICENCE new file mode 100644 index 0000000..a84f0ec --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/LICENCE @@ -0,0 +1,190 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2023 Gleam Community Contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
\ No newline at end of file diff --git a/aoc2023/build/packages/gleam_community_maths/README.md b/aoc2023/build/packages/gleam_community_maths/README.md new file mode 100644 index 0000000..c912757 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/README.md @@ -0,0 +1,59 @@ +# gleam-community/maths + +[](https://hex.pm/packages/gleam_community_maths) +[](https://hexdocs.pm/gleam_community_maths/) + +A basic mathematics library that contains some of the most fundamental mathematics functions and utilities. + +The library supports both targets: Erlang and JavaScript. + +## Quickstart + +```gleam +import gleam_community/maths/arithmetics +import gleam_community/maths/combinatorics +import gleam_community/maths/elementary +import gleam_community/maths/piecewise +import gleam_community/maths/predicates +import gleam/float + +pub fn main() { + // Evaluate the sine function + elementary.sin(elementary.pi()) + // Returns Float: 0.0 + + // Find the greatest common divisor + arithmetics.gcd(54, 24) + // Returns Int: 6 + + // Find the minimum and maximum of a list + piecewise.extrema([10.0, 3.0, 50.0, 20.0, 3.0], float.compare) + // Returns Tuple: Ok(#(3.0, 50.0)) + + // Find the list indices of the smallest value + piecewise.arg_minimum([10, 3, 50, 20, 3], float.compare) + // Returns List: Ok([1, 4]) + + // Determine if a number is fractional + predicates.is_fractional(0.3333) + // Returns Bool: True + + // Determine if 28 is a power of 3 + predicates.is_power(28, 3) + // Returns Bool: False + + // Generate all k = 1 combinations of [1, 2] + combinatorics.list_combination([1, 2], 1) + // Returns List: Ok([[1], [2]]) +} + +``` + +## Installation + +`gleam_community` packages are published to [hex.pm](https://hex.pm/packages/gleam_community_maths) +with the prefix `gleam_community_`. You can add them to your Gleam projects directly: + +```sh +gleam add gleam_community_maths +``` diff --git a/aoc2023/build/packages/gleam_community_maths/gleam.toml b/aoc2023/build/packages/gleam_community_maths/gleam.toml new file mode 100644 index 0000000..9dc5fd7 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/gleam.toml @@ -0,0 +1,12 @@ +name = "gleam_community_maths" +version = "1.0.1" + +licences = ["Apache-2.0"] +description = "A basic maths library" +repository = { type = "github", user = "gleam-community", repo = "maths" } + +[dependencies] +gleam_stdlib = "~> 0.33" + +[dev-dependencies] +gleeunit = "~> 1.0" diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/arithmetics.gleam b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/arithmetics.gleam new file mode 100644 index 0000000..3e0f63a --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/arithmetics.gleam @@ -0,0 +1,618 @@ +////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous"> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script> +////<script> +//// document.addEventListener("DOMContentLoaded", function() { +//// renderMathInElement(document.body, { +//// // customised options +//// // • auto-render specific keys, e.g.: +//// delimiters: [ +//// {left: '$$', right: '$$', display: false}, +//// // {left: '$', right: '$', display: false}, +//// // {left: '\\(', right: '\\)', display: false}, +//// {left: '\\[', right: '\\]', display: true} +//// ], +//// // • rendering keys, e.g.: +//// throwOnError : false +//// }); +//// }); +////</script> +////<style> +//// .katex { font-size: 1.1em; } +////</style> +//// +//// --- +//// +//// Arithmetics: A module containing a collection of fundamental mathematical functions relating to simple arithmetics (addition, subtraction, multiplication, etc.), but also number theory. +//// +//// * **Division functions** +//// * [`gcd`](#gcd) +//// * [`lcm`](#lcm) +//// * [`divisors`](#divisors) +//// * [`proper_divisors`](#proper_divisors) +//// * **Sums and products** +//// * [`float_sum`](#float_sum) +//// * [`int_sum`](#int_sum) +//// * [`float_product`](#float_product) +//// * [`int_product`](#int_product) +//// * [`float_cumulative_sum`](#float_cumulative_sum) +//// * [`int_cumulative_sum`](#int_cumulative_sum) +//// * [`float_cumulative_product`](#float_cumulative_product) +//// * [`int_cumulative_product`](#int_cumulative_product) +//// + +import gleam/int +import gleam/list +import gleam_community/maths/conversion +import gleam_community/maths/elementary +import gleam_community/maths/piecewise + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function calculates the greatest common multiple of two integers $$x, y \in \mathbb{Z}$$. +/// The greatest common multiple is the largest positive integer that is divisible by both $$x$$ and $$y$$. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example() { +/// arithmetics.lcm(1, 1) +/// |> should.equal(1) +/// +/// arithmetics.lcm(100, 10) +/// |> should.equal(10) +/// +/// arithmetics.gcd(-36, -17) +/// |> should.equal(1) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn gcd(x: Int, y: Int) -> Int { + let absx: Int = piecewise.int_absolute_value(x) + let absy: Int = piecewise.int_absolute_value(y) + do_gcd(absx, absy) +} + +fn do_gcd(x: Int, y: Int) -> Int { + case x == 0 { + True -> y + False -> { + let assert Ok(z) = int.modulo(y, x) + do_gcd(z, x) + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function calculates the least common multiple of two integers $$x, y \in \mathbb{Z}$$. +/// The least common multiple is the smallest positive integer that has both $$x$$ and $$y$$ as factors. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example() { +/// arithmetics.lcm(1, 1) +/// |> should.equal(1) +/// +/// arithmetics.lcm(100, 10) +/// |> should.equal(100) +/// +/// arithmetics.lcm(-36, -17) +/// |> should.equal(612) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn lcm(x: Int, y: Int) -> Int { + let absx: Int = piecewise.int_absolute_value(x) + let absy: Int = piecewise.int_absolute_value(y) + absx * absy / do_gcd(absx, absy) +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function returns all the positive divisors of an integer, including the number iteself. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example() { +/// arithmetics.divisors(4) +/// |> should.equal([1, 2, 4]) +/// +/// arithmetics.divisors(6) +/// |> should.equal([1, 2, 3, 6]) +/// +/// arithmetics.proper_divisors(13) +/// |> should.equal([1, 13]) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn divisors(n: Int) -> List(Int) { + find_divisors(n) +} + +fn find_divisors(n: Int) -> List(Int) { + let nabs: Float = piecewise.float_absolute_value(conversion.int_to_float(n)) + let assert Ok(sqrt_result) = elementary.square_root(nabs) + let max: Int = conversion.float_to_int(sqrt_result) + 1 + list.range(2, max) + |> list.fold( + [1, n], + fn(acc: List(Int), i: Int) -> List(Int) { + case n % i == 0 { + True -> [i, n / i, ..acc] + False -> acc + } + }, + ) + |> list.unique() + |> list.sort(int.compare) +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function returns all the positive divisors of an integer, excluding the number iteself. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example() { +/// arithmetics.proper_divisors(4) +/// |> should.equal([1, 2]) +/// +/// arithmetics.proper_divisors(6) +/// |> should.equal([1, 2, 3]) +/// +/// arithmetics.proper_divisors(13) +/// |> should.equal([1]) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn proper_divisors(n: Int) -> List(Int) { + let divisors: List(Int) = find_divisors(n) + divisors + |> list.take(list.length(divisors) - 1) +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the sum of the elements in a list: +/// +/// \\[ +/// \sum_{i=1}^n x_i +/// \\] +/// +/// In the formula, $$n$$ is the length of the list and $$x_i \in \mathbb{R}$$ is the value in the input list indexed by $$i$$. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example () { +/// // An empty list returns an error +/// [] +/// |> arithmetics.float_sum() +/// |> should.equal(0.0) +/// +/// // Valid input returns a result +/// [1.0, 2.0, 3.0] +/// |> arithmetics.float_sum() +/// |> should.equal(6.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn float_sum(arr: List(Float)) -> Float { + case arr { + [] -> 0.0 + _ -> + arr + |> list.fold(0.0, fn(acc: Float, a: Float) -> Float { a +. acc }) + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the sum of the elements in a list: +/// +/// \\[ +/// \sum_{i=1}^n x_i +/// \\] +/// +/// In the formula, $$n$$ is the length of the list and $$x_i \in \mathbb{Z}$$ is the value in the input list indexed by $$i$$. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example () { +/// // An empty list returns 0 +/// [] +/// |> arithmetics.int_sum() +/// |> should.equal(0) +/// +/// // Valid input returns a result +/// [1, 2, 3] +/// |> arithmetics.int_sum() +/// |> should.equal(6) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn int_sum(arr: List(Int)) -> Int { + case arr { + [] -> 0 + _ -> + arr + |> list.fold(0, fn(acc: Int, a: Int) -> Int { a + acc }) + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the product of the elements in a list: +/// +/// \\[ +/// \prod_{i=1}^n x_i +/// \\] +/// +/// In the formula, $$n$$ is the length of the list and $$x_i \in \mathbb{R}$$ is the value in the input list indexed by $$i$$. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example () { +/// // An empty list returns 0.0 +/// [] +/// |> arithmetics.float_product() +/// |> should.equal(0.0) +/// +/// // Valid input returns a result +/// [1.0, 2.0, 3.0] +/// |> arithmetics.float_product() +/// |> should.equal(6.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn float_product(arr: List(Float)) -> Float { + case arr { + [] -> 1.0 + _ -> + arr + |> list.fold(1.0, fn(acc: Float, a: Float) -> Float { a *. acc }) + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the product of the elements in a list: +/// +/// \\[ +/// \prod_{i=1}^n x_i +/// \\] +/// +/// In the formula, $$n$$ is the length of the list and $$x_i \in \mathbb{Z}$$ is the value in the input list indexed by $$i$$. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example () { +/// // An empty list returns 0 +/// [] +/// |> arithmetics.int_product() +/// |> should.equal(0) +/// +/// // Valid input returns a result +/// [1, 2, 3] +/// |> arithmetics.int_product() +/// |> should.equal(6) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn int_product(arr: List(Int)) -> Int { + case arr { + [] -> 1 + _ -> + arr + |> list.fold(1, fn(acc: Int, a: Int) -> Int { a * acc }) + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the cumulative sum of the elements in a list: +/// +/// \\[ +/// v_j = \sum_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n +/// \\] +/// +/// In the formula, $$v_j$$ is the $$j$$'th element in the cumulative sum of $$n$$ elements. +/// That is, $$n$$ is the length of the list and $$x_i \in \mathbb{R}$$ is the value in the input list indexed by $$i$$. +/// The value $$v_j$$ is thus the sum of the $$1$$ to $$j$$ first elements in the given list. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example () { +/// [] +/// |> arithmetics.float_cumulative_sum() +/// |> should.equal([]) +/// +/// // Valid input returns a result +/// [1.0, 2.0, 3.0] +/// |> arithmetics.float_cumulative_sum() +/// |> should.equal([1.0, 3.0, 6.0]) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn float_cumulative_sum(arr: List(Float)) -> List(Float) { + case arr { + [] -> [] + _ -> + arr + |> list.scan(0.0, fn(acc: Float, a: Float) -> Float { a +. acc }) + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the cumulative sum of the elements in a list: +/// +/// \\[ +/// v_j = \sum_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n +/// \\] +/// +/// In the formula, $$v_j$$ is the $$j$$'th element in the cumulative sum of $$n$$ elements. +/// That is, $$n$$ is the length of the list and $$x_i \in \mathbb{Z}$$ is the value in the input list indexed by $$i$$. +/// The value $$v_j$$ is thus the sum of the $$1$$ to $$j$$ first elements in the given list. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example () { +/// [] +/// |> arithmetics.int_cumulative_sum() +/// |> should.equal([]) +/// +/// // Valid input returns a result +/// [1, 2, 3] +/// |> arithmetics.int_cumulative_sum() +/// |> should.equal([1, 3, 6]) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn int_cumulative_sum(arr: List(Int)) -> List(Int) { + case arr { + [] -> [] + _ -> + arr + |> list.scan(0, fn(acc: Int, a: Int) -> Int { a + acc }) + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the cumulative product of the elements in a list: +/// +/// \\[ +/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n +/// \\] +/// +/// In the formula, $$v_j$$ is the $$j$$'th element in the cumulative product of $$n$$ elements. +/// That is, $$n$$ is the length of the list and $$x_i \in \mathbb{R}$$ is the value in the input list indexed by $$i$$. +/// The value $$v_j$$ is thus the sum of the $$1$$ to $$j$$ first elements in the given list. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example () { +/// // An empty list returns an error +/// [] +/// |> arithmetics.float_cumulative_product() +/// |> should.equal([]) +/// +/// // Valid input returns a result +/// [1.0, 2.0, 3.0] +/// |> arithmetics.float_cumulative_product() +/// |> should.equal([1.0, 2.0, 6.0]) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn float_cumumlative_product(arr: List(Float)) -> List(Float) { + case arr { + [] -> [] + _ -> + arr + |> list.scan(1.0, fn(acc: Float, a: Float) -> Float { a *. acc }) + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the cumulative product of the elements in a list: +/// +/// \\[ +/// v_j = \prod_{i=1}^j x_i \\;\\; \forall j = 1,\dots, n +/// \\] +/// +/// In the formula, $$v_j$$ is the $$j$$'th element in the cumulative product of $$n$$ elements. +/// That is, $$n$$ is the length of the list and $$x_i \in \mathbb{Z}$$ is the value in the input list indexed by $$i$$. +/// The value $$v_j$$ is thus the product of the $$1$$ to $$j$$ first elements in the given list. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/arithmetics +/// +/// pub fn example () { +/// // An empty list returns an error +/// [] +/// |> arithmetics.int_cumulative_product() +/// |> should.equal([]) +/// +/// // Valid input returns a result +/// [1, 2, 3] +/// |> arithmetics.int_cumulative_product() +/// |> should.equal([1, 2, 6]) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn int_cumulative_product(arr: List(Int)) -> List(Int) { + case arr { + [] -> [] + _ -> + arr + |> list.scan(1, fn(acc: Int, a: Int) -> Int { a * acc }) + } +} diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/combinatorics.gleam b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/combinatorics.gleam new file mode 100644 index 0000000..ee771a1 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/combinatorics.gleam @@ -0,0 +1,432 @@ +////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous"> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script> +////<script> +//// document.addEventListener("DOMContentLoaded", function() { +//// renderMathInElement(document.body, { +//// // customised options +//// // • auto-render specific keys, e.g.: +//// delimiters: [ +//// {left: '$$', right: '$$', display: false}, +//// // {left: '$', right: '$', display: false}, +//// // {left: '\\(', right: '\\)', display: false}, +//// {left: '\\[', right: '\\]', display: true} +//// ], +//// // • rendering keys, e.g.: +//// throwOnError : false +//// }); +//// }); +////</script> +////<style> +//// .katex { font-size: 1.1em; } +////</style> +//// +//// --- +//// +//// Combinatorics: A module that offers mathematical functions related to counting, arrangements, and combinations. +//// +//// * **Combinatorial functions** +//// * [`combination`](#combination) +//// * [`factorial`](#factorial) +//// * [`permutation`](#permutation) +//// * [`list_combination`](#list_combination) +//// * [`list_permutation`](#list_permutation) +//// * [`cartesian_product`](#cartesian_product) +//// + +import gleam/list +import gleam/set + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// A combinatorial function for computing the number of a $$k$$-combinations of $$n$$ elements: +/// +/// \\[ +/// C(n, k) = \binom{n}{k} = \frac{n!}{k! (n-k)!} +/// \\] +/// Also known as "$$n$$ choose $$k$$" or the binomial coefficient. +/// +/// The implementation uses the effecient iterative multiplicative formula for the computation. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/combinatorics +/// +/// pub fn example() { +/// // Invalid input gives an error +/// // Error on: n = -1 < 0 +/// combinatorics.combination(-1, 1) +/// |> should.be_error() +/// +/// // Valid input returns a result +/// combinatorics.combination(4, 0) +/// |> should.equal(Ok(1)) +/// +/// combinatorics.combination(4, 4) +/// |> should.equal(Ok(1)) +/// +/// combinatorics.combination(4, 2) +/// |> should.equal(Ok(6)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn combination(n: Int, k: Int) -> Result(Int, String) { + case n < 0 { + True -> + "Invalid input argument: n < 0. Valid input is n > 0." + |> Error + False -> + case k < 0 || k > n { + True -> + 0 + |> Ok + False -> + case k == 0 || k == n { + True -> + 1 + |> Ok + False -> { + let min = case k < n - k { + True -> k + False -> n - k + } + list.range(1, min) + |> list.fold( + 1, + fn(acc: Int, x: Int) -> Int { acc * { n + 1 - x } / x }, + ) + |> Ok + } + } + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// A combinatorial function for computing the total number of combinations of $$n$$ +/// elements, that is $$n!$$. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/combinatorics +/// +/// pub fn example() { +/// // Invalid input gives an error +/// combinatorics.factorial(-1) +/// |> should.be_error() +/// +/// // Valid input returns a result +/// combinatorics.factorial(0) +/// |> should.equal(Ok(1)) +/// +/// combinatorics.factorial(1) +/// |> should.equal(Ok(1)) +/// +/// combinatorics.factorial(2) +/// |> should.equal(Ok(2)) +/// +/// combinatorics.factorial(3) +/// |> should.equal(Ok(6)) +/// +/// combinatorics.factorial(4) +/// |> should.equal(Ok(24)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn factorial(n) -> Result(Int, String) { + case n < 0 { + True -> + "Invalid input argument: n < 0. Valid input is n > 0." + |> Error + False -> + case n { + 0 -> + 1 + |> Ok + 1 -> + 1 + |> Ok + _ -> + list.range(1, n) + |> list.fold(1, fn(acc: Int, x: Int) { acc * x }) + |> Ok + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// A combinatorial function for computing the number of $$k$$-permuations (without repetitions) +/// of $$n$$ elements: +/// +/// \\[ +/// P(n, k) = \frac{n!}{(n - k)!} +/// \\] +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/combinatorics +/// +/// pub fn example() { +/// // Invalid input gives an error +/// // Error on: n = -1 < 0 +/// combinatorics.permutation(-1, 1) +/// |> should.be_error() +/// +/// // Valid input returns a result +/// combinatorics.permutation(4, 0) +/// |> should.equal(Ok(1)) +/// +/// combinatorics.permutation(4, 4) +/// |> should.equal(Ok(1)) +/// +/// combinatorics.permutation(4, 2) +/// |> should.equal(Ok(12)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn permutation(n: Int, k: Int) -> Result(Int, String) { + case n < 0 { + True -> + "Invalid input argument: n < 0. Valid input is n > 0." + |> Error + False -> + case k < 0 || k > n { + True -> + 0 + |> Ok + False -> + case k == n { + True -> + 1 + |> Ok + False -> { + let assert Ok(v1) = factorial(n) + let assert Ok(v2) = factorial(n - k) + v1 / v2 + |> Ok + } + } + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Generate all $$k$$-combinations based on a given list. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam/set +/// import gleam_community/maths/combinatorics +/// +/// pub fn example () { +/// let assert Ok(result) = combinatorics.list_combination([1, 2, 3, 4], 3) +/// result +/// |> set.from_list() +/// |> should.equal(set.from_list([[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]])) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn list_combination(arr: List(a), k: Int) -> Result(List(List(a)), String) { + case k < 0 { + True -> + "Invalid input argument: k < 0. Valid input is k > 0." + |> Error + False -> { + case k > list.length(arr) { + True -> + "Invalid input argument: k > length(arr). Valid input is 0 < k <= length(arr)." + |> Error + False -> { + do_list_combination(arr, k, []) + |> Ok + } + } + } + } +} + +fn do_list_combination(arr: List(a), k: Int, prefix: List(a)) -> List(List(a)) { + case k { + 0 -> [list.reverse(prefix)] + _ -> + case arr { + [] -> [] + [x, ..xs] -> { + let with_x = do_list_combination(xs, k - 1, [x, ..prefix]) + let without_x = do_list_combination(xs, k, prefix) + list.append(with_x, without_x) + } + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Generate all permutations of a given list. +/// +/// Repeated elements are treated as distinct for the +/// purpose of permutations, so two identical elements +/// for example will appear "both ways round". This +/// means lists with repeated elements return the same +/// number of permutations as ones without. +/// +/// N.B. The output of this function is a list of size +/// factorial in the size of the input list. Caution is +/// advised on input lists longer than ~11 elements, which +/// may cause the VM to use unholy amounts of memory for +/// the output. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam/set +/// import gleam_community/maths/combinatorics +/// +/// pub fn example () { +/// [1, 2, 3] +/// |> combinatorics.list_permutation() +/// |> set.from_list() +/// |> should.equal(set.from_list([ +/// [1, 2, 3], +/// [2, 1, 3], +/// [3, 1, 2], +/// [1, 3, 2], +/// [2, 3, 1], +/// [3, 2, 1], +/// ])) +/// +/// [1.0, 1.0] +/// |> combinatorics.list_permutation() +/// |> should.equal([[1.0, 1.0], [1.0, 1.0]]) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn list_permutation(arr: List(a)) -> List(List(a)) { + case arr { + [] -> [[]] + _ -> { + use x <- list.flat_map(arr) + // `x` is drawn from the list `arr` above, + // so Ok(...) can be safely asserted as the result of `list.pop` below + let assert Ok(#(_, remaining)) = list.pop(arr, fn(y) { x == y }) + list.map(list_permutation(remaining), fn(perm) { [x, ..perm] }) + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Generate a list containing all combinations of pairs of elements coming from two given lists. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam/list +/// import gleam_community/maths/combinatorics +/// +/// pub fn example () { +/// [] +/// |> combinatorics.cartesian_product([]) +/// |> should.equal([]) +/// +/// [1.0, 10.0] +/// |> combinatorics.cartesian_product([1.0, 2.0]) +/// |> should.equal([#(1.0, 1.0), #(1.0, 2.0), #(10.0, 1.0), #(10.0, 2.0)]) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn cartesian_product(xarr: List(a), yarr: List(a)) -> List(#(a, a)) { + let xset: set.Set(a) = + xarr + |> set.from_list() + let yset: set.Set(a) = + yarr + |> set.from_list() + xset + |> set.fold( + set.new(), + fn(accumulator0: set.Set(#(a, a)), member0: a) -> set.Set(#(a, a)) { + set.fold( + yset, + accumulator0, + fn(accumulator1: set.Set(#(a, a)), member1: a) -> set.Set(#(a, a)) { + set.insert(accumulator1, #(member0, member1)) + }, + ) + }, + ) + |> set.to_list() +} diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/conversion.gleam b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/conversion.gleam new file mode 100644 index 0000000..017aabd --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/conversion.gleam @@ -0,0 +1,183 @@ +////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous"> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script> +////<script> +//// document.addEventListener("DOMContentLoaded", function() { +//// renderMathInElement(document.body, { +//// // customised options +//// // • auto-render specific keys, e.g.: +//// delimiters: [ +//// {left: '$$', right: '$$', display: false}, +//// // {left: '$', right: '$', display: false}, +//// // {left: '\\(', right: '\\)', display: false}, +//// {left: '\\[', right: '\\]', display: true} +//// ], +//// // • rendering keys, e.g.: +//// throwOnError : false +//// }); +//// }); +////</script> +////<style> +//// .katex { font-size: 1.1em; } +////</style> +//// +//// --- +//// +//// Conversion: A module containing various functions for converting between types and quantities. +//// +//// * **Misc. functions** +//// * [`float_to_int`](#float_to_int) +//// * [`int_to_float`](#int_to_float) +//// * [`degrees_to_radians`](#degrees_to_radians) +//// * [`radians_to_degrees`](#radians_to_degrees) + +import gleam/int + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// A function that produces a number of type `Float` from an `Int`. +/// +/// Note: The function is equivalent to the `int.to_float` function in the Gleam stdlib. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/conversion +/// +/// pub fn example() { +/// conversion.int_to_float(-1) +/// |> should.equal(-1.0) +/// +/// conversion.int_to_float(1) +/// |> should.equal(1.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn int_to_float(x: Int) -> Float { + int.to_float(x) +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function returns the integral part of a given floating point value. +/// That is, everything after the decimal point of a given floating point value is discarded and only the integer value before the decimal point is returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam/option +/// import gleam_community/maths/conversion +/// import gleam_community/maths/piecewise +/// +/// pub fn example() { +/// conversion.float_to_int(12.0654) +/// |> should.equal(12) +/// +/// // Note: Making the following function call is equivalent +/// // but instead of returning a value of type 'Int' a value +/// // of type 'Float' is returned. +/// piecewise.round(12.0654, option.Some(0), option.Some(piecewise.RoundToZero)) +/// |> should.equal(Ok(12.0)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn float_to_int(x: Float) -> Int { + do_to_int(x) +} + +@external(erlang, "erlang", "trunc") +@external(javascript, "../../maths.mjs", "truncate") +fn do_to_int(a: Float) -> Int + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Convert a value in degrees to a value measured in radians. +/// That is, $$1 \text{ degrees } = \frac{\pi}{180} \text{ radians }$$. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/conversion +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// conversion.degrees_to_radians(360.) +/// |> should.equal(2. *. elementary.pi()) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn degrees_to_radians(x: Float) -> Float { + x *. do_pi() /. 180.0 +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Convert a value in degrees to a value measured in radians. +/// That is, $$1 \text{ radians } = \frac{180}{\pi} \text{ degrees }$$. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/conversion +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// conversion.radians_to_degrees(0.0) +/// |> should.equal(0.0) +/// +/// conversion.radians_to_degrees(2. *. elementary.pi()) +/// |> should.equal(360.) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn radians_to_degrees(x: Float) -> Float { + x *. 180.0 /. do_pi() +} + +@external(erlang, "math", "pi") +@external(javascript, "../../maths.mjs", "pi") +fn do_pi() -> Float diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/elementary.gleam b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/elementary.gleam new file mode 100644 index 0000000..1b518a4 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/elementary.gleam @@ -0,0 +1,1256 @@ +////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous"> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script> +////<script> +//// document.addEventListener("DOMContentLoaded", function() { +//// renderMathInElement(document.body, { +//// // customised options +//// // • auto-render specific keys, e.g.: +//// delimiters: [ +//// {left: '$$', right: '$$', display: false}, +//// // {left: '$', right: '$', display: false}, +//// // {left: '\\(', right: '\\)', display: false}, +//// {left: '\\[', right: '\\]', display: true} +//// ], +//// // • rendering keys, e.g.: +//// throwOnError : false +//// }); +//// }); +////</script> +////<style> +//// .katex { font-size: 1.1em; } +////</style> +//// +//// --- +//// +//// Elementary: A module containing a comprehensive set of foundational mathematical functions and constants. +//// +//// * **Trigonometric and hyperbolic functions** +//// * [`acos`](#acos) +//// * [`acosh`](#acosh) +//// * [`asin`](#asin) +//// * [`asinh`](#asinh) +//// * [`atan`](#atan) +//// * [`atan2`](#atan2) +//// * [`atanh`](#atanh) +//// * [`cos`](#cos) +//// * [`cosh`](#cosh) +//// * [`sin`](#sin) +//// * [`sinh`](#sinh) +//// * [`tan`](#tan) +//// * [`tanh`](#tanh) +//// * **Powers, logs and roots** +//// * [`exponential`](#exponential) +//// * [`natural_logarithm`](#natural_logarithm) +//// * [`logarithm`](#logarithm) +//// * [`logarithm_2`](#logarithm_2) +//// * [`logarithm_10`](#logarithm_10) +//// * [`power`](#power) +//// * [`square_root`](#square_root) +//// * [`cube_root`](#cube_root) +//// * [`nth_root`](#nth_root) +//// * **Mathematical constants** +//// * [`pi`](#pi) +//// * [`tau`](#tau) +//// * [`e`](#e) +//// + +import gleam/int +import gleam/option + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The inverse cosine function: +/// +/// \\[ +/// \forall x \in \[-1, 1\], \\; \cos^{-1}{(x)} = y \in \[0, \pi \] +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\[-1, 1\]$$ as input and returns a +/// numeric value $$y$$ that lies in the range $$\[0, \pi \]$$ (an angle in radians). +/// If the input value is outside the domain of the function an error is returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.acos(1.0) +/// |> should.equal(Ok(0.0)) +/// +/// elementary.acos(1.1) +/// |> should.be_error() +/// +/// elementary.acos(-1.1) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn acos(x: Float) -> Result(Float, String) { + case x >=. -1.0 && x <=. 1.0 { + True -> + do_acos(x) + |> Ok + False -> + "Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1." + |> Error + } +} + +@external(erlang, "math", "acos") +@external(javascript, "../../maths.mjs", "acos") +fn do_acos(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The inverse hyperbolic cosine function: +/// +/// \\[ +/// \forall x \in [1, +\infty\), \\; \cosh^{-1}{(x)} = y \in \[0, +\infty\) +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\[1, +\infty\)$$ as input and returns +/// a numeric value $$y$$ that lies in the range $$\[0, +\infty\)$$ (an angle in radians). +/// If the input value is outside the domain of the function an error is returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.acosh(1.0) +/// |> should.equal(Ok(0.0)) +/// +/// elementary.acosh(0.0) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn acosh(x: Float) -> Result(Float, String) { + case x >=. 1.0 { + True -> + do_acosh(x) + |> Ok + False -> + "Invalid input argument: x < 1. Valid input is x >= 1." + |> Error + } +} + +@external(erlang, "math", "acosh") +@external(javascript, "../../maths.mjs", "acosh") +fn do_acosh(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The inverse sine function: +/// +/// \\[ +/// \forall x \in \[-1, 1\], \\; \sin^{-1}{(x)} = y \in \(-\infty, +\infty\) +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\[-1, 1\]$$ as input and returns a numeric +/// value $$y$$ that lies in the range $$\[-\frac{\pi}{2}, \frac{\pi}{2}\]$$ (an angle in radians). +/// If the input value is outside the domain of the function an error is returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.asin(0.0) +/// |> should.equal(Ok(0.0)) +/// +/// elementary.asin(1.1) +/// |> should.be_error() +/// +/// elementary.asin(-1.1) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn asin(x: Float) -> Result(Float, String) { + case x >=. -1.0 && x <=. 1.0 { + True -> + do_asin(x) + |> Ok + False -> + "Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1." + |> Error + } +} + +@external(erlang, "math", "asin") +@external(javascript, "../../maths.mjs", "asin") +fn do_asin(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The inverse hyperbolic sine function: +/// +/// \\[ +/// \forall x \in \(-\infty, \infty\), \\; \sinh^{-1}{(x)} = y \in \(-\infty, +\infty\) +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(-\infty, +\infty\)$$ as input and returns +/// a numeric value $$y$$ that lies in the range $$\(-\infty, +\infty\)$$ (an angle in radians). +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.asinh(0.0) +/// |> should.equal(0.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn asinh(x: Float) -> Float { + do_asinh(x) +} + +@external(erlang, "math", "asinh") +@external(javascript, "../../maths.mjs", "asinh") +fn do_asinh(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The inverse tangent function: +/// +/// \\[ +/// \forall x \in \(-\infty, \infty\), \\; \tan^{-1}{(x)} = y \in \[-\frac{\pi}{2}, \frac{\pi}{2}\] +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(-\infty, +\infty\)$$ as input and returns +/// a numeric value $$y$$ that lies in the range $$\[-\frac{\pi}{2}, \frac{\pi}{2}\]$$ (an angle in radians). +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.atan(0.0) +/// |> should.equal(0.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn atan(x: Float) -> Float { + do_atan(x) +} + +@external(erlang, "math", "atan") +@external(javascript, "../../maths.mjs", "atan") +fn do_atan(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The inverse 2-argument tangent function: +/// +/// \\[ +/// \text{atan2}(y, x) = +/// \begin{cases} +/// \tan^{-1}(\frac y x) &\text{if } x > 0, \\\\ +/// \tan^{-1}(\frac y x) + \pi &\text{if } x < 0 \text{ and } y \ge 0, \\\\ +/// \tan^{-1}(\frac y x) - \pi &\text{if } x < 0 \text{ and } y < 0, \\\\ +/// +\frac{\pi}{2} &\text{if } x = 0 \text{ and } y > 0, \\\\ +/// -\frac{\pi}{2} &\text{if } x = 0 \text{ and } y < 0, \\\\ +/// \text{undefined} &\text{if } x = 0 \text{ and } y = 0. +/// \end{cases} +/// \\] +/// +/// The function returns the angle in radians from the x-axis to the line containing the +/// origin $$\(0, 0\)$$ and a point given as input with coordinates $$\(x, y\)$$. The numeric value +/// returned by $$\text{atan2}(y, x)$$ is in the range $$\[-\pi, \pi\]$$. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.atan2(0.0, 0.0) +/// |> should.equal(0.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn atan2(y: Float, x: Float) -> Float { + do_atan2(y, x) +} + +@external(erlang, "math", "atan2") +@external(javascript, "../../maths.mjs", "atan2") +fn do_atan2(a: Float, b: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The inverse hyperbolic tangent function: +/// +/// \\[ +/// \forall x \in \(-1, 1\), \\; \tanh^{-1}{(x)} = y \in \(-\infty, +\infty\) +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(-1, 1\)$$ as input and returns +/// a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$ (an angle in radians). +/// If the input value is outside the domain of the function an error is returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.atanh(0.0) +/// |> should.equal(Ok(0.0)) +/// +/// elementary.atanh(1.0) +/// |> should.be_error() +/// +/// elementary.atanh(-1.0) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn atanh(x: Float) -> Result(Float, String) { + case x >. -1.0 && x <. 1.0 { + True -> + do_atanh(x) + |> Ok + False -> + "Invalid input argument: x > -1 or x < 1. Valid input is -1. < x < 1." + |> Error + } +} + +@external(erlang, "math", "atanh") +@external(javascript, "../../maths.mjs", "atanh") +fn do_atanh(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The cosine function: +/// +/// \\[ +/// \forall x \in \(-\infty, +\infty\), \\; \cos{(x)} = y \in \[-1, 1\] +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(-\infty, \infty\)$$ (an angle in radians) +/// as input and returns a numeric value $$y$$ that lies in the range $$\[-1, 1\]$$. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.cos(0.0) +/// |> should.equal(1.0) +/// +/// elementary.cos(elementary.pi()) +/// |> should.equal(-1.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn cos(x: Float) -> Float { + do_cos(x) +} + +@external(erlang, "math", "cos") +@external(javascript, "../../maths.mjs", "cos") +fn do_cos(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The hyperbolic cosine function: +/// +/// \\[ +/// \forall x \in \(-\infty, \infty\), \\; \cosh{(x)} = y \in \(-\infty, +\infty\) +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(-\infty, \infty\)$$ as input (an angle in radians) +/// and returns a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$. +/// If the input value is too large an overflow error might occur. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.cosh(0.0) +/// |> should.equal(0.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn cosh(x: Float) -> Float { + do_cosh(x) +} + +@external(erlang, "math", "cosh") +@external(javascript, "../../maths.mjs", "cosh") +fn do_cosh(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The sine function: +/// +/// \\[ +/// \forall x \in \(-\infty, +\infty\), \\; \sin{(x)} = y \in \[-1, 1\] +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(-\infty, \infty\)$$ (an angle in radians) +/// as input and returns a numeric value $$y$$ that lies in the range $$\[-1, 1\]$$. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.sin(0.0) +/// |> should.equal(0.0) +/// +/// elementary.sin(0.5 *. elementary.pi()) +/// |> should.equal(1.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn sin(x: Float) -> Float { + do_sin(x) +} + +@external(erlang, "math", "sin") +@external(javascript, "../../maths.mjs", "sin") +fn do_sin(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The hyperbolic sine function: +/// +/// \\[ +/// \forall x \in \(-\infty, +\infty\), \\; \sinh{(x)} = y \in \(-\infty, +\infty\) +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(-\infty, +\infty\)$$ as input +/// (an angle in radians) and returns a numeric value $$y$$ that lies in the range +/// $$\(-\infty, +\infty\)$$. If the input value is too large an overflow error might +/// occur. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.sinh(0.0) +/// |> should.equal(0.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn sinh(x: Float) -> Float { + do_sinh(x) +} + +@external(erlang, "math", "sinh") +@external(javascript, "../../maths.mjs", "sinh") +fn do_sinh(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The tangent function: +/// +/// \\[ +/// \forall x \in \(-\infty, +\infty\), \\; \tan{(x)} = y \in \(-\infty, +\infty\) +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(-\infty, +\infty\)$$ as input +/// (an angle in radians) and returns a numeric value $$y$$ that lies in the range +/// $$\(-\infty, +\infty\)$$. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.tan(0.0) +/// |> should.equal(0.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn tan(x: Float) -> Float { + do_tan(x) +} + +@external(erlang, "math", "tan") +@external(javascript, "../../maths.mjs", "tan") +fn do_tan(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The hyperbolic tangent function: +/// +/// \\[ +/// \forall x \in \(-\infty, \infty\), \\; \tanh{(x)} = y \in \[-1, 1\] +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(-\infty, \infty\)$$ as input (an angle in radians) +/// and returns a numeric value $$y$$ that lies in the range $$\[-1, 1\]$$. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example () { +/// elementary.tanh(0.0) +/// |> should.equal(0.0) +/// +/// elementary.tanh(25.0) +/// |> should.equal(1.0) +/// +/// elementary.tanh(-25.0) +/// |> should.equal(-1.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn tanh(x: Float) -> Float { + do_tanh(x) +} + +@external(erlang, "math", "tanh") +@external(javascript, "../../maths.mjs", "tanh") +fn do_tanh(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The exponential function: +/// +/// \\[ +/// \forall x \in \(-\infty, \infty\), \\; e^{(x)} = y \in \(0, +\infty\) +/// \\] +/// +/// $$e \approx 2.71828\dots$$ is Eulers' number. +/// +/// Note: If the input value $$x$$ is too large an overflow error might occur. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.exponential(0.0) +/// |> should.equal(1.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn exponential(x: Float) -> Float { + do_exponential(x) +} + +@external(erlang, "math", "exp") +@external(javascript, "../../maths.mjs", "exponential") +fn do_exponential(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The natural logarithm function: +/// +/// \\[ +/// \forall x \in \(0, \infty\), \\; \log_{e}{(x)} = y \in \(-\infty, +\infty\) +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(0, \infty\)$$ as input and returns +/// a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$. +/// If the input value is outside the domain of the function an error is returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example () { +/// elementary.natural_logarithm(1.0) +/// |> should.equal(Ok(0.0)) +/// +/// elementary.natural_logarithm(elementary.e()) +/// |> should.equal(Ok(1.0)) +/// +/// elementary.natural_logarithm(-1.0) +/// |> should.be_error() +/// } +/// </details> +/// +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn natural_logarithm(x: Float) -> Result(Float, String) { + case x >. 0.0 { + True -> + do_natural_logarithm(x) + |> Ok + False -> + "Invalid input argument: x <= 0. Valid input is x > 0." + |> Error + } +} + +@external(erlang, "math", "log") +@external(javascript, "../../maths.mjs", "logarithm") +fn do_natural_logarithm(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The base $$b$$ logarithm function (computed through the "change of base" formula): +/// +/// \\[ +/// \forall x \in \(0, \infty\) \textnormal{ and } b > 1, \\; \log_{b}{(x)} = y \in \(-\infty, +\infty\) +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(0, \infty\)$$ and a base $$b > 1$$ as input and returns +/// a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$. +/// If the input value is outside the domain of the function an error is returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam/option +/// import gleam_community/maths/elementary +/// +/// pub fn example () { +/// elementary.logarithm(1.0, option.Some(10.0)) +/// |> should.equal(Ok(0.0)) +/// +/// elementary.logarithm(elementary.e(), option.Some(elementary.e())) +/// |> should.equal(Ok(1.0)) +/// +/// elementary.logarithm(-1.0, option.Some(2.0)) +/// |> should.be_error() +/// } +/// </details> +/// +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn logarithm(x: Float, base: option.Option(Float)) -> Result(Float, String) { + case x >. 0.0 { + True -> + case base { + option.Some(a) -> + case a >. 0.0 && a != 1.0 { + True -> { + // Apply the "change of base formula" + let assert Ok(numerator) = logarithm_10(x) + let assert Ok(denominator) = logarithm_10(a) + numerator /. denominator + |> Ok + } + False -> + "Invalid input argument: base <= 0 or base == 1. Valid input is base > 0 and base != 1." + |> Error + } + _ -> + "Invalid input argument: base <= 0 or base == 1. Valid input is base > 0 and base != 1." + |> Error + } + _ -> + "Invalid input argument: x <= 0. Valid input is x > 0." + |> Error + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The The base-2 logarithm function: +/// +/// \\[ +/// \forall x \in \(0, \infty), \\; \log_{2}{(x)} = y \in \(-\infty, +\infty\) +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(0, \infty\)$$ as input and returns +/// a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$. +/// If the input value is outside the domain of the function an error is returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example () { +/// elementary.logarithm_2(1.0) +/// |> should.equal(Ok(0.0)) +/// +/// elementary.logarithm_2(2.0) +/// |> should.equal(Ok(1.0)) +/// +/// elementary.logarithm_2(-1.0) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn logarithm_2(x: Float) -> Result(Float, String) { + case x >. 0.0 { + True -> + do_logarithm_2(x) + |> Ok + False -> + "Invalid input argument: x <= 0. Valid input is x > 0." + |> Error + } +} + +@external(erlang, "math", "log2") +@external(javascript, "../../maths.mjs", "logarithm_2") +fn do_logarithm_2(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The base-10 logarithm function: +/// +/// \\[ +/// \forall x \in \(0, \infty), \\; \log_{10}{(x)} = y \in \(-\infty, +\infty\) +/// \\] +/// +/// The function takes a number $$x$$ in its domain $$\(0, \infty\)$$ as input and returns +/// a numeric value $$y$$ that lies in the range $$\(-\infty, \infty\)$$. +/// If the input value is outside the domain of the function an error is returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example () { +/// elementary.logarithm_10(1.0) +/// |> should.equal(Ok(0.0)) +/// +/// elementary.logarithm_10(10.0) +/// |> should.equal(Ok(1.0)) +/// +/// elementary.logarithm_10(-1.0) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn logarithm_10(x: Float) -> Result(Float, String) { + case x >. 0.0 { + True -> + do_logarithm_10(x) + |> Ok + False -> + "Invalid input argument: x <= 0. Valid input is x > 0." + |> Error + } +} + +@external(erlang, "math", "log10") +@external(javascript, "../../maths.mjs", "logarithm_10") +fn do_logarithm_10(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The exponentiation function: $$y = x^{a}$$. +/// +/// Note that the function is not defined if: +/// 1. The base is negative ($$x < 0$$) and the exponent is fractional +/// ($$a = \frac{n}{m}$$ is an irrreducible fraction). An error will be returned +/// as an imaginary number will otherwise have to be returned. +/// 2. The base is zero ($$x = 0$$) and the exponent is negative ($$a < 0$$) then the +/// expression is equivalent to the exponent $$y$$ divided by $$0$$ and an +/// error will have to be returned as the expression is otherwise undefined. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.power(2., -1.) +/// |> should.equal(Ok(0.5)) +/// +/// elementary.power(2., 2.) +/// |> should.equal(Ok(4.0)) +/// +/// elementary.power(-1., 0.5) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn power(x: Float, y: Float) -> Result(Float, String) { + let fractional: Bool = do_ceiling(y) -. y >. 0.0 + // In the following check: + // 1. If the base (x) is negative and the exponent (y) is fractional + // then return an error as it will otherwise be an imaginary number + // 2. If the base (x) is 0 and the exponent (y) is negative then the + // expression is equivalent to the exponent (y) divided by 0 and an + // error should be returned + case x <. 0.0 && fractional || x == 0.0 && y <. 0.0 { + True -> + "Invalid input argument: x < 0 and y is fractional or x = 0 and y < 0." + |> Error + False -> + do_power(x, y) + |> Ok + } +} + +@external(erlang, "math", "pow") +@external(javascript, "../../maths.mjs", "power") +fn do_power(a: Float, b: Float) -> Float + +@external(erlang, "math", "ceil") +@external(javascript, "../../maths.mjs", "ceiling") +fn do_ceiling(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The square root function: $$y = \sqrt[2]{x} = x^{\frac{1}{2}}$$. +/// +/// Note that the function is not defined if: +/// 1. The input is negative ($$x < 0$$). An error will be returned +/// as an imaginary number will otherwise have to be returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.square_root(1.0) +/// |> should.equal(Ok(1.0)) +/// +/// elementary.square_root(4.0) +/// |> should.equal(Ok(2.0)) +/// +/// elementary.square_root(-1.0) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn square_root(x: Float) -> Result(Float, String) { + // In the following check: + // 1. If x is negative then return an error as it will otherwise be an + // imaginary number + case x <. 0.0 { + True -> + "Invalid input argument: x < 0." + |> Error + False -> { + let assert Ok(result) = power(x, 1.0 /. 2.0) + result + |> Ok + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The cube root function: $$y = \sqrt[3]{x} = x^{\frac{1}{3}}$$. +/// +/// Note that the function is not defined if: +/// 1. The input is negative ($$x < 0$$). An error will be returned +/// as an imaginary number will otherwise have to be returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.cube_root(1.0) +/// |> should.equal(Ok(1.0)) +/// +/// elementary.cube_root(27.0) +/// |> should.equal(Ok(3.0)) +/// +/// elementary.cube_root(-1.0) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn cube_root(x: Float) -> Result(Float, String) { + // In the following check: + // 1. If x is negative then return an error as it will otherwise be an + // imaginary number + case x <. 0.0 { + True -> + "Invalid input argument: x < 0." + |> Error + False -> { + let assert Ok(result) = power(x, 1.0 /. 3.0) + result + |> Ok + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The $$n$$'th root function: $$y = \sqrt[n]{x} = x^{\frac{1}{n}}$$. +/// +/// Note that the function is not defined if: +/// 1. The input is negative ($$x < 0$$). An error will be returned +/// as an imaginary number will otherwise have to be returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// elementary.nth_root(1.0, 2) +/// |> should.equal(Ok(1.0)) +/// +/// elementary.nth_root(27.0, 3) +/// |> should.equal(Ok(3.0)) +/// +/// elementary.nth_root(256.0, 4) +/// |> should.equal(Ok(4.0)) +/// +/// elementary.nth_root(-1.0, 2) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn nth_root(x: Float, n: Int) -> Result(Float, String) { + // In the following check: + // 1. If x is negative then return an error as it will otherwise be an + // imaginary number + case x <. 0.0 { + True -> + "Invalid input argument: x < 0. Valid input is x > 0" + |> Error + False -> + case n >= 1 { + True -> { + let assert Ok(result) = power(x, 1.0 /. int.to_float(n)) + result + |> Ok + } + False -> + "Invalid input argument: n < 1. Valid input is n >= 2." + |> Error + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The mathematical constant pi: $$\pi \approx 3.1415\dots$$ +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn pi() -> Float { + do_pi() +} + +@external(erlang, "math", "pi") +@external(javascript, "../../maths.mjs", "pi") +fn do_pi() -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The mathematical constant tau: $$\tau = 2 \cdot \pi \approx 6.283\dots$$ +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn tau() -> Float { + 2.0 *. pi() +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Euler's number $$e \approx 2.71828\dots$$. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// +/// pub fn example() { +/// // Test that the constant is approximately equal to 2.7128... +/// elementary.e() +/// |> elementary.is_close(2.7128, 0.0, 0.000001) +/// |> should.be_true() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn e() -> Float { + exponential(1.0) +} diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/metrics.gleam b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/metrics.gleam new file mode 100644 index 0000000..1dab2b4 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/metrics.gleam @@ -0,0 +1,560 @@ +////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous"> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script> +////<script> +//// document.addEventListener("DOMContentLoaded", function() { +//// renderMathInElement(document.body, { +//// // customised options +//// // • auto-render specific keys, e.g.: +//// delimiters: [ +//// {left: '$$', right: '$$', display: false}, +//// // {left: '$', right: '$', display: false}, +//// // {left: '\\(', right: '\\)', display: false}, +//// {left: '\\[', right: '\\]', display: true} +//// ], +//// // • rendering keys, e.g.: +//// throwOnError : false +//// }); +//// }); +////</script> +////<style> +//// .katex { font-size: 1.1em; } +////</style> +//// +//// --- +//// +//// Metrics: A module offering functions for calculating distances and other types of metrics. +//// +//// * **Distances** +//// * [`norm`](#norm) +//// * [`manhatten_distance`](#float_manhatten_distance) +//// * [`minkowski_distance`](#minkowski_distance) +//// * [`euclidean_distance`](#euclidean_distance) +//// * **Basic statistical measures** +//// * [`mean`](#mean) +//// * [`median`](#median) +//// * [`variance`](#variance) +//// * [`standard_deviation`](#standard_deviation) +//// + +import gleam_community/maths/elementary +import gleam_community/maths/piecewise +import gleam_community/maths/arithmetics +import gleam_community/maths/predicates +import gleam_community/maths/conversion +import gleam/list +import gleam/pair +import gleam/float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the $$p$$-norm of a list (representing a vector): +/// +/// \\[ +/// \left( \sum_{i=1}^n \left|x_i\right|^{p} \right)^{\frac{1}{p}} +/// \\] +/// +/// In the formula, $$n$$ is the length of the list and $$x_i$$ is the value in the input list indexed by $$i$$. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// import gleam_community/maths/metrics +/// import gleam_community/maths/predicates +/// +/// pub fn example () { +/// let assert Ok(tol) = elementary.power(-10.0, -6.0) +/// +/// [1.0, 1.0, 1.0] +/// |> metrics.norm(1.0) +/// |> predicates.is_close(3.0, 0.0, tol) +/// |> should.be_true() +/// +/// [1.0, 1.0, 1.0] +/// |> metrics.norm(-1.0) +/// |> predicates.is_close(0.3333333333333333, 0.0, tol) +/// |> should.be_true() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn norm(arr: List(Float), p: Float) -> Float { + case arr { + [] -> 0.0 + _ -> { + let agg: Float = + arr + |> list.fold( + 0.0, + fn(acc: Float, a: Float) -> Float { + let assert Ok(result) = + elementary.power(piecewise.float_absolute_value(a), p) + result +. acc + }, + ) + let assert Ok(result) = elementary.power(agg, 1.0 /. p) + result + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the Manhatten distance between two lists (representing vectors): +/// +/// \\[ +/// \sum_{i=1}^n \left|x_i - y_i \right| +/// \\] +/// +/// In the formula, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i, j$$. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// import gleam_community/maths/metrics +/// import gleam_community/maths/predicates +/// +/// pub fn example () { +/// let assert Ok(tol) = elementary.power(-10.0, -6.0) +/// +/// // Empty lists returns 0.0 +/// metrics.float_manhatten_distance([], []) +/// |> should.equal(Ok(0.0)) +/// +/// // Differing lengths returns error +/// metrics.manhatten_distance([], [1.0]) +/// |> should.be_error() +/// +/// let assert Ok(result) = metrics.manhatten_distance([0.0, 0.0], [1.0, 2.0]) +/// result +/// |> predicates.is_close(3.0, 0.0, tol) +/// |> should.be_true() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn manhatten_distance( + xarr: List(Float), + yarr: List(Float), +) -> Result(Float, String) { + minkowski_distance(xarr, yarr, 1.0) +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the Minkowski distance between two lists (representing vectors): +/// +/// \\[ +/// \left( \sum_{i=1}^n \left|x_i - y_i \right|^{p} \right)^{\frac{1}{p}} +/// \\] +/// +/// In the formula, $$p >= 1$$ is the order, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i, j$$. +/// +/// The Minkowski distance is a generalization of both the Euclidean distance ($$p=2$$) and the Manhattan distance ($$p = 1$$). +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// import gleam_community/maths/metrics +/// import gleam_community/maths/predicates +/// +/// pub fn example () { +/// let assert Ok(tol) = elementary.power(-10.0, -6.0) +/// +/// // Empty lists returns 0.0 +/// metrics.minkowski_distance([], [], 1.0) +/// |> should.equal(Ok(0.0)) +/// +/// // Differing lengths returns error +/// metrics.minkowski_distance([], [1.0], 1.0) +/// |> should.be_error() +/// +/// // Test order < 1 +/// metrics.minkowski_distance([0.0, 0.0], [0.0, 0.0], -1.0) +/// |> should.be_error() +/// +/// let assert Ok(result) = metrics.minkowski_distance([0.0, 0.0], [1.0, 2.0], 1.0) +/// result +/// |> predicates.is_close(3.0, 0.0, tol) +/// |> should.be_true() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn minkowski_distance( + xarr: List(Float), + yarr: List(Float), + p: Float, +) -> Result(Float, String) { + let xlen: Int = list.length(xarr) + let ylen: Int = list.length(yarr) + case xlen == ylen { + False -> + "Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)." + |> Error + True -> + case p <. 1.0 { + True -> + "Invalid input argument: p < 1. Valid input is p >= 1." + |> Error + False -> + list.zip(xarr, yarr) + |> list.map(fn(tuple: #(Float, Float)) -> Float { + pair.first(tuple) -. pair.second(tuple) + }) + |> norm(p) + |> Ok + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the Euclidean distance between two lists (representing vectors): +/// +/// \\[ +/// \left( \sum_{i=1}^n \left|x_i - y_i \right|^{2} \right)^{\frac{1}{2}} +/// \\] +/// +/// In the formula, $$n$$ is the length of the two lists and $$x_i, y_i$$ are the values in the respective input lists indexed by $$i, j$$. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// import gleam_community/maths/metrics +/// import gleam_community/maths/predicates +/// +/// pub fn example () { +/// let assert Ok(tol) = elementary.power(-10.0, -6.0) +/// +/// // Empty lists returns 0.0 +/// metrics.euclidean_distance([], []) +/// |> should.equal(Ok(0.0)) +/// +/// // Differing lengths returns error +/// metrics.euclidean_distance([], [1.0]) +/// |> should.be_error() +/// +/// let assert Ok(result) = metrics.euclidean_distance([0.0, 0.0], [1.0, 2.0]) +/// result +/// |> predicates.is_close(2.23606797749979, 0.0, tol) +/// |> should.be_true() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn euclidean_distance( + xarr: List(Float), + yarr: List(Float), +) -> Result(Float, String) { + minkowski_distance(xarr, yarr, 2.0) +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/nicklasxyz/gleam_stats/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the arithmetic mean of the elements in a list: +/// +/// \\[ +/// \bar{x} = \frac{1}{n}\sum_{i=1}^n x_i +/// \\] +/// +/// In the formula, $$n$$ is the sample size (the length of the list) and +/// $$x_i$$ is the sample point in the input list indexed by $$i$$. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/metrics +/// +/// pub fn example () { +/// // An empty list returns an error +/// [] +/// |> metrics.mean() +/// |> should.be_error() +/// +/// // Valid input returns a result +/// [1., 2., 3.] +/// |> metrics.mean() +/// |> should.equal(Ok(2.)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn mean(arr: List(Float)) -> Result(Float, String) { + case arr { + [] -> + "Invalid input argument: The list is empty." + |> Error + _ -> + arr + |> arithmetics.float_sum() + |> fn(a: Float) -> Float { + a /. conversion.int_to_float(list.length(arr)) + } + |> Ok + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/nicklasxyz/gleam_stats/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the median of the elements in a list. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/metrics +/// +/// pub fn example () { +/// // An empty list returns an error +/// [] +/// |> metrics.median() +/// |> should.be_error() +/// +/// // Valid input returns a result +/// [1., 2., 3.] +/// |> metrics.median() +/// |> should.equal(Ok(2.)) +/// +/// [1., 2., 3., 4.] +/// |> metrics.median() +/// |> should.equal(Ok(2.5)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn median(arr: List(Float)) -> Result(Float, String) { + case arr { + [] -> + "Invalid input argument: The list is empty." + |> Error + _ -> { + let count: Int = list.length(arr) + let mid: Int = list.length(arr) / 2 + let sorted: List(Float) = list.sort(arr, float.compare) + case predicates.is_odd(count) { + // If there is an odd number of elements in the list, then the median + // is just the middle value + True -> { + let assert Ok(val0) = list.at(sorted, mid) + val0 + |> Ok + } + // If there is an even number of elements in the list, then the median + // is the mean of the two middle values + False -> { + let assert Ok(val0) = list.at(sorted, mid - 1) + let assert Ok(val1) = list.at(sorted, mid) + [val0, val1] + |> mean() + } + } + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/nicklasxyz/gleam_stats/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the sample variance of the elements in a list: +/// \\[ +/// s^{2} = \frac{1}{n - d} \sum_{i=1}^{n}(x_i - \bar{x}) +/// \\] +/// +/// In the formula, $$n$$ is the sample size (the length of the list) and +/// $$x_i$$ is the sample point in the input list indexed by $$i$$. +/// Furthermore, $$\bar{x}$$ is the sample mean and $$d$$ is the "Delta +/// Degrees of Freedom", and is by default set to $$d = 0$$, which gives a biased +/// estimate of the sample variance. Setting $$d = 1$$ gives an unbiased estimate. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/metrics +/// +/// pub fn example () { +/// // Degrees of freedom +/// let ddof: Int = 1 +/// +/// // An empty list returns an error +/// [] +/// |> metrics.variance(ddof) +/// |> should.be_error() +/// +/// // Valid input returns a result +/// [1., 2., 3.] +/// |> metrics.variance(ddof) +/// |> should.equal(Ok(1.)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn variance(arr: List(Float), ddof: Int) -> Result(Float, String) { + case arr { + [] -> + "Invalid input argument: The list is empty." + |> Error + _ -> + case ddof < 0 { + True -> + "Invalid input argument: ddof < 0. Valid input is ddof >= 0." + |> Error + False -> { + let assert Ok(mean) = mean(arr) + arr + |> list.map(fn(a: Float) -> Float { + let assert Ok(result) = elementary.power(a -. mean, 2.0) + result + }) + |> arithmetics.float_sum() + |> fn(a: Float) -> Float { + a /. { + conversion.int_to_float(list.length(arr)) -. conversion.int_to_float( + ddof, + ) + } + } + |> Ok + } + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/nicklasxyz/gleam_stats/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Calculcate the sample standard deviation of the elements in a list: +/// \\[ +/// s = \left(\frac{1}{n - d} \sum_{i=1}^{n}(x_i - \bar{x})\right)^{\frac{1}{2}} +/// \\] +/// +/// In the formula, $$n$$ is the sample size (the length of the list) and +/// $$x_i$$ is the sample point in the input list indexed by $$i$$. +/// Furthermore, $$\bar{x}$$ is the sample mean and $$d$$ is the "Delta +/// Degrees of Freedom", and is by default set to $$d = 0$$, which gives a biased +/// estimate of the sample standard deviation. Setting $$d = 1$$ gives an unbiased estimate. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/metrics +/// +/// pub fn example () { +/// // Degrees of freedom +/// let ddof: Int = 1 +/// +/// // An empty list returns an error +/// [] +/// |> metrics.standard_deviationddof) +/// |> should.be_error() +/// +/// // Valid input returns a result +/// [1., 2., 3.] +/// |> metrics.standard_deviation(ddof) +/// |> should.equal(Ok(1.)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn standard_deviation(arr: List(Float), ddof: Int) -> Result(Float, String) { + case arr { + [] -> + "Invalid input argument: The list is empty." + |> Error + _ -> + case ddof < 0 { + True -> + "Invalid input argument: ddof < 0. Valid input is ddof >= 0." + |> Error + False -> { + let assert Ok(variance) = variance(arr, ddof) + // The computed variance will always be positive + // So an error should never be returned + let assert Ok(stdev) = elementary.square_root(variance) + stdev + |> Ok + } + } + } +} diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/piecewise.gleam b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/piecewise.gleam new file mode 100644 index 0000000..3b40a18 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/piecewise.gleam @@ -0,0 +1,1228 @@ +////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous"> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script> +////<script> +//// document.addEventListener("DOMContentLoaded", function() { +//// renderMathInElement(document.body, { +//// // customised options +//// // • auto-render specific keys, e.g.: +//// delimiters: [ +//// {left: '$$', right: '$$', display: false}, +//// // {left: '$', right: '$', display: false}, +//// // {left: '\\(', right: '\\)', display: false}, +//// {left: '\\[', right: '\\]', display: true} +//// ], +//// // • rendering keys, e.g.: +//// throwOnError : false +//// }); +//// }); +////</script> +////<style> +//// .katex { font-size: 1.1em; } +////</style> +//// +//// --- +//// +//// Piecewise: A module containing functions that have different definitions depending on conditions or intervals of their domain. +//// +//// * **Rounding functions** +//// * [`ceiling`](#ceiling) +//// * [`floor`](#floor) +//// * [`truncate`](#truncate) +//// * [`round`](#round) +//// * **Sign and absolute value functions** +//// * [`float_absolute_value`](#float_absolute_value) +//// * [`int_absolute_value`](#int_absolute_value) +//// * [`float_absolute_difference`](#float_absolute_difference) +//// * [`int_absolute_difference`](#int_absolute_difference) +//// * [`float_sign`](#float_sign) +//// * [`int_sign`](#int_sign) +//// * [`float_copy_sign`](#float_copy_sign) +//// * [`int_copy_sign`](#float_copy_sign) +//// * [`float_flip_sign`](#float_flip_sign) +//// * [`int_flip_sign`](#int_flip_sign) +//// * **Misc. mathematical functions** +//// * [`minimum`](#minimum) +//// * [`maximum`](#maximum) +//// * [`minmax`](#minmax) +//// * [`list_minimum`](#list_minimum) +//// * [`list_maximum`](#list_maximum) +//// * [`extrema`](#extrema) +//// * [`arg_minimum`](#arg_minimum) +//// * [`arg_maximum`](#arg_maximum) +//// + +import gleam/option +import gleam/list +import gleam/order +import gleam/pair +import gleam/int +import gleam_community/maths/conversion +import gleam_community/maths/elementary + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The ceiling function rounds a given input value $$x \in \mathbb{R}$$ to the nearest integer value (at the specified digit) that is larger than or equal to the input $$x$$. +/// +/// Note: The ceiling function is used as an alias for the rounding function [`round`](#round) with rounding mode `RoundUp`. +/// +/// <details> +/// <summary>Details</summary> +/// +/// For example, $$12.0654$$ is rounded to: +/// - $$13.0$$ for 0 digits after the decimal point (`digits = 0`) +/// - $$12.1$$ for 1 digit after the decimal point (`digits = 1`) +/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`) +/// - $$12.066$$ for 3 digits after the decimal point (`digits = 3`) +/// +/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point. +/// For example, $$12.0654$$ is rounded to: +/// - $$20.0$$ for 1 digit places before the decimal point (`digit = -1`) +/// - $$100.0$$ for 2 digits before the decimal point (`digits = -2`) +/// - $$1000.0$$ for 3 digits before the decimal point (`digits = -3`) +/// +/// </details> +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam/option +/// import gleam_community/maths/piecewise +/// +/// pub fn example() { +/// piecewise.ceiling(12.0654, option.Some(1)) +/// |> should.equal(Ok(12.1)) +/// +/// piecewise.ceiling(12.0654, option.Some(2)) +/// |> should.equal(Ok(12.07)) +/// +/// piecewise.ceiling(12.0654, option.Some(3)) +/// |> should.equal(Ok(12.066)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn ceiling(x: Float, digits: option.Option(Int)) -> Result(Float, String) { + round(x, digits, option.Some(RoundUp)) +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The floor function rounds input $$x \in \mathbb{R}$$ to the nearest integer value (at the specified digit) that is less than or equal to the input $$x$$. +/// +/// Note: The floor function is used as an alias for the rounding function [`round`](#round) with rounding mode `RoundDown`. +/// +/// <details> +/// <summary>Details</summary> +/// +/// For example, $$12.0654$$ is rounded to: +/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`) +/// - $$12.0$$ for 1 digits after the decimal point (`digits = 1`) +/// - $$12.06$$ for 2 digits after the decimal point (`digits = 2`) +/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`) +/// +/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point. +/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`) +/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`) +/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`) +/// +/// </details> +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam/option +/// import gleam_community/maths/piecewise +/// +/// pub fn example() { +/// piecewise.floor(12.0654, option.Some(1)) +/// |> should.equal(Ok(12.0)) +/// +/// piecewise.floor(12.0654, option.Some(2)) +/// |> should.equal(Ok(12.06)) +/// +/// piecewise.floor(12.0654, option.Some(3)) +/// |> should.equal(Ok(12.065)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn floor(x: Float, digits: option.Option(Int)) -> Result(Float, String) { + round(x, digits, option.Some(RoundDown)) +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The truncate function rounds a given input $$x \in \mathbb{R}$$ to the nearest integer value (at the specified digit) that is less than or equal to the absolute value of the input $$x$$. +/// +/// Note: The truncate function is used as an alias for the rounding function [`round`](#round) with rounding mode `RoundToZero`. +/// +/// <details> +/// <summary>Details</summary> +/// +/// For example, $$12.0654$$ is rounded to: +/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`) +/// - $$12.0$$ for 1 digits after the decimal point (`digits = 1`) +/// - $$12.06$$ for 2 digits after the decimal point (`digits = 2`) +/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`) +/// +/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point. +/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`) +/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`) +/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`) +/// +/// </details> +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam/option +/// import gleam_community/maths/piecewise +/// +/// pub fn example() { +/// piecewise.truncate(12.0654, option.Some(1)) +/// |> should.equal(Ok(12.0)) +/// +/// piecewise.truncate(12.0654, option.Some(2)) +/// |> should.equal(Ok(12.0)) +/// +/// piecewise.truncate(12.0654, option.Some(3)) +/// |> should.equal(Ok(12.0)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn truncate(x: Float, digits: option.Option(Int)) -> Result(Float, String) { + round(x, digits, option.Some(RoundToZero)) +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function rounds a float to a specific number of digits (after the decimal place or before if negative) using a specified rounding mode. +/// +/// Valid rounding modes include: +/// - `RoundNearest` (default): The input $$x$$ is rounded to the nearest integer value (at the specified digit) with ties (fractional values of 0.5) being rounded to the nearest even integer. +/// - `RoundTiesAway`: The input $$x$$ is rounded to the nearest integer value (at the specified digit) with ties (fractional values of 0.5) being rounded away from zero (C/C++ rounding behavior). +/// - `RoundTiesUp`: The input $$x$$ is rounded to the nearest integer value (at the specified digit) with ties (fractional values of 0.5) being rounded towards $$+\infty$$ (Java/JavaScript rounding behaviour). +/// - `RoundToZero`: The input $$x$$ is rounded to the nearest integer value (at the specified digit) that is less than or equal to the absolute value of the input $$x$$. An alias for this rounding mode is [`truncate`](#truncate). +/// - `RoundDown`: The input $$x$$ is rounded to the nearest integer value (at the specified digit) that is less than or equal to the input $$x$$. An alias for this rounding mode is [`floor`](#floor). +/// - `RoundUp`: The input $$x$$ is rounded to the nearest integer value (at the specified digit) that is larger than or equal to the input $$x$$. An alias for this rounding mode is [`ceiling`](#ceiling). +/// +/// <details> +/// <summary>Details</summary> +/// +/// The `RoundNearest` rounding mode, rounds $$12.0654$$ to: +/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`) +/// - $$12.1$$ for 1 digit after the decimal point (`digits = 1`) +/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`) +/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`) +/// +/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point. +/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`) +/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`) +/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`) +/// +/// The `RoundTiesAway` rounding mode, rounds $$12.0654$$ to: +/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`) +/// - $$12.1$$ for 1 digit after the decimal point (`digits = 1`) +/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`) +/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`) +/// +/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point. +/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`) +/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`) +/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`) +/// +/// The `RoundTiesUp` rounding mode, rounds $$12.0654$$ to: +/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`) +/// - $$12.1$$ for 1 digits after the decimal point (`digits = 1`) +/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`) +/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`) +/// +/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point. +/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`) +/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`) +/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`) +/// +/// The `RoundToZero` rounding mode, rounds $$12.0654$$ to: +/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`) +/// - $$12.0$$ for 1 digit after the decimal point (`digits = 1`) +/// - $$12.06$$ for 2 digits after the decimal point (`digits = 2`) +/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`) +/// +/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point. +/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`) +/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`) +/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`) +/// +/// The `RoundDown` rounding mode, rounds $$12.0654$$ to: +/// - $$12.0$$ for 0 digits after the decimal point (`digits = 0`) +/// - $$12.0$$ for 1 digits after the decimal point (`digits = 1`) +/// - $$12.06$$ for 2 digits after the decimal point (`digits = 2`) +/// - $$12.065$$ for 3 digits after the decimal point (`digits = 3`) +/// +/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point. +/// - $$10.0$$ for 1 digit before the decimal point (`digits = -1`) +/// - $$0.0$$ for 2 digits before the decimal point (`digits = -2`) +/// - $$0.0$$ for 3 digits before the decimal point (`digits = -3`) +/// +/// The `RoundUp` rounding mode, rounds $$12.0654$$ to: +/// - $$13.0$$ for 0 digits after the decimal point (`digits = 0`) +/// - $$12.1$$ for 1 digit after the decimal point (`digits = 1`) +/// - $$12.07$$ for 2 digits after the decimal point (`digits = 2`) +/// - $$12.066$$ for 3 digits after the decimal point (`digits = 3`) +/// +/// It is also possible to specify a negative number of digits. In that case, the negative number refers to the digits before the decimal point. +/// - $$20.0$$ for 1 digit places before the decimal point (`digit = -1`) +/// - $$100.0$$ for 2 digits before the decimal point (`digits = -2`) +/// - $$1000.0$$ for 3 digits before the decimal point (`digits = -3`) +/// +/// </details> +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam/option +/// import gleam_community/maths/piecewise +/// +/// pub fn example() { +/// // The default number of digits is 0 if None is provided +/// piecewise.round(12.0654, option.None, option.Some(piecewise.RoundNearest)) +/// |> should.equal(Ok(12.0)) +/// +/// // The default rounding mode is "RoundNearest" if None is provided +/// piecewise.round(12.0654, option.None, option.None) +/// |> should.equal(Ok(12.0)) +/// +/// // Try different rounding modes +/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundNearest)) +/// |> should.equal(Ok(12.07)) +/// +/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundTiesAway)) +/// |> should.equal(Ok(12.07)) +/// +/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundTiesUp)) +/// |> should.equal(Ok(12.07)) +/// +/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundToZero)) +/// |> should.equal(Ok(12.06)) +/// +/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundDown)) +/// |> should.equal(Ok(12.06)) +/// +/// piecewise.round(12.0654, option.Some(2), option.Some(piecewise.RoundUp)) +/// |> should.equal(Ok(12.07)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn round( + x: Float, + digits: option.Option(Int), + mode: option.Option(RoundingMode), +) -> Result(Float, String) { + case digits { + option.Some(a) -> { + let assert Ok(p) = elementary.power(10.0, conversion.int_to_float(a)) + // Round the given input x using at the specified digit + do_round(p, x, mode) + } + // Round the given input x using at the default digit + option.None -> do_round(1.0, x, mode) + } +} + +pub type RoundingMode { + RoundNearest + RoundTiesAway + RoundTiesUp + RoundToZero + RoundDown + RoundUp +} + +fn do_round( + p: Float, + x: Float, + mode: option.Option(RoundingMode), +) -> Result(Float, String) { + case mode { + // Determine the rounding mode + option.Some(RoundNearest) -> + round_to_nearest(p, x) + |> Ok + option.Some(RoundTiesAway) -> + round_ties_away(p, x) + |> Ok + option.Some(RoundTiesUp) -> + round_ties_up(p, x) + |> Ok + option.Some(RoundToZero) -> + round_to_zero(p, x) + |> Ok + option.Some(RoundDown) -> + round_down(p, x) + |> Ok + option.Some(RoundUp) -> + round_up(p, x) + |> Ok + // Otherwise, use the default rounding mode + option.None -> + round_to_nearest(p, x) + |> Ok + } +} + +fn round_to_nearest(p: Float, x: Float) -> Float { + let xabs: Float = float_absolute_value(x) *. p + let xabs_truncated: Float = truncate_float(xabs) + let remainder: Float = xabs -. xabs_truncated + case remainder { + _ if remainder >. 0.5 -> float_sign(x) *. truncate_float(xabs +. 1.0) /. p + _ if remainder == 0.5 -> { + let assert Ok(is_even) = int.modulo(conversion.float_to_int(xabs), 2) + case is_even == 0 { + True -> float_sign(x) *. xabs_truncated /. p + False -> float_sign(x) *. truncate_float(xabs +. 1.0) /. p + } + } + _ -> float_sign(x) *. xabs_truncated /. p + } +} + +fn round_ties_away(p: Float, x: Float) -> Float { + let xabs: Float = float_absolute_value(x) *. p + let remainder: Float = xabs -. truncate_float(xabs) + case remainder { + _ if remainder >=. 0.5 -> float_sign(x) *. truncate_float(xabs +. 1.0) /. p + _ -> float_sign(x) *. truncate_float(xabs) /. p + } +} + +fn round_ties_up(p: Float, x: Float) -> Float { + let xabs: Float = float_absolute_value(x) *. p + let xabs_truncated: Float = truncate_float(xabs) + let remainder: Float = xabs -. xabs_truncated + case remainder { + _ if remainder >=. 0.5 && x >=. 0.0 -> + float_sign(x) *. truncate_float(xabs +. 1.0) /. p + _ -> float_sign(x) *. xabs_truncated /. p + } +} + +// Rounding mode: ToZero / Truncate +fn round_to_zero(p: Float, x: Float) -> Float { + truncate_float(x *. p) /. p +} + +fn truncate_float(x: Float) -> Float { + do_truncate_float(x) +} + +@external(erlang, "erlang", "trunc") +@external(javascript, "../../maths.mjs", "truncate") +fn do_truncate_float(a: Float) -> Float + +// Rounding mode: Down / Floor +fn round_down(p: Float, x: Float) -> Float { + do_floor(x *. p) /. p +} + +@external(erlang, "math", "floor") +@external(javascript, "../../maths.mjs", "floor") +fn do_floor(a: Float) -> Float + +// Rounding mode: Up / Ceiling +fn round_up(p: Float, x: Float) -> Float { + do_ceiling(x *. p) /. p +} + +@external(erlang, "math", "ceil") +@external(javascript, "../../maths.mjs", "ceiling") +fn do_ceiling(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The absolute value: +/// +/// \\[ +/// \forall x, y \in \mathbb{R}, \\; |x| \in \mathbb{R}_{+}. +/// \\] +/// +/// The function takes an input $$x$$ and returns a positive float value. +/// +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn float_absolute_value(x: Float) -> Float { + case x >. 0.0 { + True -> x + False -> -1.0 *. x + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The absolute value: +/// +/// \\[ +/// \forall x, y \in \mathbb{Z}, \\; |x| \in \mathbb{Z}_{+}. +/// \\] +/// +/// The function takes an input $$x$$ and returns a positive integer value. +/// +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn int_absolute_value(x: Int) -> Int { + case x > 0 { + True -> x + False -> -1 * x + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The absolute difference: +/// +/// \\[ +/// \forall x, y \in \mathbb{R}, \\; |x - y| \in \mathbb{R}_{+}. +/// \\] +/// +/// The function takes two inputs $$x$$ and $$y$$ and returns a positive float +/// value which is the the absolute difference of the inputs. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/piecewise +/// +/// pub fn example() { +/// piecewise.float_absolute_difference(-10.0, 10.0) +/// |> should.equal(20.0) +/// +/// piecewise.float_absolute_difference(0.0, -2.0) +/// |> should.equal(2.0) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn float_absolute_difference(a: Float, b: Float) -> Float { + a -. b + |> float_absolute_value() +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The absolute difference: +/// +/// \\[ +/// \forall x, y \in \mathbb{Z}, \\; |x - y| \in \mathbb{Z}_{+}. +/// \\] +/// +/// The function takes two inputs $$x$$ and $$y$$ and returns a positive integer value which is the the absolute difference of the inputs. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/piecewise +/// +/// pub fn example() { +/// piecewise.absolute_difference(-10, 10) +/// |> should.equal(20) +/// +/// piecewise.absolute_difference(0, -2) +/// |> should.equal(2) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn int_absolute_difference(a: Int, b: Int) -> Int { + a - b + |> int_absolute_value() +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function takes an input $$x \in \mathbb{R}$$ and returns the sign of +/// the input, indicating whether it is positive (+1.0), negative (-1.0), or +/// zero (0.0). +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn float_sign(x: Float) -> Float { + do_float_sign(x) +} + +@target(erlang) +fn do_float_sign(x: Float) -> Float { + case x <. 0.0 { + True -> -1.0 + False -> + case x == 0.0 { + True -> 0.0 + False -> 1.0 + } + } +} + +@target(javascript) +@external(javascript, "../../maths.mjs", "sign") +fn do_float_sign(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function takes an input $$x \in \mathbb{Z}$$ and returns the sign of +/// the input, indicating whether it is positive (+1), negative (-1), or zero +/// (0). +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn int_sign(x: Int) -> Int { + do_int_sign(x) +} + +@target(erlang) +fn do_int_sign(x: Int) -> Int { + case x < 0 { + True -> -1 + False -> + case x == 0 { + True -> 0 + False -> 1 + } + } +} + +@target(javascript) +@external(javascript, "../../maths.mjs", "sign") +fn do_int_sign(a: Int) -> Int + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function takes two arguments $$x, y \in \mathbb{R}$$ and returns $$x$$ such that it has the same sign as $$y$$. +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn float_copy_sign(x: Float, y: Float) -> Float { + case float_sign(x) == float_sign(y) { + // x and y have the same sign, just return x + True -> x + // x and y have different signs: + // - x is positive and y is negative, then flip sign of x + // - x is negative and y is positive, then flip sign of x + False -> float_flip_sign(x) + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function takes two arguments $$x, y \in \mathbb{Z}$$ and returns $$x$$ such that it has the same sign as $$y$$. +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn int_copy_sign(x: Int, y: Int) -> Int { + case int_sign(x) == int_sign(y) { + // x and y have the same sign, just return x + True -> x + // x and y have different signs: + // - x is positive and y is negative, then flip sign of x + // - x is negative and y is positive, then flip sign of x + False -> int_flip_sign(x) + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function flips the sign of a given input value $$x \in \mathbb{R}$$. +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn float_flip_sign(x: Float) -> Float { + -1.0 *. x +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function flips the sign of a given input value $$x \in \mathbb{Z}$$. +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn int_flip_sign(x: Int) -> Int { + -1 * x +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The minimum function takes two arguments $$x, y$$ along with a function +/// for comparing $$x, y$$. The function returns the smallest of the two given +/// values. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam/float +/// import gleam_community/maths/piecewise +/// +/// pub fn example() { +/// piecewise.minimum(2.0, 1.5, float.compare) +/// |> should.equal(1.5) +/// +/// piecewise.minimum(1.5, 2.0, float.compare) +/// |> should.equal(1.5) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn minimum(x: a, y: a, compare: fn(a, a) -> order.Order) -> a { + case compare(x, y) { + order.Lt -> x + order.Eq -> x + order.Gt -> y + } +} + +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The maximum function takes two arguments $$x, y$$ along with a function +/// for comparing $$x, y$$. The function returns the largest of the two given +/// values. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam/float +/// import gleam_community/maths/piecewise +/// +/// pub fn example() { +/// piecewise.maximum(2.0, 1.5, float.compare) +/// |> should.equal(1.5) +/// +/// piecewise.maximum(1.5, 2.0, float.compare) +/// |> should.equal(1.5) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn maximum(x: a, y: a, compare: fn(a, a) -> order.Order) -> a { + case compare(x, y) { + order.Lt -> y + order.Eq -> y + order.Gt -> x + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The minmax function takes two arguments $$x, y$$ along with a function +/// for comparing $$x, y$$. The function returns a tuple with the smallest +/// value first and largest second. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam/float +/// import gleam_community/maths/piecewise +/// +/// pub fn example() { +/// piecewise.minmax(2.0, 1.5, float.compare) +/// |> should.equal(#(1.5, 2.0)) +/// +/// piecewise.minmax(1.5, 2.0, float.compare) +/// |> should.equal(#(1.5, 2.0)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn minmax(x: a, y: a, compare: fn(a, a) -> order.Order) -> #(a, a) { + #(minimum(x, y, compare), maximum(x, y, compare)) +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Returns the minimum value of a given list. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam/int +/// import gleam_community/maths/piecewise +/// +/// pub fn example () { +/// // An empty lists returns an error +/// [] +/// |> piecewise.list_minimum(int.compare) +/// |> should.be_error() +/// +/// // Valid input returns a result +/// [4, 4, 3, 2, 1] +/// |> piecewise.list_minimum(int.compare) +/// |> should.equal(Ok(1)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +pub fn list_minimum( + arr: List(a), + compare: fn(a, a) -> order.Order, +) -> Result(a, String) { + case arr { + [] -> + "Invalid input argument: The list is empty." + |> Error + _ -> { + let assert Ok(val0) = list.at(arr, 0) + arr + |> list.fold( + val0, + fn(acc: a, element: a) { + case compare(element, acc) { + order.Lt -> element + _ -> acc + } + }, + ) + |> Ok + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Returns the maximum value of a given list. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam/float +/// import gleam_community/maths/piecewise +/// +/// pub fn example () { +/// // An empty lists returns an error +/// [] +/// |> piecewise.list_maximum(float.compare) +/// |> should.be_error() +/// +/// // Valid input returns a result +/// [4.0, 4.0, 3.0, 2.0, 1.0] +/// |> piecewise.list_maximum(float.compare) +/// |> should.equal(Ok(4.0)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn list_maximum( + arr: List(a), + compare: fn(a, a) -> order.Order, +) -> Result(a, String) { + case arr { + [] -> + "Invalid input argument: The list is empty." + |> Error + _ -> { + let assert Ok(val0) = list.at(arr, 0) + arr + |> list.fold( + val0, + fn(acc: a, element: a) { + case compare(acc, element) { + order.Lt -> element + _ -> acc + } + }, + ) + |> Ok + } + } +} + +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Returns the indices of the minimum values in a given list. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam/float +/// import gleam_community/maths/piecewise +/// +/// pub fn example () { +/// // An empty lists returns an error +/// [] +/// |> piecewise.arg_minimum(float.compare) +/// |> should.be_error() +/// +/// // Valid input returns a result +/// [4.0, 4.0, 3.0, 2.0, 1.0] +/// |> piecewise.arg_minimum(float.compare) +/// |> should.equal(Ok([4])) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn arg_minimum( + arr: List(a), + compare: fn(a, a) -> order.Order, +) -> Result(List(Int), String) { + case arr { + [] -> + "Invalid input argument: The list is empty." + |> Error + _ -> { + let assert Ok(min) = + arr + |> list_minimum(compare) + arr + |> list.index_map(fn(index: Int, element: a) -> Int { + case compare(element, min) { + order.Eq -> index + _ -> -1 + } + }) + |> list.filter(fn(index: Int) -> Bool { + case index { + -1 -> False + _ -> True + } + }) + |> Ok + } + } +} + +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Returns the indices of the maximum values in a given list. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam/float +/// import gleam_community/maths/piecewise +/// +/// pub fn example () { +/// // An empty lists returns an error +/// [] +/// |> piecewise.arg_maximum(float.compare) +/// |> should.be_error() +/// +/// // Valid input returns a result +/// [4.0, 4.0, 3.0, 2.0, 1.0] +/// |> piecewise.arg_maximum(float.compare) +/// |> should.equal(Ok([0, 1])) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn arg_maximum( + arr: List(a), + compare: fn(a, a) -> order.Order, +) -> Result(List(Int), String) { + case arr { + [] -> + "Invalid input argument: The list is empty." + |> Error + _ -> { + let assert Ok(max) = + arr + |> list_maximum(compare) + arr + |> list.index_map(fn(index: Int, element: a) -> Int { + case compare(element, max) { + order.Eq -> index + _ -> -1 + } + }) + |> list.filter(fn(index: Int) -> Bool { + case index { + -1 -> False + _ -> True + } + }) + |> Ok + } + } +} + +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Returns a tuple consisting of the minimum and maximum values of a given list. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam/float +/// import gleam_community/maths/piecewise +/// +/// pub fn example () { +/// // An empty lists returns an error +/// [] +/// |> piecewise.extrema(float.compare) +/// |> should.be_error() +/// +/// // Valid input returns a result +/// [4.0, 4.0, 3.0, 2.0, 1.0] +/// |> piecewise.extrema(float.compare) +/// |> should.equal(Ok(#(1.0, 4.0))) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn extrema( + arr: List(a), + compare: fn(a, a) -> order.Order, +) -> Result(#(a, a), String) { + case arr { + [] -> + "Invalid input argument: The list is empty." + |> Error + _ -> { + let assert Ok(val_max) = list.at(arr, 0) + let assert Ok(val_min) = list.at(arr, 0) + arr + |> list.fold( + #(val_min, val_max), + fn(acc: #(a, a), element: a) { + let first: a = pair.first(acc) + let second: a = pair.second(acc) + case compare(element, first), compare(second, element) { + order.Lt, order.Lt -> #(element, element) + order.Lt, _ -> #(element, second) + _, order.Lt -> #(first, element) + _, _ -> #(first, second) + } + }, + ) + |> Ok + } + } +} diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/predicates.gleam b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/predicates.gleam new file mode 100644 index 0000000..f8d357c --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/predicates.gleam @@ -0,0 +1,363 @@ +////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous"> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script> +////<script> +//// document.addEventListener("DOMContentLoaded", function() { +//// renderMathInElement(document.body, { +//// // customised options +//// // • auto-render specific keys, e.g.: +//// delimiters: [ +//// {left: '$$', right: '$$', display: false}, +//// // {left: '$', right: '$', display: false}, +//// // {left: '\\(', right: '\\)', display: false}, +//// {left: '\\[', right: '\\]', display: true} +//// ], +//// // • rendering keys, e.g.: +//// throwOnError : false +//// }); +//// }); +////</script> +////<style> +//// .katex { font-size: 1.1em; } +////</style> +//// +//// --- +//// +//// Predicates: A module containing functions for testing various mathematical properties of numbers. +//// +//// * **Tests** +//// * [`is_close`](#is_close) +//// * [`list_all_close`](#all_close) +//// * [`is_fractional`](#is_fractional) +//// * [`is_power`](#is_power) +//// * [`is_perfect`](#is_perfect) +//// * [`is_even`](#is_even) +//// * [`is_odd`](#is_odd) + +import gleam/pair +import gleam/int +import gleam/list +import gleam/option +import gleam_community/maths/elementary +import gleam_community/maths/piecewise +import gleam_community/maths/arithmetics + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Determine if a given value $$a$$ is close to or equivalent to a reference value +/// $$b$$ based on supplied relative $$r_{tol}$$ and absolute $$a_{tol}$$ tolerance values. +/// The equivalance of the two given values are then determined based on the equation: +/// +/// \\[ +/// \|a - b\| \leq (a_{tol} + r_{tol} \cdot \|b\|) +/// \\] +/// +/// `True` is returned if statement holds, otherwise `False` is returned. +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/tests +/// +/// pub fn example () { +/// let val: Float = 99. +/// let ref_val: Float = 100. +/// // We set 'atol' and 'rtol' such that the values are equivalent +/// // if 'val' is within 1 percent of 'ref_val' +/- 0.1 +/// let rtol: Float = 0.01 +/// let atol: Float = 0.10 +/// floatx.is_close(val, ref_val, rtol, atol) +/// |> should.be_true() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn is_close(a: Float, b: Float, rtol: Float, atol: Float) -> Bool { + let x: Float = float_absolute_difference(a, b) + let y: Float = atol +. rtol *. float_absolute_value(b) + case x <=. y { + True -> True + False -> False + } +} + +fn float_absolute_value(x: Float) -> Float { + case x >. 0.0 { + True -> x + False -> -1.0 *. x + } +} + +fn float_absolute_difference(a: Float, b: Float) -> Float { + a -. b + |> float_absolute_value() +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Determine if a list of values are close to or equivalent to a another list of reference values. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam/list +/// import gleam_community/maths/tests +/// +/// pub fn example () { +/// let val: Float = 99. +/// let ref_val: Float = 100. +/// let xarr: List(Float) = list.repeat(val, 42) +/// let yarr: List(Float) = list.repeat(ref_val, 42) +/// // We set 'atol' and 'rtol' such that the values are equivalent +/// // if 'val' is within 1 percent of 'ref_val' +/- 0.1 +/// let rtol: Float = 0.01 +/// let atol: Float = 0.10 +/// tests.all_close(xarr, yarr, rtol, atol) +/// |> fn(zarr: Result(List(Bool), String)) -> Result(Bool, Nil) { +/// case zarr { +/// Ok(arr) -> +/// arr +/// |> list.all(fn(a: Bool) -> Bool { a }) +/// |> Ok +/// _ -> Nil |> Error +/// } +/// } +/// |> should.equal(Ok(True)) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn all_close( + xarr: List(Float), + yarr: List(Float), + rtol: Float, + atol: Float, +) -> Result(List(Bool), String) { + let xlen: Int = list.length(xarr) + let ylen: Int = list.length(yarr) + case xlen == ylen { + False -> + "Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)." + |> Error + True -> + list.zip(xarr, yarr) + |> list.map(fn(z: #(Float, Float)) -> Bool { + is_close(pair.first(z), pair.second(z), rtol, atol) + }) + |> Ok + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Determine if a given value is fractional. +/// +/// `True` is returned if the given value is fractional, otherwise `False` is returned. +/// +/// <details> +/// <summary>Example</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/tests +/// +/// pub fn example () { +/// tests.is_fractional(0.3333) +/// |> should.equal(True) +/// +/// tests.is_fractional(1.0) +/// |> should.equal(False) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn is_fractional(x: Float) -> Bool { + do_ceiling(x) -. x >. 0.0 +} + +@external(erlang, "math", "ceil") +@external(javascript, "../../maths.mjs", "ceiling") +fn do_ceiling(a: Float) -> Float + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// A function that tests whether a given integer value $$x \in \mathbb{Z}$$ is a power of another integer value $$y \in \mathbb{Z}$$. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/tests +/// +/// pub fn example() { +/// // Check if 4 is a power of 2 (it is) +/// tests.is_power(4, 2) +/// |> should.equal(True) +/// +/// // Check if 5 is a power of 2 (it is not) +/// tests.is_power(5, 2) +/// |> should.equal(False) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn is_power(x: Int, y: Int) -> Bool { + let assert Ok(value) = + elementary.logarithm(int.to_float(x), option.Some(int.to_float(y))) + let assert Ok(truncated) = piecewise.truncate(value, option.Some(0)) + let rem = value -. truncated + rem == 0.0 +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// A function that tests whether a given integer value $$n \in \mathbb{Z}$$ is a perfect number. A number is perfect if it is equal to the sum of its proper positive divisors. +/// +/// <details> +/// <summary>Details</summary> +/// +/// For example: +/// - $$6$$ is a perfect number since the divisors of 6 are $$1 + 2 + 3 = 6$$. +/// - $$28$$ is a perfect number since the divisors of 28 are $$1 + 2 + 4 + 7 + 14 = 28$$ +/// +/// </details> +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/tests +/// +/// pub fn example() { +/// tests.is_perfect(6) +/// |> should.equal(True) +/// +/// tests.is_perfect(28) +/// |> should.equal(True) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn is_perfect(n: Int) -> Bool { + do_sum(arithmetics.proper_divisors(n)) == n +} + +fn do_sum(arr: List(Int)) -> Int { + case arr { + [] -> 0 + _ -> + arr + |> list.fold(0, fn(acc: Int, a: Int) -> Int { a + acc }) + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// A function that tests whether a given integer value $$x \in \mathbb{Z}$$ is even. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/tests +/// +/// pub fn example() { +/// tests.is_even(-3) +/// |> should.equal(False) +/// +/// tests.is_even(-4) +/// |> should.equal(True) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn is_even(x: Int) -> Bool { + x % 2 == 0 +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// A function that tests whether a given integer value $$x \in \mathbb{Z}$$ is odd. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/tests +/// +/// pub fn example() { +/// tests.is_odd(-3) +/// |> should.equal(True) +/// +/// tests.is_odd(-4) +/// |> should.equal(False) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn is_odd(x: Int) -> Bool { + x % 2 != 0 +} diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/sequences.gleam b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/sequences.gleam new file mode 100644 index 0000000..e7c0388 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/sequences.gleam @@ -0,0 +1,302 @@ +////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous"> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script> +////<script> +//// document.addEventListener("DOMContentLoaded", function() { +//// renderMathInElement(document.body, { +//// // customised options +//// // • auto-render specific keys, e.g.: +//// delimiters: [ +//// {left: '$$', right: '$$', display: false}, +//// // {left: '$', right: '$', display: false}, +//// // {left: '\\(', right: '\\)', display: false}, +//// {left: '\\[', right: '\\]', display: true} +//// ], +//// // • rendering keys, e.g.: +//// throwOnError : false +//// }); +//// }); +////</script> +////<style> +//// .katex { font-size: 1.1em; } +////</style> +//// +//// --- +//// +//// Sequences: A module containing functions for generating various types of sequences, ranges and intervals. +//// +//// * **Ranges and intervals** +//// * [`arange`](#arange) +//// * [`linear_space`](#linear_space) +//// * [`logarithmic_space`](#logarithmic_space) +//// * [`geometric_space`](#geometric_space) + +import gleam_community/maths/elementary +import gleam_community/maths/piecewise +import gleam_community/maths/conversion +import gleam/list + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function returns a list with evenly spaced values within a given interval based on a start, stop value and a given increment (step-length) between consecutive values. +/// The list returned includes the given start value but excludes the stop value. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/sequences +/// +/// pub fn example () { +/// sequences.arange(1.0, 5.0, 1.0) +/// |> should.equal([1.0, 2.0, 3.0, 4.0]) +/// +/// // No points returned since +/// // start smaller than stop and positive step +/// sequences.arange(5.0, 1.0, 1.0) +/// |> should.equal([]) +/// +/// // Points returned since +/// // start smaller than stop but negative step +/// sequences.arange(5.0, 1.0, -1.0) +/// |> should.equal([5.0, 4.0, 3.0, 2.0]) +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn arange(start: Float, stop: Float, step: Float) -> List(Float) { + case start >=. stop && step >. 0.0 || start <=. stop && step <. 0.0 { + True -> [] + False -> { + let direction: Float = case start <=. stop { + True -> 1.0 + False -> -1.0 + } + let step_abs: Float = piecewise.float_absolute_value(step) + let num: Float = piecewise.float_absolute_value(start -. stop) /. step_abs + + list.range(0, conversion.float_to_int(num) - 1) + |> list.map(fn(i: Int) -> Float { + start +. conversion.int_to_float(i) *. step_abs *. direction + }) + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Generate a linearly spaced list of points over a specified interval. The endpoint of the interval can optionally be included/excluded. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// import gleam_community/maths/sequences +/// import gleam_community/maths/predicates +/// +/// pub fn example () { +/// let assert Ok(tol) = elementary.power(-10.0, -6.0) +/// let assert Ok(linspace) = sequences.linear_space(10.0, 50.0, 5, True) +/// let assert Ok(result) = +/// predicates.all_close(linspace, [10.0, 20.0, 30.0, 40.0, 50.0], 0.0, tol) +/// result +/// |> list.all(fn(x) { x == True }) +/// |> should.be_true() +/// +/// // A negative number of points (-5) does not work +/// sequences.linear_space(10.0, 50.0, -5, True) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn linear_space( + start: Float, + stop: Float, + num: Int, + endpoint: Bool, +) -> Result(List(Float), String) { + let direction: Float = case start <=. stop { + True -> 1.0 + False -> -1.0 + } + case num > 0 { + True -> + case endpoint { + True -> { + let increment: Float = + piecewise.float_absolute_value(start -. stop) /. conversion.int_to_float( + num - 1, + ) + list.range(0, num - 1) + |> list.map(fn(i: Int) -> Float { + start +. conversion.int_to_float(i) *. increment *. direction + }) + |> Ok + } + False -> { + let increment: Float = + piecewise.float_absolute_value(start -. stop) /. conversion.int_to_float( + num, + ) + list.range(0, num - 1) + |> list.map(fn(i: Int) -> Float { + start +. conversion.int_to_float(i) *. increment *. direction + }) + |> Ok + } + } + + False -> + "Invalid input: num < 0. Valid input is num > 0." + |> Error + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// Generate a logarithmically spaced list of points over a specified interval. The endpoint of the interval can optionally be included/excluded. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// import gleam_community/maths/sequences +/// import gleam_community/maths/predicates +/// +/// pub fn example () { +/// let assert Ok(tol) = elementary.power(-10.0, -6.0) +/// let assert Ok(logspace) = sequences.logarithmic_space(1.0, 3.0, 3, True, 10.0) +/// let assert Ok(result) = +/// predicates.all_close(logspace, [10.0, 100.0, 1000.0], 0.0, tol) +/// result +/// |> list.all(fn(x) { x == True }) +/// |> should.be_true() +/// +/// // A negative number of points (-3) does not work +/// sequences.logarithmic_space(1.0, 3.0, -3, False, 10.0) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn logarithmic_space( + start: Float, + stop: Float, + num: Int, + endpoint: Bool, + base: Float, +) -> Result(List(Float), String) { + case num > 0 { + True -> { + let assert Ok(linspace) = linear_space(start, stop, num, endpoint) + linspace + |> list.map(fn(i: Float) -> Float { + let assert Ok(result) = elementary.power(base, i) + result + }) + |> Ok + } + False -> + "Invalid input: num < 0. Valid input is num > 0." + |> Error + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The function returns a list of numbers spaced evenly on a log scale (a geometric progression). Each point in the list is a constant multiple of the previous. +/// The function is similar to the [`logarithmic_space`](#logarithmic_space) function, but with endpoints specified directly. +/// +/// <details> +/// <summary>Example:</summary> +/// +/// import gleeunit/should +/// import gleam_community/maths/elementary +/// import gleam_community/maths/sequences +/// import gleam_community/maths/predicates +/// +/// pub fn example () { +/// let assert Ok(tol) = elementary.power(-10.0, -6.0) +/// let assert Ok(logspace) = sequences.geometric_space(10.0, 1000.0, 3, True) +/// let assert Ok(result) = +/// predicates.all_close(logspace, [10.0, 100.0, 1000.0], 0.0, tol) +/// result +/// |> list.all(fn(x) { x == True }) +/// |> should.be_true() +/// +/// // Input (start and stop can't be equal to 0.0) +/// sequences.geometric_space(0.0, 1000.0, 3, False) +/// |> should.be_error() +/// +/// sequences.geometric_space(-1000.0, 0.0, 3, False) +/// |> should.be_error() +/// +/// // A negative number of points (-3) does not work +/// sequences.geometric_space(10.0, 1000.0, -3, False) +/// |> should.be_error() +/// } +/// </details> +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn geometric_space( + start: Float, + stop: Float, + num: Int, + endpoint: Bool, +) -> Result(List(Float), String) { + case start == 0.0 || stop == 0.0 { + True -> + "" + |> Error + False -> + case num > 0 { + True -> { + let assert Ok(log_start) = elementary.logarithm_10(start) + let assert Ok(log_stop) = elementary.logarithm_10(stop) + logarithmic_space(log_start, log_stop, num, endpoint, 10.0) + } + False -> + "Invalid input: num < 0. Valid input is num > 0." + |> Error + } + } +} diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/special.gleam b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/special.gleam new file mode 100644 index 0000000..dfd9cbb --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/special.gleam @@ -0,0 +1,205 @@ +////<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous"> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script> +////<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script> +////<script> +//// document.addEventListener("DOMContentLoaded", function() { +//// renderMathInElement(document.body, { +//// // customised options +//// // • auto-render specific keys, e.g.: +//// delimiters: [ +//// {left: '$$', right: '$$', display: false}, +//// // {left: '$', right: '$', display: false}, +//// // {left: '\\(', right: '\\)', display: false}, +//// {left: '\\[', right: '\\]', display: true} +//// ], +//// // • rendering keys, e.g.: +//// throwOnError : false +//// }); +//// }); +////</script> +////<style> +//// .katex { font-size: 1.1em; } +////</style> +//// +//// --- +//// +//// Special: A module containing special mathematical functions. +//// +//// * **Special mathematical functions** +//// * [`beta`](#beta) +//// * [`erf`](#erf) +//// * [`gamma`](#gamma) +//// * [`incomplete_gamma`](#incomplete_gamma) +//// + +import gleam_community/maths/conversion +import gleam_community/maths/elementary +import gleam_community/maths/piecewise +import gleam/list + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The beta function over the real numbers: +/// +/// \\[ +/// \text{B}(x, y) = \frac{\Gamma(x) \cdot \Gamma(y)}{\Gamma(x + y)} +/// \\] +/// +/// The beta function is evaluated through the use of the gamma function. +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn beta(x: Float, y: Float) -> Float { + gamma(x) *. gamma(y) /. gamma(x +. y) +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The error function. +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn erf(x: Float) -> Float { + let assert [a1, a2, a3, a4, a5]: List(Float) = [ + 0.254829592, -0.284496736, 1.421413741, -1.453152027, 1.061405429, + ] + let p: Float = 0.3275911 + + let sign: Float = piecewise.float_sign(x) + let x: Float = piecewise.float_absolute_value(x) + + // Formula 7.1.26 given in Abramowitz and Stegun. + let t: Float = 1.0 /. { 1.0 +. p *. x } + let y: Float = + 1.0 -. { { { { a5 *. t +. a4 } *. t +. a3 } *. t +. a2 } *. t +. a1 } *. t *. elementary.exponential( + -1.0 *. x *. x, + ) + sign *. y +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The gamma function over the real numbers. The function is essentially equal to the +/// factorial for any positive integer argument: $$\Gamma(n) = (n - 1)!$$ +/// +/// The implemented gamma function is approximated through Lanczos approximation +/// using the same coefficients used by the GNU Scientific Library. +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn gamma(x: Float) -> Float { + gamma_lanczos(x) +} + +const lanczos_g: Float = 7.0 + +const lanczos_p: List(Float) = [ + 0.99999999999980993, 676.5203681218851, -1259.1392167224028, + 771.32342877765313, -176.61502916214059, 12.507343278686905, + -0.13857109526572012, 0.0000099843695780195716, 0.00000015056327351493116, +] + +fn gamma_lanczos(x: Float) -> Float { + case x <. 0.5 { + True -> + elementary.pi() /. { + elementary.sin(elementary.pi() *. x) *. gamma_lanczos(1.0 -. x) + } + False -> { + let z = x -. 1.0 + let x: Float = + list.index_fold( + lanczos_p, + 0.0, + fn(acc: Float, v: Float, index: Int) { + case index > 0 { + True -> acc +. v /. { z +. conversion.int_to_float(index) } + False -> v + } + }, + ) + let t: Float = z +. lanczos_g +. 0.5 + let assert Ok(v1) = elementary.power(2.0 *. elementary.pi(), 0.5) + let assert Ok(v2) = elementary.power(t, z +. 0.5) + v1 *. v2 *. elementary.exponential(-1.0 *. t) *. x + } + } +} + +/// <div style="text-align: right;"> +/// <a href="https://github.com/gleam-community/maths/issues"> +/// <small>Spot a typo? Open an issue!</small> +/// </a> +/// </div> +/// +/// The lower incomplete gamma function over the real numbers. +/// +/// The implemented incomplete gamma function is evaluated through a power series +/// expansion. +/// +/// <div style="text-align: right;"> +/// <a href="#"> +/// <small>Back to top ↑</small> +/// </a> +/// </div> +/// +pub fn incomplete_gamma(a: Float, x: Float) -> Result(Float, String) { + case a >. 0.0 && x >=. 0.0 { + True -> { + let assert Ok(v) = elementary.power(x, a) + v *. elementary.exponential(-1.0 *. x) *. incomplete_gamma_sum( + a, + x, + 1.0 /. a, + 0.0, + 1.0, + ) + |> Ok + } + + False -> + "Invlaid input argument: a <= 0 or x < 0. Valid input is a > 0 and x >= 0." + |> Error + } +} + +fn incomplete_gamma_sum( + a: Float, + x: Float, + t: Float, + s: Float, + n: Float, +) -> Float { + case t { + 0.0 -> s + _ -> { + let ns: Float = s +. t + let nt: Float = t *. { x /. { a +. n } } + incomplete_gamma_sum(a, x, nt, ns, n +. 1.0) + } + } +} diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@arithmetics.erl b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@arithmetics.erl new file mode 100644 index 0000000..ca266c8 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@arithmetics.erl @@ -0,0 +1,172 @@ +-module(gleam_community@maths@arithmetics). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([gcd/2, lcm/2, divisors/1, proper_divisors/1, float_sum/1, int_sum/1, float_product/1, int_product/1, float_cumulative_sum/1, int_cumulative_sum/1, float_cumumlative_product/1, int_cumulative_product/1]). + +-spec do_gcd(integer(), integer()) -> integer(). +do_gcd(X, Y) -> + case X =:= 0 of + true -> + Y; + + false -> + _assert_subject = gleam@int:modulo(Y, X), + {ok, Z} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/arithmetics"/utf8>>, + function => <<"do_gcd"/utf8>>, + line => 93}) + end, + do_gcd(Z, X) + end. + +-spec gcd(integer(), integer()) -> integer(). +gcd(X, Y) -> + Absx = gleam_community@maths@piecewise:int_absolute_value(X), + Absy = gleam_community@maths@piecewise:int_absolute_value(Y), + do_gcd(Absx, Absy). + +-spec lcm(integer(), integer()) -> integer(). +lcm(X, Y) -> + Absx = gleam_community@maths@piecewise:int_absolute_value(X), + Absy = gleam_community@maths@piecewise:int_absolute_value(Y), + case do_gcd(Absx, Absy) of + 0 -> 0; + Gleam@denominator -> (Absx * Absy) div Gleam@denominator + end. + +-spec find_divisors(integer()) -> list(integer()). +find_divisors(N) -> + Nabs = gleam_community@maths@piecewise:float_absolute_value( + gleam_community@maths@conversion:int_to_float(N) + ), + _assert_subject = gleam_community@maths@elementary:square_root(Nabs), + {ok, Sqrt_result} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/arithmetics"/utf8>>, + function => <<"find_divisors"/utf8>>, + line => 176}) + end, + Max = gleam_community@maths@conversion:float_to_int(Sqrt_result) + 1, + _pipe = gleam@list:range(2, Max), + _pipe@1 = gleam@list:fold(_pipe, [1, N], fun(Acc, I) -> case (case I of + 0 -> 0; + Gleam@denominator -> N rem Gleam@denominator + end) =:= 0 of + true -> + [I, case I of + 0 -> 0; + Gleam@denominator@1 -> N div Gleam@denominator@1 + end | Acc]; + + false -> + Acc + end end), + _pipe@2 = gleam@list:unique(_pipe@1), + gleam@list:sort(_pipe@2, fun gleam@int:compare/2). + +-spec divisors(integer()) -> list(integer()). +divisors(N) -> + find_divisors(N). + +-spec proper_divisors(integer()) -> list(integer()). +proper_divisors(N) -> + Divisors = find_divisors(N), + _pipe = Divisors, + gleam@list:take(_pipe, gleam@list:length(Divisors) - 1). + +-spec float_sum(list(float())) -> float(). +float_sum(Arr) -> + case Arr of + [] -> + +0.0; + + _ -> + _pipe = Arr, + gleam@list:fold(_pipe, +0.0, fun(Acc, A) -> A + Acc end) + end. + +-spec int_sum(list(integer())) -> integer(). +int_sum(Arr) -> + case Arr of + [] -> + 0; + + _ -> + _pipe = Arr, + gleam@list:fold(_pipe, 0, fun(Acc, A) -> A + Acc end) + end. + +-spec float_product(list(float())) -> float(). +float_product(Arr) -> + case Arr of + [] -> + 1.0; + + _ -> + _pipe = Arr, + gleam@list:fold(_pipe, 1.0, fun(Acc, A) -> A * Acc end) + end. + +-spec int_product(list(integer())) -> integer(). +int_product(Arr) -> + case Arr of + [] -> + 1; + + _ -> + _pipe = Arr, + gleam@list:fold(_pipe, 1, fun(Acc, A) -> A * Acc end) + end. + +-spec float_cumulative_sum(list(float())) -> list(float()). +float_cumulative_sum(Arr) -> + case Arr of + [] -> + []; + + _ -> + _pipe = Arr, + gleam@list:scan(_pipe, +0.0, fun(Acc, A) -> A + Acc end) + end. + +-spec int_cumulative_sum(list(integer())) -> list(integer()). +int_cumulative_sum(Arr) -> + case Arr of + [] -> + []; + + _ -> + _pipe = Arr, + gleam@list:scan(_pipe, 0, fun(Acc, A) -> A + Acc end) + end. + +-spec float_cumumlative_product(list(float())) -> list(float()). +float_cumumlative_product(Arr) -> + case Arr of + [] -> + []; + + _ -> + _pipe = Arr, + gleam@list:scan(_pipe, 1.0, fun(Acc, A) -> A * Acc end) + end. + +-spec int_cumulative_product(list(integer())) -> list(integer()). +int_cumulative_product(Arr) -> + case Arr of + [] -> + []; + + _ -> + _pipe = Arr, + gleam@list:scan(_pipe, 1, fun(Acc, A) -> A * Acc end) + end. diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@combinatorics.erl b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@combinatorics.erl new file mode 100644 index 0000000..17644c4 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@combinatorics.erl @@ -0,0 +1,218 @@ +-module(gleam_community@maths@combinatorics). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([combination/2, factorial/1, permutation/2, list_combination/2, list_permutation/1, cartesian_product/2]). + +-spec combination(integer(), integer()) -> {ok, integer()} | {error, binary()}. +combination(N, K) -> + case N < 0 of + true -> + _pipe = <<"Invalid input argument: n < 0. Valid input is n > 0."/utf8>>, + {error, _pipe}; + + false -> + case (K < 0) orelse (K > N) of + true -> + _pipe@1 = 0, + {ok, _pipe@1}; + + false -> + case (K =:= 0) orelse (K =:= N) of + true -> + _pipe@2 = 1, + {ok, _pipe@2}; + + false -> + Min = case K < (N - K) of + true -> + K; + + false -> + N - K + end, + _pipe@3 = gleam@list:range(1, Min), + _pipe@4 = gleam@list:fold( + _pipe@3, + 1, + fun(Acc, X) -> case X of + 0 -> 0; + Gleam@denominator -> (Acc * ((N + 1) - X)) + div Gleam@denominator + end end + ), + {ok, _pipe@4} + end + end + end. + +-spec factorial(integer()) -> {ok, integer()} | {error, binary()}. +factorial(N) -> + case N < 0 of + true -> + _pipe = <<"Invalid input argument: n < 0. Valid input is n > 0."/utf8>>, + {error, _pipe}; + + false -> + case N of + 0 -> + _pipe@1 = 1, + {ok, _pipe@1}; + + 1 -> + _pipe@2 = 1, + {ok, _pipe@2}; + + _ -> + _pipe@3 = gleam@list:range(1, N), + _pipe@4 = gleam@list:fold( + _pipe@3, + 1, + fun(Acc, X) -> Acc * X end + ), + {ok, _pipe@4} + end + end. + +-spec permutation(integer(), integer()) -> {ok, integer()} | {error, binary()}. +permutation(N, K) -> + case N < 0 of + true -> + _pipe = <<"Invalid input argument: n < 0. Valid input is n > 0."/utf8>>, + {error, _pipe}; + + false -> + case (K < 0) orelse (K > N) of + true -> + _pipe@1 = 0, + {ok, _pipe@1}; + + false -> + case K =:= N of + true -> + _pipe@2 = 1, + {ok, _pipe@2}; + + false -> + _assert_subject = factorial(N), + {ok, V1} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/combinatorics"/utf8>>, + function => <<"permutation"/utf8>>, + line => 241}) + end, + _assert_subject@1 = factorial(N - K), + {ok, V2} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/combinatorics"/utf8>>, + function => <<"permutation"/utf8>>, + line => 242}) + end, + _pipe@3 = case V2 of + 0 -> 0; + Gleam@denominator -> V1 div Gleam@denominator + end, + {ok, _pipe@3} + end + end + end. + +-spec do_list_combination(list(GIO), integer(), list(GIO)) -> list(list(GIO)). +do_list_combination(Arr, K, Prefix) -> + case K of + 0 -> + [gleam@list:reverse(Prefix)]; + + _ -> + case Arr of + [] -> + []; + + [X | Xs] -> + With_x = do_list_combination(Xs, K - 1, [X | Prefix]), + Without_x = do_list_combination(Xs, K, Prefix), + gleam@list:append(With_x, Without_x) + end + end. + +-spec list_combination(list(GII), integer()) -> {ok, list(list(GII))} | + {error, binary()}. +list_combination(Arr, K) -> + case K < 0 of + true -> + _pipe = <<"Invalid input argument: k < 0. Valid input is k > 0."/utf8>>, + {error, _pipe}; + + false -> + case K > gleam@list:length(Arr) of + true -> + _pipe@1 = <<"Invalid input argument: k > length(arr). Valid input is 0 < k <= length(arr)."/utf8>>, + {error, _pipe@1}; + + false -> + _pipe@2 = do_list_combination(Arr, K, []), + {ok, _pipe@2} + end + end. + +-spec list_permutation(list(GIT)) -> list(list(GIT)). +list_permutation(Arr) -> + case Arr of + [] -> + [[]]; + + _ -> + gleam@list:flat_map( + Arr, + fun(X) -> + _assert_subject = gleam@list:pop(Arr, fun(Y) -> X =:= Y end), + {ok, {_, Remaining}} = case _assert_subject of + {ok, {_, _}} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/combinatorics"/utf8>>, + function => <<"list_permutation"/utf8>>, + line => 373}) + end, + gleam@list:map( + list_permutation(Remaining), + fun(Perm) -> [X | Perm] end + ) + end + ) + end. + +-spec cartesian_product(list(GIX), list(GIX)) -> list({GIX, GIX}). +cartesian_product(Xarr, Yarr) -> + Xset = begin + _pipe = Xarr, + gleam@set:from_list(_pipe) + end, + Yset = begin + _pipe@1 = Yarr, + gleam@set:from_list(_pipe@1) + end, + _pipe@2 = Xset, + _pipe@3 = gleam@set:fold( + _pipe@2, + gleam@set:new(), + fun(Accumulator0, Member0) -> + gleam@set:fold( + Yset, + Accumulator0, + fun(Accumulator1, Member1) -> + gleam@set:insert(Accumulator1, {Member0, Member1}) + end + ) + end + ), + gleam@set:to_list(_pipe@3). diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@conversion.erl b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@conversion.erl new file mode 100644 index 0000000..0f6decb --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@conversion.erl @@ -0,0 +1,23 @@ +-module(gleam_community@maths@conversion). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([int_to_float/1, float_to_int/1, degrees_to_radians/1, radians_to_degrees/1]). + +-spec int_to_float(integer()) -> float(). +int_to_float(X) -> + gleam@int:to_float(X). + +-spec float_to_int(float()) -> integer(). +float_to_int(X) -> + erlang:trunc(X). + +-spec degrees_to_radians(float()) -> float(). +degrees_to_radians(X) -> + (X * math:pi()) / 180.0. + +-spec radians_to_degrees(float()) -> float(). +radians_to_degrees(X) -> + case math:pi() of + 0.0 -> 0.0; + Gleam@denominator -> (X * 180.0) / Gleam@denominator + end. diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@elementary.erl b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@elementary.erl new file mode 100644 index 0000000..dab5d68 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@elementary.erl @@ -0,0 +1,284 @@ +-module(gleam_community@maths@elementary). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([acos/1, acosh/1, asin/1, asinh/1, atan/1, atan2/2, atanh/1, cos/1, cosh/1, sin/1, sinh/1, tan/1, tanh/1, exponential/1, natural_logarithm/1, logarithm_2/1, logarithm_10/1, logarithm/2, power/2, square_root/1, cube_root/1, nth_root/2, pi/0, tau/0, e/0]). + +-spec acos(float()) -> {ok, float()} | {error, binary()}. +acos(X) -> + case (X >= -1.0) andalso (X =< 1.0) of + true -> + _pipe = math:acos(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1."/utf8>>, + {error, _pipe@1} + end. + +-spec acosh(float()) -> {ok, float()} | {error, binary()}. +acosh(X) -> + case X >= 1.0 of + true -> + _pipe = math:acosh(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x < 1. Valid input is x >= 1."/utf8>>, + {error, _pipe@1} + end. + +-spec asin(float()) -> {ok, float()} | {error, binary()}. +asin(X) -> + case (X >= -1.0) andalso (X =< 1.0) of + true -> + _pipe = math:asin(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1."/utf8>>, + {error, _pipe@1} + end. + +-spec asinh(float()) -> float(). +asinh(X) -> + math:asinh(X). + +-spec atan(float()) -> float(). +atan(X) -> + math:atan(X). + +-spec atan2(float(), float()) -> float(). +atan2(Y, X) -> + math:atan2(Y, X). + +-spec atanh(float()) -> {ok, float()} | {error, binary()}. +atanh(X) -> + case (X > -1.0) andalso (X < 1.0) of + true -> + _pipe = math:atanh(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x > -1 or x < 1. Valid input is -1. < x < 1."/utf8>>, + {error, _pipe@1} + end. + +-spec cos(float()) -> float(). +cos(X) -> + math:cos(X). + +-spec cosh(float()) -> float(). +cosh(X) -> + math:cosh(X). + +-spec sin(float()) -> float(). +sin(X) -> + math:sin(X). + +-spec sinh(float()) -> float(). +sinh(X) -> + math:sinh(X). + +-spec tan(float()) -> float(). +tan(X) -> + math:tan(X). + +-spec tanh(float()) -> float(). +tanh(X) -> + math:tanh(X). + +-spec exponential(float()) -> float(). +exponential(X) -> + math:exp(X). + +-spec natural_logarithm(float()) -> {ok, float()} | {error, binary()}. +natural_logarithm(X) -> + case X > +0.0 of + true -> + _pipe = math:log(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x <= 0. Valid input is x > 0."/utf8>>, + {error, _pipe@1} + end. + +-spec logarithm_2(float()) -> {ok, float()} | {error, binary()}. +logarithm_2(X) -> + case X > +0.0 of + true -> + _pipe = math:log2(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x <= 0. Valid input is x > 0."/utf8>>, + {error, _pipe@1} + end. + +-spec logarithm_10(float()) -> {ok, float()} | {error, binary()}. +logarithm_10(X) -> + case X > +0.0 of + true -> + _pipe = math:log10(X), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: x <= 0. Valid input is x > 0."/utf8>>, + {error, _pipe@1} + end. + +-spec logarithm(float(), gleam@option:option(float())) -> {ok, float()} | + {error, binary()}. +logarithm(X, Base) -> + case X > +0.0 of + true -> + case Base of + {some, A} -> + case (A > +0.0) andalso (A /= 1.0) of + true -> + _assert_subject = logarithm_10(X), + {ok, Numerator} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/elementary"/utf8>>, + function => <<"logarithm"/utf8>>, + line => 820}) + end, + _assert_subject@1 = logarithm_10(A), + {ok, Denominator} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/elementary"/utf8>>, + function => <<"logarithm"/utf8>>, + line => 821}) + end, + _pipe = case Denominator of + 0.0 -> 0.0; + Gleam@denominator -> Numerator / Gleam@denominator + end, + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invalid input argument: base <= 0 or base == 1. Valid input is base > 0 and base != 1."/utf8>>, + {error, _pipe@1} + end; + + _ -> + _pipe@2 = <<"Invalid input argument: base <= 0 or base == 1. Valid input is base > 0 and base != 1."/utf8>>, + {error, _pipe@2} + end; + + _ -> + _pipe@3 = <<"Invalid input argument: x <= 0. Valid input is x > 0."/utf8>>, + {error, _pipe@3} + end. + +-spec power(float(), float()) -> {ok, float()} | {error, binary()}. +power(X, Y) -> + Fractional = (math:ceil(Y) - Y) > +0.0, + case ((X < +0.0) andalso Fractional) orelse ((X =:= +0.0) andalso (Y < +0.0)) of + true -> + _pipe = <<"Invalid input argument: x < 0 and y is fractional or x = 0 and y < 0."/utf8>>, + {error, _pipe}; + + false -> + _pipe@1 = math:pow(X, Y), + {ok, _pipe@1} + end. + +-spec square_root(float()) -> {ok, float()} | {error, binary()}. +square_root(X) -> + case X < +0.0 of + true -> + _pipe = <<"Invalid input argument: x < 0."/utf8>>, + {error, _pipe}; + + false -> + _assert_subject = power(X, 1.0 / 2.0), + {ok, Result} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/elementary"/utf8>>, + function => <<"square_root"/utf8>>, + line => 1066}) + end, + _pipe@1 = Result, + {ok, _pipe@1} + end. + +-spec cube_root(float()) -> {ok, float()} | {error, binary()}. +cube_root(X) -> + case X < +0.0 of + true -> + _pipe = <<"Invalid input argument: x < 0."/utf8>>, + {error, _pipe}; + + false -> + _assert_subject = power(X, 1.0 / 3.0), + {ok, Result} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/elementary"/utf8>>, + function => <<"cube_root"/utf8>>, + line => 1118}) + end, + _pipe@1 = Result, + {ok, _pipe@1} + end. + +-spec nth_root(float(), integer()) -> {ok, float()} | {error, binary()}. +nth_root(X, N) -> + case X < +0.0 of + true -> + _pipe = <<"Invalid input argument: x < 0. Valid input is x > 0"/utf8>>, + {error, _pipe}; + + false -> + case N >= 1 of + true -> + _assert_subject = power(X, case gleam@int:to_float(N) of + 0.0 -> 0.0; + Gleam@denominator -> 1.0 / Gleam@denominator + end), + {ok, Result} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/elementary"/utf8>>, + function => <<"nth_root"/utf8>>, + line => 1175}) + end, + _pipe@1 = Result, + {ok, _pipe@1}; + + false -> + _pipe@2 = <<"Invalid input argument: n < 1. Valid input is n >= 2."/utf8>>, + {error, _pipe@2} + end + end. + +-spec pi() -> float(). +pi() -> + math:pi(). + +-spec tau() -> float(). +tau() -> + 2.0 * pi(). + +-spec e() -> float(). +e() -> + exponential(1.0). diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@metrics.erl b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@metrics.erl new file mode 100644 index 0000000..2a58da6 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@metrics.erl @@ -0,0 +1,278 @@ +-module(gleam_community@maths@metrics). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([norm/2, minkowski_distance/3, manhatten_distance/2, euclidean_distance/2, mean/1, median/1, variance/2, standard_deviation/2]). + +-spec norm(list(float()), float()) -> float(). +norm(Arr, P) -> + case Arr of + [] -> + +0.0; + + _ -> + Agg = begin + _pipe = Arr, + gleam@list:fold( + _pipe, + +0.0, + fun(Acc, A) -> + _assert_subject = gleam_community@maths@elementary:power( + gleam_community@maths@piecewise:float_absolute_value( + A + ), + P + ), + {ok, Result} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"norm"/utf8>>, + line => 101}) + end, + Result + Acc + end + ) + end, + _assert_subject@1 = gleam_community@maths@elementary:power( + Agg, + case P of + 0.0 -> 0.0; + Gleam@denominator -> 1.0 / Gleam@denominator + end + ), + {ok, Result@1} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"norm"/utf8>>, + line => 106}) + end, + Result@1 + end. + +-spec minkowski_distance(list(float()), list(float()), float()) -> {ok, float()} | + {error, binary()}. +minkowski_distance(Xarr, Yarr, P) -> + Xlen = gleam@list:length(Xarr), + Ylen = gleam@list:length(Yarr), + case Xlen =:= Ylen of + false -> + _pipe = <<"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."/utf8>>, + {error, _pipe}; + + true -> + case P < 1.0 of + true -> + _pipe@1 = <<"Invalid input argument: p < 1. Valid input is p >= 1."/utf8>>, + {error, _pipe@1}; + + false -> + _pipe@2 = gleam@list:zip(Xarr, Yarr), + _pipe@3 = gleam@list:map( + _pipe@2, + fun(Tuple) -> + gleam@pair:first(Tuple) - gleam@pair:second(Tuple) + end + ), + _pipe@4 = norm(_pipe@3, P), + {ok, _pipe@4} + end + end. + +-spec manhatten_distance(list(float()), list(float())) -> {ok, float()} | + {error, binary()}. +manhatten_distance(Xarr, Yarr) -> + minkowski_distance(Xarr, Yarr, 1.0). + +-spec euclidean_distance(list(float()), list(float())) -> {ok, float()} | + {error, binary()}. +euclidean_distance(Xarr, Yarr) -> + minkowski_distance(Xarr, Yarr, 2.0). + +-spec mean(list(float())) -> {ok, float()} | {error, binary()}. +mean(Arr) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _pipe@1 = Arr, + _pipe@2 = gleam_community@maths@arithmetics:float_sum(_pipe@1), + _pipe@3 = (fun(A) -> + case gleam_community@maths@conversion:int_to_float( + gleam@list:length(Arr) + ) of + 0.0 -> 0.0; + Gleam@denominator -> A / Gleam@denominator + end + end)(_pipe@2), + {ok, _pipe@3} + end. + +-spec median(list(float())) -> {ok, float()} | {error, binary()}. +median(Arr) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + Count = gleam@list:length(Arr), + Mid = gleam@list:length(Arr) div 2, + Sorted = gleam@list:sort(Arr, fun gleam@float:compare/2), + case gleam_community@maths@predicates:is_odd(Count) of + true -> + _assert_subject = gleam@list:at(Sorted, Mid), + {ok, Val0} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"median"/utf8>>, + line => 402}) + end, + _pipe@1 = Val0, + {ok, _pipe@1}; + + false -> + _assert_subject@1 = gleam@list:at(Sorted, Mid - 1), + {ok, Val0@1} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"median"/utf8>>, + line => 409}) + end, + _assert_subject@2 = gleam@list:at(Sorted, Mid), + {ok, Val1} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"median"/utf8>>, + line => 410}) + end, + _pipe@2 = [Val0@1, Val1], + mean(_pipe@2) + end + end. + +-spec variance(list(float()), integer()) -> {ok, float()} | {error, binary()}. +variance(Arr, Ddof) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + case Ddof < 0 of + true -> + _pipe@1 = <<"Invalid input argument: ddof < 0. Valid input is ddof >= 0."/utf8>>, + {error, _pipe@1}; + + false -> + _assert_subject = mean(Arr), + {ok, Mean} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"variance"/utf8>>, + line => 475}) + end, + _pipe@2 = Arr, + _pipe@3 = gleam@list:map( + _pipe@2, + fun(A) -> + _assert_subject@1 = gleam_community@maths@elementary:power( + A - Mean, + 2.0 + ), + {ok, Result} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"variance"/utf8>>, + line => 478}) + end, + Result + end + ), + _pipe@4 = gleam_community@maths@arithmetics:float_sum( + _pipe@3 + ), + _pipe@5 = (fun(A@1) -> + case (gleam_community@maths@conversion:int_to_float( + gleam@list:length(Arr) + ) + - gleam_community@maths@conversion:int_to_float(Ddof)) of + 0.0 -> 0.0; + Gleam@denominator -> A@1 / Gleam@denominator + end + end)(_pipe@4), + {ok, _pipe@5} + end + end. + +-spec standard_deviation(list(float()), integer()) -> {ok, float()} | + {error, binary()}. +standard_deviation(Arr, Ddof) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + case Ddof < 0 of + true -> + _pipe@1 = <<"Invalid input argument: ddof < 0. Valid input is ddof >= 0."/utf8>>, + {error, _pipe@1}; + + false -> + _assert_subject = variance(Arr, Ddof), + {ok, Variance} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"standard_deviation"/utf8>>, + line => 551}) + end, + _assert_subject@1 = gleam_community@maths@elementary:square_root( + Variance + ), + {ok, Stdev} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/metrics"/utf8>>, + function => <<"standard_deviation"/utf8>>, + line => 554}) + end, + _pipe@2 = Stdev, + {ok, _pipe@2} + end + end. diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@piecewise.erl b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@piecewise.erl new file mode 100644 index 0000000..258d879 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@piecewise.erl @@ -0,0 +1,553 @@ +-module(gleam_community@maths@piecewise). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([float_absolute_value/1, int_absolute_value/1, float_absolute_difference/2, int_absolute_difference/2, float_sign/1, round/3, ceiling/2, floor/2, truncate/2, int_sign/1, float_flip_sign/1, float_copy_sign/2, int_flip_sign/1, int_copy_sign/2, minimum/3, maximum/3, minmax/3, list_minimum/2, list_maximum/2, arg_minimum/2, arg_maximum/2, extrema/2]). +-export_type([rounding_mode/0]). + +-type rounding_mode() :: round_nearest | + round_ties_away | + round_ties_up | + round_to_zero | + round_down | + round_up. + +-spec truncate_float(float()) -> float(). +truncate_float(X) -> + erlang:trunc(X). + +-spec round_to_zero(float(), float()) -> float(). +round_to_zero(P, X) -> + case P of + 0.0 -> 0.0; + Gleam@denominator -> truncate_float(X * P) / Gleam@denominator + end. + +-spec round_down(float(), float()) -> float(). +round_down(P, X) -> + case P of + 0.0 -> 0.0; + Gleam@denominator -> math:floor(X * P) / Gleam@denominator + end. + +-spec round_up(float(), float()) -> float(). +round_up(P, X) -> + case P of + 0.0 -> 0.0; + Gleam@denominator -> math:ceil(X * P) / Gleam@denominator + end. + +-spec float_absolute_value(float()) -> float(). +float_absolute_value(X) -> + case X > +0.0 of + true -> + X; + + false -> + -1.0 * X + end. + +-spec int_absolute_value(integer()) -> integer(). +int_absolute_value(X) -> + case X > 0 of + true -> + X; + + false -> + -1 * X + end. + +-spec float_absolute_difference(float(), float()) -> float(). +float_absolute_difference(A, B) -> + _pipe = A - B, + float_absolute_value(_pipe). + +-spec int_absolute_difference(integer(), integer()) -> integer(). +int_absolute_difference(A, B) -> + _pipe = A - B, + int_absolute_value(_pipe). + +-spec do_float_sign(float()) -> float(). +do_float_sign(X) -> + case X < +0.0 of + true -> + -1.0; + + false -> + case X =:= +0.0 of + true -> + +0.0; + + false -> + 1.0 + end + end. + +-spec float_sign(float()) -> float(). +float_sign(X) -> + do_float_sign(X). + +-spec round_to_nearest(float(), float()) -> float(). +round_to_nearest(P, X) -> + Xabs = float_absolute_value(X) * P, + Xabs_truncated = truncate_float(Xabs), + Remainder = Xabs - Xabs_truncated, + case Remainder of + _ when Remainder > 0.5 -> + case P of + 0.0 -> 0.0; + Gleam@denominator -> (float_sign(X) * truncate_float(Xabs + 1.0)) + / Gleam@denominator + end; + + _ when Remainder =:= 0.5 -> + _assert_subject = gleam@int:modulo( + gleam_community@maths@conversion:float_to_int(Xabs), + 2 + ), + {ok, Is_even} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"round_to_nearest"/utf8>>, + line => 423}) + end, + case Is_even =:= 0 of + true -> + case P of + 0.0 -> 0.0; + Gleam@denominator@1 -> (float_sign(X) * Xabs_truncated) + / Gleam@denominator@1 + end; + + false -> + case P of + 0.0 -> 0.0; + Gleam@denominator@2 -> (float_sign(X) * truncate_float( + Xabs + 1.0 + )) + / Gleam@denominator@2 + end + end; + + _ -> + case P of + 0.0 -> 0.0; + Gleam@denominator@3 -> (float_sign(X) * Xabs_truncated) / Gleam@denominator@3 + end + end. + +-spec round_ties_away(float(), float()) -> float(). +round_ties_away(P, X) -> + Xabs = float_absolute_value(X) * P, + Remainder = Xabs - truncate_float(Xabs), + case Remainder of + _ when Remainder >= 0.5 -> + case P of + 0.0 -> 0.0; + Gleam@denominator -> (float_sign(X) * truncate_float(Xabs + 1.0)) + / Gleam@denominator + end; + + _ -> + case P of + 0.0 -> 0.0; + Gleam@denominator@1 -> (float_sign(X) * truncate_float(Xabs)) / Gleam@denominator@1 + end + end. + +-spec round_ties_up(float(), float()) -> float(). +round_ties_up(P, X) -> + Xabs = float_absolute_value(X) * P, + Xabs_truncated = truncate_float(Xabs), + Remainder = Xabs - Xabs_truncated, + case Remainder of + _ when (Remainder >= 0.5) andalso (X >= +0.0) -> + case P of + 0.0 -> 0.0; + Gleam@denominator -> (float_sign(X) * truncate_float(Xabs + 1.0)) + / Gleam@denominator + end; + + _ -> + case P of + 0.0 -> 0.0; + Gleam@denominator@1 -> (float_sign(X) * Xabs_truncated) / Gleam@denominator@1 + end + end. + +-spec do_round(float(), float(), gleam@option:option(rounding_mode())) -> {ok, + float()} | + {error, binary()}. +do_round(P, X, Mode) -> + case Mode of + {some, round_nearest} -> + _pipe = round_to_nearest(P, X), + {ok, _pipe}; + + {some, round_ties_away} -> + _pipe@1 = round_ties_away(P, X), + {ok, _pipe@1}; + + {some, round_ties_up} -> + _pipe@2 = round_ties_up(P, X), + {ok, _pipe@2}; + + {some, round_to_zero} -> + _pipe@3 = round_to_zero(P, X), + {ok, _pipe@3}; + + {some, round_down} -> + _pipe@4 = round_down(P, X), + {ok, _pipe@4}; + + {some, round_up} -> + _pipe@5 = round_up(P, X), + {ok, _pipe@5}; + + none -> + _pipe@6 = round_to_nearest(P, X), + {ok, _pipe@6} + end. + +-spec round( + float(), + gleam@option:option(integer()), + gleam@option:option(rounding_mode()) +) -> {ok, float()} | {error, binary()}. +round(X, Digits, Mode) -> + case Digits of + {some, A} -> + _assert_subject = gleam_community@maths@elementary:power( + 10.0, + gleam_community@maths@conversion:int_to_float(A) + ), + {ok, P} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"round"/utf8>>, + line => 366}) + end, + do_round(P, X, Mode); + + none -> + do_round(1.0, X, Mode) + end. + +-spec ceiling(float(), gleam@option:option(integer())) -> {ok, float()} | + {error, binary()}. +ceiling(X, Digits) -> + round(X, Digits, {some, round_up}). + +-spec floor(float(), gleam@option:option(integer())) -> {ok, float()} | + {error, binary()}. +floor(X, Digits) -> + round(X, Digits, {some, round_down}). + +-spec truncate(float(), gleam@option:option(integer())) -> {ok, float()} | + {error, binary()}. +truncate(X, Digits) -> + round(X, Digits, {some, round_to_zero}). + +-spec do_int_sign(integer()) -> integer(). +do_int_sign(X) -> + case X < 0 of + true -> + -1; + + false -> + case X =:= 0 of + true -> + 0; + + false -> + 1 + end + end. + +-spec int_sign(integer()) -> integer(). +int_sign(X) -> + do_int_sign(X). + +-spec float_flip_sign(float()) -> float(). +float_flip_sign(X) -> + -1.0 * X. + +-spec float_copy_sign(float(), float()) -> float(). +float_copy_sign(X, Y) -> + case float_sign(X) =:= float_sign(Y) of + true -> + X; + + false -> + float_flip_sign(X) + end. + +-spec int_flip_sign(integer()) -> integer(). +int_flip_sign(X) -> + -1 * X. + +-spec int_copy_sign(integer(), integer()) -> integer(). +int_copy_sign(X, Y) -> + case int_sign(X) =:= int_sign(Y) of + true -> + X; + + false -> + int_flip_sign(X) + end. + +-spec minimum(FQL, FQL, fun((FQL, FQL) -> gleam@order:order())) -> FQL. +minimum(X, Y, Compare) -> + case Compare(X, Y) of + lt -> + X; + + eq -> + X; + + gt -> + Y + end. + +-spec maximum(FQM, FQM, fun((FQM, FQM) -> gleam@order:order())) -> FQM. +maximum(X, Y, Compare) -> + case Compare(X, Y) of + lt -> + Y; + + eq -> + Y; + + gt -> + X + end. + +-spec minmax(FQN, FQN, fun((FQN, FQN) -> gleam@order:order())) -> {FQN, FQN}. +minmax(X, Y, Compare) -> + {minimum(X, Y, Compare), maximum(X, Y, Compare)}. + +-spec list_minimum(list(FQO), fun((FQO, FQO) -> gleam@order:order())) -> {ok, + FQO} | + {error, binary()}. +list_minimum(Arr, Compare) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _assert_subject = gleam@list:at(Arr, 0), + {ok, Val0} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"list_minimum"/utf8>>, + line => 945}) + end, + _pipe@1 = Arr, + _pipe@2 = gleam@list:fold( + _pipe@1, + Val0, + fun(Acc, Element) -> case Compare(Element, Acc) of + lt -> + Element; + + _ -> + Acc + end end + ), + {ok, _pipe@2} + end. + +-spec list_maximum(list(FQS), fun((FQS, FQS) -> gleam@order:order())) -> {ok, + FQS} | + {error, binary()}. +list_maximum(Arr, Compare) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _assert_subject = gleam@list:at(Arr, 0), + {ok, Val0} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"list_maximum"/utf8>>, + line => 1004}) + end, + _pipe@1 = Arr, + _pipe@2 = gleam@list:fold( + _pipe@1, + Val0, + fun(Acc, Element) -> case Compare(Acc, Element) of + lt -> + Element; + + _ -> + Acc + end end + ), + {ok, _pipe@2} + end. + +-spec arg_minimum(list(FQW), fun((FQW, FQW) -> gleam@order:order())) -> {ok, + list(integer())} | + {error, binary()}. +arg_minimum(Arr, Compare) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _assert_subject = begin + _pipe@1 = Arr, + list_minimum(_pipe@1, Compare) + end, + {ok, Min} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"arg_minimum"/utf8>>, + line => 1069}) + end, + _pipe@2 = Arr, + _pipe@3 = gleam@list:index_map( + _pipe@2, + fun(Index, Element) -> case Compare(Element, Min) of + eq -> + Index; + + _ -> + -1 + end end + ), + _pipe@4 = gleam@list:filter(_pipe@3, fun(Index@1) -> case Index@1 of + -1 -> + false; + + _ -> + true + end end), + {ok, _pipe@4} + end. + +-spec arg_maximum(list(FRB), fun((FRB, FRB) -> gleam@order:order())) -> {ok, + list(integer())} | + {error, binary()}. +arg_maximum(Arr, Compare) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _assert_subject = begin + _pipe@1 = Arr, + list_maximum(_pipe@1, Compare) + end, + {ok, Max} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"arg_maximum"/utf8>>, + line => 1139}) + end, + _pipe@2 = Arr, + _pipe@3 = gleam@list:index_map( + _pipe@2, + fun(Index, Element) -> case Compare(Element, Max) of + eq -> + Index; + + _ -> + -1 + end end + ), + _pipe@4 = gleam@list:filter(_pipe@3, fun(Index@1) -> case Index@1 of + -1 -> + false; + + _ -> + true + end end), + {ok, _pipe@4} + end. + +-spec extrema(list(FRG), fun((FRG, FRG) -> gleam@order:order())) -> {ok, + {FRG, FRG}} | + {error, binary()}. +extrema(Arr, Compare) -> + case Arr of + [] -> + _pipe = <<"Invalid input argument: The list is empty."/utf8>>, + {error, _pipe}; + + _ -> + _assert_subject = gleam@list:at(Arr, 0), + {ok, Val_max} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"extrema"/utf8>>, + line => 1209}) + end, + _assert_subject@1 = gleam@list:at(Arr, 0), + {ok, Val_min} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/piecewise"/utf8>>, + function => <<"extrema"/utf8>>, + line => 1210}) + end, + _pipe@1 = Arr, + _pipe@2 = gleam@list:fold( + _pipe@1, + {Val_min, Val_max}, + fun(Acc, Element) -> + First = gleam@pair:first(Acc), + Second = gleam@pair:second(Acc), + case {Compare(Element, First), Compare(Second, Element)} of + {lt, lt} -> + {Element, Element}; + + {lt, _} -> + {Element, Second}; + + {_, lt} -> + {First, Element}; + + {_, _} -> + {First, Second} + end + end + ), + {ok, _pipe@2} + end. diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@predicates.erl b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@predicates.erl new file mode 100644 index 0000000..d991d89 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@predicates.erl @@ -0,0 +1,118 @@ +-module(gleam_community@maths@predicates). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([is_close/4, all_close/4, is_fractional/1, is_power/2, is_perfect/1, is_even/1, is_odd/1]). + +-spec float_absolute_value(float()) -> float(). +float_absolute_value(X) -> + case X > +0.0 of + true -> + X; + + false -> + -1.0 * X + end. + +-spec float_absolute_difference(float(), float()) -> float(). +float_absolute_difference(A, B) -> + _pipe = A - B, + float_absolute_value(_pipe). + +-spec is_close(float(), float(), float(), float()) -> boolean(). +is_close(A, B, Rtol, Atol) -> + X = float_absolute_difference(A, B), + Y = Atol + (Rtol * float_absolute_value(B)), + case X =< Y of + true -> + true; + + false -> + false + end. + +-spec all_close(list(float()), list(float()), float(), float()) -> {ok, + list(boolean())} | + {error, binary()}. +all_close(Xarr, Yarr, Rtol, Atol) -> + Xlen = gleam@list:length(Xarr), + Ylen = gleam@list:length(Yarr), + case Xlen =:= Ylen of + false -> + _pipe = <<"Invalid input argument: length(xarr) != length(yarr). Valid input is when length(xarr) == length(yarr)."/utf8>>, + {error, _pipe}; + + true -> + _pipe@1 = gleam@list:zip(Xarr, Yarr), + _pipe@2 = gleam@list:map( + _pipe@1, + fun(Z) -> + is_close( + gleam@pair:first(Z), + gleam@pair:second(Z), + Rtol, + Atol + ) + end + ), + {ok, _pipe@2} + end. + +-spec is_fractional(float()) -> boolean(). +is_fractional(X) -> + (math:ceil(X) - X) > +0.0. + +-spec is_power(integer(), integer()) -> boolean(). +is_power(X, Y) -> + _assert_subject = gleam_community@maths@elementary:logarithm( + gleam@int:to_float(X), + {some, gleam@int:to_float(Y)} + ), + {ok, Value} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/predicates"/utf8>>, + function => <<"is_power"/utf8>>, + line => 241}) + end, + _assert_subject@1 = gleam_community@maths@piecewise:truncate( + Value, + {some, 0} + ), + {ok, Truncated} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/predicates"/utf8>>, + function => <<"is_power"/utf8>>, + line => 243}) + end, + Rem = Value - Truncated, + Rem =:= +0.0. + +-spec do_sum(list(integer())) -> integer(). +do_sum(Arr) -> + case Arr of + [] -> + 0; + + _ -> + _pipe = Arr, + gleam@list:fold(_pipe, 0, fun(Acc, A) -> A + Acc end) + end. + +-spec is_perfect(integer()) -> boolean(). +is_perfect(N) -> + do_sum(gleam_community@maths@arithmetics:proper_divisors(N)) =:= N. + +-spec is_even(integer()) -> boolean(). +is_even(X) -> + (X rem 2) =:= 0. + +-spec is_odd(integer()) -> boolean(). +is_odd(X) -> + (X rem 2) /= 0. diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@sequences.erl b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@sequences.erl new file mode 100644 index 0000000..74dcff4 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@sequences.erl @@ -0,0 +1,199 @@ +-module(gleam_community@maths@sequences). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([arange/3, linear_space/4, logarithmic_space/5, geometric_space/4]). + +-spec arange(float(), float(), float()) -> list(float()). +arange(Start, Stop, Step) -> + case ((Start >= Stop) andalso (Step > +0.0)) orelse ((Start =< Stop) andalso (Step + < +0.0)) of + true -> + []; + + false -> + Direction = case Start =< Stop of + true -> + 1.0; + + false -> + -1.0 + end, + Step_abs = gleam_community@maths@piecewise:float_absolute_value( + Step + ), + Num = case Step_abs of + 0.0 -> 0.0; + Gleam@denominator -> gleam_community@maths@piecewise:float_absolute_value( + Start - Stop + ) + / Gleam@denominator + end, + _pipe = gleam@list:range( + 0, + gleam_community@maths@conversion:float_to_int(Num) - 1 + ), + gleam@list:map( + _pipe, + fun(I) -> + Start + ((gleam_community@maths@conversion:int_to_float(I) * Step_abs) + * Direction) + end + ) + end. + +-spec linear_space(float(), float(), integer(), boolean()) -> {ok, + list(float())} | + {error, binary()}. +linear_space(Start, Stop, Num, Endpoint) -> + Direction = case Start =< Stop of + true -> + 1.0; + + false -> + -1.0 + end, + case Num > 0 of + true -> + case Endpoint of + true -> + Increment = case gleam_community@maths@conversion:int_to_float( + Num - 1 + ) of + 0.0 -> 0.0; + Gleam@denominator -> gleam_community@maths@piecewise:float_absolute_value( + Start - Stop + ) + / Gleam@denominator + end, + _pipe = gleam@list:range(0, Num - 1), + _pipe@1 = gleam@list:map( + _pipe, + fun(I) -> + Start + ((gleam_community@maths@conversion:int_to_float( + I + ) + * Increment) + * Direction) + end + ), + {ok, _pipe@1}; + + false -> + Increment@1 = case gleam_community@maths@conversion:int_to_float( + Num + ) of + 0.0 -> 0.0; + Gleam@denominator@1 -> gleam_community@maths@piecewise:float_absolute_value( + Start - Stop + ) + / Gleam@denominator@1 + end, + _pipe@2 = gleam@list:range(0, Num - 1), + _pipe@3 = gleam@list:map( + _pipe@2, + fun(I@1) -> + Start + ((gleam_community@maths@conversion:int_to_float( + I@1 + ) + * Increment@1) + * Direction) + end + ), + {ok, _pipe@3} + end; + + false -> + _pipe@4 = <<"Invalid input: num < 0. Valid input is num > 0."/utf8>>, + {error, _pipe@4} + end. + +-spec logarithmic_space(float(), float(), integer(), boolean(), float()) -> {ok, + list(float())} | + {error, binary()}. +logarithmic_space(Start, Stop, Num, Endpoint, Base) -> + case Num > 0 of + true -> + _assert_subject = linear_space(Start, Stop, Num, Endpoint), + {ok, Linspace} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/sequences"/utf8>>, + function => <<"logarithmic_space"/utf8>>, + line => 221}) + end, + _pipe = Linspace, + _pipe@1 = gleam@list:map( + _pipe, + fun(I) -> + _assert_subject@1 = gleam_community@maths@elementary:power( + Base, + I + ), + {ok, Result} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/sequences"/utf8>>, + function => <<"logarithmic_space"/utf8>>, + line => 224}) + end, + Result + end + ), + {ok, _pipe@1}; + + false -> + _pipe@2 = <<"Invalid input: num < 0. Valid input is num > 0."/utf8>>, + {error, _pipe@2} + end. + +-spec geometric_space(float(), float(), integer(), boolean()) -> {ok, + list(float())} | + {error, binary()}. +geometric_space(Start, Stop, Num, Endpoint) -> + case (Start =:= +0.0) orelse (Stop =:= +0.0) of + true -> + _pipe = <<""/utf8>>, + {error, _pipe}; + + false -> + case Num > 0 of + true -> + _assert_subject = gleam_community@maths@elementary:logarithm_10( + Start + ), + {ok, Log_start} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/sequences"/utf8>>, + function => <<"geometric_space"/utf8>>, + line => 293}) + end, + _assert_subject@1 = gleam_community@maths@elementary:logarithm_10( + Stop + ), + {ok, Log_stop} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/sequences"/utf8>>, + function => <<"geometric_space"/utf8>>, + line => 294}) + end, + logarithmic_space(Log_start, Log_stop, Num, Endpoint, 10.0); + + false -> + _pipe@1 = <<"Invalid input: num < 0. Valid input is num > 0."/utf8>>, + {error, _pipe@1} + end + end. diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@special.erl b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@special.erl new file mode 100644 index 0000000..925f4bb --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@special.erl @@ -0,0 +1,157 @@ +-module(gleam_community@maths@special). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([erf/1, gamma/1, beta/2, incomplete_gamma/2]). + +-spec erf(float()) -> float(). +erf(X) -> + _assert_subject = [0.254829592, + -0.284496736, + 1.421413741, + -1.453152027, + 1.061405429], + [A1, A2, A3, A4, A5] = case _assert_subject of + [_, _, _, _, _] -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/special"/utf8>>, + function => <<"erf"/utf8>>, + line => 79}) + end, + P = 0.3275911, + Sign = gleam_community@maths@piecewise:float_sign(X), + X@1 = gleam_community@maths@piecewise:float_absolute_value(X), + T = case (1.0 + (P * X@1)) of + 0.0 -> 0.0; + Gleam@denominator -> 1.0 / Gleam@denominator + end, + Y = 1.0 - ((((((((((A5 * T) + A4) * T) + A3) * T) + A2) * T) + A1) * T) * gleam_community@maths@elementary:exponential( + (-1.0 * X@1) * X@1 + )), + Sign * Y. + +-spec gamma_lanczos(float()) -> float(). +gamma_lanczos(X) -> + case X < 0.5 of + true -> + case (gleam_community@maths@elementary:sin( + gleam_community@maths@elementary:pi() * X + ) + * gamma_lanczos(1.0 - X)) of + 0.0 -> 0.0; + Gleam@denominator -> gleam_community@maths@elementary:pi() / Gleam@denominator + end; + + false -> + Z = X - 1.0, + X@1 = gleam@list:index_fold( + [0.99999999999980993, + 676.5203681218851, + -1259.1392167224028, + 771.32342877765313, + -176.61502916214059, + 12.507343278686905, + -0.13857109526572012, + 0.0000099843695780195716, + 0.00000015056327351493116], + +0.0, + fun(Acc, V, Index) -> case Index > 0 of + true -> + Acc + (case (Z + gleam_community@maths@conversion:int_to_float( + Index + )) of + 0.0 -> 0.0; + Gleam@denominator@1 -> V / Gleam@denominator@1 + end); + + false -> + V + end end + ), + T = (Z + 7.0) + 0.5, + _assert_subject = gleam_community@maths@elementary:power( + 2.0 * gleam_community@maths@elementary:pi(), + 0.5 + ), + {ok, V1} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/special"/utf8>>, + function => <<"gamma_lanczos"/utf8>>, + line => 146}) + end, + _assert_subject@1 = gleam_community@maths@elementary:power( + T, + Z + 0.5 + ), + {ok, V2} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"gleam_community/maths/special"/utf8>>, + function => <<"gamma_lanczos"/utf8>>, + line => 147}) + end, + ((V1 * V2) * gleam_community@maths@elementary:exponential(-1.0 * T)) + * X@1 + end. + +-spec gamma(float()) -> float(). +gamma(X) -> + gamma_lanczos(X). + +-spec beta(float(), float()) -> float(). +beta(X, Y) -> + case gamma(X + Y) of + 0.0 -> 0.0; + Gleam@denominator -> (gamma(X) * gamma(Y)) / Gleam@denominator + end. + +-spec incomplete_gamma_sum(float(), float(), float(), float(), float()) -> float(). +incomplete_gamma_sum(A, X, T, S, N) -> + case T of + +0.0 -> + S; + + _ -> + Ns = S + T, + Nt = T * (case (A + N) of + 0.0 -> 0.0; + Gleam@denominator -> X / Gleam@denominator + end), + incomplete_gamma_sum(A, X, Nt, Ns, N + 1.0) + end. + +-spec incomplete_gamma(float(), float()) -> {ok, float()} | {error, binary()}. +incomplete_gamma(A, X) -> + case (A > +0.0) andalso (X >= +0.0) of + true -> + _assert_subject = gleam_community@maths@elementary:power(X, A), + {ok, V} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam_community/maths/special"/utf8>>, + function => <<"incomplete_gamma"/utf8>>, + line => 173}) + end, + _pipe = (V * gleam_community@maths@elementary:exponential(-1.0 * X)) + * incomplete_gamma_sum(A, X, case A of + 0.0 -> 0.0; + Gleam@denominator -> 1.0 / Gleam@denominator + end, +0.0, 1.0), + {ok, _pipe}; + + false -> + _pipe@1 = <<"Invlaid input argument: a <= 0 or x < 0. Valid input is a > 0 and x >= 0."/utf8>>, + {error, _pipe@1} + end. diff --git a/aoc2023/build/packages/gleam_community_maths/src/gleam_community_maths.app.src b/aoc2023/build/packages/gleam_community_maths/src/gleam_community_maths.app.src new file mode 100644 index 0000000..091e679 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/gleam_community_maths.app.src @@ -0,0 +1,16 @@ +{application, gleam_community_maths, [ + {vsn, "1.0.1"}, + {applications, [gleam_stdlib, + gleeunit]}, + {description, "A basic maths library"}, + {modules, [gleam_community@maths@arithmetics, + gleam_community@maths@combinatorics, + gleam_community@maths@conversion, + gleam_community@maths@elementary, + gleam_community@maths@metrics, + gleam_community@maths@piecewise, + gleam_community@maths@predicates, + gleam_community@maths@sequences, + gleam_community@maths@special]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/gleam_community_maths/src/maths.mjs b/aoc2023/build/packages/gleam_community_maths/src/maths.mjs new file mode 100644 index 0000000..5c5ab31 --- /dev/null +++ b/aoc2023/build/packages/gleam_community_maths/src/maths.mjs @@ -0,0 +1,95 @@ +export function sin(float) { + return Math.sin(float) +} + +export function pi() { + return Math.PI +} + +export function acos(float) { + return Math.acos(float) +} + +export function acosh(float) { + return Math.acosh(float) +} + +export function asin(float) { + return Math.asin(float) +} + +export function asinh(float) { + return Math.asinh(float) +} + +export function atan(float) { + return Math.atan(float) +} + +export function tan(float) { + return Math.tan(float) +} + +export function atan2(floaty, floatx) { + return Math.atan2(floaty, floatx) +} + +export function atanh(float) { + return Math.atanh(float) +} + +export function cos(float) { + return Math.cos(float) +} + +export function cosh(float) { + return Math.cosh(float) +} + +export function exponential(float) { + return Math.exp(float) +} + +export function ceiling(float) { + return Math.ceil(float) +} + +export function floor(float) { + return Math.floor(float) +} + +export function power(base, exponent) { + return Math.pow(base, exponent) +} + +export function logarithm(float) { + return Math.log(float) +} + +export function logarithm_10(float) { + return Math.log10(float) +} + +export function logarithm_2(float) { + return Math.log2(float) +} + +export function sinh(float) { + return Math.sinh(float) +} + +export function tanh(float) { + return Math.tanh(float) +} + +export function sign(float) { + return Math.sign(float) +} + +export function truncate(float) { + return Math.trunc(float) +} + +export function to_int(float) { + return Math.trunc(float) +} diff --git a/aoc2023/build/packages/gleam_erlang/LICENSE b/aoc2023/build/packages/gleam_erlang/LICENSE new file mode 100644 index 0000000..59e1345 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/LICENSE @@ -0,0 +1,191 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright {{copyright_year}}, {{author_name}} <{{author_email}}>. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/aoc2023/build/packages/gleam_erlang/README.md b/aoc2023/build/packages/gleam_erlang/README.md new file mode 100644 index 0000000..ffee4cd --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/README.md @@ -0,0 +1,37 @@ +# Gleam Erlang 🐙 + +A library for making use of Erlang specific code! + +## Features + +- Typed Erlang processes and message sending. +- Erlang binary format (de)serialisation. +- Functions for working with Erlang's charlists. +- Reading, writing, and deletion of files. +- Basic distributed Erlang support and working with nodes. +- Reading and writing of environment variables. +- Functions for working with atoms. + +## Usage + +Add this library to your Gleam project + +```shell +gleam add gleam_erlang +``` + +And then use it in your code + +```gleam +import gleam/io +import gleam/erlang/file + +pub fn main() { + assert Ok(contents) = file.read("pokedex.txt") + io.println(contents) +} +``` + +Documentation can be found at <https://hexdocs.pm/gleam_erlang/>. + +This library requires OTP 23.0 or higher. diff --git a/aoc2023/build/packages/gleam_erlang/gleam.toml b/aoc2023/build/packages/gleam_erlang/gleam.toml new file mode 100644 index 0000000..8d62603 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/gleam.toml @@ -0,0 +1,18 @@ +name = "gleam_erlang" + +version = "0.23.1" +licences = ["Apache-2.0"] +description = "A Gleam library for working with Erlang" + +repository = { type = "github", user = "gleam-lang", repo = "erlang" } +links = [ + { title = "Website", href = "https://gleam.run" }, + { title = "Sponsor", href = "https://github.com/sponsors/lpil" }, +] +gleam = ">= 0.32.0" + +[dependencies] +gleam_stdlib = "~> 0.32" + +[dev-dependencies] +gleeunit = "~> 0.6" diff --git a/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@file_FileInfo.hrl b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@file_FileInfo.hrl new file mode 100644 index 0000000..b38d11e --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@file_FileInfo.hrl @@ -0,0 +1,15 @@ +-record(file_info, { + size :: integer(), + file_type :: gleam@erlang@file:file_type(), + access :: gleam@erlang@file:access(), + atime :: integer(), + mtime :: integer(), + ctime :: integer(), + mode :: integer(), + links :: integer(), + major_device :: integer(), + minor_device :: integer(), + inode :: integer(), + user_id :: integer(), + group_id :: integer() +}). diff --git a/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Abnormal.hrl b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Abnormal.hrl new file mode 100644 index 0000000..4cd0452 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Abnormal.hrl @@ -0,0 +1 @@ +-record(abnormal, {reason :: binary()}). diff --git a/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_CalleeDown.hrl b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_CalleeDown.hrl new file mode 100644 index 0000000..5dd5047 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_CalleeDown.hrl @@ -0,0 +1 @@ +-record(callee_down, {reason :: gleam@dynamic:dynamic_()}). diff --git a/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Cancelled.hrl b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Cancelled.hrl new file mode 100644 index 0000000..b82b49f --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Cancelled.hrl @@ -0,0 +1 @@ +-record(cancelled, {time_remaining :: integer()}). diff --git a/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ExitMessage.hrl b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ExitMessage.hrl new file mode 100644 index 0000000..c476308 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ExitMessage.hrl @@ -0,0 +1,4 @@ +-record(exit_message, { + pid :: gleam@erlang@process:pid_(), + reason :: gleam@erlang@process:exit_reason() +}). diff --git a/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ProcessDown.hrl b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ProcessDown.hrl new file mode 100644 index 0000000..df0b6b7 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ProcessDown.hrl @@ -0,0 +1,4 @@ +-record(process_down, { + pid :: gleam@erlang@process:pid_(), + reason :: gleam@dynamic:dynamic_() +}). diff --git a/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ProcessMonitor.hrl b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ProcessMonitor.hrl new file mode 100644 index 0000000..ce552e2 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ProcessMonitor.hrl @@ -0,0 +1 @@ +-record(process_monitor, {tag :: gleam@erlang:reference_()}). diff --git a/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Subject.hrl b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Subject.hrl new file mode 100644 index 0000000..abc46b2 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Subject.hrl @@ -0,0 +1,4 @@ +-record(subject, { + owner :: gleam@erlang@process:pid_(), + tag :: gleam@erlang:reference_() +}). diff --git a/aoc2023/build/packages/gleam_erlang/include/gleam@erlang_ApplicationFailedToStart.hrl b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang_ApplicationFailedToStart.hrl new file mode 100644 index 0000000..52c9896 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang_ApplicationFailedToStart.hrl @@ -0,0 +1,4 @@ +-record(application_failed_to_start, { + name :: gleam@erlang@atom:atom_(), + reason :: gleam@dynamic:dynamic_() +}). diff --git a/aoc2023/build/packages/gleam_erlang/include/gleam@erlang_UnknownApplication.hrl b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang_UnknownApplication.hrl new file mode 100644 index 0000000..fde3c61 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/include/gleam@erlang_UnknownApplication.hrl @@ -0,0 +1 @@ +-record(unknown_application, {name :: gleam@erlang@atom:atom_()}). diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam/erlang.gleam b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang.gleam new file mode 100644 index 0000000..783cd53 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang.gleam @@ -0,0 +1,158 @@ +import gleam/dynamic.{type Dynamic} +import gleam/list +import gleam/erlang/atom.{type Atom} +import gleam/erlang/charlist.{type Charlist} + +@external(erlang, "io_lib", "format") +fn erl_format(a: String, b: List(a)) -> Charlist + +/// Return a string representation of any term +pub fn format(term: any) -> String { + charlist.to_string(erl_format("~p", [term])) +} + +@external(erlang, "erlang", "term_to_binary") +pub fn term_to_binary(a: a) -> BitArray + +type Safe { + Safe +} + +@external(erlang, "erlang", "binary_to_term") +fn erl_binary_to_term(a: BitArray, b: List(Safe)) -> Dynamic + +pub fn binary_to_term(binary: BitArray) -> Result(Dynamic, Nil) { + case rescue(fn() { erl_binary_to_term(binary, [Safe]) }) { + Ok(term) -> Ok(term) + Error(_) -> Error(Nil) + } +} + +pub fn unsafe_binary_to_term(binary: BitArray) -> Result(Dynamic, Nil) { + case rescue(fn() { erl_binary_to_term(binary, []) }) { + Ok(term) -> Ok(term) + Error(_) -> Error(Nil) + } +} + +/// Error value returned by `get_line` function +/// +pub type GetLineError { + Eof + NoData +} + +/// Reads a line from standard input with the given prompt. +/// +/// # Example +/// +/// > get_line("Language: ") +/// // -> Language: <- gleam +/// Ok("gleam\n") +/// +@external(erlang, "gleam_erlang_ffi", "get_line") +pub fn get_line(prompt prompt: String) -> Result(String, GetLineError) + +pub type TimeUnit { + Second + Millisecond + Microsecond + Nanosecond +} + +/// Returns the current OS system time. +/// +/// <https://erlang.org/doc/apps/erts/time_correction.html#OS_System_Time> +@external(erlang, "os", "system_time") +pub fn system_time(a: TimeUnit) -> Int + +/// Returns the current OS system time as a tuple of Ints +/// +/// http://erlang.org/doc/man/os.html#timestamp-0 +@external(erlang, "os", "timestamp") +pub fn erlang_timestamp() -> #(Int, Int, Int) + +/// Gleam doesn't offer any way to raise exceptions, but they may still occur +/// due to bugs when working with unsafe code, such as when calling Erlang +/// function. +/// +/// This function will catch any error thrown and convert it into a result +/// rather than crashing the process. +/// +@external(erlang, "gleam_erlang_ffi", "rescue") +pub fn rescue(a: fn() -> a) -> Result(a, Crash) + +pub type Crash { + Exited(Dynamic) + Thrown(Dynamic) + Errored(Dynamic) +} + +@external(erlang, "init", "get_plain_arguments") +fn get_start_arguments() -> List(Charlist) + +/// Get the arguments given to the program when it was started. +/// +/// This is sometimes called `argv` in other languages. +pub fn start_arguments() -> List(String) { + get_start_arguments() + |> list.map(charlist.to_string) +} + +/// Starts an OTP application's process tree in the background, as well as +/// the trees of any applications that the given application depends upon. An +/// OTP application typically maps onto a Gleam or Hex package. +/// +/// Returns a list of the applications that were started. Calling this function +/// for application that have already been started is a no-op so you do not need +/// to check the application state beforehand. +/// +/// In Gleam we prefer to not use these implicit background process trees, but +/// you will likely still need to start the trees of OTP applications written in +/// other BEAM languages such as Erlang or Elixir, including those included by +/// default with Erlang/OTP. +/// +/// For more information see the OTP documentation. +/// - <https://www.erlang.org/doc/man/application.html#ensure_all_started-1> +/// - <https://www.erlang.org/doc/man/application.html#start-1> +/// +@external(erlang, "gleam_erlang_ffi", "ensure_all_started") +pub fn ensure_all_started( + application application: Atom, +) -> Result(List(Atom), EnsureAllStartedError) + +pub type EnsureAllStartedError { + UnknownApplication(name: Atom) + ApplicationFailedToStart(name: Atom, reason: Dynamic) +} + +/// A unique reference value. +/// +/// It holds no particular meaning or value, but unique values are often useful +/// in programs are used heavily within both Gleam and Erlang's OTP frameworks. +/// +/// More can be read about references in the [Erlang documentation][1]. +/// +/// [1]: https://www.erlang.org/doc/efficiency_guide/advanced.html#unique_references +/// +pub type Reference + +/// Create a new unique reference. +/// +@external(erlang, "erlang", "make_ref") +pub fn make_reference() -> Reference + +/// Returns the path of a package's `priv` directory, where extra non-Gleam +/// or Erlang files are typically kept. +/// +/// Returns an error if no package was found with the given name. +/// +/// # Example +/// +/// ```gleam +/// > erlang.priv_directory("my_app") +/// // -> Ok("/some/location/my_app/priv") +/// ``` +/// +@external(erlang, "gleam_erlang_ffi", "priv_directory") +pub fn priv_directory(name: String) -> Result(String, Nil) diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/atom.gleam b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/atom.gleam new file mode 100644 index 0000000..a27289c --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/atom.gleam @@ -0,0 +1,79 @@ +import gleam/dynamic.{type DecodeErrors, type Dynamic} + +/// Atom is a special string-like data-type that is most commonly used for +/// interfacing with code written in other BEAM languages such as Erlang and +/// Elixir. It is preferable to define your own custom types to use instead of +/// atoms where possible. +/// +/// Atoms are not used much in typical Gleam code! +/// +/// ## Creating atoms +/// +/// We can create atoms with the the [`create_from_string`](#create_from_string) +/// function, though we must be careful when doing so as atoms are never +/// garbage collected. If we create too many atoms (for example, if we convert +/// user input into atoms) we may hit the max limit of atoms and cause the +/// virtual machine to crash. +/// +pub type Atom + +/// An error returned when no atom is found in the virtual machine's atom table +/// for a given string when calling the [`from_string`](#from_string) function. +pub type FromStringError { + AtomNotLoaded +} + +/// Finds an existing Atom for the given String. +/// +/// If no atom is found in the virtual machine's atom table for the String then +/// an error is returned. +/// +/// ## Examples +/// +/// > from_string("ok") +/// Ok(create_from_string("ok")) +/// +/// > from_string("some_new_atom") +/// Error(AtomNotLoaded) +/// +@external(erlang, "gleam_erlang_ffi", "atom_from_string") +pub fn from_string(a: String) -> Result(Atom, FromStringError) + +/// Creates an atom from a string, inserting a new value into the virtual +/// machine's atom table if an atom does not already exist for the given +/// string. +/// +/// We must be careful when using this function as there is a limit to the +/// number of atom that can fit in the virtual machine's atom table. Never +/// convert user input into atoms as filling the atom table will cause the +/// virtual machine to crash! +/// +@external(erlang, "erlang", "binary_to_atom") +pub fn create_from_string(a: String) -> Atom + +/// Returns a `String` corresponding to the text representation of the given +/// `Atom`. +/// +/// ## Examples +/// +/// > let ok_atom = create_from_string("ok") +/// > to_string(ok_atom) +/// "ok" +/// +@external(erlang, "erlang", "atom_to_binary") +pub fn to_string(a: Atom) -> String + +/// Checks to see whether a `Dynamic` value is an atom, and return the atom if +/// it is. +/// +/// ## Examples +/// +/// > import gleam/dynamic +/// > from_dynamic(dynamic.from(create_from_string("hello"))) +/// Ok(create_from_string("hello")) +/// +/// > from_dynamic(dynamic.from(123)) +/// Error([DecodeError(expected: "Atom", found: "Int", path: [])]) +/// +@external(erlang, "gleam_erlang_ffi", "atom_from_dynamic") +pub fn from_dynamic(from from: Dynamic) -> Result(Atom, DecodeErrors) diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/charlist.gleam b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/charlist.gleam new file mode 100644 index 0000000..e5b6d65 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/charlist.gleam @@ -0,0 +1,25 @@ +//// A charlist is a list of integers where all the integers are valid code +//// points. +//// +//// In practice, you will not come across them often, except perhaps when +//// interfacing with Erlang, in particular when using older libraries that do +//// not accept binaries as arguments. + +/// A list of characters represented as ints. Commonly used by older Erlang +/// modules. +pub type Charlist + +/// Transform a charlist to a string +@external(erlang, "unicode", "characters_to_binary") +pub fn to_string(a: Charlist) -> String + +// Calls `unicode:characters_to_binary(Data, unicode, unicode)` +// Note: `unicode is an alias for utf8` +// See <https://www.erlang.org/doc/man/unicode.html#characters_to_binary-1> + +/// Transform a string to a charlist +@external(erlang, "unicode", "characters_to_list") +pub fn from_string(a: String) -> Charlist +// Calls `unicode:characters_to_list(Data, unicode)` +// Note: `unicode is an alias for utf8` +// See <https://www.erlang.org/doc/man/unicode.html#characters_to_list-1> diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/file.gleam b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/file.gleam new file mode 100644 index 0000000..48e11a7 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/file.gleam @@ -0,0 +1,737 @@ +//// Working with files on the filesystem. +//// +//// The functions included in this module are for high-level concepts such as +//// reading and writing. + +import gleam/bit_array +import gleam/result + +/// Reason represents all of the reasons that Erlang surfaces of why a file +/// system operation could fail. Most of these reasons are POSIX errors, which +/// come from the operating system and start with `E`. Others have been added to +/// represent other issues that may arise. +pub type Reason { + /// Permission denied. + Eacces + /// Resource temporarily unavailable. + Eagain + /// Bad file number + Ebadf + /// Bad message. + Ebadmsg + /// File busy. + Ebusy + /// Resource deadlock avoided. + Edeadlk + /// On most architectures, same as `Edeadlk`. On some architectures, it + /// means "File locking deadlock error." + Edeadlock + /// Disk quota exceeded. + Edquot + /// File already exists. + Eexist + /// Bad address in system call argument. + Efault + /// File too large. + Efbig + /// Inappropriate file type or format. Usually caused by trying to set the + /// "sticky bit" on a regular file (not a directory). + Eftype + /// Interrupted system call. + Eintr + /// Invalid argument. + Einval + /// I/O error. + Eio + /// Illegal operation on a directory. + Eisdir + /// Too many levels of symbolic links. + Eloop + /// Too many open files. + Emfile + /// Too many links. + Emlink + /// Multihop attempted. + Emultihop + /// Filename too long + Enametoolong + /// File table overflow + Enfile + /// No buffer space available. + Enobufs + /// No such device. + Enodev + /// No locks available. + Enolck + /// Link has been severed. + Enolink + /// No such file or directory. + Enoent + /// Not enough memory. + Enomem + /// No space left on device. + Enospc + /// No STREAM resources. + Enosr + /// Not a STREAM. + Enostr + /// Function not implemented. + Enosys + /// Block device required. + Enotblk + /// Not a directory. + Enotdir + /// Operation not supported. + Enotsup + /// No such device or address. + Enxio + /// Operation not supported on socket. + Eopnotsupp + /// Value too large to be stored in data type. + Eoverflow + /// Not owner. + Eperm + /// Broken pipe. + Epipe + /// Result too large. + Erange + /// Read-only file system. + Erofs + /// Invalid seek. + Espipe + /// No such process. + Esrch + /// Stale remote file handle. + Estale + /// Text file busy. + Etxtbsy + /// Cross-domain link. + Exdev + /// File was requested to be read as UTF-8, but is not UTF-8 encoded. + NotUtf8 +} + +/// The type of file found by `file_info` or `link_info`. +/// +pub type FileType { + Device + Directory + Other + Regular + Symlink +} + +/// The read/write permissions a user can have for a file. +/// +pub type Access { + NoAccess + Read + ReadWrite + Write +} + +/// Meta information for a file. +/// +/// Timestamps are in seconds before or after the Unix time epoch, +/// `1970-01-01 00:00:00 UTC`. +/// +pub type FileInfo { + FileInfo( + /// File size in bytes. + /// + size: Int, + /// `Regular`, `Directory`, `Symlink`, `Device`, or `Other`. + /// + file_type: FileType, + /// `ReadWrite`, `Read`, `Write`, or `NoAccess`. + /// + access: Access, + /// Timestamp of most recent access. + /// + atime: Int, + /// Timestamp of most recent modification. + /// + mtime: Int, + /// Timestamp of most recent change (or file creation, depending on + /// operating system). + /// + ctime: Int, + /// File permissions encoded as a sum of bit values, including but not + /// limited to: + /// + /// Owner read, write, execute. + /// + /// `0o400`, `0o200`, `0o100` + /// + /// Group read, write, execute. + /// + /// `0o40`, `0o20`, `0o10` + /// + /// Other read, write, execute. + /// + /// `0o4`, `0o2`, `0o1` + /// + /// Set user ID, group ID on execution. + /// + /// `0x800`, `0x400` + /// + mode: Int, + /// Total links to a file (always `1` for file systems without links). + /// + links: Int, + /// The file system where a file is located (`0` for drive `A:` on Windows, + /// `1` for `B:`, etc.). + /// + major_device: Int, + /// Character device (or `0` on non-Unix systems). + /// + minor_device: Int, + /// The `inode` number for a file (always `0` on non-Unix file systems). + /// + inode: Int, + /// The owner of a file (always `0` on non-Unix file systems). + /// + user_id: Int, + /// The group id of a file (always `0` on non-Unix file systems). + /// + group_id: Int, + ) +} + +/// Results in `FileInfo` about the given `path` on success, otherwise a +/// `Reason` for failure. +/// +/// When `path` refers to a symlink, the result pertains to the link's target. +/// To get `FileInfo` about a symlink itself, use `link_info`. +/// +/// ## Examples +/// +/// ```gleam +/// > file_info("gleam.toml") +/// Ok(FileInfo( +/// size: 430, +/// file_type: Regular, +/// access: ReadWrite, +/// atime: 1680580321, +/// mtime: 1680580272, +/// ctime: 1680580272, +/// mode: 33188, +/// links: 1, +/// major_device: 64, +/// minor_device: 0, +/// inode: 469028, +/// user_id: 1000, +/// group_id: 1000, +/// )) +/// +/// > file_info("/root") +/// Ok(FileInfo( +/// size: 16, +/// file_type: Directory, +/// access: Read, +/// atime: 1677789967, +/// mtime: 1664561240, +/// ctime: 1664561240, +/// mode: 16877, +/// links: 11, +/// major_device: 54, +/// minor_device: 0, +/// inode: 34, +/// user_id: 0, +/// group_id: 0, +/// )) +/// +/// > file_info("./build/dev/erlang/rad/priv") +/// Ok(FileInfo( +/// size: 140, +/// file_type: Directory, +/// access: ReadWrite, +/// atime: 1680580321, +/// mtime: 1680580272, +/// ctime: 1680580272, +/// mode: 33188, +/// links: 1, +/// major_device: 64, +/// minor_device: 0, +/// inode: 469028, +/// user_id: 1000, +/// group_id: 1000, +/// )) +/// +/// > file_info("/does_not_exist") +/// Error(Enoent) +/// +/// > file_info("/root/.local/maybe_exists") +/// Error(Eacces) +/// ``` +/// +@deprecated("Use the simplifile package instead") +pub fn file_info(a: String) -> Result(FileInfo, Reason) { + do_file_info(a) +} + +@external(erlang, "gleam_erlang_ffi", "file_info") +fn do_file_info(a: String) -> Result(FileInfo, Reason) + +/// Results in `FileInfo` about the given `path` on success, otherwise a +/// `Reason` for failure. +/// +/// When `path` refers to a symlink, the result pertains to the link itself. +/// To get `FileInfo` about a symlink's target, use `file_info`. +/// +/// ## Examples +/// +/// ```gleam +/// > link_info("gleam.toml") +/// Ok(FileInfo( +/// size: 430, +/// file_type: Regular, +/// access: ReadWrite, +/// atime: 1680580321, +/// mtime: 1680580272, +/// ctime: 1680580272, +/// mode: 33188, +/// links: 1, +/// major_device: 64, +/// minor_device: 0, +/// inode: 469028, +/// user_id: 1000, +/// group_id: 1000, +/// )) +/// +/// > link_info("/root") +/// Ok(FileInfo( +/// size: 16, +/// file_type: Directory, +/// access: Read, +/// atime: 1677789967, +/// mtime: 1664561240, +/// ctime: 1664561240, +/// mode: 16877, +/// links: 11, +/// major_device: 54, +/// minor_device: 0, +/// inode: 34, +/// user_id: 0, +/// group_id: 0, +/// )) +/// +/// > link_info("./build/dev/erlang/rad/priv") +/// Ok(FileInfo( +/// size: 41, +/// file_type: Symlink, +/// access: ReadWrite, +/// atime: 1680581150, +/// mtime: 1680581150, +/// ctime: 1680581150, +/// mode: 41471, +/// links: 1, +/// major_device: 64, +/// minor_device: 0, +/// inode: 471587, +/// user_id: 1000, +/// group_id: 1000, +/// )) +/// +/// > link_info("/does_not_exist") +/// Error(Enoent) +/// +/// > link_info("/root/.local/maybe_exists") +/// Error(Eacces) +/// ``` +/// +@deprecated("Use the simplifile package instead") +pub fn link_info(a: String) -> Result(FileInfo, Reason) { + do_link_info(a) +} + +@external(erlang, "gleam_erlang_ffi", "link_info") +fn do_link_info(a: String) -> Result(FileInfo, Reason) + +/// Results in a `Bool` on success that indicates whether the given `path` has +/// a `Directory` `FileType`, otherwise a `Reason` for failure. +/// +/// When `path` refers to a symlink, the result pertains to the link's target. +/// +/// ## Examples +/// +/// ```gleam +/// > is_directory("/tmp") +/// Ok(True) +/// +/// > is_directory("resume.pdf") +/// Ok(False) +/// +/// > is_directory("/does_not_exist") +/// Error(Enoent) +/// ``` +/// +@deprecated("Use the simplifile package instead") +pub fn is_directory(path: String) -> Result(Bool, Reason) { + use FileInfo(file_type: file_type, ..) <- result.map(over: do_file_info(path)) + file_type == Directory +} + +/// Results in a `Bool` on success that indicates whether the given `path` has +/// a `Regular` `FileType`, otherwise a `Reason` for failure. +/// +/// When `path` refers to a symlink, the result pertains to the link's target. +/// +/// ## Examples +/// +/// ```gleam +/// > is_regular("resume.pdf") +/// Ok(True) +/// +/// > is_regular("/tmp") +/// Ok(False) +/// +/// > is_regular("/does_not_exist.txt") +/// Error(Enoent) +/// ``` +/// +@deprecated("Use the simplifile package instead") +pub fn is_regular(path: String) -> Result(Bool, Reason) { + use FileInfo(file_type: file_type, ..) <- result.map(over: do_file_info(path)) + file_type == Regular +} + +/// Results in a `Bool` on success that indicates whether the given `path` +/// exists, otherwise a `Reason` for failure. +/// +/// When `path` refers to a symlink, the result pertains to the link's target. +/// To find whether a symlink itself exists, use `link_exists`. +/// +/// ## Examples +/// +/// ```gleam +/// > file_exists("resume.pdf") +/// Ok(True) +/// +/// > file_exists("/tmp") +/// Ok(True) +/// +/// > file_exists("/does_not_exist") +/// Ok(False) +/// +/// > file_exists("/root/.local/maybe_exists") +/// Error(Eacces) +/// ``` +/// +@deprecated("Use the simplifile package instead") +pub fn file_exists(path: String) -> Result(Bool, Reason) { + let result = + path + |> do_file_info + |> result.replace(True) + case result { + Error(Enoent) -> Ok(False) + _ -> result + } +} + +/// Results in a `Bool` on success that indicates whether the given `path` +/// exists, otherwise a `Reason` for failure. +/// +/// When `path` refers to a symlink, the result pertains to the link itself. +/// To find whether a symlink's target exists, use `file_exists`. +/// +/// ## Examples +/// +/// ```gleam +/// > link_exists("resume.pdf") +/// Ok(True) +/// +/// > link_exists("/tmp") +/// Ok(True) +/// +/// > link_exists("/does_not_exist") +/// Ok(False) +/// +/// > link_exists("/root/.local/maybe_exists") +/// Error(Eacces) +/// ``` +/// +@deprecated("Use the simplifile package instead") +pub fn link_exists(path: String) -> Result(Bool, Reason) { + let result = + path + |> do_link_info + |> result.replace(True) + case result { + Error(Enoent) -> Ok(False) + _ -> result + } +} + +/// Tries to create a directory. Missing parent directories are not created. +/// +/// Returns a Result of nil if the directory is created or Reason if the +/// operation failed. +/// +/// ## Examples +/// +/// ```gleam +/// > make_directory("/tmp/foo") +/// Ok(Nil) +/// +/// > make_directory("relative_directory") +/// Ok(Nil) +/// +/// > make_directory("/tmp/missing_intermediate_directory/foo") +/// Error(Enoent) +/// ``` +/// +@deprecated("Use the simplifile package instead") +@external(erlang, "gleam_erlang_ffi", "make_directory") +pub fn make_directory(a: String) -> Result(Nil, Reason) + +/// Lists all files in a directory, except files with +/// [raw filenames](https://www.erlang.org/doc/apps/stdlib/unicode_usage.html#notes-about-raw-filenames). +/// +/// Returns a Result containing the list of filenames in the directory, or Reason +/// if the operation failed. +/// +/// ## Examples +/// +/// ```gleam +/// > list_directory("/tmp") +/// Ok(["FB01293B-8597-4359-80D5-130140A0C0DE","AlTest2.out"]) +/// +/// > list_directory("resume.docx") +/// Error(Enotdir) +/// ``` +/// +@deprecated("Use the simplifile package instead") +@external(erlang, "gleam_erlang_ffi", "list_directory") +pub fn list_directory(a: String) -> Result(List(String), Reason) + +/// Deletes a directory. +/// +/// The directory must be empty before it can be deleted. Returns a nil Success +/// or Reason if the operation failed. +/// +/// ## Examples +/// +/// ```gleam +/// > delete_directory("foo") +/// Ok(Nil) +/// +/// > delete_directory("does_not_exist/") +/// Error(Enoent) +/// ``` +/// +@deprecated("Use the simplifile package instead") +@external(erlang, "gleam_erlang_ffi", "delete_directory") +pub fn delete_directory(a: String) -> Result(Nil, Reason) + +/// Deletes a file or directory recursively. +/// +/// Returns a nil Success or Reason if the operation failed. +/// +/// ## Examples +/// +/// ```gleam +/// > recursive_delete("foo") +/// Ok(Nil) +/// +/// > recursive_delete("/bar") +/// Ok(Nil) +/// +/// > recursive_delete("does_not_exist/") +/// Error(Enoent) +/// ``` +/// +@deprecated("Use the simplifile package instead") +@external(erlang, "gleam_erlang_ffi", "recursive_delete") +pub fn recursive_delete(a: String) -> Result(Nil, Reason) + +/// Read the contents of the given file as a String +/// +/// Assumes the file is UTF-8 encoded. Returns a Result containing the file's +/// contents as a String if the operation was successful, or Reason if the file +/// operation failed. If the file is not UTF-8 encoded, the `NotUTF8` variant +/// will be returned. +/// +/// ## Examples +/// +/// ```gleam +/// > read("example.txt") +/// Ok("Hello, World!") +/// +/// > read(from: "example.txt") +/// Ok("Hello, World!") +/// +/// > read("does_not_exist.txt") +/// Error(Enoent) +/// +/// > read("cat.gif") +/// Error(NotUTF8) +/// ``` +/// +@deprecated("Use the simplifile package instead?") +pub fn read(from path: String) -> Result(String, Reason) { + path + |> do_read_bits() + |> result.then(fn(content) { + case bit_array.to_string(content) { + Ok(string) -> Ok(string) + Error(Nil) -> Error(NotUtf8) + } + }) +} + +/// Read the contents of the given file as a BitString +/// +/// Returns a Result containing the file's contents as a BitString if the +/// operation was successful, or Reason if the operation failed. +/// +/// ## Examples +/// +/// ```gleam +/// > read_bits("example.txt") +/// Ok(<<"Hello, World!">>) +/// +/// > read_bits(from: "cat.gif") +/// Ok(<<71,73,70,56,57,97,1,0,1,0,0,0,0,59>>) +/// +/// > read_bits("does_not_exist.txt") +/// Error(Enoent) +/// ``` +/// +@deprecated("Use the simplifile package instead") +pub fn read_bits(from path: String) -> Result(BitArray, Reason) { + do_read_bits(path) +} + +@external(erlang, "gleam_erlang_ffi", "read_file") +fn do_read_bits(a: path) -> Result(BitArray, Reason) + +/// Write the given String contents to a file of the given name. +/// +/// Returns a Result with Nil if the operation was successful or a Reason +/// otherwise. +/// +/// ## Examples +/// +/// ```gleam +/// > write("Hello, World!", "file.txt") +/// Ok(Nil) +/// +/// > write(to: "file.txt", contents: "Hello, World!") +/// Ok(Nil) +/// +/// > write("Hello, World!", "does_not_exist/file.txt") +/// Error(Enoent) +/// ``` +/// +@deprecated("Use the simplifile package instead") +pub fn write(contents contents: String, to path: String) -> Result(Nil, Reason) { + contents + |> bit_array.from_string + |> do_write_bits(path) +} + +/// Write the given BitString contents to a file of the given name. +/// +/// Returns a Result with Nil if the operation was successful or a Reason +/// otherwise. +/// +/// ## Examples +/// +/// ```gleam +/// > write_bits(<<71,73,70,56,57,97,1,0,1,0,0,0,0,59>>, "cat.gif") +/// Ok(Nil) +/// +/// > write_bits(to: "cat.gif", contents: <<71,73,70,56,57,97,1,0,1,0,0,0,0,59>>) +/// Ok(Nil) +/// +/// > write_bits(<<71,73,70,56,57,97,1,0,1,0,0,0,0,59>>, "does_not_exist/cat.gif") +/// Error(Enoent) +/// ``` +/// +@deprecated("Use the simplifile package instead") +pub fn write_bits( + contents contents: BitArray, + to path: String, +) -> Result(Nil, Reason) { + do_write_bits(contents, path) +} + +@external(erlang, "gleam_erlang_ffi", "write_file") +fn do_write_bits(a: BitArray, b: String) -> Result(Nil, Reason) + +/// Append the given String contents to a file of the given name. +/// +/// Returns a Result with Nil if the operation was successful or a Reason +/// otherwise. +/// +/// ## Examples +/// +/// ```gleam +/// > append("Hello, World!", "file.txt") +/// Ok(Nil) +/// +/// > append(to: "file.txt", contents: "Hello, World!") +/// Ok(Nil) +/// +/// > append("Hello, World!", "does_not_exist/file.txt") +/// Error(Enoent) +/// ``` +/// +@deprecated("Use the simplifile package instead") +pub fn append(contents contents: String, to path: String) -> Result(Nil, Reason) { + contents + |> bit_array.from_string + |> do_append_bits(path) +} + +/// Append the given BitString contents to a file of the given name. +/// +/// Returns a Result with Nil if the operation was successful or a Reason +/// otherwise. +/// +/// ## Examples +/// +/// ```gleam +/// > append_bits(<<71,73,70,56,57,97,1,0,1,0,0,0,0,59>>, "cat.gif") +/// Ok(Nil) +/// +/// > append_bits(to: "cat.gif", contents: <<71,73,70,56,57,97,1,0,1,0,0,0,0,59>>) +/// Ok(Nil) +/// +/// > append_bits(<<71,73,70,56,57,97,1,0,1,0,0,0,0,59>>, "does_not_exist/cat.gif") +/// Error(Enoent) +/// ``` +/// +pub fn append_bits( + contents contents: BitArray, + to path: String, +) -> Result(Nil, Reason) { + do_append_bits(contents, path) +} + +@external(erlang, "gleam_erlang_ffi", "append_file") +fn do_append_bits( + contents contents: BitArray, + path path: String, +) -> Result(Nil, Reason) + +/// Delete the given file. +/// +/// Returns a Result with Nil if the operation was successful or a Reason +/// otherwise. +/// +/// ## Examples +/// +/// ```gleam +/// > delete("file.txt") +/// Ok(Nil) +/// +/// > delete("does_not_exist.txt") +/// Error(Enoent) +/// ``` +/// +@deprecated("Use the simplifile package instead") +@external(erlang, "gleam_erlang_ffi", "delete_file") +pub fn delete(a: String) -> Result(Nil, Reason) diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/node.gleam b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/node.gleam new file mode 100644 index 0000000..339415c --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/node.gleam @@ -0,0 +1,62 @@ +import gleam/erlang/atom.{type Atom} + +pub type Node + +type DoNotLeak + +/// Return the current node. +/// +@external(erlang, "erlang", "node") +pub fn self() -> Node + +/// Return a list of all visible nodes in the cluster, not including the current +/// node. +/// +/// The current node can be included by calling `self()` and prepending the +/// result. +/// +/// ```gleam +/// let all_nodes = [node.self(), ..node.visible()] +/// ``` +/// +@external(erlang, "erlang", "nodes") +pub fn visible() -> List(Node) + +pub type ConnectError { + /// Was unable to connect to the node. + FailedToConnect + /// The local node is not alive, so it is not possible to connect to the other + /// node. + LocalNodeIsNotAlive +} + +// TODO: test unknown node +// TODO: test successfully connecting +/// Establish a connection to a node, so the nodes can send messages to each +/// other and any other connected nodes. +/// +/// Returns `Error(FailedToConnect)` if the node is not reachable. +/// +/// Returns `Error(LocalNodeIsNotAlive)` if the local node is not alive, meaning +/// it is not running in distributed mode. +/// +@external(erlang, "gleam_erlang_ffi", "connect_node") +pub fn connect(node: Atom) -> Result(Node, ConnectError) + +// TODO: test +/// Send a message to a named process on a given node. +/// +/// These messages are untyped, like regular Erlang messages. +/// +pub fn send(node: Node, name: Atom, message: message) -> Nil { + raw_send(#(name, node), message) + Nil +} + +@external(erlang, "erlang", "send") +fn raw_send(receiver: #(Atom, Node), message: message) -> DoNotLeak + +/// Convert a node to the atom of its name. +/// +@external(erlang, "gleam_erlang_ffi", "identity") +pub fn to_atom(node: Node) -> Atom diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/os.gleam b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/os.gleam new file mode 100644 index 0000000..e135974 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/os.gleam @@ -0,0 +1,95 @@ +//// Access to the shell's environment variables + +import gleam/map.{type Map} + +/// Returns the list of all available environment variables as a list of key, +/// tuples. +/// +/// ## Examples +/// +/// > get_all_env() +/// map.from_list([ +/// #("SHELL", "/bin/bash"), +/// #("PWD", "/home/j3rn"), +/// ... +/// ]) +/// +@external(erlang, "gleam_erlang_ffi", "get_all_env") +pub fn get_all_env() -> Map(String, String) + +/// Returns the value associated with the given environment variable name. +/// +/// ## Examples +/// +/// > get_env("SHELL") +/// "/bin/bash" +/// +/// > get_env(name: "PWD") +/// "/home/j3rn" +/// +@external(erlang, "gleam_erlang_ffi", "get_env") +pub fn get_env(name name: String) -> Result(String, Nil) + +/// Associates the given value with the given environment variable name. +/// +/// ## Examples +/// +/// > set_env("MYVAR", "MYVALUE") +/// Nil +/// > get_env("MYVAR") +/// "MYVALUE" +/// +/// > set_env(value: "MYVALUE", name: "MYVAR") +/// Nil +/// +@external(erlang, "gleam_erlang_ffi", "set_env") +pub fn set_env(name name: String, value value: String) -> Nil + +/// Removes the environment variable with the given name. +/// +/// Returns Nil regardless of whether the variable ever existed. +/// +/// ## Examples +/// +/// > get_env("MYVAR") +/// Ok("MYVALUE") +/// > unset_env("MYVAR") +/// Nil +/// > get_env("MYVAR") +/// Error(Nil) +/// +/// > unset_env(name: "MYVAR") +/// Nil +/// +@external(erlang, "gleam_erlang_ffi", "unset_env") +pub fn unset_env(name name: String) -> Nil + +/// Represents operating system kernels +pub type OsFamily { + // The family which includes modern versions of the Windows operating system. + WindowsNt + // The family of operating systems based on the open source Linux kernel. + Linux + // The family of Apple operating systems such as macOS and iOS. + Darwin + // The family of operating systems based on the FreeBSD kernel. + FreeBsd + // An operating system kernel other than Linux, Darwin, FreeBSD, or NT. + Other(String) +} + +/// Returns the kernel of the host operating system. +/// +/// Unknown kernels are reported as `Other(String)`; e.g. `Other("sunos")`. +/// +/// ## Examples +/// +/// > family() +/// Linux +/// > family() +/// Darwin +/// > family() +/// Other("sunos") +/// +@external(erlang, "gleam_erlang_ffi", "os_family") +pub fn family() -> OsFamily diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/process.gleam b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/process.gleam new file mode 100644 index 0000000..f660306 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam/erlang/process.gleam @@ -0,0 +1,744 @@ +import gleam/string +import gleam/dynamic.{type Dynamic} +import gleam/erlang.{type Reference} +import gleam/erlang/atom.{type Atom} + +/// A `Pid` (or Process identifier) is a reference to an Erlang process. Each +/// process has a `Pid` and it is one of the lowest level building blocks of +/// inter-process communication in the Erlang and Gleam OTP frameworks. +/// +pub type Pid + +/// Get the `Pid` for the current process. +@external(erlang, "erlang", "self") +pub fn self() -> Pid + +/// Create a new Erlang process that runs concurrently to the creator. In other +/// languages this might be called a fibre, a green thread, or a coroutine. +/// +/// If `linked` is `True` then the created process is linked to the creator +/// process. When a process terminates an exit signal is sent to all other +/// processes that are linked to it, causing the process to either terminate or +/// have to handle the signal. +/// +/// More can be read about processes and links in the [Erlang documentation][1]. +/// +/// [1]: https://www.erlang.org/doc/reference_manual/processes.html +/// +pub fn start(running implementation: fn() -> anything, linked link: Bool) -> Pid { + case link { + True -> spawn_link(implementation) + False -> spawn(implementation) + } +} + +@external(erlang, "erlang", "spawn") +fn spawn(a: fn() -> anything) -> Pid + +@external(erlang, "erlang", "spawn_link") +fn spawn_link(a: fn() -> anything) -> Pid + +/// A `Subject` is a value that processes can use to send and receive messages +/// to and from each other in a well typed way. +/// +/// Each subject is "owned" by the process that created it. Any process can use +/// the `send` function to sent a message of the correct type to the process +/// that owns the subject, and the owner can use the `receive` function or the +/// `Selector` type to receive these messages. +/// +/// The `Subject` type is similar to the "channel" types found in other +/// languages and the "topic" concept found in some pub-sub systems. +/// +/// # Examples +/// +/// ```gleam +/// let subject = new_subject() +/// +/// // Send a message with the subject +/// send(subject, "Hello, Joe!") +/// +/// // Receive the message +/// receive(subject, within: 10) +/// ``` +/// +pub opaque type Subject(message) { + Subject(owner: Pid, tag: Reference) +} + +/// Create a new `Subject` owned by the current process. +/// +pub fn new_subject() -> Subject(message) { + Subject(owner: self(), tag: erlang.make_reference()) +} + +/// Get the owner process for a `Subject`. This is the process that created the +/// `Subject` and will receive messages sent with it. +/// +pub fn subject_owner(subject: Subject(message)) -> Pid { + subject.owner +} + +type DoNotLeak + +@external(erlang, "erlang", "send") +fn raw_send(a: Pid, b: message) -> DoNotLeak + +/// Send a message to a process using a `Subject`. The message must be of the +/// type that the `Subject` accepts. +/// +/// This function does not wait for the `Subject` owner process to call the +/// `receive` function, instead it returns once the message has been placed in +/// the process' mailbox. +/// +/// # Ordering +/// +/// If process P1 sends two messages to process P2 it is guaranteed that process +/// P1 will receive the messages in the order they were sent. +/// +/// If you wish to receive the messages in a different order you can send them +/// on two different subjects and the receiver function can call the `receive` +/// function for each subject in the desired order, or you can write some Erlang +/// code to perform a selective receive. +/// +/// # Examples +/// +/// ```gleam +/// let subject = new_subject() +/// send(subject, "Hello, Joe!") +/// ``` +/// +pub fn send(subject: Subject(message), message: message) -> Nil { + raw_send(subject.owner, #(subject.tag, message)) + Nil +} + +/// Receive a message that has been sent to current process using the `Subject`. +/// +/// If there is not an existing message for the `Subject` in the process' +/// mailbox or one does not arrive `within` the permitted timeout then the +/// `Error(Nil)` is returned. +/// +/// Only the process that is owner of the `Subject` can receive a message using +/// it. If a process that does not own the `Subject` attempts to receive with it +/// then it will not receive a message. +/// +/// To wait for messages from multiple `Subject`s at the same time see the +/// `Selector` type. +/// +pub fn receive( + from subject: Subject(message), + within milliseconds: Int, +) -> Result(message, Nil) { + new_selector() + |> selecting(subject, fn(x) { x }) + |> select(within: milliseconds) +} + +/// A type that enables a process to wait for messages from multiple `Subject`s +/// at the same time, returning whichever message arrives first. +/// +/// Used with the `new_selector`, `selecting`, and `select` functions. +/// +/// # Examples +/// +/// ```gleam +/// > let int_subject = new_subject() +/// > let float_subject = new_subject() +/// > send(int_subject, 1) +/// > +/// > let selector = +/// > new_selector() +/// > |> selecting(int_subject, int.to_string) +/// > |> selecting(float_subject, float.to_string) +/// > +/// > select(selector, 10) +/// Ok("1") +/// ``` +/// +pub type Selector(payload) + +/// Create a new `Selector` which can be used to receive messages on multiple +/// `Subject`s at once. +/// +@external(erlang, "gleam_erlang_ffi", "new_selector") +pub fn new_selector() -> Selector(payload) + +/// Receive a message that has been sent to current process using any of the +/// `Subject`s that have been added to the `Selector` with the `selecting` +/// function. +/// +/// If there is not an existing message for the `Selector` in the process' +/// mailbox or one does not arrive `within` the permitted timeout then the +/// `Error(Nil)` is returned. +/// +/// Only the process that is owner of the `Subject`s can receive a message using +/// them. If a process that does not own the a `Subject` attempts to receive +/// with it then it will not receive a message. +/// +/// To wait forever for the next message rather than for a limited amount of +/// time see the `select_forever` function. +/// +@external(erlang, "gleam_erlang_ffi", "select") +pub fn select( + from from: Selector(payload), + within within: Int, +) -> Result(payload, Nil) + +/// Similar to the `select` function but will wait forever for a message to +/// arrive rather than timing out after a specified amount of time. +/// +@external(erlang, "gleam_erlang_ffi", "select") +pub fn select_forever(from from: Selector(payload)) -> payload + +/// Add a transformation function to a selector. When a message is received +/// using this selector the transformation function is applied to the message. +/// +/// This function can be used to change the type of messages received and may +/// be useful when combined with the `merge_selector` function. +/// +@external(erlang, "gleam_erlang_ffi", "map_selector") +pub fn map_selector(a: Selector(a), b: fn(a) -> b) -> Selector(b) + +/// Merge one selector into another, producing a selector that contains the +/// message handlers of both. +/// +/// If a subject is handled by both selectors the handler function of the +/// second selector is used. +/// +@external(erlang, "gleam_erlang_ffi", "merge_selector") +pub fn merge_selector(a: Selector(a), b: Selector(a)) -> Selector(a) + +pub type ExitMessage { + ExitMessage(pid: Pid, reason: ExitReason) +} + +pub type ExitReason { + Normal + Killed + Abnormal(reason: String) +} + +/// Add a handler for trapped exit messages. In order for these messages to be +/// sent to the process when a linked process exits the process must call the +/// `trap_exit` beforehand. +/// +pub fn selecting_trapped_exits( + selector: Selector(a), + handler: fn(ExitMessage) -> a, +) -> Selector(a) { + let tag = atom.create_from_string("EXIT") + let handler = fn(message: #(Atom, Pid, Dynamic)) -> a { + let reason = message.2 + let normal = dynamic.from(Normal) + let killed = dynamic.from(Killed) + let reason = case dynamic.string(reason) { + _ if reason == normal -> Normal + _ if reason == killed -> Killed + Ok(reason) -> Abnormal(reason) + Error(_) -> Abnormal(string.inspect(reason)) + } + handler(ExitMessage(message.1, reason)) + } + insert_selector_handler(selector, #(tag, 3), handler) +} + +// TODO: implement in Gleam +/// Discard all messages in the current process' mailbox. +/// +/// Warning: This function may cause other processes to crash if they sent a +/// message to the current process and are waiting for a response, so use with +/// caution. +/// +@external(erlang, "gleam_erlang_ffi", "flush_messages") +pub fn flush_messages() -> Nil + +/// Add a new `Subject` to the `Selector` to that it's messages can be received. +/// +/// The `mapping` function provided with the `Subject` can be used to convert +/// the type of messages received using this `Subject`. This is useful for when +/// you wish to add multiple `Subject`s to a `Seletor` when they have differing +/// message types. If you do not wish to transform the incoming messages in any +/// way then the `identity` function can be given. +/// +pub fn selecting( + selector: Selector(payload), + for subject: Subject(message), + mapping transform: fn(message) -> payload, +) -> Selector(payload) { + let handler = fn(message: #(Reference, message)) { transform(message.1) } + insert_selector_handler(selector, #(subject.tag, 2), handler) +} + +/// Add a handler to a selector for 2 element tuple messages with a given tag +/// element in the first position. +/// +/// Typically you want to use the `selecting` function with a `Subject` instead, +/// but this function may be useful if you need to receive messages sent from +/// other BEAM languages that do not use the `Subject` type. +/// +pub fn selecting_record2( + selector: Selector(payload), + tag: tag, + mapping transform: fn(Dynamic) -> payload, +) -> Selector(payload) { + let handler = fn(message: #(tag, Dynamic)) { transform(message.1) } + insert_selector_handler(selector, #(tag, 2), handler) +} + +/// Add a handler to a selector for 3 element tuple messages with a given tag +/// element in the first position. +/// +/// Typically you want to use the `selecting` function with a `Subject` instead, +/// but this function may be useful if you need to receive messages sent from +/// other BEAM languages that do not use the `Subject` type. +/// +pub fn selecting_record3( + selector: Selector(payload), + tag: tag, + mapping transform: fn(Dynamic, Dynamic) -> payload, +) -> Selector(payload) { + let handler = fn(message: #(tag, Dynamic, Dynamic)) { + transform(message.1, message.2) + } + insert_selector_handler(selector, #(tag, 3), handler) +} + +/// Add a handler to a selector for 4 element tuple messages with a given tag +/// element in the first position. +/// +/// Typically you want to use the `selecting` function with a `Subject` instead, +/// but this function may be useful if you need to receive messages sent from +/// other BEAM languages that do not use the `Subject` type. +/// +pub fn selecting_record4( + selector: Selector(payload), + tag: tag, + mapping transform: fn(Dynamic, Dynamic, Dynamic) -> payload, +) -> Selector(payload) { + let handler = fn(message: #(tag, Dynamic, Dynamic, Dynamic)) { + transform(message.1, message.2, message.3) + } + insert_selector_handler(selector, #(tag, 4), handler) +} + +/// Add a handler to a selector for 5 element tuple messages with a given tag +/// element in the first position. +/// +/// Typically you want to use the `selecting` function with a `Subject` instead, +/// but this function may be useful if you need to receive messages sent from +/// other BEAM languages that do not use the `Subject` type. +/// +pub fn selecting_record5( + selector: Selector(payload), + tag: tag, + mapping transform: fn(Dynamic, Dynamic, Dynamic, Dynamic) -> payload, +) -> Selector(payload) { + let handler = fn(message: #(tag, Dynamic, Dynamic, Dynamic, Dynamic)) { + transform(message.1, message.2, message.3, message.4) + } + insert_selector_handler(selector, #(tag, 5), handler) +} + +/// Add a handler to a selector for 6 element tuple messages with a given tag +/// element in the first position. +/// +/// Typically you want to use the `selecting` function with a `Subject` instead, +/// but this function may be useful if you need to receive messages sent from +/// other BEAM languages that do not use the `Subject` type. +/// +pub fn selecting_record6( + selector: Selector(payload), + tag: tag, + mapping transform: fn(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic) -> payload, +) -> Selector(payload) { + let handler = fn(message: #(tag, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic)) { + transform(message.1, message.2, message.3, message.4, message.5) + } + insert_selector_handler(selector, #(tag, 6), handler) +} + +/// Add a handler to a selector for 7 element tuple messages with a given tag +/// element in the first position. +/// +/// Typically you want to use the `selecting` function with a `Subject` instead, +/// but this function may be useful if you need to receive messages sent from +/// other BEAM languages that do not use the `Subject` type. +/// +pub fn selecting_record7( + selector: Selector(payload), + tag: tag, + mapping transform: fn(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic) -> + payload, +) -> Selector(payload) { + let handler = fn( + message: #(tag, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), + ) { + transform(message.1, message.2, message.3, message.4, message.5, message.6) + } + insert_selector_handler(selector, #(tag, 7), handler) +} + +/// Add a handler to a selector for 8 element tuple messages with a given tag +/// element in the first position. +/// +/// Typically you want to use the `selecting` function with a `Subject` instead, +/// but this function may be useful if you need to receive messages sent from +/// other BEAM languages that do not use the `Subject` type. +/// +pub fn selecting_record8( + selector: Selector(payload), + tag: tag, + mapping transform: fn( + Dynamic, + Dynamic, + Dynamic, + Dynamic, + Dynamic, + Dynamic, + Dynamic, + ) -> + payload, +) -> Selector(payload) { + let handler = fn( + message: #( + tag, + Dynamic, + Dynamic, + Dynamic, + Dynamic, + Dynamic, + Dynamic, + Dynamic, + ), + ) { + transform( + message.1, + message.2, + message.3, + message.4, + message.5, + message.6, + message.7, + ) + } + insert_selector_handler(selector, #(tag, 8), handler) +} + +type AnythingSelectorTag { + Anything +} + +/// Add a catch-all handler to a selector that will be used when no other +/// handler in a selector is suitable for a given message. +/// +/// This may be useful for when you want to ensure that any message in the inbox +/// is handled, or when you need to handle messages from other BEAM languages +/// which do not use subjects or record format messages. +/// +pub fn selecting_anything( + selector: Selector(payload), + mapping handler: fn(Dynamic) -> payload, +) -> Selector(payload) { + insert_selector_handler(selector, Anything, handler) +} + +@external(erlang, "gleam_erlang_ffi", "insert_selector_handler") +fn insert_selector_handler( + a: Selector(payload), + for for: tag, + mapping mapping: fn(message) -> payload, +) -> Selector(payload) + +/// Suspends the process calling this function for the specified number of +/// milliseconds. +/// +@external(erlang, "gleam_erlang_ffi", "sleep") +pub fn sleep(a: Int) -> Nil + +/// Suspends the process forever! This may be useful for suspending the main +/// process in a Gleam program when it has no more work to do but we want other +/// processes to continue to work. +/// +@external(erlang, "gleam_erlang_ffi", "sleep_forever") +pub fn sleep_forever() -> Nil + +/// Check to see whether the process for a given `Pid` is alive. +/// +/// See the [Erlang documentation][1] for more information. +/// +/// [1]: http://erlang.org/doc/man/erlang.html#is_process_alive-1 +/// +@external(erlang, "erlang", "is_process_alive") +pub fn is_alive(a: Pid) -> Bool + +type ProcessMonitorFlag { + Process +} + +@external(erlang, "erlang", "monitor") +fn erlang_monitor_process(a: ProcessMonitorFlag, b: Pid) -> Reference + +pub opaque type ProcessMonitor { + ProcessMonitor(tag: Reference) +} + +/// A message received when a monitored process exits. +/// +pub type ProcessDown { + ProcessDown(pid: Pid, reason: Dynamic) +} + +/// Start monitoring a process so that when the monitored process exits a +/// message is sent to the monitoring process. +/// +/// The message is only sent once, when the target process exits. If the +/// process was not alive when this function is called the message will never +/// be received. +/// +/// The down message can be received with a `Selector` and the +/// `selecting_process_down` function. +/// +/// The process can be demonitored with the `demonitor_process` function. +/// +pub fn monitor_process(pid: Pid) -> ProcessMonitor { + Process + |> erlang_monitor_process(pid) + |> ProcessMonitor +} + +/// Add a `ProcessMonitor` to a `Selector` so that the `ProcessDown` message can +/// be received using the `Selector` and the `select` function. +/// +pub fn selecting_process_down( + selector: Selector(payload), + monitor: ProcessMonitor, + mapping: fn(ProcessDown) -> payload, +) -> Selector(payload) { + insert_selector_handler(selector, monitor.tag, mapping) +} + +/// Remove the monitor for a process so that when the monitor process exits a +/// `ProcessDown` message is not sent to the monitoring process. +/// +/// If the message has already been sent it is removed from the monitoring +/// process' mailbox. +/// +@external(erlang, "gleam_erlang_ffi", "demonitor") +pub fn demonitor_process(monitor monitor: ProcessMonitor) -> Nil + +/// An error returned when making a call to a process. +/// +pub type CallError(msg) { + /// The process being called exited before it sent a response. + /// + CalleeDown(reason: Dynamic) + + /// The process being called did not response within the permitted amount of + /// time. + /// + CallTimeout +} + +// This function is based off of Erlang's gen:do_call/4. +/// Send a message to a process and wait for a reply. +/// +/// If the receiving process exits or does not reply within the allowed amount +/// of time then an error is returned. +/// +pub fn try_call( + subject: Subject(request), + make_request: fn(Subject(response)) -> request, + within timeout: Int, +) -> Result(response, CallError(response)) { + let reply_subject = new_subject() + + // Monitor the callee process so we can tell if it goes down (meaning we + // won't get a reply) + let monitor = monitor_process(subject_owner(subject)) + + // Send the request to the process over the channel + send(subject, make_request(reply_subject)) + + // Await a reply or handle failure modes (timeout, process down, etc) + let result = + new_selector() + |> selecting(reply_subject, Ok) + |> selecting_process_down( + monitor, + fn(down: ProcessDown) { Error(CalleeDown(reason: down.reason)) }, + ) + |> select(timeout) + + // Demonitor the process and close the channels as we're done + demonitor_process(monitor) + + // Prepare an appropriate error (if present) for the caller + case result { + Error(Nil) -> Error(CallTimeout) + Ok(res) -> res + } +} + +/// Send a message to a process and wait for a reply. +/// +/// If the receiving process exits or does not reply within the allowed amount +/// of time the calling process crashes. If you wish an error to be returned +/// instead see the `try_call` function. +/// +pub fn call( + subject: Subject(request), + make_request: fn(Subject(response)) -> request, + within timeout: Int, +) -> response { + let assert Ok(resp) = try_call(subject, make_request, timeout) + resp +} + +/// Creates a link between the calling process and another process. +/// +/// When a process crashes any linked processes will also crash. This is useful +/// to ensure that groups of processes that depend on each other all either +/// succeed or fail together. +/// +/// Returns `True` if the link was created successfully, returns `False` if the +/// process was not alive and as such could not be linked. +/// +@external(erlang, "gleam_erlang_ffi", "link") +pub fn link(pid pid: Pid) -> Bool + +@external(erlang, "erlang", "unlink") +fn erlang_unlink(pid pid: Pid) -> Bool + +/// Removes any existing link between the caller process and the target process. +/// +pub fn unlink(pid: Pid) -> Nil { + erlang_unlink(pid) + Nil +} + +pub type Timer + +@external(erlang, "erlang", "send_after") +fn erlang_send_after(a: Int, b: Pid, c: msg) -> Timer + +/// Send a message over a channel after a specified number of milliseconds. +/// +pub fn send_after(subject: Subject(msg), delay: Int, message: msg) -> Timer { + erlang_send_after(delay, subject.owner, #(subject.tag, message)) +} + +@external(erlang, "erlang", "cancel_timer") +fn erlang_cancel_timer(a: Timer) -> Dynamic + +/// Values returned when a timer is cancelled. +/// +pub type Cancelled { + /// The timer could not be found. It likely has already triggered. + /// + TimerNotFound + + /// The timer was found and cancelled before it triggered. + /// + /// The amount of remaining time before the timer was due to be triggered is + /// returned in milliseconds. + /// + Cancelled(time_remaining: Int) +} + +/// Cancel a given timer, causing it not to trigger if it has not done already. +/// +pub fn cancel_timer(timer: Timer) -> Cancelled { + case dynamic.int(erlang_cancel_timer(timer)) { + Ok(i) -> Cancelled(i) + Error(_) -> TimerNotFound + } +} + +type KillFlag { + Kill +} + +@external(erlang, "erlang", "exit") +fn erlang_kill(to to: Pid, because because: KillFlag) -> Bool + +// Go, my pretties. Kill! Kill! +// - Bart Simpson +// +/// Send an untrappable `kill` exit signal to the target process. +/// +/// See the documentation for the Erlang [`erlang:exit`][1] function for more +/// information. +/// +/// [1]: https://erlang.org/doc/man/erlang.html#exit-1 +/// +pub fn kill(pid: Pid) -> Nil { + erlang_kill(pid, Kill) + Nil +} + +@external(erlang, "erlang", "exit") +fn erlang_send_exit(to to: Pid, because because: whatever) -> Bool + +// TODO: test +/// Sends an exit signal to a process, indicating that the process is to shut +/// down. +/// +/// See the [Erlang documentation][erl] for more information. +/// [erl]: http://erlang.org/doc/man/erlang.html#exit-2 +/// +pub fn send_exit(to pid: Pid) -> Nil { + erlang_send_exit(pid, Normal) + Nil +} + +/// Sends an exit signal to a process, indicating that the process is to shut +/// down due to an abnormal reason such as a failure. +/// +/// See the [Erlang documentation][erl] for more information. +/// [erl]: http://erlang.org/doc/man/erlang.html#exit-2 +/// +pub fn send_abnormal_exit(pid: Pid, reason: String) -> Nil { + erlang_send_exit(pid, Abnormal(reason)) + Nil +} + +/// Set whether the current process is to trap exit signals or not. +/// +/// When not trapping exits if a linked process crashes the exit signal +/// propagates to the process which will also crash. +/// This is the normal behaviour before this function is called. +/// +/// When trapping exits (after this function is called) if a linked process +/// crashes an exit message is sent to the process instead. These messages can +/// be handled with the `selecting_trapped_exits` function. +/// +@external(erlang, "gleam_erlang_ffi", "trap_exits") +pub fn trap_exits(a: Bool) -> Nil + +/// Register a process under a given name, allowing it to be looked up using +/// the `named` function. +/// +/// This function will return an error under the following conditions: +/// - The process for the pid no longer exists. +/// - The name has already been registered. +/// - The process already has a name. +/// - The name is the atom `undefined`, which is reserved by Erlang. +/// +@external(erlang, "gleam_erlang_ffi", "register_process") +pub fn register(pid: Pid, name: Atom) -> Result(Nil, Nil) + +/// Un-register a process name, after which the process can no longer be looked +/// up by that name, and both the name and the process can be re-used in other +/// registrations. +/// +/// It is possible to un-register process that are not from your application, +/// including those from Erlang/OTP itself. This is not recommended and will +/// likely result in undesirable behaviour and crashes. +/// +@external(erlang, "gleam_erlang_ffi", "unregister_process") +pub fn unregister(name: Atom) -> Result(Nil, Nil) + +/// Look up a process by name, returning the pid if it exists. +/// +@external(erlang, "gleam_erlang_ffi", "process_named") +pub fn named(name: Atom) -> Result(Pid, Nil) diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam@erlang.erl b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang.erl new file mode 100644 index 0000000..14a5538 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang.erl @@ -0,0 +1,90 @@ +-module(gleam@erlang). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([format/1, term_to_binary/1, get_line/1, system_time/1, erlang_timestamp/0, rescue/1, binary_to_term/1, unsafe_binary_to_term/1, start_arguments/0, ensure_all_started/1, make_reference/0, priv_directory/1]). +-export_type([safe/0, get_line_error/0, time_unit/0, crash/0, ensure_all_started_error/0, reference_/0]). + +-type safe() :: safe. + +-type get_line_error() :: eof | no_data. + +-type time_unit() :: second | millisecond | microsecond | nanosecond. + +-type crash() :: {exited, gleam@dynamic:dynamic_()} | + {thrown, gleam@dynamic:dynamic_()} | + {errored, gleam@dynamic:dynamic_()}. + +-type ensure_all_started_error() :: {unknown_application, + gleam@erlang@atom:atom_()} | + {application_failed_to_start, + gleam@erlang@atom:atom_(), + gleam@dynamic:dynamic_()}. + +-type reference_() :: any(). + +-spec format(any()) -> binary(). +format(Term) -> + unicode:characters_to_binary(io_lib:format(<<"~p"/utf8>>, [Term])). + +-spec term_to_binary(any()) -> bitstring(). +term_to_binary(A) -> + erlang:term_to_binary(A). + +-spec get_line(binary()) -> {ok, binary()} | {error, get_line_error()}. +get_line(Prompt) -> + gleam_erlang_ffi:get_line(Prompt). + +-spec system_time(time_unit()) -> integer(). +system_time(A) -> + os:system_time(A). + +-spec erlang_timestamp() -> {integer(), integer(), integer()}. +erlang_timestamp() -> + os:timestamp(). + +-spec rescue(fun(() -> FHH)) -> {ok, FHH} | {error, crash()}. +rescue(A) -> + gleam_erlang_ffi:rescue(A). + +-spec binary_to_term(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | + {error, nil}. +binary_to_term(Binary) -> + case gleam_erlang_ffi:rescue( + fun() -> erlang:binary_to_term(Binary, [safe]) end + ) of + {ok, Term} -> + {ok, Term}; + + {error, _} -> + {error, nil} + end. + +-spec unsafe_binary_to_term(bitstring()) -> {ok, gleam@dynamic:dynamic_()} | + {error, nil}. +unsafe_binary_to_term(Binary) -> + case gleam_erlang_ffi:rescue(fun() -> erlang:binary_to_term(Binary, []) end) of + {ok, Term} -> + {ok, Term}; + + {error, _} -> + {error, nil} + end. + +-spec start_arguments() -> list(binary()). +start_arguments() -> + _pipe = init:get_plain_arguments(), + gleam@list:map(_pipe, fun unicode:characters_to_binary/1). + +-spec ensure_all_started(gleam@erlang@atom:atom_()) -> {ok, + list(gleam@erlang@atom:atom_())} | + {error, ensure_all_started_error()}. +ensure_all_started(Application) -> + gleam_erlang_ffi:ensure_all_started(Application). + +-spec make_reference() -> reference_(). +make_reference() -> + erlang:make_ref(). + +-spec priv_directory(binary()) -> {ok, binary()} | {error, nil}. +priv_directory(Name) -> + gleam_erlang_ffi:priv_directory(Name). diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@atom.erl b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@atom.erl new file mode 100644 index 0000000..e9ad530 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@atom.erl @@ -0,0 +1,26 @@ +-module(gleam@erlang@atom). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([from_string/1, create_from_string/1, to_string/1, from_dynamic/1]). +-export_type([atom_/0, from_string_error/0]). + +-type atom_() :: any(). + +-type from_string_error() :: atom_not_loaded. + +-spec from_string(binary()) -> {ok, atom_()} | {error, from_string_error()}. +from_string(A) -> + gleam_erlang_ffi:atom_from_string(A). + +-spec create_from_string(binary()) -> atom_(). +create_from_string(A) -> + erlang:binary_to_atom(A). + +-spec to_string(atom_()) -> binary(). +to_string(A) -> + erlang:atom_to_binary(A). + +-spec from_dynamic(gleam@dynamic:dynamic_()) -> {ok, atom_()} | + {error, list(gleam@dynamic:decode_error())}. +from_dynamic(From) -> + gleam_erlang_ffi:atom_from_dynamic(From). diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@charlist.erl b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@charlist.erl new file mode 100644 index 0000000..9f9c0fa --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@charlist.erl @@ -0,0 +1,15 @@ +-module(gleam@erlang@charlist). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([to_string/1, from_string/1]). +-export_type([charlist/0]). + +-type charlist() :: any(). + +-spec to_string(charlist()) -> binary(). +to_string(A) -> + unicode:characters_to_binary(A). + +-spec from_string(binary()) -> charlist(). +from_string(A) -> + unicode:characters_to_list(A). diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@file.erl b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@file.erl new file mode 100644 index 0000000..1fe6628 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@file.erl @@ -0,0 +1,190 @@ +-module(gleam@erlang@file). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([file_info/1, link_info/1, is_directory/1, is_regular/1, file_exists/1, link_exists/1, make_directory/1, list_directory/1, delete_directory/1, recursive_delete/1, read/1, read_bits/1, write/2, write_bits/2, append/2, append_bits/2, delete/1]). +-export_type([reason/0, file_type/0, access/0, file_info/0]). + +-type reason() :: eacces | + eagain | + ebadf | + ebadmsg | + ebusy | + edeadlk | + edeadlock | + edquot | + eexist | + efault | + efbig | + eftype | + eintr | + einval | + eio | + eisdir | + eloop | + emfile | + emlink | + emultihop | + enametoolong | + enfile | + enobufs | + enodev | + enolck | + enolink | + enoent | + enomem | + enospc | + enosr | + enostr | + enosys | + enotblk | + enotdir | + enotsup | + enxio | + eopnotsupp | + eoverflow | + eperm | + epipe | + erange | + erofs | + espipe | + esrch | + estale | + etxtbsy | + exdev | + not_utf8. + +-type file_type() :: device | directory | other | regular | symlink. + +-type access() :: no_access | read | read_write | write. + +-type file_info() :: {file_info, + integer(), + file_type(), + access(), + integer(), + integer(), + integer(), + integer(), + integer(), + integer(), + integer(), + integer(), + integer(), + integer()}. + +-spec file_info(binary()) -> {ok, file_info()} | {error, reason()}. +file_info(A) -> + gleam_erlang_ffi:file_info(A). + +-spec link_info(binary()) -> {ok, file_info()} | {error, reason()}. +link_info(A) -> + gleam_erlang_ffi:link_info(A). + +-spec is_directory(binary()) -> {ok, boolean()} | {error, reason()}. +is_directory(Path) -> + gleam@result:map( + gleam_erlang_ffi:file_info(Path), + fun(_use0) -> + {file_info, _, File_type, _, _, _, _, _, _, _, _, _, _, _} = _use0, + File_type =:= directory + end + ). + +-spec is_regular(binary()) -> {ok, boolean()} | {error, reason()}. +is_regular(Path) -> + gleam@result:map( + gleam_erlang_ffi:file_info(Path), + fun(_use0) -> + {file_info, _, File_type, _, _, _, _, _, _, _, _, _, _, _} = _use0, + File_type =:= regular + end + ). + +-spec file_exists(binary()) -> {ok, boolean()} | {error, reason()}. +file_exists(Path) -> + Result = begin + _pipe = Path, + _pipe@1 = gleam_erlang_ffi:file_info(_pipe), + gleam@result:replace(_pipe@1, true) + end, + case Result of + {error, enoent} -> + {ok, false}; + + _ -> + Result + end. + +-spec link_exists(binary()) -> {ok, boolean()} | {error, reason()}. +link_exists(Path) -> + Result = begin + _pipe = Path, + _pipe@1 = gleam_erlang_ffi:link_info(_pipe), + gleam@result:replace(_pipe@1, true) + end, + case Result of + {error, enoent} -> + {ok, false}; + + _ -> + Result + end. + +-spec make_directory(binary()) -> {ok, nil} | {error, reason()}. +make_directory(A) -> + gleam_erlang_ffi:make_directory(A). + +-spec list_directory(binary()) -> {ok, list(binary())} | {error, reason()}. +list_directory(A) -> + gleam_erlang_ffi:list_directory(A). + +-spec delete_directory(binary()) -> {ok, nil} | {error, reason()}. +delete_directory(A) -> + gleam_erlang_ffi:delete_directory(A). + +-spec recursive_delete(binary()) -> {ok, nil} | {error, reason()}. +recursive_delete(A) -> + gleam_erlang_ffi:recursive_delete(A). + +-spec read(binary()) -> {ok, binary()} | {error, reason()}. +read(Path) -> + _pipe = Path, + _pipe@1 = gleam_erlang_ffi:read_file(_pipe), + gleam@result:then( + _pipe@1, + fun(Content) -> case gleam@bit_array:to_string(Content) of + {ok, String} -> + {ok, String}; + + {error, nil} -> + {error, not_utf8} + end end + ). + +-spec read_bits(binary()) -> {ok, bitstring()} | {error, reason()}. +read_bits(Path) -> + gleam_erlang_ffi:read_file(Path). + +-spec write(binary(), binary()) -> {ok, nil} | {error, reason()}. +write(Contents, Path) -> + _pipe = Contents, + _pipe@1 = gleam_stdlib:identity(_pipe), + gleam_erlang_ffi:write_file(_pipe@1, Path). + +-spec write_bits(bitstring(), binary()) -> {ok, nil} | {error, reason()}. +write_bits(Contents, Path) -> + gleam_erlang_ffi:write_file(Contents, Path). + +-spec append(binary(), binary()) -> {ok, nil} | {error, reason()}. +append(Contents, Path) -> + _pipe = Contents, + _pipe@1 = gleam_stdlib:identity(_pipe), + gleam_erlang_ffi:append_file(_pipe@1, Path). + +-spec append_bits(bitstring(), binary()) -> {ok, nil} | {error, reason()}. +append_bits(Contents, Path) -> + gleam_erlang_ffi:append_file(Contents, Path). + +-spec delete(binary()) -> {ok, nil} | {error, reason()}. +delete(A) -> + gleam_erlang_ffi:delete_file(A). diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@node.erl b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@node.erl new file mode 100644 index 0000000..f57d029 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@node.erl @@ -0,0 +1,33 @@ +-module(gleam@erlang@node). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([self/0, visible/0, connect/1, send/3, to_atom/1]). +-export_type([node_/0, do_not_leak/0, connect_error/0]). + +-type node_() :: any(). + +-type do_not_leak() :: any(). + +-type connect_error() :: failed_to_connect | local_node_is_not_alive. + +-spec self() -> node_(). +self() -> + erlang:node(). + +-spec visible() -> list(node_()). +visible() -> + erlang:nodes(). + +-spec connect(gleam@erlang@atom:atom_()) -> {ok, node_()} | + {error, connect_error()}. +connect(Node) -> + gleam_erlang_ffi:connect_node(Node). + +-spec send(node_(), gleam@erlang@atom:atom_(), any()) -> nil. +send(Node, Name, Message) -> + erlang:send({Name, Node}, Message), + nil. + +-spec to_atom(node_()) -> gleam@erlang@atom:atom_(). +to_atom(Node) -> + gleam_erlang_ffi:identity(Node). diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@os.erl b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@os.erl new file mode 100644 index 0000000..6604255 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@os.erl @@ -0,0 +1,27 @@ +-module(gleam@erlang@os). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([get_all_env/0, get_env/1, set_env/2, unset_env/1, family/0]). +-export_type([os_family/0]). + +-type os_family() :: windows_nt | linux | darwin | free_bsd | {other, binary()}. + +-spec get_all_env() -> gleam@map:map_(binary(), binary()). +get_all_env() -> + gleam_erlang_ffi:get_all_env(). + +-spec get_env(binary()) -> {ok, binary()} | {error, nil}. +get_env(Name) -> + gleam_erlang_ffi:get_env(Name). + +-spec set_env(binary(), binary()) -> nil. +set_env(Name, Value) -> + gleam_erlang_ffi:set_env(Name, Value). + +-spec unset_env(binary()) -> nil. +unset_env(Name) -> + gleam_erlang_ffi:unset_env(Name). + +-spec family() -> os_family(). +family() -> + gleam_erlang_ffi:os_family(). diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@process.erl b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@process.erl new file mode 100644 index 0000000..fc8e0ff --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam@erlang@process.erl @@ -0,0 +1,374 @@ +-module(gleam@erlang@process). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([self/0, start/2, new_subject/0, subject_owner/1, send/2, new_selector/0, select/2, select_forever/1, map_selector/2, merge_selector/2, flush_messages/0, selecting_trapped_exits/2, selecting/3, 'receive'/2, selecting_record2/3, selecting_record3/3, selecting_record4/3, selecting_record5/3, selecting_record6/3, selecting_record7/3, selecting_record8/3, selecting_anything/2, sleep/1, sleep_forever/0, is_alive/1, monitor_process/1, selecting_process_down/3, demonitor_process/1, try_call/3, call/3, link/1, unlink/1, send_after/3, cancel_timer/1, kill/1, send_exit/1, send_abnormal_exit/2, trap_exits/1, register/2, unregister/1, named/1]). +-export_type([pid_/0, subject/1, do_not_leak/0, selector/1, exit_message/0, exit_reason/0, anything_selector_tag/0, process_monitor_flag/0, process_monitor/0, process_down/0, call_error/1, timer/0, cancelled/0, kill_flag/0]). + +-type pid_() :: any(). + +-opaque subject(FJD) :: {subject, pid_(), gleam@erlang:reference_()} | + {gleam_phantom, FJD}. + +-type do_not_leak() :: any(). + +-type selector(FJE) :: any() | {gleam_phantom, FJE}. + +-type exit_message() :: {exit_message, pid_(), exit_reason()}. + +-type exit_reason() :: normal | killed | {abnormal, binary()}. + +-type anything_selector_tag() :: anything. + +-type process_monitor_flag() :: process. + +-opaque process_monitor() :: {process_monitor, gleam@erlang:reference_()}. + +-type process_down() :: {process_down, pid_(), gleam@dynamic:dynamic_()}. + +-type call_error(FJF) :: {callee_down, gleam@dynamic:dynamic_()} | + call_timeout | + {gleam_phantom, FJF}. + +-type timer() :: any(). + +-type cancelled() :: timer_not_found | {cancelled, integer()}. + +-type kill_flag() :: kill. + +-spec self() -> pid_(). +self() -> + erlang:self(). + +-spec start(fun(() -> any()), boolean()) -> pid_(). +start(Implementation, Link) -> + case Link of + true -> + erlang:spawn_link(Implementation); + + false -> + erlang:spawn(Implementation) + end. + +-spec new_subject() -> subject(any()). +new_subject() -> + {subject, erlang:self(), erlang:make_ref()}. + +-spec subject_owner(subject(any())) -> pid_(). +subject_owner(Subject) -> + erlang:element(2, Subject). + +-spec send(subject(FJO), FJO) -> nil. +send(Subject, Message) -> + erlang:send( + erlang:element(2, Subject), + {erlang:element(3, Subject), Message} + ), + nil. + +-spec new_selector() -> selector(any()). +new_selector() -> + gleam_erlang_ffi:new_selector(). + +-spec select(selector(FJW), integer()) -> {ok, FJW} | {error, nil}. +select(From, Within) -> + gleam_erlang_ffi:select(From, Within). + +-spec select_forever(selector(FKA)) -> FKA. +select_forever(From) -> + gleam_erlang_ffi:select(From). + +-spec map_selector(selector(FKC), fun((FKC) -> FKE)) -> selector(FKE). +map_selector(A, B) -> + gleam_erlang_ffi:map_selector(A, B). + +-spec merge_selector(selector(FKG), selector(FKG)) -> selector(FKG). +merge_selector(A, B) -> + gleam_erlang_ffi:merge_selector(A, B). + +-spec flush_messages() -> nil. +flush_messages() -> + gleam_erlang_ffi:flush_messages(). + +-spec selecting_trapped_exits(selector(FKK), fun((exit_message()) -> FKK)) -> selector(FKK). +selecting_trapped_exits(Selector, Handler) -> + Tag = erlang:binary_to_atom(<<"EXIT"/utf8>>), + Handler@1 = fun(Message) -> + Reason = erlang:element(3, Message), + Normal = gleam@dynamic:from(normal), + Killed = gleam@dynamic:from(killed), + Reason@2 = case gleam@dynamic:string(Reason) of + _ when Reason =:= Normal -> + normal; + + _ when Reason =:= Killed -> + killed; + + {ok, Reason@1} -> + {abnormal, Reason@1}; + + {error, _} -> + {abnormal, gleam@string:inspect(Reason)} + end, + Handler({exit_message, erlang:element(2, Message), Reason@2}) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 3}, Handler@1). + +-spec selecting(selector(FKN), subject(FKP), fun((FKP) -> FKN)) -> selector(FKN). +selecting(Selector, Subject, Transform) -> + Handler = fun(Message) -> Transform(erlang:element(2, Message)) end, + gleam_erlang_ffi:insert_selector_handler( + Selector, + {erlang:element(3, Subject), 2}, + Handler + ). + +-spec 'receive'(subject(FJQ), integer()) -> {ok, FJQ} | {error, nil}. +'receive'(Subject, Milliseconds) -> + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = selecting(_pipe, Subject, fun(X) -> X end), + gleam_erlang_ffi:select(_pipe@1, Milliseconds). + +-spec selecting_record2( + selector(FKS), + any(), + fun((gleam@dynamic:dynamic_()) -> FKS) +) -> selector(FKS). +selecting_record2(Selector, Tag, Transform) -> + Handler = fun(Message) -> Transform(erlang:element(2, Message)) end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 2}, Handler). + +-spec selecting_record3( + selector(FKW), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> FKW) +) -> selector(FKW). +selecting_record3(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform(erlang:element(2, Message), erlang:element(3, Message)) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 3}, Handler). + +-spec selecting_record4( + selector(FLA), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> FLA) +) -> selector(FLA). +selecting_record4(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform( + erlang:element(2, Message), + erlang:element(3, Message), + erlang:element(4, Message) + ) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 4}, Handler). + +-spec selecting_record5( + selector(FLE), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> FLE) +) -> selector(FLE). +selecting_record5(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform( + erlang:element(2, Message), + erlang:element(3, Message), + erlang:element(4, Message), + erlang:element(5, Message) + ) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 5}, Handler). + +-spec selecting_record6( + selector(FLI), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> FLI) +) -> selector(FLI). +selecting_record6(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform( + erlang:element(2, Message), + erlang:element(3, Message), + erlang:element(4, Message), + erlang:element(5, Message), + erlang:element(6, Message) + ) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 6}, Handler). + +-spec selecting_record7( + selector(FLM), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> FLM) +) -> selector(FLM). +selecting_record7(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform( + erlang:element(2, Message), + erlang:element(3, Message), + erlang:element(4, Message), + erlang:element(5, Message), + erlang:element(6, Message), + erlang:element(7, Message) + ) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 7}, Handler). + +-spec selecting_record8( + selector(FLQ), + any(), + fun((gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_()) -> FLQ) +) -> selector(FLQ). +selecting_record8(Selector, Tag, Transform) -> + Handler = fun(Message) -> + Transform( + erlang:element(2, Message), + erlang:element(3, Message), + erlang:element(4, Message), + erlang:element(5, Message), + erlang:element(6, Message), + erlang:element(7, Message), + erlang:element(8, Message) + ) + end, + gleam_erlang_ffi:insert_selector_handler(Selector, {Tag, 8}, Handler). + +-spec selecting_anything(selector(FLU), fun((gleam@dynamic:dynamic_()) -> FLU)) -> selector(FLU). +selecting_anything(Selector, Handler) -> + gleam_erlang_ffi:insert_selector_handler(Selector, anything, Handler). + +-spec sleep(integer()) -> nil. +sleep(A) -> + gleam_erlang_ffi:sleep(A). + +-spec sleep_forever() -> nil. +sleep_forever() -> + gleam_erlang_ffi:sleep_forever(). + +-spec is_alive(pid_()) -> boolean(). +is_alive(A) -> + erlang:is_process_alive(A). + +-spec monitor_process(pid_()) -> process_monitor(). +monitor_process(Pid) -> + _pipe = process, + _pipe@1 = erlang:monitor(_pipe, Pid), + {process_monitor, _pipe@1}. + +-spec selecting_process_down( + selector(FMC), + process_monitor(), + fun((process_down()) -> FMC) +) -> selector(FMC). +selecting_process_down(Selector, Monitor, Mapping) -> + gleam_erlang_ffi:insert_selector_handler( + Selector, + erlang:element(2, Monitor), + Mapping + ). + +-spec demonitor_process(process_monitor()) -> nil. +demonitor_process(Monitor) -> + gleam_erlang_ffi:demonitor(Monitor). + +-spec try_call(subject(FMF), fun((subject(FMH)) -> FMF), integer()) -> {ok, FMH} | + {error, call_error(FMH)}. +try_call(Subject, Make_request, Timeout) -> + Reply_subject = new_subject(), + Monitor = monitor_process(subject_owner(Subject)), + send(Subject, Make_request(Reply_subject)), + Result = begin + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = selecting( + _pipe, + Reply_subject, + fun(Field@0) -> {ok, Field@0} end + ), + _pipe@2 = selecting_process_down( + _pipe@1, + Monitor, + fun(Down) -> {error, {callee_down, erlang:element(3, Down)}} end + ), + gleam_erlang_ffi:select(_pipe@2, Timeout) + end, + gleam_erlang_ffi:demonitor(Monitor), + case Result of + {error, nil} -> + {error, call_timeout}; + + {ok, Res} -> + Res + end. + +-spec call(subject(FMM), fun((subject(FMO)) -> FMM), integer()) -> FMO. +call(Subject, Make_request, Timeout) -> + _assert_subject = try_call(Subject, Make_request, Timeout), + {ok, Resp} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam/erlang/process"/utf8>>, + function => <<"call"/utf8>>, + line => 593}) + end, + Resp. + +-spec link(pid_()) -> boolean(). +link(Pid) -> + gleam_erlang_ffi:link(Pid). + +-spec unlink(pid_()) -> nil. +unlink(Pid) -> + erlang:unlink(Pid), + nil. + +-spec send_after(subject(FMR), integer(), FMR) -> timer(). +send_after(Subject, Delay, Message) -> + erlang:send_after( + Delay, + erlang:element(2, Subject), + {erlang:element(3, Subject), Message} + ). + +-spec cancel_timer(timer()) -> cancelled(). +cancel_timer(Timer) -> + case gleam@dynamic:int(erlang:cancel_timer(Timer)) of + {ok, I} -> + {cancelled, I}; + + {error, _} -> + timer_not_found + end. + +-spec kill(pid_()) -> nil. +kill(Pid) -> + erlang:exit(Pid, kill), + nil. + +-spec send_exit(pid_()) -> nil. +send_exit(Pid) -> + erlang:exit(Pid, normal), + nil. + +-spec send_abnormal_exit(pid_(), binary()) -> nil. +send_abnormal_exit(Pid, Reason) -> + erlang:exit(Pid, {abnormal, Reason}), + nil. + +-spec trap_exits(boolean()) -> nil. +trap_exits(A) -> + gleam_erlang_ffi:trap_exits(A). + +-spec register(pid_(), gleam@erlang@atom:atom_()) -> {ok, nil} | {error, nil}. +register(Pid, Name) -> + gleam_erlang_ffi:register_process(Pid, Name). + +-spec unregister(gleam@erlang@atom:atom_()) -> {ok, nil} | {error, nil}. +unregister(Name) -> + gleam_erlang_ffi:unregister_process(Name). + +-spec named(gleam@erlang@atom:atom_()) -> {ok, pid_()} | {error, nil}. +named(Name) -> + gleam_erlang_ffi:process_named(Name). diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam_erlang.app.src b/aoc2023/build/packages/gleam_erlang/src/gleam_erlang.app.src new file mode 100644 index 0000000..bb1b8e6 --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam_erlang.app.src @@ -0,0 +1,14 @@ +{application, gleam_erlang, [ + {vsn, "0.23.1"}, + {applications, [gleam_stdlib, + gleeunit]}, + {description, "A Gleam library for working with Erlang"}, + {modules, [gleam@erlang, + gleam@erlang@atom, + gleam@erlang@charlist, + gleam@erlang@file, + gleam@erlang@node, + gleam@erlang@os, + gleam@erlang@process]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/gleam_erlang/src/gleam_erlang_ffi.erl b/aoc2023/build/packages/gleam_erlang/src/gleam_erlang_ffi.erl new file mode 100644 index 0000000..872126f --- /dev/null +++ b/aoc2023/build/packages/gleam_erlang/src/gleam_erlang_ffi.erl @@ -0,0 +1,263 @@ +-module(gleam_erlang_ffi). +-export([ + atom_from_dynamic/1, rescue/1, atom_from_string/1, get_line/1, + ensure_all_started/1, sleep/1, os_family/0, sleep_forever/0, read_file/1, + append_file/2, write_file/2, delete_file/1, get_all_env/0, get_env/1, + set_env/2, unset_env/1, delete_directory/1, recursive_delete/1, + list_directory/1, demonitor/1, make_directory/1, new_selector/0, link/1, + insert_selector_handler/3, select/1, select/2, trap_exits/1, map_selector/2, + merge_selector/2, flush_messages/0, file_info/1, link_info/1, + priv_directory/1, connect_node/1, register_process/2, unregister_process/1, + process_named/1, identity/1 +]). + +-define(is_posix_error(Error), + Error =:= eacces orelse Error =:= eagain orelse Error =:= ebadf orelse + Error =:= ebadmsg orelse Error =:= ebusy orelse Error =:= edeadlk orelse + Error =:= edeadlock orelse Error =:= edquot orelse Error =:= eexist orelse + Error =:= efault orelse Error =:= efbig orelse Error =:= eftype orelse + Error =:= eintr orelse Error =:= einval orelse Error =:= eio orelse + Error =:= eisdir orelse Error =:= eloop orelse Error =:= emfile orelse + Error =:= emlink orelse Error =:= emultihop orelse Error =:= enametoolong orelse + Error =:= enfile orelse Error =:= enobufs orelse Error =:= enodev orelse + Error =:= enolck orelse Error =:= enolink orelse Error =:= enoent orelse + Error =:= enomem orelse Error =:= enospc orelse Error =:= enosr orelse + Error =:= enostr orelse Error =:= enosys orelse Error =:= enotblk orelse + Error =:= enotdir orelse Error =:= enotsup orelse Error =:= enxio orelse + Error =:= eopnotsupp orelse Error =:= eoverflow orelse Error =:= eperm orelse + Error =:= epipe orelse Error =:= erange orelse Error =:= erofs orelse + Error =:= espipe orelse Error =:= esrch orelse Error =:= estale orelse + Error =:= etxtbsy orelse Error =:= exdev +). + +-spec atom_from_string(binary()) -> {ok, atom()} | {error, atom_not_loaded}. +atom_from_string(S) -> + try {ok, binary_to_existing_atom(S)} + catch error:badarg -> {error, atom_not_loaded} + end. + +atom_from_dynamic(Data) when is_atom(Data) -> + {ok, Data}; +atom_from_dynamic(Data) -> + {error, [{decode_error, <<"Atom">>, gleam@dynamic:classify(Data), []}]}. + +-spec get_line(io:prompt()) -> {ok, unicode:unicode_binary()} | {error, eof | no_data}. +get_line(Prompt) -> + case io:get_line(Prompt) of + eof -> {error, eof}; + {error, _} -> {error, no_data}; + Data when is_binary(Data) -> {ok, Data}; + Data when is_list(Data) -> {ok, unicode:characters_to_binary(Data)} + end. + +rescue(F) -> + try {ok, F()} + catch + throw:X -> {error, {thrown, X}}; + error:X -> {error, {errored, X}}; + exit:X -> {error, {exited, X}} + end. + +ensure_all_started(Application) -> + case application:ensure_all_started(Application) of + {ok, _} = Ok -> Ok; + + {error, {ProblemApp, {"no such file or directory", _}}} -> + {error, {unknown_application, ProblemApp}} + end. + +sleep(Microseconds) -> + timer:sleep(Microseconds), + nil. + +sleep_forever() -> + timer:sleep(infinity), + nil. + +file_info_result(Result) -> + case Result of + {ok, {file_info, Size, Type, Access, Atime, Mtime, Ctime, Mode, Links, MajorDevice, MinorDevice, Inode, Uid, Gid}} when Access =:= none -> + {ok, {file_info, Size, Type, no_access, Atime, Mtime, Ctime, Mode, Links, MajorDevice, MinorDevice, Inode, Uid, Gid}}; + {ok, _} -> + Result; + {error, Reason} when ?is_posix_error(Reason) -> + Result + end. + +file_info(Filename) -> + file_info_result(file:read_file_info(Filename, [{time, posix}])). + +link_info(Filename) -> + file_info_result(file:read_link_info(Filename, [{time, posix}])). + +posix_result(Result) -> + case Result of + ok -> {ok, nil}; + {ok, Value} -> {ok, Value}; + {error, Reason} when ?is_posix_error(Reason) -> {error, Reason} + end. + +read_file(Filename) -> + posix_result(file:read_file(Filename)). + +write_file(Contents, Filename) -> + posix_result(file:write_file(Filename, Contents)). + +append_file(Contents, Filename) -> + posix_result(file:write_file(Filename, Contents, [append])). + +delete_file(Filename) -> + posix_result(file:delete(Filename)). + +make_directory(Dir) -> + posix_result(file:make_dir(Dir)). + +list_directory(Dir) -> + case file:list_dir(Dir) of + {ok, Filenames} -> + {ok, [list_to_binary(Filename) || Filename <- Filenames]}; + {error, Reason} when ?is_posix_error(Reason) -> + {error, Reason} + end. + +delete_directory(Dir) -> + posix_result(file:del_dir(Dir)). + +recursive_delete(Dir) -> + posix_result(file:del_dir_r(Dir)). + +get_all_env() -> + BinVars = lists:map(fun(VarString) -> + [VarName, VarVal] = string:split(VarString, "="), + {list_to_binary(VarName), list_to_binary(VarVal)} + end, os:getenv()), + maps:from_list(BinVars). + +get_env(Name) -> + case os:getenv(binary_to_list(Name)) of + false -> {error, nil}; + Value -> {ok, list_to_binary(Value)} + end. + +set_env(Name, Value) -> + os:putenv(binary_to_list(Name), binary_to_list(Value)), + nil. + +unset_env(Name) -> + os:unsetenv(binary_to_list(Name)), + nil. + +os_family() -> + case os:type() of + {win32, nt} -> + windows_nt; + {unix, linux} -> + linux; + {unix, darwin} -> + darwin; + {unix, freebsd} -> + free_bsd; + {_, Other} -> + {other, atom_to_binary(Other, utf8)} + end. + +new_selector() -> + {selector, #{}}. + +map_selector({selector, Handlers}, Fn) -> + MappedHandlers = maps:map(fun(_Tag, Handler) -> + fun(Message) -> Fn(Handler(Message)) end + end, Handlers), + {selector, MappedHandlers}. + +merge_selector({selector, HandlersA}, {selector, HandlersB}) -> + {selector, maps:merge(HandlersA, HandlersB)}. + +insert_selector_handler({selector, Handlers}, Tag, Fn) -> + {selector, Handlers#{Tag => Fn}}. + +select(Selector) -> + {ok, Message} = select(Selector, infinity), + Message. + +select({selector, Handlers}, Timeout) -> + AnythingHandler = maps:get(anything, Handlers, undefined), + receive + % Monitored process down messages. + % This is special cased so we can selectively receive based on the + % reference as well as the record tag. + {'DOWN', Ref, process, Pid, Reason} when is_map_key(Ref, Handlers) -> + Fn = maps:get(Ref, Handlers), + {ok, Fn({process_down, Pid, Reason})}; + + Msg when is_map_key({element(1, Msg), tuple_size(Msg)}, Handlers) -> + Fn = maps:get({element(1, Msg), tuple_size(Msg)}, Handlers), + {ok, Fn(Msg)}; + + Msg when AnythingHandler =/= undefined -> + {ok, AnythingHandler(Msg)} + after Timeout -> + {error, nil} + end. + +demonitor({_, Reference}) -> + erlang:demonitor(Reference, [flush]). + +link(Pid) -> + try + erlang:link(Pid) + catch + error:_ -> false + end. + +trap_exits(ShouldTrap) -> + erlang:process_flag(trap_exit, ShouldTrap), + nil. + +flush_messages() -> + receive _Message -> flush_messages() + after 0 -> nil + end. + +priv_directory(Name) -> + try erlang:binary_to_existing_atom(Name) of + Atom -> + case code:priv_dir(Atom) of + {error, _} -> {error, nil}; + Path -> {ok, unicode:characters_to_binary(Path)} + end + catch + error:badarg -> {error, nil} + end. + +connect_node(Node) -> + case net_kernel:connect_node(Node) of + true -> {ok, Node}; + false -> {error, failed_to_connect}; + ignored -> {error, local_node_is_not_alive} + end. + +register_process(Pid, Name) -> + try + true = erlang:register(Name, Pid), + {ok, nil} + catch + error:badarg -> {error, nil} + end. + +unregister_process(Name) -> + try + true = erlang:unregister(Name), + {ok, nil} + catch + error:badarg -> {error, nil} + end. + +process_named(Name) -> + case erlang:whereis(Name) of + Pid when is_pid(Pid) -> {ok, Pid}; + _ -> {error, nil} + end. + +identity(X) -> + X. diff --git a/aoc2023/build/packages/gleam_http/LICENSE b/aoc2023/build/packages/gleam_http/LICENSE new file mode 100644 index 0000000..619ec77 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/LICENSE @@ -0,0 +1,191 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2019, Louis Pilfold <louis@lpil.uk>. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/aoc2023/build/packages/gleam_http/README.md b/aoc2023/build/packages/gleam_http/README.md new file mode 100644 index 0000000..9e06952 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/README.md @@ -0,0 +1,67 @@ +# Gleam HTTP + +Types and functions for HTTP clients and servers! + +## HTTP Service Example + +```gleam +import gleam/http/elli +import gleam/http/response.{Response} +import gleam/http/request.{Request} +import gleam/bit_builder.{BitBuilder} + +// Define a HTTP service +// +pub fn my_service(request: Request(t)) -> Response(BitBuilder) { + let body = bit_builder.from_string("Hello, world!") + + response.new(200) + |> response.prepend_header("made-with", "Gleam") + |> response.set_body(body) +} + +// Start it on port 3000 using the Elli web server +// +pub fn main() { + elli.become(my_service, on_port: 3000) +} +``` + +## Server adapters + +In the example above the Elli Erlang web server is used to run the Gleam HTTP +service. Here's a full list of the server adapters available, sorted +alphabetically. + +| Adapter | About | +| --- | --- | +| [Mist][mist] | [Mist][mist] is a high performance pure Gleam web server | +| [gleam_cowboy][cowboy-adapter] | [Cowboy][cowboy] is an Erlang HTTP2 & HTTP1.1 web server | +| [gleam_elli][elli-adapter] | [Elli][elli] is an Erlang HTTP1.1 web server | +| [gleam_plug][plug-adapter] | [Plug][plug] is an Elixir web application interface | + +[cowboy]:https://github.com/ninenines/cowboy +[cowboy-adapter]: https://github.com/gleam-lang/cowboy +[elli]:https://github.com/elli-lib/elli +[elli-adapter]: https://github.com/gleam-lang/elli +[plug]:https://github.com/elixir-plug/plug +[plug-adapter]: https://github.com/gleam-lang/plug +[mist]: https://github.com/rawhat/mist + +## Client adapters + +Client adapters are used to send HTTP requests to services over the network. +Here's a full list of the client adapters available, sorted alphabetically. + +| Adapter | About | +| --- | --- | +| [gleam_fetch][fetch-adapter] | [fetch][fetch] is a HTTP client included with JavaScript | +| [gleam_hackney][hackney-adapter] | [Hackney][hackney] is a simple HTTP client for Erlang | +| [gleam_httpc][httpc-adapter] | [httpc][httpc] is a HTTP client included with Erlang | + +[hackney]: https://github.com/benoitc/hackney +[hackney-adapter]: https://github.com/gleam-lang/hackney +[httpc]: https://erlang.org/doc/man/httpc.html +[httpc-adapter]: https://github.com/gleam-lang/httpc +[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API +[fetch-adapter]: https://github.com/gleam-lang/fetch diff --git a/aoc2023/build/packages/gleam_http/gleam.toml b/aoc2023/build/packages/gleam_http/gleam.toml new file mode 100644 index 0000000..ba733e8 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/gleam.toml @@ -0,0 +1,17 @@ +name = "gleam_http" +version = "3.5.2" +licences = ["Apache-2.0"] +description = "Types and functions for Gleam HTTP clients and servers" +gleam = ">= 0.32.0" + +repository = { type = "github", user = "gleam-lang", repo = "http" } +links = [ + { title = "Website", href = "https://gleam.run" }, + { title = "Sponsor", href = "https://github.com/sponsors/lpil" }, +] + +[dependencies] +gleam_stdlib = "~> 0.32" + +[dev-dependencies] +gleeunit = "~> 1.0" diff --git a/aoc2023/build/packages/gleam_http/include/gleam@http@cookie_Attributes.hrl b/aoc2023/build/packages/gleam_http/include/gleam@http@cookie_Attributes.hrl new file mode 100644 index 0000000..78a7d02 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/include/gleam@http@cookie_Attributes.hrl @@ -0,0 +1,8 @@ +-record(attributes, { + max_age :: gleam@option:option(integer()), + domain :: gleam@option:option(binary()), + path :: gleam@option:option(binary()), + secure :: boolean(), + http_only :: boolean(), + same_site :: gleam@option:option(gleam@http@cookie:same_site_policy()) +}). diff --git a/aoc2023/build/packages/gleam_http/include/gleam@http@request_Request.hrl b/aoc2023/build/packages/gleam_http/include/gleam@http@request_Request.hrl new file mode 100644 index 0000000..c8bbae6 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/include/gleam@http@request_Request.hrl @@ -0,0 +1,10 @@ +-record(request, { + method :: gleam@http:method(), + headers :: list({binary(), binary()}), + body :: any(), + scheme :: gleam@http:scheme(), + host :: binary(), + port :: gleam@option:option(integer()), + path :: binary(), + 'query' :: gleam@option:option(binary()) +}). diff --git a/aoc2023/build/packages/gleam_http/include/gleam@http@response_Response.hrl b/aoc2023/build/packages/gleam_http/include/gleam@http@response_Response.hrl new file mode 100644 index 0000000..ba6f077 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/include/gleam@http@response_Response.hrl @@ -0,0 +1,5 @@ +-record(response, { + status :: integer(), + headers :: list({binary(), binary()}), + body :: any() +}). diff --git a/aoc2023/build/packages/gleam_http/include/gleam@http_MoreRequiredForBody.hrl b/aoc2023/build/packages/gleam_http/include/gleam@http_MoreRequiredForBody.hrl new file mode 100644 index 0000000..abd56dd --- /dev/null +++ b/aoc2023/build/packages/gleam_http/include/gleam@http_MoreRequiredForBody.hrl @@ -0,0 +1,5 @@ +-record(more_required_for_body, { + chunk :: bitstring(), + continuation :: fun((bitstring()) -> {ok, gleam@http:multipart_body()} | + {error, nil}) +}). diff --git a/aoc2023/build/packages/gleam_http/include/gleam@http_MoreRequiredForHeaders.hrl b/aoc2023/build/packages/gleam_http/include/gleam@http_MoreRequiredForHeaders.hrl new file mode 100644 index 0000000..43729c1 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/include/gleam@http_MoreRequiredForHeaders.hrl @@ -0,0 +1,4 @@ +-record(more_required_for_headers, { + continuation :: fun((bitstring()) -> {ok, gleam@http:multipart_headers()} | + {error, nil}) +}). diff --git a/aoc2023/build/packages/gleam_http/include/gleam@http_MultipartBody.hrl b/aoc2023/build/packages/gleam_http/include/gleam@http_MultipartBody.hrl new file mode 100644 index 0000000..4521591 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/include/gleam@http_MultipartBody.hrl @@ -0,0 +1,5 @@ +-record(multipart_body, { + chunk :: bitstring(), + done :: boolean(), + remaining :: bitstring() +}). diff --git a/aoc2023/build/packages/gleam_http/include/gleam@http_MultipartHeaders.hrl b/aoc2023/build/packages/gleam_http/include/gleam@http_MultipartHeaders.hrl new file mode 100644 index 0000000..d9fca5c --- /dev/null +++ b/aoc2023/build/packages/gleam_http/include/gleam@http_MultipartHeaders.hrl @@ -0,0 +1,4 @@ +-record(multipart_headers, { + headers :: list({binary(), binary()}), + remaining :: bitstring() +}). diff --git a/aoc2023/build/packages/gleam_http/src/gleam/http.gleam b/aoc2023/build/packages/gleam_http/src/gleam/http.gleam new file mode 100644 index 0000000..a892006 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam/http.gleam @@ -0,0 +1,560 @@ +//// Functions for working with HTTP data structures in Gleam. +//// +//// This module makes it easy to create and modify Requests and Responses, data types. +//// A general HTTP message type is defined that enables functions to work on both requests and responses. +//// +//// This module does not implement a HTTP client or HTTP server, but it can be used as a base for them. + +import gleam/dynamic.{type DecodeError, type Dynamic, DecodeError} +import gleam/string +import gleam/bit_array +import gleam/result +import gleam/list +import gleam/bool + +/// HTTP standard method as defined by [RFC 2616](https://tools.ietf.org/html/rfc2616), +/// and PATCH which is defined by [RFC 5789](https://tools.ietf.org/html/rfc5789). +pub type Method { + Get + Post + Head + Put + Delete + Trace + Connect + Options + Patch + + /// Non-standard but valid HTTP methods. + Other(String) +} + +// TODO: check if the a is a valid HTTP method (i.e. it is a token, as per the +// spec) and return Ok(Other(s)) if so. +pub fn parse_method(s) -> Result(Method, Nil) { + case string.lowercase(s) { + "connect" -> Ok(Connect) + "delete" -> Ok(Delete) + "get" -> Ok(Get) + "head" -> Ok(Head) + "options" -> Ok(Options) + "patch" -> Ok(Patch) + "post" -> Ok(Post) + "put" -> Ok(Put) + "trace" -> Ok(Trace) + _ -> Error(Nil) + } +} + +pub fn method_to_string(method: Method) -> String { + case method { + Connect -> "connect" + Delete -> "delete" + Get -> "get" + Head -> "head" + Options -> "options" + Patch -> "patch" + Post -> "post" + Put -> "put" + Trace -> "trace" + Other(s) -> s + } +} + +/// The two URI schemes for HTTP +/// +pub type Scheme { + Http + Https +} + +/// Convert a scheme into a string. +/// +/// # Examples +/// +/// > scheme_to_string(Http) +/// "http" +/// +/// > scheme_to_string(Https) +/// "https" +/// +pub fn scheme_to_string(scheme: Scheme) -> String { + case scheme { + Http -> "http" + Https -> "https" + } +} + +/// Parse a HTTP scheme from a string +/// +/// # Examples +/// +/// > scheme_from_string("http") +/// Ok(Http) +/// +/// > scheme_from_string("ftp") +/// Error(Nil) +/// +pub fn scheme_from_string(scheme: String) -> Result(Scheme, Nil) { + case string.lowercase(scheme) { + "http" -> Ok(Http) + "https" -> Ok(Https) + _ -> Error(Nil) + } +} + +pub fn method_from_dynamic(value: Dynamic) -> Result(Method, List(DecodeError)) { + case do_method_from_dynamic(value) { + Ok(method) -> Ok(method) + Error(_) -> Error([DecodeError("HTTP method", dynamic.classify(value), [])]) + } +} + +pub type MultipartHeaders { + /// The headers for the part have been fully parsed. + MultipartHeaders( + headers: List(Header), + /// The remaining content that has not yet been parsed. This will contain + /// the body for this part, if any, and can be parsed with the + /// `parse_multipart_body` function. + remaining: BitArray, + ) + /// More input is required to parse the headers for this part. + MoreRequiredForHeaders( + /// Call this function to continue parsing the headers for this part. + continuation: fn(BitArray) -> Result(MultipartHeaders, Nil), + ) +} + +pub type MultipartBody { + /// The body for the part has been fully parsed. + MultipartBody( + // The rest of the body for this part. The full body of the part is this + // concatenated onto the end of each chunk returned by any previous + // `MoreRequiredForBody` returns. + chunk: BitArray, + /// This is `True` if this was the last part in the multipart message, + /// otherwise there are more parts to parse. + done: Bool, + /// The remaining content that has not yet been parsed. This will contain + /// the next part if `done` is `False`, otherwise it will contain the + /// epilogue, if any. + remaining: BitArray, + ) + MoreRequiredForBody( + // The body that has been parsed so far. The full body of the part is this + // concatenated with the chunk returned by each `MoreRequiredForBody` return + // value, and the final `MultipartBody` return value. + chunk: BitArray, + /// Call this function to continue parsing the body for this part. + continuation: fn(BitArray) -> Result(MultipartBody, Nil), + ) +} + +/// Parse the headers for part of a multipart message, as defined in RFC 2045. +/// +/// This function skips any preamble before the boundary. The preamble may be +/// retrieved using `parse_multipart_body`. +/// +/// This function will accept input of any size, it is up to the caller to limit +/// it if needed. +/// +/// To enable streaming parsing of multipart messages, this function will return +/// a continuation if there is not enough data to fully parse the headers. +/// Further information is available in the documentation for `MultipartBody`. +/// +pub fn parse_multipart_headers( + data: BitArray, + boundary: String, +) -> Result(MultipartHeaders, Nil) { + let boundary = bit_array.from_string(boundary) + // TODO: rewrite this to use a bit pattern once JavaScript supports + // the `b:binary-size(bsize)` pattern. + let prefix = <<45, 45, boundary:bits>> + case bit_array.slice(data, 0, bit_array.byte_size(prefix)) == Ok(prefix) { + // There is no preamble, parse the headers. + True -> parse_headers_after_prelude(data, boundary) + // There is a preamble, skip it before parsing. + False -> skip_preamble(data, boundary) + } +} + +/// Parse the body for part of a multipart message, as defined in RFC 2045. The +/// body is everything until the next boundary. This function is generally to be +/// called after calling `parse_multipart_headers` for a given part. +/// +/// This function will accept input of any size, it is up to the caller to limit +/// it if needed. +/// +/// To enable streaming parsing of multipart messages, this function will return +/// a continuation if there is not enough data to fully parse the body, along +/// with the data that has been parsed so far. Further information is available +/// in the documentation for `MultipartBody`. +/// +pub fn parse_multipart_body( + data: BitArray, + boundary: String, +) -> Result(MultipartBody, Nil) { + boundary + |> bit_array.from_string + |> parse_body_with_bit_array(data, _) +} + +fn parse_body_with_bit_array( + data: BitArray, + boundary: BitArray, +) -> Result(MultipartBody, Nil) { + let bsize = bit_array.byte_size(boundary) + let prefix = bit_array.slice(data, 0, 2 + bsize) + case prefix == Ok(<<45, 45, boundary:bits>>) { + True -> Ok(MultipartBody(<<>>, done: False, remaining: data)) + False -> parse_body_loop(data, boundary, <<>>) + } +} + +fn parse_body_loop( + data: BitArray, + boundary: BitArray, + body: BitArray, +) -> Result(MultipartBody, Nil) { + let dsize = bit_array.byte_size(data) + let bsize = bit_array.byte_size(boundary) + let required = 6 + bsize + case data { + _ if dsize < required -> { + more_please_body(parse_body_loop(_, boundary, <<>>), body, data) + } + + // TODO: flatten this into a single case expression once JavaScript supports + // the `b:binary-size(bsize)` pattern. + // + // \r\n + <<13, 10, data:bytes>> -> { + let desired = <<45, 45, boundary:bits>> + let size = bit_array.byte_size(desired) + let dsize = bit_array.byte_size(data) + let prefix = bit_array.slice(data, 0, size) + let rest = bit_array.slice(data, size, dsize - size) + case prefix == Ok(desired), rest { + // --boundary\r\n + True, Ok(<<13, 10, _:bytes>>) -> + Ok(MultipartBody(body, done: False, remaining: data)) + + // --boundary-- + True, Ok(<<45, 45, data:bytes>>) -> + Ok(MultipartBody(body, done: True, remaining: data)) + + False, _ -> parse_body_loop(data, boundary, <<body:bits, 13, 10>>) + _, _ -> Error(Nil) + } + } + + <<char, data:bytes>> -> { + parse_body_loop(data, boundary, <<body:bits, char>>) + } + } +} + +fn parse_headers_after_prelude( + data: BitArray, + boundary: BitArray, +) -> Result(MultipartHeaders, Nil) { + let dsize = bit_array.byte_size(data) + let bsize = bit_array.byte_size(boundary) + let required_size = bsize + 4 + + // TODO: this could be written as a single case expression if JavaScript had + // support for the `b:binary-size(bsize)` pattern. Rewrite this once the + // compiler support this. + + use <- bool.guard( + when: dsize < required_size, + return: more_please_headers(parse_headers_after_prelude(_, boundary), data), + ) + + use prefix <- result.try(bit_array.slice(data, 0, required_size - 2)) + use second <- result.try(bit_array.slice(data, 2 + bsize, 2)) + let desired = <<45, 45, boundary:bits>> + + use <- bool.guard(prefix != desired, return: Error(Nil)) + + case second == <<45, 45>> { + // --boundary-- + // The last boundary. Return the epilogue. + True -> { + let rest_size = dsize - required_size + use data <- result.map(bit_array.slice(data, required_size, rest_size)) + MultipartHeaders([], remaining: data) + } + + // --boundary + False -> { + let start = required_size - 2 + let rest_size = dsize - required_size + 2 + use data <- result.try(bit_array.slice(data, start, rest_size)) + do_parse_headers(data) + } + } +} + +fn skip_preamble( + data: BitArray, + boundary: BitArray, +) -> Result(MultipartHeaders, Nil) { + let data_size = bit_array.byte_size(data) + let boundary_size = bit_array.byte_size(boundary) + let required = boundary_size + 4 + case data { + _ if data_size < required -> + more_please_headers(skip_preamble(_, boundary), data) + + // TODO: change this to use one non-nested case expression once the compiler + // supports the `b:binary-size(bsize)` pattern on JS. + // \r\n-- + <<13, 10, 45, 45, data:bytes>> -> { + case bit_array.slice(data, 0, boundary_size) { + // --boundary + Ok(prefix) if prefix == boundary -> { + let start = boundary_size + let length = bit_array.byte_size(data) - boundary_size + use rest <- result.try(bit_array.slice(data, start, length)) + do_parse_headers(rest) + } + Ok(_) -> skip_preamble(data, boundary) + Error(_) -> Error(Nil) + } + } + + <<_, data:bytes>> -> skip_preamble(data, boundary) + } +} + +fn skip_whitespace(data: BitArray) -> BitArray { + case data { + // Space or tab. + <<32, data:bytes>> | <<9, data:bytes>> -> skip_whitespace(data) + _ -> data + } +} + +fn do_parse_headers(data: BitArray) -> Result(MultipartHeaders, Nil) { + case data { + // \r\n\r\n + // We've reached the end, there are no headers. + <<13, 10, 13, 10, data:bytes>> -> Ok(MultipartHeaders([], remaining: data)) + + // \r\n + // Skip the line break after the boundary. + <<13, 10, data:bytes>> -> parse_header_name(data, [], <<>>) + + <<13>> | <<>> -> more_please_headers(do_parse_headers, data) + + _ -> Error(Nil) + } +} + +fn parse_header_name( + data: BitArray, + headers: List(Header), + name: BitArray, +) -> Result(MultipartHeaders, Nil) { + case skip_whitespace(data) { + // : + <<58, data:bytes>> -> + data + |> skip_whitespace + |> parse_header_value(headers, name, <<>>) + + <<char, data:bytes>> -> + parse_header_name(data, headers, <<name:bits, char>>) + + <<>> -> more_please_headers(parse_header_name(_, headers, name), data) + } +} + +fn parse_header_value( + data: BitArray, + headers: List(Header), + name: BitArray, + value: BitArray, +) -> Result(MultipartHeaders, Nil) { + let size = bit_array.byte_size(data) + case data { + // We need at least 4 bytes to check for the end of the headers. + _ if size < 4 -> + fn(data) { + data + |> skip_whitespace + |> parse_header_value(headers, name, value) + } + |> more_please_headers(data) + + // \r\n\r\n + <<13, 10, 13, 10, data:bytes>> -> { + use name <- result.try(bit_array.to_string(name)) + use value <- result.map(bit_array.to_string(value)) + let headers = list.reverse([#(string.lowercase(name), value), ..headers]) + MultipartHeaders(headers, data) + } + + // \r\n\s + // \r\n\t + <<13, 10, 32, data:bytes>> | <<13, 10, 9, data:bytes>> -> + parse_header_value(data, headers, name, value) + + // \r\n + <<13, 10, data:bytes>> -> { + use name <- result.try(bit_array.to_string(name)) + use value <- result.try(bit_array.to_string(value)) + let headers = [#(string.lowercase(name), value), ..headers] + parse_header_name(data, headers, <<>>) + } + + <<char, rest:bytes>> -> { + let value = <<value:bits, char>> + parse_header_value(rest, headers, name, value) + } + + _ -> Error(Nil) + } +} + +fn more_please_headers( + continuation: fn(BitArray) -> Result(MultipartHeaders, Nil), + existing: BitArray, +) -> Result(MultipartHeaders, Nil) { + Ok(MoreRequiredForHeaders(fn(more) { + use <- bool.guard(more == <<>>, return: Error(Nil)) + continuation(<<existing:bits, more:bits>>) + })) +} + +pub type ContentDisposition { + ContentDisposition(String, parameters: List(#(String, String))) +} + +pub fn parse_content_disposition( + header: String, +) -> Result(ContentDisposition, Nil) { + parse_content_disposition_type(header, "") +} + +fn parse_content_disposition_type( + header: String, + name: String, +) -> Result(ContentDisposition, Nil) { + case string.pop_grapheme(header) { + Error(Nil) -> Ok(ContentDisposition(name, [])) + + Ok(#(" ", rest)) | Ok(#("\t", rest)) | Ok(#(";", rest)) -> { + let result = parse_rfc_2045_parameters(rest, []) + use parameters <- result.map(result) + ContentDisposition(name, parameters) + } + + Ok(#(grapheme, rest)) -> + parse_content_disposition_type(rest, name <> string.lowercase(grapheme)) + } +} + +fn parse_rfc_2045_parameters( + header: String, + parameters: List(#(String, String)), +) -> Result(List(#(String, String)), Nil) { + case string.pop_grapheme(header) { + Error(Nil) -> Ok(list.reverse(parameters)) + + Ok(#(";", rest)) | Ok(#(" ", rest)) | Ok(#("\t", rest)) -> + parse_rfc_2045_parameters(rest, parameters) + + Ok(#(grapheme, rest)) -> { + let acc = string.lowercase(grapheme) + use #(parameter, rest) <- result.try(parse_rfc_2045_parameter(rest, acc)) + parse_rfc_2045_parameters(rest, [parameter, ..parameters]) + } + } +} + +fn parse_rfc_2045_parameter( + header: String, + name: String, +) -> Result(#(#(String, String), String), Nil) { + use #(grapheme, rest) <- result.try(string.pop_grapheme(header)) + case grapheme { + "=" -> parse_rfc_2045_parameter_value(rest, name) + _ -> parse_rfc_2045_parameter(rest, name <> string.lowercase(grapheme)) + } +} + +fn parse_rfc_2045_parameter_value( + header: String, + name: String, +) -> Result(#(#(String, String), String), Nil) { + case string.pop_grapheme(header) { + Error(Nil) -> Error(Nil) + Ok(#("\"", rest)) -> parse_rfc_2045_parameter_quoted_value(rest, name, "") + Ok(#(grapheme, rest)) -> + Ok(parse_rfc_2045_parameter_unquoted_value(rest, name, grapheme)) + } +} + +fn parse_rfc_2045_parameter_quoted_value( + header: String, + name: String, + value: String, +) -> Result(#(#(String, String), String), Nil) { + case string.pop_grapheme(header) { + Error(Nil) -> Error(Nil) + Ok(#("\"", rest)) -> Ok(#(#(name, value), rest)) + Ok(#("\\", rest)) -> { + use #(grapheme, rest) <- result.try(string.pop_grapheme(rest)) + parse_rfc_2045_parameter_quoted_value(rest, name, value <> grapheme) + } + Ok(#(grapheme, rest)) -> + parse_rfc_2045_parameter_quoted_value(rest, name, value <> grapheme) + } +} + +fn parse_rfc_2045_parameter_unquoted_value( + header: String, + name: String, + value: String, +) -> #(#(String, String), String) { + case string.pop_grapheme(header) { + Error(Nil) -> #(#(name, value), header) + + Ok(#(";", rest)) | Ok(#(" ", rest)) | Ok(#("\t", rest)) -> #( + #(name, value), + rest, + ) + + Ok(#(grapheme, rest)) -> + parse_rfc_2045_parameter_unquoted_value(rest, name, value <> grapheme) + } +} + +fn more_please_body( + continuation: fn(BitArray) -> Result(MultipartBody, Nil), + chunk: BitArray, + existing: BitArray, +) -> Result(MultipartBody, Nil) { + fn(more) { + use <- bool.guard(more == <<>>, return: Error(Nil)) + continuation(<<existing:bits, more:bits>>) + } + |> MoreRequiredForBody(chunk, _) + |> Ok +} + +@target(erlang) +@external(erlang, "gleam_http_native", "decode_method") +fn do_method_from_dynamic(a: Dynamic) -> Result(Method, nil) + +@target(javascript) +@external(javascript, "../gleam_http_native.mjs", "decode_method") +fn do_method_from_dynamic(a: Dynamic) -> Result(Method, Nil) + +/// A HTTP header is a key-value pair. Header keys should be all lowercase +/// characters. +pub type Header = + #(String, String) diff --git a/aoc2023/build/packages/gleam_http/src/gleam/http/cookie.gleam b/aoc2023/build/packages/gleam_http/src/gleam/http/cookie.gleam new file mode 100644 index 0000000..e9ccb55 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam/http/cookie.gleam @@ -0,0 +1,128 @@ +import gleam/result +import gleam/int +import gleam/list +import gleam/regex +import gleam/string +import gleam/option.{type Option, Some} +import gleam/http.{type Scheme} + +/// Policy options for the SameSite cookie attribute +/// +/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite +pub type SameSitePolicy { + Lax + Strict + None +} + +fn same_site_to_string(policy) { + case policy { + Lax -> "Lax" + Strict -> "Strict" + None -> "None" + } +} + +/// Attributes of a cookie when sent to a client in the `set-cookie` header. +pub type Attributes { + Attributes( + max_age: Option(Int), + domain: Option(String), + path: Option(String), + secure: Bool, + http_only: Bool, + same_site: Option(SameSitePolicy), + ) +} + +/// Helper to create sensible default attributes for a set cookie. +/// +/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Attributes +pub fn defaults(scheme: Scheme) { + Attributes( + max_age: option.None, + domain: option.None, + path: option.Some("/"), + secure: scheme == http.Https, + http_only: True, + same_site: Some(Lax), + ) +} + +const epoch = "Expires=Thu, 01 Jan 1970 00:00:00 GMT" + +fn cookie_attributes_to_list(attributes) { + let Attributes( + max_age: max_age, + domain: domain, + path: path, + secure: secure, + http_only: http_only, + same_site: same_site, + ) = attributes + [ + // Expires is a deprecated attribute for cookies, it has been replaced with MaxAge + // MaxAge is widely supported and so Expires values are not set. + // Only when deleting cookies is the exception made to use the old format, + // to ensure complete clearup of cookies if required by an application. + case max_age { + option.Some(0) -> option.Some([epoch]) + _ -> option.None + }, + option.map(max_age, fn(max_age) { ["Max-Age=", int.to_string(max_age)] }), + option.map(domain, fn(domain) { ["Domain=", domain] }), + option.map(path, fn(path) { ["Path=", path] }), + case secure { + True -> option.Some(["Secure"]) + False -> option.None + }, + case http_only { + True -> option.Some(["HttpOnly"]) + False -> option.None + }, + option.map( + same_site, + fn(same_site) { ["SameSite=", same_site_to_string(same_site)] }, + ), + ] + |> list.filter_map(option.to_result(_, Nil)) +} + +pub fn set_header(name: String, value: String, attributes: Attributes) -> String { + [[name, "=", value], ..cookie_attributes_to_list(attributes)] + |> list.map(string.join(_, "")) + |> string.join("; ") +} + +/// Parse a list of cookies from a header string. Any malformed cookies will be +/// discarded. +/// +pub fn parse(cookie_string: String) -> List(#(String, String)) { + let assert Ok(re) = regex.from_string("[,;]") + regex.split(re, cookie_string) + |> list.filter_map(fn(pair) { + case string.split_once(string.trim(pair), "=") { + Ok(#("", _)) -> Error(Nil) + Ok(#(key, value)) -> { + let key = string.trim(key) + let value = string.trim(value) + use _ <- result.then(check_token(key)) + use _ <- result.then(check_token(value)) + Ok(#(key, value)) + } + Error(Nil) -> Error(Nil) + } + }) +} + +fn check_token(token: String) -> Result(Nil, Nil) { + case string.pop_grapheme(token) { + Error(Nil) -> Ok(Nil) + Ok(#(" ", _)) -> Error(Nil) + Ok(#("\t", _)) -> Error(Nil) + Ok(#("\r", _)) -> Error(Nil) + Ok(#("\n", _)) -> Error(Nil) + Ok(#("\f", _)) -> Error(Nil) + Ok(#(_, rest)) -> check_token(rest) + } +} diff --git a/aoc2023/build/packages/gleam_http/src/gleam/http/request.gleam b/aoc2023/build/packages/gleam_http/src/gleam/http/request.gleam new file mode 100644 index 0000000..0bf9af9 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam/http/request.gleam @@ -0,0 +1,267 @@ +import gleam/result +// TODO: validate_req +import gleam/http.{type Header, type Method, type Scheme, Get} +import gleam/http/cookie +import gleam/option.{type Option} +import gleam/uri.{type Uri, Uri} +import gleam/list +import gleam/string +import gleam/string_builder + +// TODO: document +pub type Request(body) { + Request( + method: Method, + headers: List(Header), + body: body, + scheme: Scheme, + host: String, + port: Option(Int), + path: String, + query: Option(String), + ) +} + +/// Return the uri that a request was sent to. +/// +pub fn to_uri(request: Request(a)) -> Uri { + Uri( + scheme: option.Some(http.scheme_to_string(request.scheme)), + userinfo: option.None, + host: option.Some(request.host), + port: request.port, + path: request.path, + query: request.query, + fragment: option.None, + ) +} + +/// Construct a request from a URI. +/// +pub fn from_uri(uri: Uri) -> Result(Request(String), Nil) { + use scheme <- result.then( + uri.scheme + |> option.unwrap("") + |> http.scheme_from_string, + ) + use host <- result.then( + uri.host + |> option.to_result(Nil), + ) + let req = + Request( + method: Get, + headers: [], + body: "", + scheme: scheme, + host: host, + port: uri.port, + path: uri.path, + query: uri.query, + ) + Ok(req) +} + +/// Get the value for a given header. +/// +/// If the request does not have that header then `Error(Nil)` is returned. +/// +pub fn get_header(request: Request(body), key: String) -> Result(String, Nil) { + list.key_find(request.headers, string.lowercase(key)) +} + +/// Set the header with the given value under the given header key. +/// +/// If already present, it is replaced. +pub fn set_header( + request: Request(body), + key: String, + value: String, +) -> Request(body) { + let headers = list.key_set(request.headers, string.lowercase(key), value) + Request(..request, headers: headers) +} + +/// Prepend the header with the given value under the given header key. +/// +/// Similar to `set_header` except if the header already exists it prepends +/// another header with the same key. +pub fn prepend_header( + request: Request(body), + key: String, + value: String, +) -> Request(body) { + let headers = [#(string.lowercase(key), value), ..request.headers] + Request(..request, headers: headers) +} + +// TODO: record update syntax, which can't be done currently as body type changes +/// Set the body of the request, overwriting any existing body. +/// +pub fn set_body(req: Request(old_body), body: new_body) -> Request(new_body) { + let Request( + method: method, + headers: headers, + scheme: scheme, + host: host, + port: port, + path: path, + query: query, + .., + ) = req + Request( + method: method, + headers: headers, + body: body, + scheme: scheme, + host: host, + port: port, + path: path, + query: query, + ) +} + +/// Update the body of a request using a given function. +/// +pub fn map( + request: Request(old_body), + transform: fn(old_body) -> new_body, +) -> Request(new_body) { + request.body + |> transform + |> set_body(request, _) +} + +/// Return the non-empty segments of a request path. +/// +/// # Examples +/// +/// ```gleam +/// > new() +/// > |> set_path("/one/two/three") +/// > |> path_segments +/// ["one", "two", "three"] +/// ``` +/// +pub fn path_segments(request: Request(body)) -> List(String) { + request.path + |> uri.path_segments +} + +/// Decode the query of a request. +pub fn get_query(request: Request(body)) -> Result(List(#(String, String)), Nil) { + case request.query { + option.Some(query_string) -> uri.parse_query(query_string) + option.None -> Ok([]) + } +} + +// TODO: escape +/// Set the query of the request. +/// +pub fn set_query( + req: Request(body), + query: List(#(String, String)), +) -> Request(body) { + let pair = fn(t: #(String, String)) { + string_builder.from_strings([t.0, "=", t.1]) + } + let query = + query + |> list.map(pair) + |> list.intersperse(string_builder.from_string("&")) + |> string_builder.concat + |> string_builder.to_string + |> option.Some + Request(..req, query: query) +} + +/// Set the method of the request. +/// +pub fn set_method(req: Request(body), method: Method) -> Request(body) { + Request(..req, method: method) +} + +/// A request with commonly used default values. This request can be used as +/// an initial value and then update to create the desired request. +/// +pub fn new() -> Request(String) { + Request( + method: Get, + headers: [], + body: "", + scheme: http.Https, + host: "localhost", + port: option.None, + path: "", + query: option.None, + ) +} + +/// Construct a request from a URL string +/// +pub fn to(url: String) -> Result(Request(String), Nil) { + url + |> uri.parse + |> result.then(from_uri) +} + +/// Set the scheme (protocol) of the request. +/// +pub fn set_scheme(req: Request(body), scheme: Scheme) -> Request(body) { + Request(..req, scheme: scheme) +} + +/// Set the method of the request. +/// +pub fn set_host(req: Request(body), host: String) -> Request(body) { + Request(..req, host: host) +} + +/// Set the port of the request. +/// +pub fn set_port(req: Request(body), port: Int) -> Request(body) { + Request(..req, port: option.Some(port)) +} + +/// Set the path of the request. +/// +pub fn set_path(req: Request(body), path: String) -> Request(body) { + Request(..req, path: path) +} + +/// Send a cookie with a request +/// +/// Multiple cookies are added to the same cookie header. +pub fn set_cookie(req: Request(body), name: String, value: String) { + let new_cookie_string = string.join([name, value], "=") + + let #(cookies_string, headers) = case list.key_pop(req.headers, "cookie") { + Ok(#(cookies_string, headers)) -> { + let cookies_string = + string.join([cookies_string, new_cookie_string], "; ") + #(cookies_string, headers) + } + Error(Nil) -> #(new_cookie_string, req.headers) + } + + Request(..req, headers: [#("cookie", cookies_string), ..headers]) +} + +/// Fetch the cookies sent in a request. +/// +/// Note badly formed cookie pairs will be ignored. +/// RFC6265 specifies that invalid cookie names/attributes should be ignored. +pub fn get_cookies(req) -> List(#(String, String)) { + let Request(headers: headers, ..) = req + + headers + |> list.filter_map(fn(header) { + let #(name, value) = header + case name { + "cookie" -> Ok(cookie.parse(value)) + _ -> Error(Nil) + } + }) + |> list.flatten() +} diff --git a/aoc2023/build/packages/gleam_http/src/gleam/http/response.gleam b/aoc2023/build/packages/gleam_http/src/gleam/http/response.gleam new file mode 100644 index 0000000..87f9140 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam/http/response.gleam @@ -0,0 +1,141 @@ +import gleam/result +import gleam/http.{type Header} +import gleam/http/cookie +import gleam/list +import gleam/string +import gleam/option + +// TODO: document +pub type Response(body) { + Response(status: Int, headers: List(Header), body: body) +} + +/// Update the body of a response using a given result returning function. +/// +/// If the given function returns an `Ok` value the body is set, if it returns +/// an `Error` value then the error is returned. +/// +pub fn try_map( + response: Response(old_body), + transform: fn(old_body) -> Result(new_body, error), +) -> Result(Response(new_body), error) { + use body <- result.then(transform(response.body)) + Ok(set_body(response, body)) +} + +/// Construct an empty Response. +/// +/// The body type of the returned response is `String` and could be set with a +/// call to `set_body`. +/// +pub fn new(status: Int) -> Response(String) { + Response(status: status, headers: [], body: "") +} + +/// Get the value for a given header. +/// +/// If the response does not have that header then `Error(Nil)` is returned. +/// +pub fn get_header(response: Response(body), key: String) -> Result(String, Nil) { + list.key_find(response.headers, string.lowercase(key)) +} + +/// Set the header with the given value under the given header key. +/// +/// If the response already has that key, it is replaced. +pub fn set_header( + response: Response(body), + key: String, + value: String, +) -> Response(body) { + let headers = list.key_set(response.headers, string.lowercase(key), value) + Response(..response, headers: headers) +} + +/// Prepend the header with the given value under the given header key. +/// +/// Similar to `set_header` except if the header already exists it prepends +/// another header with the same key. +pub fn prepend_header( + response: Response(body), + key: String, + value: String, +) -> Response(body) { + let headers = [#(string.lowercase(key), value), ..response.headers] + Response(..response, headers: headers) +} + +/// Set the body of the response, overwriting any existing body. +/// +pub fn set_body( + response: Response(old_body), + body: new_body, +) -> Response(new_body) { + let Response(status: status, headers: headers, ..) = response + Response(status: status, headers: headers, body: body) +} + +/// Update the body of a response using a given function. +/// +pub fn map( + response: Response(old_body), + transform: fn(old_body) -> new_body, +) -> Response(new_body) { + response.body + |> transform + |> set_body(response, _) +} + +/// Create a response that redirects to the given uri. +/// +pub fn redirect(uri: String) -> Response(String) { + Response( + status: 303, + headers: [#("location", uri)], + body: string.append("You are being redirected to ", uri), + ) +} + +/// Fetch the cookies sent in a response. +/// +/// Badly formed cookies will be discarded. +/// +pub fn get_cookies(resp) -> List(#(String, String)) { + let Response(headers: headers, ..) = resp + headers + |> list.filter_map(fn(header) { + let #(name, value) = header + case name { + "set-cookie" -> Ok(cookie.parse(value)) + _ -> Error(Nil) + } + }) + |> list.flatten() +} + +/// Set a cookie value for a client +/// +pub fn set_cookie( + response: Response(t), + name: String, + value: String, + attributes: cookie.Attributes, +) -> Response(t) { + prepend_header( + response, + "set-cookie", + cookie.set_header(name, value, attributes), + ) +} + +/// Expire a cookie value for a client +/// +/// Note: The attributes value should be the same as when the response cookie was set. +pub fn expire_cookie( + response: Response(t), + name: String, + attributes: cookie.Attributes, +) -> Response(t) { + let attrs = cookie.Attributes(..attributes, max_age: option.Some(0)) + set_cookie(response, name, "", attrs) +} diff --git a/aoc2023/build/packages/gleam_http/src/gleam/http/service.gleam b/aoc2023/build/packages/gleam_http/src/gleam/http/service.gleam new file mode 100644 index 0000000..3dfac87 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam/http/service.gleam @@ -0,0 +1,82 @@ +import gleam/http.{Delete, Patch, Post, Put} +import gleam/http/request.{type Request} +import gleam/http/response.{type Response} +import gleam/list +import gleam/result + +// TODO: document +pub type Service(in, out) = + fn(Request(in)) -> Response(out) + +pub type Middleware(before_req, before_resp, after_req, after_resp) = + fn(Service(before_req, before_resp)) -> Service(after_req, after_resp) + +/// A middleware that transform the response body returned by the service using +/// a given function. +/// +pub fn map_response_body( + service: Service(req, a), + with mapper: fn(a) -> b, +) -> Service(req, b) { + fn(req) { + req + |> service + |> response.map(mapper) + } +} + +/// A middleware that prepends a header to the request. +/// +pub fn prepend_response_header( + service: Service(req, resp), + key: String, + value: String, +) -> Service(req, resp) { + fn(req) { + req + |> service + |> response.prepend_header(key, value) + } +} + +fn ensure_post(req: Request(a)) { + case req.method { + Post -> Ok(req) + _ -> Error(Nil) + } +} + +fn get_override_method(request: Request(t)) -> Result(http.Method, Nil) { + use query_params <- result.then(request.get_query(request)) + use method <- result.then(list.key_find(query_params, "_method")) + use method <- result.then(http.parse_method(method)) + case method { + Put | Patch | Delete -> Ok(method) + _ -> Error(Nil) + } +} + +/// A middleware that overrides an incoming POST request with a method given in +/// the request's `_method` query paramerter. This is useful as web browsers +/// typically only support GET and POST requests, but our application may +/// expect other HTTP methods that are more semantically correct. +/// +/// The methods PUT, PATCH, and DELETE are accepted for overriding, all others +/// are ignored. +/// +/// The `_method` query paramerter can be specified in a HTML form like so: +/// +/// <form method="POST" action="/item/1?_method=DELETE"> +/// <button type="submit">Delete item</button> +/// </form> +/// +pub fn method_override(service: Service(req, resp)) -> Service(req, resp) { + fn(request) { + request + |> ensure_post + |> result.then(get_override_method) + |> result.map(request.set_method(request, _)) + |> result.unwrap(request) + |> service + } +} diff --git a/aoc2023/build/packages/gleam_http/src/gleam@http.erl b/aoc2023/build/packages/gleam_http/src/gleam@http.erl new file mode 100644 index 0000000..91ee6e8 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam@http.erl @@ -0,0 +1,626 @@ +-module(gleam@http). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([parse_method/1, method_to_string/1, scheme_to_string/1, scheme_from_string/1, parse_content_disposition/1, parse_multipart_body/2, method_from_dynamic/1, parse_multipart_headers/2]). +-export_type([method/0, scheme/0, multipart_headers/0, multipart_body/0, content_disposition/0]). + +-type method() :: get | + post | + head | + put | + delete | + trace | + connect | + options | + patch | + {other, binary()}. + +-type scheme() :: http | https. + +-type multipart_headers() :: {multipart_headers, + list({binary(), binary()}), + bitstring()} | + {more_required_for_headers, + fun((bitstring()) -> {ok, multipart_headers()} | {error, nil})}. + +-type multipart_body() :: {multipart_body, bitstring(), boolean(), bitstring()} | + {more_required_for_body, + bitstring(), + fun((bitstring()) -> {ok, multipart_body()} | {error, nil})}. + +-type content_disposition() :: {content_disposition, + binary(), + list({binary(), binary()})}. + +-spec parse_method(binary()) -> {ok, method()} | {error, nil}. +parse_method(S) -> + case gleam@string:lowercase(S) of + <<"connect"/utf8>> -> + {ok, connect}; + + <<"delete"/utf8>> -> + {ok, delete}; + + <<"get"/utf8>> -> + {ok, get}; + + <<"head"/utf8>> -> + {ok, head}; + + <<"options"/utf8>> -> + {ok, options}; + + <<"patch"/utf8>> -> + {ok, patch}; + + <<"post"/utf8>> -> + {ok, post}; + + <<"put"/utf8>> -> + {ok, put}; + + <<"trace"/utf8>> -> + {ok, trace}; + + _ -> + {error, nil} + end. + +-spec method_to_string(method()) -> binary(). +method_to_string(Method) -> + case Method of + connect -> + <<"connect"/utf8>>; + + delete -> + <<"delete"/utf8>>; + + get -> + <<"get"/utf8>>; + + head -> + <<"head"/utf8>>; + + options -> + <<"options"/utf8>>; + + patch -> + <<"patch"/utf8>>; + + post -> + <<"post"/utf8>>; + + put -> + <<"put"/utf8>>; + + trace -> + <<"trace"/utf8>>; + + {other, S} -> + S + end. + +-spec scheme_to_string(scheme()) -> binary(). +scheme_to_string(Scheme) -> + case Scheme of + http -> + <<"http"/utf8>>; + + https -> + <<"https"/utf8>> + end. + +-spec scheme_from_string(binary()) -> {ok, scheme()} | {error, nil}. +scheme_from_string(Scheme) -> + case gleam@string:lowercase(Scheme) of + <<"http"/utf8>> -> + {ok, http}; + + <<"https"/utf8>> -> + {ok, https}; + + _ -> + {error, nil} + end. + +-spec skip_whitespace(bitstring()) -> bitstring(). +skip_whitespace(Data) -> + case Data of + <<32, Data@1/binary>> -> + skip_whitespace(Data@1); + + <<9, Data@1/binary>> -> + skip_whitespace(Data@1); + + _ -> + Data + end. + +-spec more_please_headers( + fun((bitstring()) -> {ok, multipart_headers()} | {error, nil}), + bitstring() +) -> {ok, multipart_headers()} | {error, nil}. +more_please_headers(Continuation, Existing) -> + {ok, + {more_required_for_headers, + fun(More) -> + gleam@bool:guard( + More =:= <<>>, + {error, nil}, + fun() -> + Continuation(<<Existing/bitstring, More/bitstring>>) + end + ) + end}}. + +-spec parse_rfc_2045_parameter_quoted_value(binary(), binary(), binary()) -> {ok, + {{binary(), binary()}, binary()}} | + {error, nil}. +parse_rfc_2045_parameter_quoted_value(Header, Name, Value) -> + case gleam@string:pop_grapheme(Header) of + {error, nil} -> + {error, nil}; + + {ok, {<<"\""/utf8>>, Rest}} -> + {ok, {{Name, Value}, Rest}}; + + {ok, {<<"\\"/utf8>>, Rest@1}} -> + gleam@result:'try'( + gleam@string:pop_grapheme(Rest@1), + fun(_use0) -> + {Grapheme, Rest@2} = _use0, + parse_rfc_2045_parameter_quoted_value( + Rest@2, + Name, + <<Value/binary, Grapheme/binary>> + ) + end + ); + + {ok, {Grapheme@1, Rest@3}} -> + parse_rfc_2045_parameter_quoted_value( + Rest@3, + Name, + <<Value/binary, Grapheme@1/binary>> + ) + end. + +-spec parse_rfc_2045_parameter_unquoted_value(binary(), binary(), binary()) -> {{binary(), + binary()}, + binary()}. +parse_rfc_2045_parameter_unquoted_value(Header, Name, Value) -> + case gleam@string:pop_grapheme(Header) of + {error, nil} -> + {{Name, Value}, Header}; + + {ok, {<<";"/utf8>>, Rest}} -> + {{Name, Value}, Rest}; + + {ok, {<<" "/utf8>>, Rest}} -> + {{Name, Value}, Rest}; + + {ok, {<<"\t"/utf8>>, Rest}} -> + {{Name, Value}, Rest}; + + {ok, {Grapheme, Rest@1}} -> + parse_rfc_2045_parameter_unquoted_value( + Rest@1, + Name, + <<Value/binary, Grapheme/binary>> + ) + end. + +-spec parse_rfc_2045_parameter_value(binary(), binary()) -> {ok, + {{binary(), binary()}, binary()}} | + {error, nil}. +parse_rfc_2045_parameter_value(Header, Name) -> + case gleam@string:pop_grapheme(Header) of + {error, nil} -> + {error, nil}; + + {ok, {<<"\""/utf8>>, Rest}} -> + parse_rfc_2045_parameter_quoted_value(Rest, Name, <<""/utf8>>); + + {ok, {Grapheme, Rest@1}} -> + {ok, + parse_rfc_2045_parameter_unquoted_value(Rest@1, Name, Grapheme)} + end. + +-spec parse_rfc_2045_parameter(binary(), binary()) -> {ok, + {{binary(), binary()}, binary()}} | + {error, nil}. +parse_rfc_2045_parameter(Header, Name) -> + gleam@result:'try'( + gleam@string:pop_grapheme(Header), + fun(_use0) -> + {Grapheme, Rest} = _use0, + case Grapheme of + <<"="/utf8>> -> + parse_rfc_2045_parameter_value(Rest, Name); + + _ -> + parse_rfc_2045_parameter( + Rest, + <<Name/binary, + (gleam@string:lowercase(Grapheme))/binary>> + ) + end + end + ). + +-spec parse_rfc_2045_parameters(binary(), list({binary(), binary()})) -> {ok, + list({binary(), binary()})} | + {error, nil}. +parse_rfc_2045_parameters(Header, Parameters) -> + case gleam@string:pop_grapheme(Header) of + {error, nil} -> + {ok, gleam@list:reverse(Parameters)}; + + {ok, {<<";"/utf8>>, Rest}} -> + parse_rfc_2045_parameters(Rest, Parameters); + + {ok, {<<" "/utf8>>, Rest}} -> + parse_rfc_2045_parameters(Rest, Parameters); + + {ok, {<<"\t"/utf8>>, Rest}} -> + parse_rfc_2045_parameters(Rest, Parameters); + + {ok, {Grapheme, Rest@1}} -> + Acc = gleam@string:lowercase(Grapheme), + gleam@result:'try'( + parse_rfc_2045_parameter(Rest@1, Acc), + fun(_use0) -> + {Parameter, Rest@2} = _use0, + parse_rfc_2045_parameters(Rest@2, [Parameter | Parameters]) + end + ) + end. + +-spec parse_content_disposition_type(binary(), binary()) -> {ok, + content_disposition()} | + {error, nil}. +parse_content_disposition_type(Header, Name) -> + case gleam@string:pop_grapheme(Header) of + {error, nil} -> + {ok, {content_disposition, Name, []}}; + + {ok, {<<" "/utf8>>, Rest}} -> + Result = parse_rfc_2045_parameters(Rest, []), + gleam@result:map( + Result, + fun(Parameters) -> {content_disposition, Name, Parameters} end + ); + + {ok, {<<"\t"/utf8>>, Rest}} -> + Result = parse_rfc_2045_parameters(Rest, []), + gleam@result:map( + Result, + fun(Parameters) -> {content_disposition, Name, Parameters} end + ); + + {ok, {<<";"/utf8>>, Rest}} -> + Result = parse_rfc_2045_parameters(Rest, []), + gleam@result:map( + Result, + fun(Parameters) -> {content_disposition, Name, Parameters} end + ); + + {ok, {Grapheme, Rest@1}} -> + parse_content_disposition_type( + Rest@1, + <<Name/binary, (gleam@string:lowercase(Grapheme))/binary>> + ) + end. + +-spec parse_content_disposition(binary()) -> {ok, content_disposition()} | + {error, nil}. +parse_content_disposition(Header) -> + parse_content_disposition_type(Header, <<""/utf8>>). + +-spec more_please_body( + fun((bitstring()) -> {ok, multipart_body()} | {error, nil}), + bitstring(), + bitstring() +) -> {ok, multipart_body()} | {error, nil}. +more_please_body(Continuation, Chunk, Existing) -> + _pipe = fun(More) -> + gleam@bool:guard( + More =:= <<>>, + {error, nil}, + fun() -> Continuation(<<Existing/bitstring, More/bitstring>>) end + ) + end, + _pipe@1 = {more_required_for_body, Chunk, _pipe}, + {ok, _pipe@1}. + +-spec parse_body_loop(bitstring(), bitstring(), bitstring()) -> {ok, + multipart_body()} | + {error, nil}. +parse_body_loop(Data, Boundary, Body) -> + Dsize = erlang:byte_size(Data), + Bsize = erlang:byte_size(Boundary), + Required = 6 + Bsize, + case Data of + _ when Dsize < Required -> + more_please_body( + fun(_capture) -> parse_body_loop(_capture, Boundary, <<>>) end, + Body, + Data + ); + + <<13, 10, Data@1/binary>> -> + Desired = <<45, 45, Boundary/bitstring>>, + Size = erlang:byte_size(Desired), + Dsize@1 = erlang:byte_size(Data@1), + Prefix = gleam_stdlib:bit_array_slice(Data@1, 0, Size), + Rest = gleam_stdlib:bit_array_slice(Data@1, Size, Dsize@1 - Size), + case {Prefix =:= {ok, Desired}, Rest} of + {true, {ok, <<13, 10, _/binary>>}} -> + {ok, {multipart_body, Body, false, Data@1}}; + + {true, {ok, <<45, 45, Data@2/binary>>}} -> + {ok, {multipart_body, Body, true, Data@2}}; + + {false, _} -> + parse_body_loop( + Data@1, + Boundary, + <<Body/bitstring, 13, 10>> + ); + + {_, _} -> + {error, nil} + end; + + <<Char, Data@3/binary>> -> + parse_body_loop(Data@3, Boundary, <<Body/bitstring, Char>>) + end. + +-spec parse_body_with_bit_array(bitstring(), bitstring()) -> {ok, + multipart_body()} | + {error, nil}. +parse_body_with_bit_array(Data, Boundary) -> + Bsize = erlang:byte_size(Boundary), + Prefix = gleam_stdlib:bit_array_slice(Data, 0, 2 + Bsize), + case Prefix =:= {ok, <<45, 45, Boundary/bitstring>>} of + true -> + {ok, {multipart_body, <<>>, false, Data}}; + + false -> + parse_body_loop(Data, Boundary, <<>>) + end. + +-spec parse_multipart_body(bitstring(), binary()) -> {ok, multipart_body()} | + {error, nil}. +parse_multipart_body(Data, Boundary) -> + _pipe = Boundary, + _pipe@1 = gleam_stdlib:identity(_pipe), + parse_body_with_bit_array(Data, _pipe@1). + +-spec method_from_dynamic(gleam@dynamic:dynamic_()) -> {ok, method()} | + {error, list(gleam@dynamic:decode_error())}. +method_from_dynamic(Value) -> + case gleam_http_native:decode_method(Value) of + {ok, Method} -> + {ok, Method}; + + {error, _} -> + {error, + [{decode_error, + <<"HTTP method"/utf8>>, + gleam@dynamic:classify(Value), + []}]} + end. + +-spec parse_header_value( + bitstring(), + list({binary(), binary()}), + bitstring(), + bitstring() +) -> {ok, multipart_headers()} | {error, nil}. +parse_header_value(Data, Headers, Name, Value) -> + Size = erlang:byte_size(Data), + case Data of + _ when Size < 4 -> + _pipe@2 = fun(Data@1) -> _pipe = Data@1, + _pipe@1 = skip_whitespace(_pipe), + parse_header_value(_pipe@1, Headers, Name, Value) end, + more_please_headers(_pipe@2, Data); + + <<13, 10, 13, 10, Data@2/binary>> -> + gleam@result:'try'( + gleam@bit_array:to_string(Name), + fun(Name@1) -> + gleam@result:map( + gleam@bit_array:to_string(Value), + fun(Value@1) -> + Headers@1 = gleam@list:reverse( + [{gleam@string:lowercase(Name@1), Value@1} | + Headers] + ), + {multipart_headers, Headers@1, Data@2} + end + ) + end + ); + + <<13, 10, 32, Data@3/binary>> -> + parse_header_value(Data@3, Headers, Name, Value); + + <<13, 10, 9, Data@3/binary>> -> + parse_header_value(Data@3, Headers, Name, Value); + + <<13, 10, Data@4/binary>> -> + gleam@result:'try'( + gleam@bit_array:to_string(Name), + fun(Name@2) -> + gleam@result:'try'( + gleam@bit_array:to_string(Value), + fun(Value@2) -> + Headers@2 = [{gleam@string:lowercase(Name@2), + Value@2} | + Headers], + parse_header_name(Data@4, Headers@2, <<>>) + end + ) + end + ); + + <<Char, Rest/binary>> -> + Value@3 = <<Value/bitstring, Char>>, + parse_header_value(Rest, Headers, Name, Value@3); + + _ -> + {error, nil} + end. + +-spec parse_header_name(bitstring(), list({binary(), binary()}), bitstring()) -> {ok, + multipart_headers()} | + {error, nil}. +parse_header_name(Data, Headers, Name) -> + case skip_whitespace(Data) of + <<58, Data@1/binary>> -> + _pipe = Data@1, + _pipe@1 = skip_whitespace(_pipe), + parse_header_value(_pipe@1, Headers, Name, <<>>); + + <<Char, Data@2/binary>> -> + parse_header_name(Data@2, Headers, <<Name/bitstring, Char>>); + + <<>> -> + more_please_headers( + fun(_capture) -> parse_header_name(_capture, Headers, Name) end, + Data + ) + end. + +-spec do_parse_headers(bitstring()) -> {ok, multipart_headers()} | {error, nil}. +do_parse_headers(Data) -> + case Data of + <<13, 10, 13, 10, Data@1/binary>> -> + {ok, {multipart_headers, [], Data@1}}; + + <<13, 10, Data@2/binary>> -> + parse_header_name(Data@2, [], <<>>); + + <<13>> -> + more_please_headers(fun do_parse_headers/1, Data); + + <<>> -> + more_please_headers(fun do_parse_headers/1, Data); + + _ -> + {error, nil} + end. + +-spec parse_headers_after_prelude(bitstring(), bitstring()) -> {ok, + multipart_headers()} | + {error, nil}. +parse_headers_after_prelude(Data, Boundary) -> + Dsize = erlang:byte_size(Data), + Bsize = erlang:byte_size(Boundary), + Required_size = Bsize + 4, + gleam@bool:guard( + Dsize < Required_size, + more_please_headers( + fun(_capture) -> parse_headers_after_prelude(_capture, Boundary) end, + Data + ), + fun() -> + gleam@result:'try'( + gleam_stdlib:bit_array_slice(Data, 0, Required_size - 2), + fun(Prefix) -> + gleam@result:'try'( + gleam_stdlib:bit_array_slice(Data, 2 + Bsize, 2), + fun(Second) -> + Desired = <<45, 45, Boundary/bitstring>>, + gleam@bool:guard( + Prefix /= Desired, + {error, nil}, + fun() -> case Second =:= <<45, 45>> of + true -> + Rest_size = Dsize - Required_size, + gleam@result:map( + gleam_stdlib:bit_array_slice( + Data, + Required_size, + Rest_size + ), + fun(Data@1) -> + {multipart_headers, + [], + Data@1} + end + ); + + false -> + Start = Required_size - 2, + Rest_size@1 = (Dsize - Required_size) + + 2, + gleam@result:'try'( + gleam_stdlib:bit_array_slice( + Data, + Start, + Rest_size@1 + ), + fun(Data@2) -> + do_parse_headers(Data@2) + end + ) + end end + ) + end + ) + end + ) + end + ). + +-spec skip_preamble(bitstring(), bitstring()) -> {ok, multipart_headers()} | + {error, nil}. +skip_preamble(Data, Boundary) -> + Data_size = erlang:byte_size(Data), + Boundary_size = erlang:byte_size(Boundary), + Required = Boundary_size + 4, + case Data of + _ when Data_size < Required -> + more_please_headers( + fun(_capture) -> skip_preamble(_capture, Boundary) end, + Data + ); + + <<13, 10, 45, 45, Data@1/binary>> -> + case gleam_stdlib:bit_array_slice(Data@1, 0, Boundary_size) of + {ok, Prefix} when Prefix =:= Boundary -> + Start = Boundary_size, + Length = erlang:byte_size(Data@1) - Boundary_size, + gleam@result:'try'( + gleam_stdlib:bit_array_slice(Data@1, Start, Length), + fun(Rest) -> do_parse_headers(Rest) end + ); + + {ok, _} -> + skip_preamble(Data@1, Boundary); + + {error, _} -> + {error, nil} + end; + + <<_, Data@2/binary>> -> + skip_preamble(Data@2, Boundary) + end. + +-spec parse_multipart_headers(bitstring(), binary()) -> {ok, + multipart_headers()} | + {error, nil}. +parse_multipart_headers(Data, Boundary) -> + Boundary@1 = gleam_stdlib:identity(Boundary), + Prefix = <<45, 45, Boundary@1/bitstring>>, + case gleam_stdlib:bit_array_slice(Data, 0, erlang:byte_size(Prefix)) =:= {ok, + Prefix} of + true -> + parse_headers_after_prelude(Data, Boundary@1); + + false -> + skip_preamble(Data, Boundary@1) + end. diff --git a/aoc2023/build/packages/gleam_http/src/gleam@http@cookie.erl b/aoc2023/build/packages/gleam_http/src/gleam@http@cookie.erl new file mode 100644 index 0000000..9d6d13e --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam@http@cookie.erl @@ -0,0 +1,153 @@ +-module(gleam@http@cookie). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([defaults/1, set_header/3, parse/1]). +-export_type([same_site_policy/0, attributes/0]). + +-type same_site_policy() :: lax | strict | none. + +-type attributes() :: {attributes, + gleam@option:option(integer()), + gleam@option:option(binary()), + gleam@option:option(binary()), + boolean(), + boolean(), + gleam@option:option(same_site_policy())}. + +-spec same_site_to_string(same_site_policy()) -> binary(). +same_site_to_string(Policy) -> + case Policy of + lax -> + <<"Lax"/utf8>>; + + strict -> + <<"Strict"/utf8>>; + + none -> + <<"None"/utf8>> + end. + +-spec defaults(gleam@http:scheme()) -> attributes(). +defaults(Scheme) -> + {attributes, + none, + none, + {some, <<"/"/utf8>>}, + Scheme =:= https, + true, + {some, lax}}. + +-spec cookie_attributes_to_list(attributes()) -> list(list(binary())). +cookie_attributes_to_list(Attributes) -> + {attributes, Max_age, Domain, Path, Secure, Http_only, Same_site} = Attributes, + _pipe = [case Max_age of + {some, 0} -> + {some, [<<"Expires=Thu, 01 Jan 1970 00:00:00 GMT"/utf8>>]}; + + _ -> + none + end, gleam@option:map( + Max_age, + fun(Max_age@1) -> + [<<"Max-Age="/utf8>>, gleam@int:to_string(Max_age@1)] + end + ), gleam@option:map( + Domain, + fun(Domain@1) -> [<<"Domain="/utf8>>, Domain@1] end + ), gleam@option:map(Path, fun(Path@1) -> [<<"Path="/utf8>>, Path@1] end), case Secure of + true -> + {some, [<<"Secure"/utf8>>]}; + + false -> + none + end, case Http_only of + true -> + {some, [<<"HttpOnly"/utf8>>]}; + + false -> + none + end, gleam@option:map( + Same_site, + fun(Same_site@1) -> + [<<"SameSite="/utf8>>, same_site_to_string(Same_site@1)] + end + )], + gleam@list:filter_map( + _pipe, + fun(_capture) -> gleam@option:to_result(_capture, nil) end + ). + +-spec set_header(binary(), binary(), attributes()) -> binary(). +set_header(Name, Value, Attributes) -> + _pipe = [[Name, <<"="/utf8>>, Value] | + cookie_attributes_to_list(Attributes)], + _pipe@1 = gleam@list:map( + _pipe, + fun(_capture) -> gleam@string:join(_capture, <<""/utf8>>) end + ), + gleam@string:join(_pipe@1, <<"; "/utf8>>). + +-spec check_token(binary()) -> {ok, nil} | {error, nil}. +check_token(Token) -> + case gleam@string:pop_grapheme(Token) of + {error, nil} -> + {ok, nil}; + + {ok, {<<" "/utf8>>, _}} -> + {error, nil}; + + {ok, {<<"\t"/utf8>>, _}} -> + {error, nil}; + + {ok, {<<"\r"/utf8>>, _}} -> + {error, nil}; + + {ok, {<<"\n"/utf8>>, _}} -> + {error, nil}; + + {ok, {<<"\f"/utf8>>, _}} -> + {error, nil}; + + {ok, {_, Rest}} -> + check_token(Rest) + end. + +-spec parse(binary()) -> list({binary(), binary()}). +parse(Cookie_string) -> + _assert_subject = gleam@regex:from_string(<<"[,;]"/utf8>>), + {ok, Re} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam/http/cookie"/utf8>>, + function => <<"parse"/utf8>>, + line => 101}) + end, + _pipe = gleam@regex:split(Re, Cookie_string), + gleam@list:filter_map( + _pipe, + fun(Pair) -> + case gleam@string:split_once(gleam@string:trim(Pair), <<"="/utf8>>) of + {ok, {<<""/utf8>>, _}} -> + {error, nil}; + + {ok, {Key, Value}} -> + Key@1 = gleam@string:trim(Key), + Value@1 = gleam@string:trim(Value), + gleam@result:then( + check_token(Key@1), + fun(_) -> + gleam@result:then( + check_token(Value@1), + fun(_) -> {ok, {Key@1, Value@1}} end + ) + end + ); + + {error, nil} -> + {error, nil} + end + end + ). diff --git a/aoc2023/build/packages/gleam_http/src/gleam@http@request.erl b/aoc2023/build/packages/gleam_http/src/gleam@http@request.erl new file mode 100644 index 0000000..630788d --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam@http@request.erl @@ -0,0 +1,202 @@ +-module(gleam@http@request). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([to_uri/1, from_uri/1, get_header/2, set_header/3, prepend_header/3, set_body/2, map/2, path_segments/1, get_query/1, set_query/2, set_method/2, new/0, to/1, set_scheme/2, set_host/2, set_port/2, set_path/2, set_cookie/3, get_cookies/1]). +-export_type([request/1]). + +-type request(FYJ) :: {request, + gleam@http:method(), + list({binary(), binary()}), + FYJ, + gleam@http:scheme(), + binary(), + gleam@option:option(integer()), + binary(), + gleam@option:option(binary())}. + +-spec to_uri(request(any())) -> gleam@uri:uri(). +to_uri(Request) -> + {uri, + {some, gleam@http:scheme_to_string(erlang:element(5, Request))}, + none, + {some, erlang:element(6, Request)}, + erlang:element(7, Request), + erlang:element(8, Request), + erlang:element(9, Request), + none}. + +-spec from_uri(gleam@uri:uri()) -> {ok, request(binary())} | {error, nil}. +from_uri(Uri) -> + gleam@result:then( + begin + _pipe = erlang:element(2, Uri), + _pipe@1 = gleam@option:unwrap(_pipe, <<""/utf8>>), + gleam@http:scheme_from_string(_pipe@1) + end, + fun(Scheme) -> + gleam@result:then( + begin + _pipe@2 = erlang:element(4, Uri), + gleam@option:to_result(_pipe@2, nil) + end, + fun(Host) -> + Req = {request, + get, + [], + <<""/utf8>>, + Scheme, + Host, + erlang:element(5, Uri), + erlang:element(6, Uri), + erlang:element(7, Uri)}, + {ok, Req} + end + ) + end + ). + +-spec get_header(request(any()), binary()) -> {ok, binary()} | {error, nil}. +get_header(Request, Key) -> + gleam@list:key_find(erlang:element(3, Request), gleam@string:lowercase(Key)). + +-spec set_header(request(FYT), binary(), binary()) -> request(FYT). +set_header(Request, Key, Value) -> + Headers = gleam@list:key_set( + erlang:element(3, Request), + gleam@string:lowercase(Key), + Value + ), + erlang:setelement(3, Request, Headers). + +-spec prepend_header(request(FYW), binary(), binary()) -> request(FYW). +prepend_header(Request, Key, Value) -> + Headers = [{gleam@string:lowercase(Key), Value} | + erlang:element(3, Request)], + erlang:setelement(3, Request, Headers). + +-spec set_body(request(any()), FZB) -> request(FZB). +set_body(Req, Body) -> + {request, Method, Headers, _, Scheme, Host, Port, Path, Query} = Req, + {request, Method, Headers, Body, Scheme, Host, Port, Path, Query}. + +-spec map(request(FZD), fun((FZD) -> FZF)) -> request(FZF). +map(Request, Transform) -> + _pipe = erlang:element(4, Request), + _pipe@1 = Transform(_pipe), + set_body(Request, _pipe@1). + +-spec path_segments(request(any())) -> list(binary()). +path_segments(Request) -> + _pipe = erlang:element(8, Request), + gleam@uri:path_segments(_pipe). + +-spec get_query(request(any())) -> {ok, list({binary(), binary()})} | + {error, nil}. +get_query(Request) -> + case erlang:element(9, Request) of + {some, Query_string} -> + gleam@uri:parse_query(Query_string); + + none -> + {ok, []} + end. + +-spec set_query(request(FZP), list({binary(), binary()})) -> request(FZP). +set_query(Req, Query) -> + Pair = fun(T) -> + gleam@string_builder:from_strings( + [erlang:element(1, T), <<"="/utf8>>, erlang:element(2, T)] + ) + end, + Query@1 = begin + _pipe = Query, + _pipe@1 = gleam@list:map(_pipe, Pair), + _pipe@2 = gleam@list:intersperse( + _pipe@1, + gleam@string_builder:from_string(<<"&"/utf8>>) + ), + _pipe@3 = gleam@string_builder:concat(_pipe@2), + _pipe@4 = gleam@string_builder:to_string(_pipe@3), + {some, _pipe@4} + end, + erlang:setelement(9, Req, Query@1). + +-spec set_method(request(FZT), gleam@http:method()) -> request(FZT). +set_method(Req, Method) -> + erlang:setelement(2, Req, Method). + +-spec new() -> request(binary()). +new() -> + {request, + get, + [], + <<""/utf8>>, + https, + <<"localhost"/utf8>>, + none, + <<""/utf8>>, + none}. + +-spec to(binary()) -> {ok, request(binary())} | {error, nil}. +to(Url) -> + _pipe = Url, + _pipe@1 = gleam@uri:parse(_pipe), + gleam@result:then(_pipe@1, fun from_uri/1). + +-spec set_scheme(request(GAA), gleam@http:scheme()) -> request(GAA). +set_scheme(Req, Scheme) -> + erlang:setelement(5, Req, Scheme). + +-spec set_host(request(GAD), binary()) -> request(GAD). +set_host(Req, Host) -> + erlang:setelement(6, Req, Host). + +-spec set_port(request(GAG), integer()) -> request(GAG). +set_port(Req, Port) -> + erlang:setelement(7, Req, {some, Port}). + +-spec set_path(request(GAJ), binary()) -> request(GAJ). +set_path(Req, Path) -> + erlang:setelement(8, Req, Path). + +-spec set_cookie(request(GAM), binary(), binary()) -> request(GAM). +set_cookie(Req, Name, Value) -> + New_cookie_string = gleam@string:join([Name, Value], <<"="/utf8>>), + {Cookies_string@2, Headers@1} = case gleam@list:key_pop( + erlang:element(3, Req), + <<"cookie"/utf8>> + ) of + {ok, {Cookies_string, Headers}} -> + Cookies_string@1 = gleam@string:join( + [Cookies_string, New_cookie_string], + <<"; "/utf8>> + ), + {Cookies_string@1, Headers}; + + {error, nil} -> + {New_cookie_string, erlang:element(3, Req)} + end, + erlang:setelement( + 3, + Req, + [{<<"cookie"/utf8>>, Cookies_string@2} | Headers@1] + ). + +-spec get_cookies(request(any())) -> list({binary(), binary()}). +get_cookies(Req) -> + {request, _, Headers, _, _, _, _, _, _} = Req, + _pipe = Headers, + _pipe@1 = gleam@list:filter_map( + _pipe, + fun(Header) -> + {Name, Value} = Header, + case Name of + <<"cookie"/utf8>> -> + {ok, gleam@http@cookie:parse(Value)}; + + _ -> + {error, nil} + end + end + ), + gleam@list:flatten(_pipe@1). diff --git a/aoc2023/build/packages/gleam_http/src/gleam@http@response.erl b/aoc2023/build/packages/gleam_http/src/gleam@http@response.erl new file mode 100644 index 0000000..b073c1d --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam@http@response.erl @@ -0,0 +1,97 @@ +-module(gleam@http@response). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([new/1, get_header/2, set_header/3, prepend_header/3, set_body/2, try_map/2, map/2, redirect/1, get_cookies/1, set_cookie/4, expire_cookie/3]). +-export_type([response/1]). + +-type response(GFN) :: {response, integer(), list({binary(), binary()}), GFN}. + +-spec new(integer()) -> response(binary()). +new(Status) -> + {response, Status, [], <<""/utf8>>}. + +-spec get_header(response(any()), binary()) -> {ok, binary()} | {error, nil}. +get_header(Response, Key) -> + gleam@list:key_find( + erlang:element(3, Response), + gleam@string:lowercase(Key) + ). + +-spec set_header(response(GGC), binary(), binary()) -> response(GGC). +set_header(Response, Key, Value) -> + Headers = gleam@list:key_set( + erlang:element(3, Response), + gleam@string:lowercase(Key), + Value + ), + erlang:setelement(3, Response, Headers). + +-spec prepend_header(response(GGF), binary(), binary()) -> response(GGF). +prepend_header(Response, Key, Value) -> + Headers = [{gleam@string:lowercase(Key), Value} | + erlang:element(3, Response)], + erlang:setelement(3, Response, Headers). + +-spec set_body(response(any()), GGK) -> response(GGK). +set_body(Response, Body) -> + {response, Status, Headers, _} = Response, + {response, Status, Headers, Body}. + +-spec try_map(response(GFO), fun((GFO) -> {ok, GFQ} | {error, GFR})) -> {ok, + response(GFQ)} | + {error, GFR}. +try_map(Response, Transform) -> + gleam@result:then( + Transform(erlang:element(4, Response)), + fun(Body) -> {ok, set_body(Response, Body)} end + ). + +-spec map(response(GGM), fun((GGM) -> GGO)) -> response(GGO). +map(Response, Transform) -> + _pipe = erlang:element(4, Response), + _pipe@1 = Transform(_pipe), + set_body(Response, _pipe@1). + +-spec redirect(binary()) -> response(binary()). +redirect(Uri) -> + {response, + 303, + [{<<"location"/utf8>>, Uri}], + gleam@string:append(<<"You are being redirected to "/utf8>>, Uri)}. + +-spec get_cookies(response(any())) -> list({binary(), binary()}). +get_cookies(Resp) -> + {response, _, Headers, _} = Resp, + _pipe = Headers, + _pipe@1 = gleam@list:filter_map( + _pipe, + fun(Header) -> + {Name, Value} = Header, + case Name of + <<"set-cookie"/utf8>> -> + {ok, gleam@http@cookie:parse(Value)}; + + _ -> + {error, nil} + end + end + ), + gleam@list:flatten(_pipe@1). + +-spec set_cookie( + response(GGT), + binary(), + binary(), + gleam@http@cookie:attributes() +) -> response(GGT). +set_cookie(Response, Name, Value, Attributes) -> + prepend_header( + Response, + <<"set-cookie"/utf8>>, + gleam@http@cookie:set_header(Name, Value, Attributes) + ). + +-spec expire_cookie(response(GGW), binary(), gleam@http@cookie:attributes()) -> response(GGW). +expire_cookie(Response, Name, Attributes) -> + Attrs = erlang:setelement(2, Attributes, {some, 0}), + set_cookie(Response, Name, <<""/utf8>>, Attrs). diff --git a/aoc2023/build/packages/gleam_http/src/gleam@http@service.erl b/aoc2023/build/packages/gleam_http/src/gleam@http@service.erl new file mode 100644 index 0000000..d07b31f --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam@http@service.erl @@ -0,0 +1,82 @@ +-module(gleam@http@service). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([map_response_body/2, prepend_response_header/3, method_override/1]). + +-spec map_response_body( + fun((gleam@http@request:request(GJL)) -> gleam@http@response:response(GJM)), + fun((GJM) -> GJP) +) -> fun((gleam@http@request:request(GJL)) -> gleam@http@response:response(GJP)). +map_response_body(Service, Mapper) -> + fun(Req) -> _pipe = Req, + _pipe@1 = Service(_pipe), + gleam@http@response:map(_pipe@1, Mapper) end. + +-spec prepend_response_header( + fun((gleam@http@request:request(GJS)) -> gleam@http@response:response(GJT)), + binary(), + binary() +) -> fun((gleam@http@request:request(GJS)) -> gleam@http@response:response(GJT)). +prepend_response_header(Service, Key, Value) -> + fun(Req) -> _pipe = Req, + _pipe@1 = Service(_pipe), + gleam@http@response:prepend_header(_pipe@1, Key, Value) end. + +-spec ensure_post(gleam@http@request:request(GJY)) -> {ok, + gleam@http@request:request(GJY)} | + {error, nil}. +ensure_post(Req) -> + case erlang:element(2, Req) of + post -> + {ok, Req}; + + _ -> + {error, nil} + end. + +-spec get_override_method(gleam@http@request:request(any())) -> {ok, + gleam@http:method()} | + {error, nil}. +get_override_method(Request) -> + gleam@result:then( + gleam@http@request:get_query(Request), + fun(Query_params) -> + gleam@result:then( + gleam@list:key_find(Query_params, <<"_method"/utf8>>), + fun(Method) -> + gleam@result:then( + gleam@http:parse_method(Method), + fun(Method@1) -> case Method@1 of + put -> + {ok, Method@1}; + + patch -> + {ok, Method@1}; + + delete -> + {ok, Method@1}; + + _ -> + {error, nil} + end end + ) + end + ) + end + ). + +-spec method_override( + fun((gleam@http@request:request(GKF)) -> gleam@http@response:response(GKG)) +) -> fun((gleam@http@request:request(GKF)) -> gleam@http@response:response(GKG)). +method_override(Service) -> + fun(Request) -> _pipe = Request, + _pipe@1 = ensure_post(_pipe), + _pipe@2 = gleam@result:then(_pipe@1, fun get_override_method/1), + _pipe@3 = gleam@result:map( + _pipe@2, + fun(_capture) -> + gleam@http@request:set_method(Request, _capture) + end + ), + _pipe@4 = gleam@result:unwrap(_pipe@3, Request), + Service(_pipe@4) end. diff --git a/aoc2023/build/packages/gleam_http/src/gleam_http.app.src b/aoc2023/build/packages/gleam_http/src/gleam_http.app.src new file mode 100644 index 0000000..c37ad54 --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam_http.app.src @@ -0,0 +1,12 @@ +{application, gleam_http, [ + {vsn, "3.5.2"}, + {applications, [gleam_stdlib, + gleeunit]}, + {description, "Types and functions for Gleam HTTP clients and servers"}, + {modules, [gleam@http, + gleam@http@cookie, + gleam@http@request, + gleam@http@response, + gleam@http@service]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/gleam_http/src/gleam_http_native.erl b/aoc2023/build/packages/gleam_http/src/gleam_http_native.erl new file mode 100644 index 0000000..bb499bb --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam_http_native.erl @@ -0,0 +1,88 @@ +-module(gleam_http_native). +-export([decode_method/1]). + +decode_method(Term) -> + case Term of + "connect" -> {ok, connect}; + "delete" -> {ok, delete}; + "get" -> {ok, get}; + "head" -> {ok, head}; + "options" -> {ok, options}; + "patch" -> {ok, patch}; + "post" -> {ok, post}; + "put" -> {ok, put}; + "trace" -> {ok, trace}; + "CONNECT" -> {ok, connect}; + "DELETE" -> {ok, delete}; + "GET" -> {ok, get}; + "HEAD" -> {ok, head}; + "OPTIONS" -> {ok, options}; + "PATCH" -> {ok, patch}; + "POST" -> {ok, post}; + "PUT" -> {ok, put}; + "TRACE" -> {ok, trace}; + "Connect" -> {ok, connect}; + "Delete" -> {ok, delete}; + "Get" -> {ok, get}; + "Head" -> {ok, head}; + "Options" -> {ok, options}; + "Patch" -> {ok, patch}; + "Post" -> {ok, post}; + "Put" -> {ok, put}; + "Trace" -> {ok, trace}; + 'connect' -> {ok, connect}; + 'delete' -> {ok, delete}; + 'get' -> {ok, get}; + 'head' -> {ok, head}; + 'options' -> {ok, options}; + 'patch' -> {ok, patch}; + 'post' -> {ok, post}; + 'put' -> {ok, put}; + 'trace' -> {ok, trace}; + 'CONNECT' -> {ok, connect}; + 'DELETE' -> {ok, delete}; + 'GET' -> {ok, get}; + 'HEAD' -> {ok, head}; + 'OPTIONS' -> {ok, options}; + 'PATCH' -> {ok, patch}; + 'POST' -> {ok, post}; + 'PUT' -> {ok, put}; + 'TRACE' -> {ok, trace}; + 'Connect' -> {ok, connect}; + 'Delete' -> {ok, delete}; + 'Get' -> {ok, get}; + 'Head' -> {ok, head}; + 'Options' -> {ok, options}; + 'Patch' -> {ok, patch}; + 'Post' -> {ok, post}; + 'Put' -> {ok, put}; + 'Trace' -> {ok, trace}; + <<"connect">> -> {ok, connect}; + <<"delete">> -> {ok, delete}; + <<"get">> -> {ok, get}; + <<"head">> -> {ok, head}; + <<"options">> -> {ok, options}; + <<"patch">> -> {ok, patch}; + <<"post">> -> {ok, post}; + <<"put">> -> {ok, put}; + <<"trace">> -> {ok, trace}; + <<"CONNECT">> -> {ok, connect}; + <<"DELETE">> -> {ok, delete}; + <<"GET">> -> {ok, get}; + <<"HEAD">> -> {ok, head}; + <<"OPTIONS">> -> {ok, options}; + <<"PATCH">> -> {ok, patch}; + <<"POST">> -> {ok, post}; + <<"PUT">> -> {ok, put}; + <<"TRACE">> -> {ok, trace}; + <<"Connect">> -> {ok, connect}; + <<"Delete">> -> {ok, delete}; + <<"Get">> -> {ok, get}; + <<"Head">> -> {ok, head}; + <<"Options">> -> {ok, options}; + <<"Patch">> -> {ok, patch}; + <<"Post">> -> {ok, post}; + <<"Put">> -> {ok, put}; + <<"Trace">> -> {ok, trace}; + _ -> {error, nil} + end. diff --git a/aoc2023/build/packages/gleam_http/src/gleam_http_native.mjs b/aoc2023/build/packages/gleam_http/src/gleam_http_native.mjs new file mode 100644 index 0000000..c871a8b --- /dev/null +++ b/aoc2023/build/packages/gleam_http/src/gleam_http_native.mjs @@ -0,0 +1,38 @@ +import { Ok, Error } from "./gleam.mjs"; +import { + Get, + Post, + Head, + Put, + Delete, + Trace, + Connect, + Options, + Patch, +} from "./gleam/http.mjs"; + +export function decode_method(value) { + try { + switch (value.toLowerCase()) { + case "get": + return new Ok(new Get()); + case "post": + return new Ok(new Post()); + case "head": + return new Ok(new Head()); + case "put": + return new Ok(new Put()); + case "delete": + return new Ok(new Delete()); + case "trace": + return new Ok(new Trace()); + case "connect": + return new Ok(new Connect()); + case "options": + return new Ok(new Options()); + case "patch": + return new Ok(new Patch()); + } + } catch {} + return new Error(undefined); +} diff --git a/aoc2023/build/packages/gleam_httpc/LICENSE b/aoc2023/build/packages/gleam_httpc/LICENSE new file mode 100644 index 0000000..59e1345 --- /dev/null +++ b/aoc2023/build/packages/gleam_httpc/LICENSE @@ -0,0 +1,191 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright {{copyright_year}}, {{author_name}} <{{author_email}}>. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/aoc2023/build/packages/gleam_httpc/README.md b/aoc2023/build/packages/gleam_httpc/README.md new file mode 100644 index 0000000..c2363c5 --- /dev/null +++ b/aoc2023/build/packages/gleam_httpc/README.md @@ -0,0 +1,52 @@ +# httpc +<a href="https://github.com/gleam-lang/httpc/releases"><img src="https://img.shields.io/github/release/gleam-lang/httpc" alt="GitHub release"></a> +<a href="https://discord.gg/Fm8Pwmy"><img src="https://img.shields.io/discord/768594524158427167?color=blue" alt="Discord chat"></a> + + +Bindings to Erlang's built in HTTP client, `httpc`. + +```gleam +import gleam/httpc +import gleam/http.{Get} +import gleam/http/request +import gleam/http/response +import gleeunit/should + +pub fn main() { + // Prepare a HTTP request record + let request = request.new() + |> request.set_method(Get) + |> request.set_host("test-api.service.hmrc.gov.uk") + |> request.set_path("/hello/world") + |> request.prepend_header("accept", "application/vnd.hmrc.1.0+json") + + // Send the HTTP request to the server + try resp = httpc.send(req) + + // We get a response record back + resp.status + |> should.equal(200) + + resp + |> response.get_header("content-type") + |> should.equal(Ok("application/json")) + + resp.body + |> should.equal("{\"message\":\"Hello World\"}") + + Ok(resp) +} +``` + +## Installation + +```shell +gleam add gleam_httpc +``` + +## Use with Erlang/OTP versions older than 26.0 + +Older versions of HTTPC do not verify TLS connections by default, so with them +your connection may not be secure when using this library. Consider upgrading to +a newer version of Erlang/OTP, or using a different HTTP client such as +[hackney](https://github.com/gleam-lang/hackney). diff --git a/aoc2023/build/packages/gleam_httpc/gleam.toml b/aoc2023/build/packages/gleam_httpc/gleam.toml new file mode 100644 index 0000000..d623a94 --- /dev/null +++ b/aoc2023/build/packages/gleam_httpc/gleam.toml @@ -0,0 +1,23 @@ +name = "gleam_httpc" +version = "2.1.1" +gleam = ">= 0.32.0" + +licences = ["Apache-2.0"] +description = "Gleam bindings to Erlang's built in HTTP client, httpc" + +repository = { type = "github", user = "gleam-lang", repo = "httpc" } +links = [ + { title = "Website", href = "https://gleam.run" }, + { title = "Sponsor", href = "https://github.com/sponsors/lpil" }, +] + +[erlang] +extra_applications = ["inets", "ssl"] + +[dependencies] +gleam_stdlib = "~> 0.32" +gleam_http = "~> 3.0" + +[dev-dependencies] +gleeunit = "~> 0.6" +gleam_erlang = "~> 0.9" diff --git a/aoc2023/build/packages/gleam_httpc/src/gleam/httpc.gleam b/aoc2023/build/packages/gleam_httpc/src/gleam/httpc.gleam new file mode 100644 index 0000000..cf166c3 --- /dev/null +++ b/aoc2023/build/packages/gleam_httpc/src/gleam/httpc.gleam @@ -0,0 +1,105 @@ +import gleam/dynamic.{type Dynamic} +import gleam/http.{type Method} +import gleam/http/response.{type Response, Response} +import gleam/http/request.{type Request} +import gleam/bit_array +import gleam/result +import gleam/list +import gleam/uri + +type Charlist + +@external(erlang, "erlang", "binary_to_list") +fn binary_to_list(a: String) -> Charlist + +@external(erlang, "erlang", "list_to_binary") +fn list_to_binary(a: Charlist) -> String + +type ErlHttpOption + +type BodyFormat { + Binary +} + +type ErlOption { + BodyFormat(BodyFormat) +} + +@external(erlang, "httpc", "request") +fn erl_request( + a: Method, + b: #(Charlist, List(#(Charlist, Charlist)), Charlist, BitArray), + c: List(ErlHttpOption), + d: List(ErlOption), +) -> Result( + #(#(Charlist, Int, Charlist), List(#(Charlist, Charlist)), BitArray), + Dynamic, +) + +@external(erlang, "httpc", "request") +fn erl_request_no_body( + a: Method, + b: #(Charlist, List(#(Charlist, Charlist))), + c: List(ErlHttpOption), + d: List(ErlOption), +) -> Result( + #(#(Charlist, Int, Charlist), List(#(Charlist, Charlist)), BitArray), + Dynamic, +) + +fn charlist_header(header: #(String, String)) -> #(Charlist, Charlist) { + let #(k, v) = header + #(binary_to_list(k), binary_to_list(v)) +} + +fn string_header(header: #(Charlist, Charlist)) -> #(String, String) { + let #(k, v) = header + #(list_to_binary(k), list_to_binary(v)) +} + +// TODO: test +// TODO: refine error type +pub fn send_bits(req: Request(BitArray)) -> Result(Response(BitArray), Dynamic) { + let erl_url = + req + |> request.to_uri + |> uri.to_string + |> binary_to_list + let erl_headers = list.map(req.headers, charlist_header) + let erl_http_options = [] + let erl_options = [BodyFormat(Binary)] + + use response <- result.then(case req.method { + http.Options | http.Head | http.Get -> { + let erl_req = #(erl_url, erl_headers) + erl_request_no_body(req.method, erl_req, erl_http_options, erl_options) + } + _ -> { + let erl_content_type = + req + |> request.get_header("content-type") + |> result.unwrap("application/octet-stream") + |> binary_to_list + let erl_req = #(erl_url, erl_headers, erl_content_type, req.body) + erl_request(req.method, erl_req, erl_http_options, erl_options) + } + }) + + let #(#(_version, status, _status), headers, resp_body) = response + Ok(Response(status, list.map(headers, string_header), resp_body)) +} + +// TODO: test +// TODO: refine error type +pub fn send(req: Request(String)) -> Result(Response(String), Dynamic) { + use resp <- result.then( + req + |> request.map(bit_array.from_string) + |> send_bits, + ) + + case bit_array.to_string(resp.body) { + Ok(body) -> Ok(response.set_body(resp, body)) + Error(_) -> Error(dynamic.from("Response body was not valid UTF-8")) + } +} diff --git a/aoc2023/build/packages/gleam_httpc/src/gleam@httpc.erl b/aoc2023/build/packages/gleam_httpc/src/gleam@httpc.erl new file mode 100644 index 0000000..1d634df --- /dev/null +++ b/aoc2023/build/packages/gleam_httpc/src/gleam@httpc.erl @@ -0,0 +1,118 @@ +-module(gleam@httpc). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([send_bits/1, send/1]). +-export_type([charlist/0, erl_http_option/0, body_format/0, erl_option/0]). + +-type charlist() :: any(). + +-type erl_http_option() :: any(). + +-type body_format() :: binary. + +-type erl_option() :: {body_format, body_format()}. + +-spec charlist_header({binary(), binary()}) -> {charlist(), charlist()}. +charlist_header(Header) -> + {K, V} = Header, + {erlang:binary_to_list(K), erlang:binary_to_list(V)}. + +-spec string_header({charlist(), charlist()}) -> {binary(), binary()}. +string_header(Header) -> + {K, V} = Header, + {erlang:list_to_binary(K), erlang:list_to_binary(V)}. + +-spec send_bits(gleam@http@request:request(bitstring())) -> {ok, + gleam@http@response:response(bitstring())} | + {error, gleam@dynamic:dynamic_()}. +send_bits(Req) -> + Erl_url = begin + _pipe = Req, + _pipe@1 = gleam@http@request:to_uri(_pipe), + _pipe@2 = gleam@uri:to_string(_pipe@1), + erlang:binary_to_list(_pipe@2) + end, + Erl_headers = gleam@list:map(erlang:element(3, Req), fun charlist_header/1), + Erl_http_options = [], + Erl_options = [{body_format, binary}], + gleam@result:then(case erlang:element(2, Req) of + options -> + Erl_req = {Erl_url, Erl_headers}, + httpc:request( + erlang:element(2, Req), + Erl_req, + Erl_http_options, + Erl_options + ); + + head -> + Erl_req = {Erl_url, Erl_headers}, + httpc:request( + erlang:element(2, Req), + Erl_req, + Erl_http_options, + Erl_options + ); + + get -> + Erl_req = {Erl_url, Erl_headers}, + httpc:request( + erlang:element(2, Req), + Erl_req, + Erl_http_options, + Erl_options + ); + + _ -> + Erl_content_type = begin + _pipe@3 = Req, + _pipe@4 = gleam@http@request:get_header( + _pipe@3, + <<"content-type"/utf8>> + ), + _pipe@5 = gleam@result:unwrap( + _pipe@4, + <<"application/octet-stream"/utf8>> + ), + erlang:binary_to_list(_pipe@5) + end, + Erl_req@1 = {Erl_url, + Erl_headers, + Erl_content_type, + erlang:element(4, Req)}, + httpc:request( + erlang:element(2, Req), + Erl_req@1, + Erl_http_options, + Erl_options + ) + end, fun(Response) -> + {{_, Status, _}, Headers, Resp_body} = Response, + {ok, + {response, + Status, + gleam@list:map(Headers, fun string_header/1), + Resp_body}} + end). + +-spec send(gleam@http@request:request(binary())) -> {ok, + gleam@http@response:response(binary())} | + {error, gleam@dynamic:dynamic_()}. +send(Req) -> + gleam@result:then( + begin + _pipe = Req, + _pipe@1 = gleam@http@request:map(_pipe, fun gleam_stdlib:identity/1), + send_bits(_pipe@1) + end, + fun(Resp) -> case gleam@bit_array:to_string(erlang:element(4, Resp)) of + {ok, Body} -> + {ok, gleam@http@response:set_body(Resp, Body)}; + + {error, _} -> + {error, + gleam@dynamic:from( + <<"Response body was not valid UTF-8"/utf8>> + )} + end end + ). diff --git a/aoc2023/build/packages/gleam_httpc/src/gleam_httpc.app.src b/aoc2023/build/packages/gleam_httpc/src/gleam_httpc.app.src new file mode 100644 index 0000000..c0d2b20 --- /dev/null +++ b/aoc2023/build/packages/gleam_httpc/src/gleam_httpc.app.src @@ -0,0 +1,12 @@ +{application, gleam_httpc, [ + {vsn, "2.1.1"}, + {applications, [gleam_erlang, + gleam_http, + gleam_stdlib, + gleeunit, + inets, + ssl]}, + {description, "Gleam bindings to Erlang's built in HTTP client, httpc"}, + {modules, [gleam@httpc]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/gleam_otp/LICENCE b/aoc2023/build/packages/gleam_otp/LICENCE new file mode 100644 index 0000000..619ec77 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/LICENCE @@ -0,0 +1,191 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2019, Louis Pilfold <louis@lpil.uk>. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/aoc2023/build/packages/gleam_otp/README.md b/aoc2023/build/packages/gleam_otp/README.md new file mode 100644 index 0000000..3c313a1 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/README.md @@ -0,0 +1,91 @@ +# Gleam OTP + +<a href="https://github.com/gleam-lang/otp/releases"><img src="https://img.shields.io/github/release/gleam-lang/otp" alt="GitHub release"></a> +<a href="https://discord.gg/Fm8Pwmy"><img src="https://img.shields.io/discord/768594524158427167?color=blue" alt="Discord chat"></a> + + +A Gleam library for building fault tolerant multi-core programs using the +actor model. It is compatible with Erlang's OTP framework. + +This library is experimental and will likely have many breaking changes in the +future! + +Gleam’s actor system is built with a few primary goals: + +- Full type safety of actors and messages. +- Be compatible with Erlang’s OTP actor framework. +- Provide fault tolerance and self-healing through supervisors. +- Have equivalent performance to Erlang’s OTP. + +This library documents its abstractions and functionality, but you may also wish +to read the documentation or other material on Erlang’s OTP framework to get a +fuller understanding of OTP, the problems it solves, and and the motivations for +its design. + +## Usage + +Add this library to your Gleam project. + +```shell +gleam add gleam_otp +``` + +## Actor hierarchy + +This library provides several different types of actor that can be used in +Gleam programs. + +### Process + +The process is the lowest level building block of OTP, all other actors are +built on top of processes either directly or indirectly. Typically this +abstraction would be not be used very often in Gleam applications, favour +other actor types that provide more functionality. + +Gleam's process module is defined in the `gleam_erlang` library. + +[[Documentation]](https://hexdocs.pm/gleam_erlang/gleam/erlang/process.html) + +### Actor + +The `actor` is the most commonly used process type in Gleam and serves as a good +building block for other abstractions. Like Erlang's `gen_server` it handles +OTP's system messages automatically to enable OTP's debugging and tracing +functionality. + +[[Documentation]](https://hexdocs.pm/gleam_otp/gleam/otp/actor.html) + +### Task + +A task is a kind of process that performs a single task and then shuts down. +Commonly tasks are used to convert sequential code into concurrent code by +performing computation in another process. + +[[Documentation]](https://hexdocs.pm/gleam_otp/gleam/otp/task.html) + +### Supervisor + +Supervisors is a process that starts and then supervises a group of processes, +restarting them if they crash. Supervisors can start other supervisors, +resulting in a hierarchical process structure called a supervision tree, +providing fault tolerance to a Gleam application. + +[[Documentation]](https://hexdocs.pm/gleam_otp/gleam/otp/supervisor.html) + +## Limitations and known issues + +This library is experimental there are some limitations that not yet been resolved. + +- There is no support for named processes. They are untyped global mutable + variables which may be uninitialized, more research is needed to find a + suitable type safe alternative. +- There are relatively few actor abstractions provided by this library. More + will be added in the future. +- Actors do not yet support all OTP system messages. Unsupported messages are + dropped. +- Supervisors do not yet support different shutdown periods per child. In + practice this means that children that are supervisors do not get an + unlimited amount of time to shut down, as is expected in Erlang or Elixir. +- This library has not seen much testing compared to the Erlang OTP + libraries, both in terms of unit tests and real world testing in + applications. diff --git a/aoc2023/build/packages/gleam_otp/gleam.toml b/aoc2023/build/packages/gleam_otp/gleam.toml new file mode 100644 index 0000000..26e451b --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/gleam.toml @@ -0,0 +1,19 @@ +name = "gleam_otp" +version = "0.8.0" +licences = ["Apache-2.0"] +description = "Fault tolerant multicore Gleam programs with OTP" + +gleam = ">= 0.32.0" + +repository = { type = "github", user = "gleam-lang", repo = "otp" } +links = [ + { title = "Website", href = "https://gleam.run" }, + { title = "Sponsor", href = "https://github.com/sponsors/lpil" }, +] + +[dependencies] +gleam_stdlib = "~> 0.32" +gleam_erlang = "~> 0.22" + +[dev-dependencies] +gleeunit = "~> 1.0" diff --git a/aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Continue.hrl b/aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Continue.hrl new file mode 100644 index 0000000..85677d1 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Continue.hrl @@ -0,0 +1,4 @@ +-record(continue, { + state :: any(), + selector :: gleam@option:option(gleam@erlang@process:selector(any())) +}). diff --git a/aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Ready.hrl b/aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Ready.hrl new file mode 100644 index 0000000..75faa95 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Ready.hrl @@ -0,0 +1 @@ +-record(ready, {state :: any(), selector :: gleam@erlang@process:selector(any())}). diff --git a/aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Spec.hrl b/aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Spec.hrl new file mode 100644 index 0000000..5287439 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Spec.hrl @@ -0,0 +1,5 @@ +-record(spec, { + init :: fun(() -> gleam@otp@actor:init_result(any(), any())), + init_timeout :: integer(), + loop :: fun((any(), any()) -> gleam@otp@actor:next(any(), any())) +}). diff --git a/aoc2023/build/packages/gleam_otp/include/gleam@otp@intensity_tracker_IntensityTracker.hrl b/aoc2023/build/packages/gleam_otp/include/gleam@otp@intensity_tracker_IntensityTracker.hrl new file mode 100644 index 0000000..3ed0b01 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/include/gleam@otp@intensity_tracker_IntensityTracker.hrl @@ -0,0 +1,5 @@ +-record(intensity_tracker, { + limit :: integer(), + period :: integer(), + events :: list(integer()) +}). diff --git a/aoc2023/build/packages/gleam_otp/include/gleam@otp@supervisor_ChildSpec.hrl b/aoc2023/build/packages/gleam_otp/include/gleam@otp@supervisor_ChildSpec.hrl new file mode 100644 index 0000000..7afd07f --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/include/gleam@otp@supervisor_ChildSpec.hrl @@ -0,0 +1,5 @@ +-record(child_spec, { + start :: fun((any()) -> {ok, gleam@erlang@process:subject(any())} | + {error, gleam@otp@actor:start_error()}), + returning :: fun((any(), gleam@erlang@process:subject(any())) -> any()) +}). diff --git a/aoc2023/build/packages/gleam_otp/include/gleam@otp@supervisor_Spec.hrl b/aoc2023/build/packages/gleam_otp/include/gleam@otp@supervisor_Spec.hrl new file mode 100644 index 0000000..b10bd9f --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/include/gleam@otp@supervisor_Spec.hrl @@ -0,0 +1,6 @@ +-record(spec, { + argument :: any(), + max_frequency :: integer(), + frequency_period :: integer(), + init :: fun((gleam@otp@supervisor:children(any())) -> gleam@otp@supervisor:children(any())) +}). diff --git a/aoc2023/build/packages/gleam_otp/include/gleam@otp@system_StatusInfo.hrl b/aoc2023/build/packages/gleam_otp/include/gleam@otp@system_StatusInfo.hrl new file mode 100644 index 0000000..99ab4cb --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/include/gleam@otp@system_StatusInfo.hrl @@ -0,0 +1,7 @@ +-record(status_info, { + module :: gleam@erlang@atom:atom_(), + parent :: gleam@erlang@process:pid_(), + mode :: gleam@otp@system:mode(), + debug_state :: gleam@otp@system:debug_state(), + state :: gleam@dynamic:dynamic_() +}). diff --git a/aoc2023/build/packages/gleam_otp/include/gleam@otp@task_Exit.hrl b/aoc2023/build/packages/gleam_otp/include/gleam@otp@task_Exit.hrl new file mode 100644 index 0000000..7c83874 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/include/gleam@otp@task_Exit.hrl @@ -0,0 +1 @@ +-record(exit, {reason :: gleam@dynamic:dynamic_()}). diff --git a/aoc2023/build/packages/gleam_otp/include/gleam@otp@task_Task.hrl b/aoc2023/build/packages/gleam_otp/include/gleam@otp@task_Task.hrl new file mode 100644 index 0000000..959bea8 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/include/gleam@otp@task_Task.hrl @@ -0,0 +1,6 @@ +-record(task, { + owner :: gleam@erlang@process:pid_(), + pid :: gleam@erlang@process:pid_(), + monitor :: gleam@erlang@process:process_monitor(), + selector :: gleam@erlang@process:selector(gleam@otp@task:message(any())) +}). diff --git a/aoc2023/build/packages/gleam_otp/src/gleam/otp/actor.gleam b/aoc2023/build/packages/gleam_otp/src/gleam/otp/actor.gleam new file mode 100644 index 0000000..9f6a6c4 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam/otp/actor.gleam @@ -0,0 +1,504 @@ +//// This module provides the _Actor_ abstraction, one of the most common +//// building blocks of Gleam OTP programs. +//// +//// An Actor is a process like any other BEAM process and can be be used to hold +//// state, execute code, and communicate with other processes by sending and +//// receiving messages. The advantage of using the actor abstraction over a bare +//// process is that it provides a single interface for commonly needed +//// functionality, including support for the [tracing and debugging +//// features in OTP](erlang-sys). +//// +//// Gleam's Actor is similar to Erlang's `gen_server` and Elixir's `GenServer` +//// but differs in that it offers a fully typed interface. This different API is +//// why Gleam uses the name Actor rather than some variation of generic-server. +//// +//// [erlang-sys]: https://www.erlang.org/doc/man/sys.html +//// +//// ## Example +//// +//// An Actor can be used to create a client-server interaction between an Actor +//// (the server) and other processes (the clients). In this example we have an +//// Actor that works as a stack, allowing clients to push and pop elements. +//// +//// ```gleam +//// pub fn main() { +//// // Start the actor with initial state of an empty list, and the +//// // `handle_message` callback function (defined below). +//// // We assert that it starts successfully. +//// // +//// // In real-world Gleam OTP programs we would likely write a wrapper functions +//// // called `start`, `push` `pop`, `shutdown` to start and interact with the +//// // Actor. We are not doing that here for the sake of showing how the Actor +//// // API works. +//// let assert Ok(actor) = actor.start([], handle_message) +//// +//// // We can send a message to the actor to push elements onto the stack. +//// process.send(actor, Push("Joe")) +//// process.send(actor, Push("Mike")) +//// process.send(actor, Push("Robert")) +//// +//// // The `Push` message expects no response, these messages are sent purely for +//// // the side effect of mutating the state held by the actor. +//// // +//// // We can also send the `Pop` message to take a value off of the actor's +//// // stack. This message expects a response, so we use `process.call` to send a +//// // message and wait until a reply is received. +//// // +//// // In this instance we are giving the actor 10 milliseconds to reply, if the +//// // `call` function doesn't get a reply within this time it will panic and +//// // crash the client process. +//// let assert Ok("Robert") = process.call(actor, Pop, 10) +//// let assert Ok("Mike") = process.call(actor, Pop, 10) +//// let assert Ok("Joe") = process.call(actor, Pop, 10) +//// +//// // The stack is now empty, so if we pop again the actor replies with an error. +//// let assert Error(Nil) = process.call(actor, Pop, 10) +//// +//// // Lastly, we can send a message to the actor asking it to shut down. +//// process.send(actor, Shutdown) +//// } +//// ``` +//// +//// Here is the code that is used to implement this actor: +//// +//// ```gleam +//// // First step of implementing the stack Actor is to define the message type that +//// // it can receive. +//// // +//// // The type of the elements in the stack is no fixed so a type parameter is used +//// // for it instead of a concrete type such as `String` or `Int`. +//// pub type Message(element) { +//// // The `Shutdown` message is used to tell the actor to stop. +//// // It is the simplest message type, it contains no data. +//// Shutdown +//// +//// // The `Push` message is used to add a new element to the stack. +//// // It contains the item to add, the type of which is the `element` +//// // parameterised type. +//// Push(push: element) +//// +//// // The `Pop` message is used to remove an element from the stack. +//// // It contains a `Subject`, which is used to send the response back to the +//// // message sender. In this case the reply is of type `Result(element, Nil)`. +//// Pop(reply_with: Subject(Result(element, Nil))) +//// } +//// +//// // The last part is to implement the `handle_message` callback function. +//// // +//// // This function is called by the Actor each for each message it receives. +//// // Actor is single threaded only does one thing at a time, so it handles +//// // messages sequentially and one at a time, in the order they are received. +//// // +//// // The function takes the message and the current state, and returns a data +//// // structure that indicates what to do next, along with the new state. +//// fn handle_message( +//// message: Message(e), +//// stack: List(e), +//// ) -> actor.Next(Message(e), List(e)) { +//// case message { +//// // For the `Shutdown` message we return the `actor.Stop` value, which causes +//// // the actor to discard any remaining messages and stop. +//// Shutdown -> actor.Stop(process.Normal) +//// +//// // For the `Push` message we add the new element to the stack and return +//// // `actor.continue` with this new stack, causing the actor to process any +//// // queued messages or wait for more. +//// Push(value) -> { +//// let new_state = [value, ..stack] +//// actor.continue(new_state) +//// } +//// +//// // For the `Pop` message we attempt to remove an element from the stack, +//// // sending it or an error back to the caller, before continuing. +//// Pop(client) -> +//// case stack { +//// [] -> { +//// // When the stack is empty we can't pop an element, so we send an +//// // error back. +//// process.send(client, Error(Nil)) +//// actor.continue([]) +//// } +//// +//// [first, ..rest] -> { +//// // Otherwise we send the first element back and use the remaining +//// // elements as the new state. +//// process.send(client, Ok(first)) +//// actor.continue(rest) +//// } +//// } +//// } +//// } +//// ``` + +import gleam/erlang/process.{ + type ExitReason, type Pid, type Selector, type Subject, Abnormal, +} +import gleam/erlang/charlist.{type Charlist} +import gleam/otp/system.{ + type DebugState, type Mode, type StatusInfo, type SystemMessage, GetState, + GetStatus, Resume, Running, StatusInfo, Suspend, Suspended, +} +import gleam/string +import gleam/dynamic.{type Dynamic} +import gleam/erlang/atom +import gleam/option.{type Option, None, Some} + +type Message(message) { + /// A regular message excepted by the process + Message(message) + + /// An OTP system message, for debugging or maintenance + System(SystemMessage) + + /// An unexpected message + Unexpected(Dynamic) +} + +/// The type used to indicate what to do after handling a message. +/// +pub type Next(message, state) { + /// Continue handling messages. + /// + Continue(state: state, selector: Option(Selector(message))) + + /// Stop handling messages and shut down. + /// + Stop(ExitReason) +} + +pub fn continue(state: state) -> Next(message, state) { + Continue(state, None) +} + +pub fn with_selector( + value: Next(message, state), + selector: Selector(message), +) -> Next(message, state) { + case value { + Continue(state, _) -> Continue(state, Some(selector)) + _ -> value + } +} + +/// The type used to indicate whether an actor has started successfully or not. +/// +pub type InitResult(state, message) { + /// The actor has successfully initialised. The actor can start handling + /// messages and actor's channel sender can be returned to the parent + /// process. + /// + Ready(state: state, selector: Selector(message)) + + /// The actor has failed to initialise. The actor shuts down and an error is + /// returned to the parent process. + /// + Failed(String) +} + +type Self(state, msg) { + Self( + mode: Mode, + parent: Pid, + state: state, + subject: Subject(msg), + selector: Selector(Message(msg)), + debug_state: DebugState, + message_handler: fn(msg, state) -> Next(msg, state), + ) +} + +/// This data structure holds all the values required by the `start_spec` +/// function in order to create an actor. +/// +/// If you do not need to configure the initialisation behaviour of your actor +/// consider using the `start` function. +/// +pub type Spec(state, msg) { + Spec( + /// The initialisation functionality for the actor. This function is called + /// just after the actor starts but before the channel sender is returned + /// to the parent. + /// + /// This function is used to ensure that any required data or state is + /// correct. If this function returns an error it means that the actor has + /// failed to start and an error is returned to the parent. + /// + init: fn() -> InitResult(state, msg), + /// How many milliseconds the `init` function has to return before it is + /// considered to have taken too long and failed. + /// + init_timeout: Int, + /// This function is called to handle each message that the actor receives. + /// + loop: fn(msg, state) -> Next(msg, state), + ) +} + +// TODO: Check needed functionality here to be OTP compatible +fn exit_process(reason: ExitReason) -> ExitReason { + // TODO + reason +} + +fn receive_message(self: Self(state, msg)) -> Message(msg) { + let selector = case self.mode { + // When suspended we only respond to system messages + Suspended -> + process.new_selector() + |> selecting_system_messages + + // When running we respond to all messages + Running -> + // We add the handler for unexpected messages first so that the user + // supplied selector can override it if desired + process.new_selector() + |> process.selecting_anything(Unexpected) + |> process.merge_selector(self.selector) + |> selecting_system_messages + } + + process.select_forever(selector) +} + +fn selecting_system_messages( + selector: Selector(Message(msg)), +) -> Selector(Message(msg)) { + selector + |> process.selecting_record3( + atom.create_from_string("system"), + convert_system_message, + ) +} + +@external(erlang, "gleam_otp_external", "convert_system_message") +fn convert_system_message(a: Dynamic, b: Dynamic) -> Message(msg) + +fn process_status_info(self: Self(state, msg)) -> StatusInfo { + StatusInfo( + module: atom.create_from_string("gleam@otp@actor"), + parent: self.parent, + mode: self.mode, + debug_state: self.debug_state, + state: dynamic.from(self.state), + ) +} + +fn loop(self: Self(state, msg)) -> ExitReason { + case receive_message(self) { + System(system) -> + case system { + GetState(callback) -> { + callback(dynamic.from(self.state)) + loop(self) + } + Resume(callback) -> { + callback() + loop(Self(..self, mode: Running)) + } + Suspend(callback) -> { + callback() + loop(Self(..self, mode: Suspended)) + } + GetStatus(callback) -> { + callback(process_status_info(self)) + loop(self) + } + } + + Unexpected(message) -> { + log_warning( + charlist.from_string("Actor discarding unexpected message: ~s"), + [charlist.from_string(string.inspect(message))], + ) + loop(self) + } + + Message(msg) -> + case self.message_handler(msg, self.state) { + Stop(reason) -> exit_process(reason) + Continue(state: state, selector: new_selector) -> { + let selector = + new_selector + |> option.map(init_selector(self.subject, _)) + |> option.unwrap(self.selector) + loop(Self(..self, state: state, selector: selector)) + } + } + } +} + +// TODO: replace this when we have Gleam bindings to the logger +@external(erlang, "logger", "warning") +fn log_warning(a: Charlist, b: List(Charlist)) -> Nil + +fn initialise_actor( + spec: Spec(state, msg), + ack: Subject(Result(Subject(msg), ExitReason)), +) { + let subject = process.new_subject() + case spec.init() { + Ready(state, selector) -> { + let selector = init_selector(subject, selector) + // Signal to parent that the process has initialised successfully + process.send(ack, Ok(subject)) + // Start message receive loop + let self = + Self( + state: state, + parent: process.subject_owner(ack), + subject: subject, + selector: selector, + message_handler: spec.loop, + debug_state: system.debug_state([]), + mode: Running, + ) + loop(self) + } + + Failed(reason) -> { + process.send(ack, Error(Abnormal(reason))) + exit_process(Abnormal(reason)) + } + } +} + +fn init_selector(subject, selector) { + process.new_selector() + |> process.selecting(subject, Message) + |> process.merge_selector(process.map_selector(selector, Message)) +} + +pub type StartError { + InitTimeout + InitFailed(ExitReason) + InitCrashed(Dynamic) +} + +/// The result of starting a Gleam actor. +/// +/// This type is compatible with Gleam supervisors. If you wish to convert it +/// to a type compatible with Erlang supervisors see the `ErlangStartResult` +/// type and `erlang_start_result` function. +/// +pub type StartResult(msg) = + Result(Subject(msg), StartError) + +/// An Erlang supervisor compatible process start result. +/// +/// If you wish to convert this into a `StartResult` compatible with Gleam +/// supervisors see the `from_erlang_start_result` and `wrap_erlang_starter` +/// functions. +/// +pub type ErlangStartResult = + Result(Pid, Dynamic) + +/// Convert a Gleam actor start result into an Erlang supervisor compatible +/// process start result. +/// +pub fn to_erlang_start_result(res: StartResult(msg)) -> ErlangStartResult { + case res { + Ok(x) -> Ok(process.subject_owner(x)) + Error(x) -> Error(dynamic.from(x)) + } +} + +type StartInitMessage(msg) { + Ack(Result(Subject(msg), ExitReason)) + Mon(process.ProcessDown) +} + +// TODO: test init_timeout. Currently if we test it eunit prints an error from +// the process death. How do we avoid this? +// +/// Start an actor from a given specification. If the actor's `init` function +/// returns an error or does not return within `init_timeout` then an error is +/// returned. +/// +/// If you do not need to specify the initialisation behaviour of your actor +/// consider using the `start` function. +/// +pub fn start_spec(spec: Spec(state, msg)) -> Result(Subject(msg), StartError) { + let ack_subject = process.new_subject() + + let child = + process.start( + linked: True, + running: fn() { initialise_actor(spec, ack_subject) }, + ) + + let monitor = process.monitor_process(child) + let selector = + process.new_selector() + |> process.selecting(ack_subject, Ack) + |> process.selecting_process_down(monitor, Mon) + + let result = case process.select(selector, spec.init_timeout) { + // Child started OK + Ok(Ack(Ok(channel))) -> Ok(channel) + + // Child initialiser returned an error + Ok(Ack(Error(reason))) -> Error(InitFailed(reason)) + + // Child went down while initialising + Ok(Mon(down)) -> Error(InitCrashed(down.reason)) + + // Child did not finish initialising in time + Error(Nil) -> { + process.kill(child) + Error(InitTimeout) + } + } + + // Remove the monitor used for the starting of the actor as to avoid an extra + // message arriving at the parent if the child dies later. + process.demonitor_process(monitor) + + result +} + +/// Start an actor with a given initial state and message handling loop +/// function. +/// +/// This function returns a `Result` but it will always be `Ok` so it is safe +/// to use with `assert` if you are not starting this actor as part of a +/// supervision tree. +/// +/// If you wish to configure the initialisation behaviour of a new actor see +/// the `Spec` record and the `start_spec` function. +/// +pub fn start( + state: state, + loop: fn(msg, state) -> Next(msg, state), +) -> Result(Subject(msg), StartError) { + start_spec(Spec( + init: fn() { Ready(state, process.new_selector()) }, + loop: loop, + init_timeout: 5000, + )) +} + +/// Send a message over a given channel. +/// +/// This is a re-export of `process.send`, for the sake of convenience. +/// +pub fn send(subject: Subject(msg), msg: msg) -> Nil { + process.send(subject, msg) +} + +// TODO: test +/// Send a synchronous message and wait for a response from the receiving +/// process. +/// +/// If a reply is not received within the given timeout then the sender process +/// crashes. If you wish receive a `Result` rather than crashing see the +/// `process.try_call` function. +/// +/// This is a re-export of `process.call`, for the sake of convenience. +/// +pub fn call( + selector: Subject(message), + make_message: fn(Subject(reply)) -> message, + timeout: Int, +) -> reply { + process.call(selector, make_message, timeout) +} diff --git a/aoc2023/build/packages/gleam_otp/src/gleam/otp/intensity_tracker.gleam b/aoc2023/build/packages/gleam_otp/src/gleam/otp/intensity_tracker.gleam new file mode 100644 index 0000000..2044be0 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam/otp/intensity_tracker.gleam @@ -0,0 +1,46 @@ +//// The intensity tracker is used to monitor how frequently an event happens, +//// erroring if it happens too many times within a period of time. + +import gleam/list + +// TODO: test +pub opaque type IntensityTracker { + IntensityTracker(limit: Int, period: Int, events: List(Int)) +} + +pub type TooIntense { + TooIntense +} + +pub fn new(limit limit: Int, period period: Int) -> IntensityTracker { + IntensityTracker(limit: limit, period: period, events: []) +} + +@external(erlang, "erlang", "monotonic_time") +fn monotonic_time(a: Int) -> Int + +fn now_seconds() -> Int { + monotonic_time(1) +} + +pub fn trim_window(events: List(Int), now: Int, period: Int) -> List(Int) { + case events { + [] -> [] + [event, ..events] -> + case now >= event + period { + True -> [event, ..trim_window(events, now, period)] + False -> [] + } + } +} + +pub fn add_event( + tracker: IntensityTracker, +) -> Result(IntensityTracker, TooIntense) { + let now = now_seconds() + let events = trim_window([now, ..tracker.events], now, tracker.period) + case list.length(events) >= tracker.limit { + True -> Error(TooIntense) + False -> Ok(IntensityTracker(..tracker, events: events)) + } +} diff --git a/aoc2023/build/packages/gleam_otp/src/gleam/otp/port.gleam b/aoc2023/build/packages/gleam_otp/src/gleam/otp/port.gleam new file mode 100644 index 0000000..4e1b4d8 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam/otp/port.gleam @@ -0,0 +1,9 @@ +/// Ports are how code running on the Erlang virtual machine interacts with +/// the outside world. Bytes of data can be sent to and read from ports, +/// providing a form of message passing to an external program or resource. +/// +/// For more information on ports see the [Erlang ports documentation][1]. +/// +/// [1]: https://erlang.org/doc/reference_manual/ports.html +/// +pub type Port diff --git a/aoc2023/build/packages/gleam_otp/src/gleam/otp/supervisor.gleam b/aoc2023/build/packages/gleam_otp/src/gleam/otp/supervisor.gleam new file mode 100644 index 0000000..b99ad8e --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam/otp/supervisor.gleam @@ -0,0 +1,410 @@ +// TODO: specify amount of time permitted for shut-down +import gleam/result +import gleam/string +import gleam/option.{type Option, None, Some} +import gleam/erlang/process.{type Pid, type Subject} +import gleam/otp/actor.{type StartError} +import gleam/otp/intensity_tracker.{type IntensityTracker} +import gleam/erlang/node.{type Node} + +/// This data structure holds all the values required by the `start_spec` +/// function in order to create an supervisor. +/// +/// If you do not need to configure the behaviour of your supervisor consider +/// using the `start` function. +/// +pub type Spec(argument, return) { + Spec( + argument: argument, + max_frequency: Int, + frequency_period: Int, + init: fn(Children(argument)) -> Children(return), + ) +} + +/// This type represents the starting children of a supervisor within the +/// `init` function. +/// +pub opaque type Children(argument) { + Ready(Starter(argument)) + Failed(ChildStartError) +} + +/// This type contains all the information required to start a new child and +/// add it to the `Children`. +/// +/// This is typically created with the `worker` function. +/// +pub opaque type ChildSpec(msg, argument, returning) { + ChildSpec( + // TODO: merge this into one field + start: fn(argument) -> Result(Subject(msg), StartError), + returning: fn(argument, Subject(msg)) -> returning, + ) +} + +type ChildStartError { + ChildStartError(previous_pid: Option(Pid), error: StartError) +} + +pub opaque type Message { + Exit(process.ExitMessage) + RetryRestart(Pid) +} + +type Instruction { + StartAll + StartFrom(Pid) +} + +type State(a) { + State( + restarts: IntensityTracker, + starter: Starter(a), + retry_restarts: Subject(Pid), + ) +} + +type Starter(argument) { + Starter( + argument: argument, + exec: Option( + fn(Instruction) -> + Result(#(Starter(argument), Instruction), ChildStartError), + ), + ) +} + +type Child(argument) { + Child(pid: Pid, argument: argument) +} + +fn start_child( + child_spec: ChildSpec(msg, argument_in, argument_out), + argument: argument_in, +) -> Result(Child(argument_out), ChildStartError) { + use subject <- result.then( + child_spec.start(argument) + |> result.map_error(ChildStartError(None, _)), + ) + + Ok(Child( + pid: process.subject_owner(subject), + // Merge the new child's pid into the argument to produce the new argument + // used to start any remaining children. + argument: child_spec.returning(argument, subject), + )) +} + +// TODO: more sophsiticated stopping of processes. i.e. give supervisors +// more time to shut down. +fn shutdown_child(pid: Pid, _spec: ChildSpec(msg, arg_1, arg_2)) -> Nil { + process.send_exit(pid) +} + +fn perform_instruction_for_child( + argument: argument_in, + instruction: Instruction, + child_spec: ChildSpec(msg, argument_in, argument_out), + child: Child(argument_out), +) -> Result(#(Child(argument_out), Instruction), ChildStartError) { + let current = child.pid + case instruction { + // This child is older than the StartFrom target, we don't need to + // restart it + StartFrom(target) if target != current -> Ok(#(child, instruction)) + + // This pid either is the cause of the problem, or we have the StartAll + // instruction. Either way it and its younger siblings need to be restarted. + _ -> { + shutdown_child(current, child_spec) + use child <- result.then(start_child(child_spec, argument)) + Ok(#(child, StartAll)) + } + } +} + +fn add_child_to_starter( + starter: Starter(argument_in), + child_spec: ChildSpec(msg, argument_in, argument_out), + child: Child(argument_out), +) -> Starter(argument_out) { + let starter = fn(instruction) { + // Restart the older children. We use `try` to return early if the older + // children failed to start + use #(starter, instruction) <- result.then(case starter.exec { + Some(start) -> start(instruction) + None -> Ok(#(starter, instruction)) + }) + + // Perform the instruction, restarting the child as required + use #(child, instruction) <- result.then(perform_instruction_for_child( + starter.argument, + instruction, + child_spec, + child, + )) + + // Create a new starter for the next time the supervisor needs to restart + let starter = add_child_to_starter(starter, child_spec, child) + + Ok(#(starter, instruction)) + } + + Starter(exec: Some(starter), argument: child.argument) +} + +fn start_and_add_child( + state: Starter(argument_0), + child_spec: ChildSpec(msg, argument_0, argument_1), +) -> Children(argument_1) { + case start_child(child_spec, state.argument) { + Ok(child) -> Ready(add_child_to_starter(state, child_spec, child)) + Error(reason) -> Failed(reason) + } +} + +/// Add a child to the collection of children of the supervisor +/// +/// This function starts the child from the child spec. +/// +pub fn add( + children: Children(argument), + child_spec: ChildSpec(msg, argument, new_argument), +) -> Children(new_argument) { + case children { + // If one of the previous children has failed then we cannot continue + Failed(fail) -> Failed(fail) + + // If everything is OK so far then we can add the child + Ready(state) -> start_and_add_child(state, child_spec) + } +} + +// TODO: test +// TODO: unlimitd shut down duration +/// Prepare a new supervisor type child. +/// +/// If you wish to prepare a new non-supervisor type child see the `worker` +/// function. +/// +/// If you wish to change the type of the argument for later children see the +/// `returning` function. +/// +/// Note: Gleam supervisors do not yet support different shutdown periods per +/// child so this function is currently identical in behaviour to `worker`. It is +/// recommended to use this function for supervisor children nevertheless so the +/// correct shut down behaviour is used in later releases of this library. +/// +pub fn supervisor( + start: fn(argument) -> Result(Subject(msg), StartError), +) -> ChildSpec(msg, argument, argument) { + ChildSpec(start: start, returning: fn(argument, _channel) { argument }) +} + +/// Prepare a new worker type child. +/// +/// If you wish to prepare a new supervisor type child see the `supervisor` +/// function. +/// +/// If you wish to change the type of the argument for later children see the +/// `returning` function. +/// +pub fn worker( + start: fn(argument) -> Result(Subject(msg), StartError), +) -> ChildSpec(msg, argument, argument) { + ChildSpec(start: start, returning: fn(argument, _channel) { argument }) +} + +// TODO: test +/// As each child is added to a supervisors children a new argument is prepared +/// with which to start the next child. By default argument is the same as the +/// previous argument, but this function can be used to change it to something +/// else by passing a function that takes the previous argument and the sender +/// of the previous child. +/// +pub fn returning( + child: ChildSpec(msg, argument_a, argument_b), + updater: fn(argument_a, Subject(msg)) -> argument_c, +) -> ChildSpec(msg, argument_a, argument_c) { + ChildSpec(start: child.start, returning: updater) +} + +fn init( + spec: Spec(argument, return), +) -> actor.InitResult(State(return), Message) { + // Create a subject so that we can asynchronously retry restarting when we + // fail to bring an exited child + let retry = process.new_subject() + + // Trap exits so that we get a message when a child crashes + process.trap_exits(True) + + // Combine selectors + let selector = + process.new_selector() + |> process.selecting(retry, RetryRestart) + |> process.selecting_trapped_exits(Exit) + + // Start any children + let result = + Starter(argument: spec.argument, exec: None) + |> Ready + |> spec.init + + // Pass back up the result + case result { + Ready(starter) -> { + let restarts = + intensity_tracker.new( + limit: spec.max_frequency, + period: spec.frequency_period, + ) + let state = + State(starter: starter, restarts: restarts, retry_restarts: retry) + actor.Ready(state, selector) + } + + Failed(error) -> + actor.Failed(case error.error { + actor.InitTimeout -> "Child initialisation timed out" + actor.InitCrashed(reason) -> + string.append( + "Child crashed during initialisation: ", + string.inspect(reason), + ) + actor.InitFailed(reason) -> + string.append( + "Child failed to start during initialisation: ", + string.inspect(reason), + ) + }) + } +} + +type HandleExitError { + RestartFailed(pid: Pid, restarts: IntensityTracker) + TooManyRestarts +} + +fn handle_exit(pid: Pid, state: State(a)) -> actor.Next(Message, State(a)) { + let outcome = { + // If we are handling an exit then we must have some children + let assert Some(start) = state.starter.exec + + // Check to see if there has been too many restarts in this period + use restarts <- result.then( + state.restarts + |> intensity_tracker.add_event + |> result.map_error(fn(_) { TooManyRestarts }), + ) + + // Restart the exited child and any following children + use #(starter, _) <- result.then( + start(StartFrom(pid)) + |> result.map_error(fn(e: ChildStartError) { + RestartFailed(option.unwrap(e.previous_pid, pid), restarts) + }), + ) + + Ok(State(..state, starter: starter, restarts: restarts)) + } + + case outcome { + Ok(state) -> actor.continue(state) + Error(RestartFailed(failed_child, restarts)) -> { + // Asynchronously enqueue the restarting of this child again as we were + // unable to restart them this time. We do this asynchronously as we want + // to have a chance to handle any system messages that have come in. + process.send(state.retry_restarts, failed_child) + let state = State(..state, restarts: restarts) + actor.continue(state) + } + Error(TooManyRestarts) -> + actor.Stop(process.Abnormal( + "Child processes restarted too many times within allowed period", + )) + } +} + +fn loop( + message: Message, + state: State(argument), +) -> actor.Next(Message, State(argument)) { + case message { + Exit(exit_message) -> handle_exit(exit_message.pid, state) + RetryRestart(pid) -> handle_exit(pid, state) + } +} + +/// Start a supervisor from a given specification. +/// +pub fn start_spec(spec: Spec(a, b)) -> Result(Subject(Message), StartError) { + actor.start_spec(actor.Spec( + init: fn() { init(spec) }, + loop: loop, + init_timeout: 60_000, + )) +} + +/// Start a supervisor from a given `init` function. +/// +/// The init argument passed to children will be `Nil` and the maximum restart +/// intensity will be 1 restart per 5 seconds (the same as the default for +/// [Erlang supervisors][erl-sup]). If you wish to specify these values, see +/// the `start_spec` function and the `Spec` type. +/// +/// [erl-sup]: https://www.erlang.org/doc/design_principles/sup_princ.html#maximum-restart-intensity +/// +pub fn start( + init: fn(Children(Nil)) -> Children(a), +) -> Result(Subject(Message), StartError) { + start_spec(Spec( + init: init, + argument: Nil, + max_frequency: 1, + frequency_period: 5, + )) +} + +/// A type used to describe the situation in which an Erlang based application +/// is starting. +/// +/// For more information see the [Erlang distributed application +/// documentation][1] and the Learn Your Some Erlang chapter on [distributed +/// applications][2]. +/// +/// [1]: https://erlang.org/doc/design_principles/distributed_applications.html +/// [2]: https://learnyousomeerlang.com/distributed-otp-applications +/// +pub type ApplicationStartMode { + Normal + Takeover(Node) + Failover(Node) +} + +pub type ApplicationStop + +@external(erlang, "gleam_otp_external", "application_stopped") +pub fn application_stopped() -> ApplicationStop + +/// The result of starting a Gleam actor. +/// +/// This type is compatible with Gleam supervisors. If you wish to convert it +/// to a type compatible with Erlang supervisors see the `ErlangStartResult` +/// type and `erlang_start_result` function. +/// +pub type StartResult(msg) = + actor.StartResult(msg) + +/// An Erlang supervisor compatible process start result. +/// +pub type ErlangStartResult = + actor.ErlangStartResult + +/// Convert a Gleam actor start result into an Erlang supervisor compatible +/// process start result. +/// +pub fn to_erlang_start_result(res: StartResult(msg)) -> ErlangStartResult { + actor.to_erlang_start_result(res) +} diff --git a/aoc2023/build/packages/gleam_otp/src/gleam/otp/system.gleam b/aoc2023/build/packages/gleam_otp/src/gleam/otp/system.gleam new file mode 100644 index 0000000..c05646b --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam/otp/system.gleam @@ -0,0 +1,89 @@ +import gleam/dynamic.{type Dynamic} +import gleam/erlang/atom.{type Atom} +import gleam/erlang/process.{type Pid} + +pub type Mode { + Running + Suspended +} + +pub type DebugOption { + NoDebug +} + +pub type DebugState + +@external(erlang, "sys", "debug_options") +pub fn debug_state(a: List(DebugOption)) -> DebugState + +pub type StatusInfo { + StatusInfo( + module: Atom, + parent: Pid, + mode: Mode, + debug_state: DebugState, + state: Dynamic, + ) +} + +// TODO: document +// TODO: implement remaining messages +pub type SystemMessage { + // {replace_state, StateFn} + // {change_code, Mod, Vsn, Extra} + // {terminate, Reason} + // {debug, {log, Flag}} + // {debug, {trace, Flag}} + // {debug, {log_to_file, FileName}} + // {debug, {statistics, Flag}} + // {debug, no_debug} + // {debug, {install, {Func, FuncState}}} + // {debug, {install, {FuncId, Func, FuncState}}} + // {debug, {remove, FuncOrId}} + Resume(fn() -> Nil) + Suspend(fn() -> Nil) + GetState(fn(Dynamic) -> Nil) + GetStatus(fn(StatusInfo) -> Nil) +} + +type DoNotLeak + +/// Get the state of a given OTP compatible process. This function is only +/// intended for debugging. +/// +/// For more information see the [Erlang documentation][1]. +/// +/// [1]: https://erlang.org/doc/man/sys.html#get_state-1 +/// +@external(erlang, "sys", "get_state") +pub fn get_state(from from: Pid) -> Dynamic + +@external(erlang, "sys", "suspend") +fn erl_suspend(a: Pid) -> DoNotLeak + +/// Request an OTP compatible process to suspend, causing it to only handle +/// system messages. +/// +/// For more information see the [Erlang documentation][1]. +/// +/// [1]: https://erlang.org/doc/man/sys.html#suspend-1 +/// +pub fn suspend(pid: Pid) -> Nil { + erl_suspend(pid) + Nil +} + +@external(erlang, "sys", "resume") +fn erl_resume(from from: Pid) -> DoNotLeak + +/// Request a suspended OTP compatible process to result, causing it to handle +/// all messages rather than only system messages. +/// +/// For more information see the [Erlang documentation][1]. +/// +/// [1]: https://erlang.org/doc/man/sys.html#resume-1 +/// +pub fn resume(pid: Pid) -> Nil { + erl_resume(pid) + Nil +} diff --git a/aoc2023/build/packages/gleam_otp/src/gleam/otp/task.gleam b/aoc2023/build/packages/gleam_otp/src/gleam/otp/task.gleam new file mode 100644 index 0000000..b2b2c5c --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam/otp/task.gleam @@ -0,0 +1,151 @@ +//// A task is a kind of process that performs a single task and then shuts +//// down. Commonly tasks are used to convert sequential code into concurrent +//// code by performing computation in another process. +//// +//// let task = task.async(fn() { do_some_work() }) +//// let value = do_some_other_work() +//// value + task.await(task, 100) +//// +//// Tasks spawned with async can be awaited on by their caller process (and +//// only their caller) as shown in the example above. They are implemented by +//// spawning a process that sends a message to the caller once the given +//// computation is performed. +//// +//// There are two important things to consider when using `async`: +//// +//// 1. If you are using async tasks, you must await a reply as they are always +//// sent. +//// +//// 2. async tasks link the caller and the spawned process. This means that, +//// if the caller crashes, the task will crash too and vice-versa. This is +//// on purpose: if the process meant to receive the result no longer +//// exists, there is no purpose in completing the computation. +//// +//// This module is inspired by Elixir's [Task module][1]. +//// +//// [1]: https://hexdocs.pm/elixir/master/Task.html +//// + +// TODO: await_many +import gleam/erlang/process.{type Pid, type ProcessMonitor, type Selector} +import gleam/dynamic.{type Dynamic} + +pub opaque type Task(value) { + Task( + owner: Pid, + pid: Pid, + monitor: ProcessMonitor, + selector: Selector(Message(value)), + ) +} + +// TODO: test +/// Spawn a task process that calls a given function in order to perform some +/// work. The result of this function is send back to the parent and can be +/// received using the `await` function. +/// +/// See the top level module documentation for more information on async/await. +/// +pub fn async(work: fn() -> value) -> Task(value) { + let owner = process.self() + let subject = process.new_subject() + let pid = + process.start(linked: True, running: fn() { process.send(subject, work()) }) + let monitor = process.monitor_process(pid) + let selector = + process.new_selector() + |> process.selecting_process_down(monitor, FromMonitor) + |> process.selecting(subject, FromSubject) + Task(owner: owner, pid: pid, monitor: monitor, selector: selector) +} + +pub type AwaitError { + Timeout + Exit(reason: Dynamic) +} + +// We can only wait on a task if we are the owner of it so crash if we are +// waiting on a task we don't own. +fn assert_owner(task: Task(a)) -> Nil { + let self = process.self() + case task.owner == self { + True -> Nil + False -> + process.send_abnormal_exit( + self, + "awaited on a task that does not belong to this process", + ) + } +} + +type Message(value) { + FromMonitor(process.ProcessDown) + FromSubject(value) +} + +// TODO: test +/// Wait for the value computed by a task. +/// +/// If the a value is not received before the timeout has elapsed or if the +/// task process crashes then an error is returned. +/// +pub fn try_await(task: Task(value), timeout: Int) -> Result(value, AwaitError) { + assert_owner(task) + case process.select(task.selector, timeout) { + // The task process has sent back a value + Ok(FromSubject(x)) -> { + process.demonitor_process(task.monitor) + Ok(x) + } + + // The task process crashed without sending a value + Ok(FromMonitor(process.ProcessDown(reason: reason, ..))) -> + Error(Exit(reason)) + + // The task process is alive but has not sent a value yet + Error(Nil) -> Error(Timeout) + } +} + +// TODO: test +/// Wait for the value computed by a task. +/// +/// If the a value is not received before the timeout has elapsed or if the +/// task process crashes then this function crashes. +/// +pub fn await(task: Task(value), timeout: Int) -> value { + let assert Ok(value) = try_await(task, timeout) + value +} + +/// Wait endlessly for the value computed by a task. +/// +/// Be Careful! This function does not return until there is a value to +/// receive. If a value is not received then the process will be stuck waiting +/// forever. +/// +pub fn try_await_forever(task: Task(value)) -> Result(value, AwaitError) { + assert_owner(task) + case process.select_forever(task.selector) { + // The task process has sent back a value + FromSubject(x) -> { + process.demonitor_process(task.monitor) + Ok(x) + } + + // The task process crashed without sending a value + FromMonitor(process.ProcessDown(reason: reason, ..)) -> Error(Exit(reason)) + } +} + +/// Wait endlessly for the value computed by a task. +/// +/// Be Careful! Like `try_await_forever`, this function does not return until there is a value to +/// receive. +/// +/// If the task process crashes then this function crashes. +/// +pub fn await_forever(task: Task(value)) -> value { + let assert Ok(value) = try_await_forever(task) + value +} diff --git a/aoc2023/build/packages/gleam_otp/src/gleam@otp@actor.erl b/aoc2023/build/packages/gleam_otp/src/gleam@otp@actor.erl new file mode 100644 index 0000000..0606147 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam@otp@actor.erl @@ -0,0 +1,273 @@ +-module(gleam@otp@actor). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([continue/1, with_selector/2, to_erlang_start_result/1, start_spec/1, start/2, send/2, call/3]). +-export_type([message/1, next/2, init_result/2, self/2, spec/2, start_error/0, start_init_message/1]). + +-type message(GAS) :: {message, GAS} | + {system, gleam@otp@system:system_message()} | + {unexpected, gleam@dynamic:dynamic_()}. + +-type next(GAT, GAU) :: {continue, + GAU, + gleam@option:option(gleam@erlang@process:selector(GAT))} | + {stop, gleam@erlang@process:exit_reason()}. + +-type init_result(GAV, GAW) :: {ready, GAV, gleam@erlang@process:selector(GAW)} | + {failed, binary()}. + +-type self(GAX, GAY) :: {self, + gleam@otp@system:mode(), + gleam@erlang@process:pid_(), + GAX, + gleam@erlang@process:subject(GAY), + gleam@erlang@process:selector(message(GAY)), + gleam@otp@system:debug_state(), + fun((GAY, GAX) -> next(GAY, GAX))}. + +-type spec(GAZ, GBA) :: {spec, + fun(() -> init_result(GAZ, GBA)), + integer(), + fun((GBA, GAZ) -> next(GBA, GAZ))}. + +-type start_error() :: init_timeout | + {init_failed, gleam@erlang@process:exit_reason()} | + {init_crashed, gleam@dynamic:dynamic_()}. + +-type start_init_message(GBB) :: {ack, + {ok, gleam@erlang@process:subject(GBB)} | + {error, gleam@erlang@process:exit_reason()}} | + {mon, gleam@erlang@process:process_down()}. + +-spec continue(GBI) -> next(any(), GBI). +continue(State) -> + {continue, State, none}. + +-spec with_selector(next(GBM, GBN), gleam@erlang@process:selector(GBM)) -> next(GBM, GBN). +with_selector(Value, Selector) -> + case Value of + {continue, State, _} -> + {continue, State, {some, Selector}}; + + _ -> + Value + end. + +-spec exit_process(gleam@erlang@process:exit_reason()) -> gleam@erlang@process:exit_reason(). +exit_process(Reason) -> + Reason. + +-spec selecting_system_messages(gleam@erlang@process:selector(message(GBY))) -> gleam@erlang@process:selector(message(GBY)). +selecting_system_messages(Selector) -> + _pipe = Selector, + gleam@erlang@process:selecting_record3( + _pipe, + erlang:binary_to_atom(<<"system"/utf8>>), + fun gleam_otp_external:convert_system_message/2 + ). + +-spec receive_message(self(any(), GBU)) -> message(GBU). +receive_message(Self) -> + Selector = case erlang:element(2, Self) of + suspended -> + _pipe = gleam_erlang_ffi:new_selector(), + selecting_system_messages(_pipe); + + running -> + _pipe@1 = gleam_erlang_ffi:new_selector(), + _pipe@2 = gleam@erlang@process:selecting_anything( + _pipe@1, + fun(Field@0) -> {unexpected, Field@0} end + ), + _pipe@3 = gleam_erlang_ffi:merge_selector( + _pipe@2, + erlang:element(6, Self) + ), + selecting_system_messages(_pipe@3) + end, + gleam_erlang_ffi:select(Selector). + +-spec process_status_info(self(any(), any())) -> gleam@otp@system:status_info(). +process_status_info(Self) -> + {status_info, + erlang:binary_to_atom(<<"gleam@otp@actor"/utf8>>), + erlang:element(3, Self), + erlang:element(2, Self), + erlang:element(7, Self), + gleam@dynamic:from(erlang:element(4, Self))}. + +-spec init_selector( + gleam@erlang@process:subject(GGN), + gleam@erlang@process:selector(GGN) +) -> gleam@erlang@process:selector(message(GGN)). +init_selector(Subject, Selector) -> + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = gleam@erlang@process:selecting( + _pipe, + Subject, + fun(Field@0) -> {message, Field@0} end + ), + gleam_erlang_ffi:merge_selector( + _pipe@1, + gleam_erlang_ffi:map_selector( + Selector, + fun(Field@0) -> {message, Field@0} end + ) + ). + +-spec loop(self(any(), any())) -> gleam@erlang@process:exit_reason(). +loop(Self) -> + case receive_message(Self) of + {system, System} -> + case System of + {get_state, Callback} -> + Callback(gleam@dynamic:from(erlang:element(4, Self))), + loop(Self); + + {resume, Callback@1} -> + Callback@1(), + loop(erlang:setelement(2, Self, running)); + + {suspend, Callback@2} -> + Callback@2(), + loop(erlang:setelement(2, Self, suspended)); + + {get_status, Callback@3} -> + Callback@3(process_status_info(Self)), + loop(Self) + end; + + {unexpected, Message} -> + logger:warning( + unicode:characters_to_list( + <<"Actor discarding unexpected message: ~s"/utf8>> + ), + [unicode:characters_to_list(gleam@string:inspect(Message))] + ), + loop(Self); + + {message, Msg} -> + case (erlang:element(8, Self))(Msg, erlang:element(4, Self)) of + {stop, Reason} -> + exit_process(Reason); + + {continue, State, New_selector} -> + Selector = begin + _pipe = New_selector, + _pipe@1 = gleam@option:map( + _pipe, + fun(_capture) -> + init_selector(erlang:element(5, Self), _capture) + end + ), + gleam@option:unwrap(_pipe@1, erlang:element(6, Self)) + end, + loop( + erlang:setelement( + 6, + erlang:setelement(4, Self, State), + Selector + ) + ) + end + end. + +-spec initialise_actor( + spec(any(), GCP), + gleam@erlang@process:subject({ok, gleam@erlang@process:subject(GCP)} | + {error, gleam@erlang@process:exit_reason()}) +) -> gleam@erlang@process:exit_reason(). +initialise_actor(Spec, Ack) -> + Subject = gleam@erlang@process:new_subject(), + case (erlang:element(2, Spec))() of + {ready, State, Selector} -> + Selector@1 = init_selector(Subject, Selector), + gleam@erlang@process:send(Ack, {ok, Subject}), + Self = {self, + running, + gleam@erlang@process:subject_owner(Ack), + State, + Subject, + Selector@1, + sys:debug_options([]), + erlang:element(4, Spec)}, + loop(Self); + + {failed, Reason} -> + gleam@erlang@process:send(Ack, {error, {abnormal, Reason}}), + exit_process({abnormal, Reason}) + end. + +-spec to_erlang_start_result( + {ok, gleam@erlang@process:subject(any())} | {error, start_error()} +) -> {ok, gleam@erlang@process:pid_()} | {error, gleam@dynamic:dynamic_()}. +to_erlang_start_result(Res) -> + case Res of + {ok, X} -> + {ok, gleam@erlang@process:subject_owner(X)}; + + {error, X@1} -> + {error, gleam@dynamic:from(X@1)} + end. + +-spec start_spec(spec(any(), GDD)) -> {ok, gleam@erlang@process:subject(GDD)} | + {error, start_error()}. +start_spec(Spec) -> + Ack_subject = gleam@erlang@process:new_subject(), + Child = gleam@erlang@process:start( + fun() -> initialise_actor(Spec, Ack_subject) end, + true + ), + Monitor = gleam@erlang@process:monitor_process(Child), + Selector = begin + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = gleam@erlang@process:selecting( + _pipe, + Ack_subject, + fun(Field@0) -> {ack, Field@0} end + ), + gleam@erlang@process:selecting_process_down( + _pipe@1, + Monitor, + fun(Field@0) -> {mon, Field@0} end + ) + end, + Result = case gleam_erlang_ffi:select(Selector, erlang:element(3, Spec)) of + {ok, {ack, {ok, Channel}}} -> + {ok, Channel}; + + {ok, {ack, {error, Reason}}} -> + {error, {init_failed, Reason}}; + + {ok, {mon, Down}} -> + {error, {init_crashed, erlang:element(3, Down)}}; + + {error, nil} -> + gleam@erlang@process:kill(Child), + {error, init_timeout} + end, + gleam_erlang_ffi:demonitor(Monitor), + Result. + +-spec start(GDJ, fun((GDK, GDJ) -> next(GDK, GDJ))) -> {ok, + gleam@erlang@process:subject(GDK)} | + {error, start_error()}. +start(State, Loop) -> + start_spec( + {spec, + fun() -> {ready, State, gleam_erlang_ffi:new_selector()} end, + 5000, + Loop} + ). + +-spec send(gleam@erlang@process:subject(GDQ), GDQ) -> nil. +send(Subject, Msg) -> + gleam@erlang@process:send(Subject, Msg). + +-spec call( + gleam@erlang@process:subject(GDS), + fun((gleam@erlang@process:subject(GDU)) -> GDS), + integer() +) -> GDU. +call(Selector, Make_message, Timeout) -> + gleam@erlang@process:call(Selector, Make_message, Timeout). diff --git a/aoc2023/build/packages/gleam_otp/src/gleam@otp@intensity_tracker.erl b/aoc2023/build/packages/gleam_otp/src/gleam@otp@intensity_tracker.erl new file mode 100644 index 0000000..8792f14 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam@otp@intensity_tracker.erl @@ -0,0 +1,53 @@ +-module(gleam@otp@intensity_tracker). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([new/2, trim_window/3, add_event/1]). +-export_type([intensity_tracker/0, too_intense/0]). + +-opaque intensity_tracker() :: {intensity_tracker, + integer(), + integer(), + list(integer())}. + +-type too_intense() :: too_intense. + +-spec new(integer(), integer()) -> intensity_tracker(). +new(Limit, Period) -> + {intensity_tracker, Limit, Period, []}. + +-spec now_seconds() -> integer(). +now_seconds() -> + erlang:monotonic_time(1). + +-spec trim_window(list(integer()), integer(), integer()) -> list(integer()). +trim_window(Events, Now, Period) -> + case Events of + [] -> + []; + + [Event | Events@1] -> + case Now >= (Event + Period) of + true -> + [Event | trim_window(Events@1, Now, Period)]; + + false -> + [] + end + end. + +-spec add_event(intensity_tracker()) -> {ok, intensity_tracker()} | + {error, too_intense()}. +add_event(Tracker) -> + Now = now_seconds(), + Events = trim_window( + [Now | erlang:element(4, Tracker)], + Now, + erlang:element(3, Tracker) + ), + case gleam@list:length(Events) >= erlang:element(2, Tracker) of + true -> + {error, too_intense}; + + false -> + {ok, erlang:setelement(4, Tracker, Events)} + end. diff --git a/aoc2023/build/packages/gleam_otp/src/gleam@otp@port.erl b/aoc2023/build/packages/gleam_otp/src/gleam@otp@port.erl new file mode 100644 index 0000000..b205739 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam@otp@port.erl @@ -0,0 +1,8 @@ +-module(gleam@otp@port). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export_type([port_/0]). + +-type port_() :: any(). + + diff --git a/aoc2023/build/packages/gleam_otp/src/gleam@otp@supervisor.erl b/aoc2023/build/packages/gleam_otp/src/gleam@otp@supervisor.erl new file mode 100644 index 0000000..39118f1 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam@otp@supervisor.erl @@ -0,0 +1,322 @@ +-module(gleam@otp@supervisor). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([add/2, supervisor/1, worker/1, returning/2, start_spec/1, start/1, application_stopped/0, to_erlang_start_result/1]). +-export_type([spec/2, children/1, child_spec/3, child_start_error/0, message/0, instruction/0, state/1, starter/1, child/1, handle_exit_error/0, application_start_mode/0, application_stop/0]). + +-type spec(GLS, GLT) :: {spec, + GLS, + integer(), + integer(), + fun((children(GLS)) -> children(GLT))}. + +-opaque children(GLU) :: {ready, starter(GLU)} | {failed, child_start_error()}. + +-opaque child_spec(GLV, GLW, GLX) :: {child_spec, + fun((GLW) -> {ok, gleam@erlang@process:subject(GLV)} | + {error, gleam@otp@actor:start_error()}), + fun((GLW, gleam@erlang@process:subject(GLV)) -> GLX)}. + +-type child_start_error() :: {child_start_error, + gleam@option:option(gleam@erlang@process:pid_()), + gleam@otp@actor:start_error()}. + +-opaque message() :: {exit, gleam@erlang@process:exit_message()} | + {retry_restart, gleam@erlang@process:pid_()}. + +-type instruction() :: start_all | {start_from, gleam@erlang@process:pid_()}. + +-type state(GLY) :: {state, + gleam@otp@intensity_tracker:intensity_tracker(), + starter(GLY), + gleam@erlang@process:subject(gleam@erlang@process:pid_())}. + +-type starter(GLZ) :: {starter, + GLZ, + gleam@option:option(fun((instruction()) -> {ok, + {starter(GLZ), instruction()}} | + {error, child_start_error()}))}. + +-type child(GMA) :: {child, gleam@erlang@process:pid_(), GMA}. + +-type handle_exit_error() :: {restart_failed, + gleam@erlang@process:pid_(), + gleam@otp@intensity_tracker:intensity_tracker()} | + too_many_restarts. + +-type application_start_mode() :: normal | + {takeover, gleam@erlang@node:node_()} | + {failover, gleam@erlang@node:node_()}. + +-type application_stop() :: any(). + +-spec start_child(child_spec(any(), GME, GMF), GME) -> {ok, child(GMF)} | + {error, child_start_error()}. +start_child(Child_spec, Argument) -> + gleam@result:then( + begin + _pipe = (erlang:element(2, Child_spec))(Argument), + gleam@result:map_error( + _pipe, + fun(_capture) -> {child_start_error, none, _capture} end + ) + end, + fun(Subject) -> + {ok, + {child, + gleam@erlang@process:subject_owner(Subject), + (erlang:element(3, Child_spec))(Argument, Subject)}} + end + ). + +-spec shutdown_child( + gleam@erlang@process:pid_(), + child_spec(any(), any(), any()) +) -> nil. +shutdown_child(Pid, _) -> + gleam@erlang@process:send_exit(Pid). + +-spec perform_instruction_for_child( + GMS, + instruction(), + child_spec(any(), GMS, GMU), + child(GMU) +) -> {ok, {child(GMU), instruction()}} | {error, child_start_error()}. +perform_instruction_for_child(Argument, Instruction, Child_spec, Child) -> + Current = erlang:element(2, Child), + case Instruction of + {start_from, Target} when Target =/= Current -> + {ok, {Child, Instruction}}; + + _ -> + shutdown_child(Current, Child_spec), + gleam@result:then( + start_child(Child_spec, Argument), + fun(Child@1) -> {ok, {Child@1, start_all}} end + ) + end. + +-spec add_child_to_starter( + starter(GNC), + child_spec(any(), GNC, GNF), + child(GNF) +) -> starter(GNF). +add_child_to_starter(Starter, Child_spec, Child) -> + Starter@3 = fun(Instruction) -> + gleam@result:then(case erlang:element(3, Starter) of + {some, Start} -> + Start(Instruction); + + none -> + {ok, {Starter, Instruction}} + end, fun(_use0) -> + {Starter@1, Instruction@1} = _use0, + gleam@result:then( + perform_instruction_for_child( + erlang:element(2, Starter@1), + Instruction@1, + Child_spec, + Child + ), + fun(_use0@1) -> + {Child@1, Instruction@2} = _use0@1, + Starter@2 = add_child_to_starter( + Starter@1, + Child_spec, + Child@1 + ), + {ok, {Starter@2, Instruction@2}} + end + ) + end) + end, + {starter, erlang:element(3, Child), {some, Starter@3}}. + +-spec start_and_add_child(starter(GNL), child_spec(any(), GNL, GNO)) -> children(GNO). +start_and_add_child(State, Child_spec) -> + case start_child(Child_spec, erlang:element(2, State)) of + {ok, Child} -> + {ready, add_child_to_starter(State, Child_spec, Child)}; + + {error, Reason} -> + {failed, Reason} + end. + +-spec add(children(GNT), child_spec(any(), GNT, GNW)) -> children(GNW). +add(Children, Child_spec) -> + case Children of + {failed, Fail} -> + {failed, Fail}; + + {ready, State} -> + start_and_add_child(State, Child_spec) + end. + +-spec supervisor( + fun((GOB) -> {ok, gleam@erlang@process:subject(GOC)} | + {error, gleam@otp@actor:start_error()}) +) -> child_spec(GOC, GOB, GOB). +supervisor(Start) -> + {child_spec, Start, fun(Argument, _) -> Argument end}. + +-spec worker( + fun((GOJ) -> {ok, gleam@erlang@process:subject(GOK)} | + {error, gleam@otp@actor:start_error()}) +) -> child_spec(GOK, GOJ, GOJ). +worker(Start) -> + {child_spec, Start, fun(Argument, _) -> Argument end}. + +-spec returning( + child_spec(GOR, GOS, any()), + fun((GOS, gleam@erlang@process:subject(GOR)) -> GOY) +) -> child_spec(GOR, GOS, GOY). +returning(Child, Updater) -> + {child_spec, erlang:element(2, Child), Updater}. + +-spec init(spec(any(), GPD)) -> gleam@otp@actor:init_result(state(GPD), message()). +init(Spec) -> + Retry = gleam@erlang@process:new_subject(), + gleam_erlang_ffi:trap_exits(true), + Selector = begin + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = gleam@erlang@process:selecting( + _pipe, + Retry, + fun(Field@0) -> {retry_restart, Field@0} end + ), + gleam@erlang@process:selecting_trapped_exits( + _pipe@1, + fun(Field@0) -> {exit, Field@0} end + ) + end, + Result = begin + _pipe@2 = {starter, erlang:element(2, Spec), none}, + _pipe@3 = {ready, _pipe@2}, + (erlang:element(5, Spec))(_pipe@3) + end, + case Result of + {ready, Starter} -> + Restarts = gleam@otp@intensity_tracker:new( + erlang:element(3, Spec), + erlang:element(4, Spec) + ), + State = {state, Restarts, Starter, Retry}, + {ready, State, Selector}; + + {failed, Error} -> + {failed, case erlang:element(3, Error) of + init_timeout -> + <<"Child initialisation timed out"/utf8>>; + + {init_crashed, Reason} -> + gleam@string:append( + <<"Child crashed during initialisation: "/utf8>>, + gleam@string:inspect(Reason) + ); + + {init_failed, Reason@1} -> + gleam@string:append( + <<"Child failed to start during initialisation: "/utf8>>, + gleam@string:inspect(Reason@1) + ) + end} + end. + +-spec handle_exit(gleam@erlang@process:pid_(), state(GPJ)) -> gleam@otp@actor:next(message(), state(GPJ)). +handle_exit(Pid, State) -> + Outcome = begin + _assert_subject = erlang:element(3, erlang:element(3, State)), + {some, Start} = case _assert_subject of + {some, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam/otp/supervisor"/utf8>>, + function => <<"handle_exit"/utf8>>, + line => 293}) + end, + gleam@result:then( + begin + _pipe = erlang:element(2, State), + _pipe@1 = gleam@otp@intensity_tracker:add_event(_pipe), + gleam@result:map_error(_pipe@1, fun(_) -> too_many_restarts end) + end, + fun(Restarts) -> + gleam@result:then( + begin + _pipe@2 = Start({start_from, Pid}), + gleam@result:map_error( + _pipe@2, + fun(E) -> + {restart_failed, + gleam@option:unwrap( + erlang:element(2, E), + Pid + ), + Restarts} + end + ) + end, + fun(_use0) -> + {Starter, _} = _use0, + {ok, + erlang:setelement( + 2, + erlang:setelement(3, State, Starter), + Restarts + )} + end + ) + end + ) + end, + case Outcome of + {ok, State@1} -> + gleam@otp@actor:continue(State@1); + + {error, {restart_failed, Failed_child, Restarts@1}} -> + gleam@erlang@process:send(erlang:element(4, State), Failed_child), + State@2 = erlang:setelement(2, State, Restarts@1), + gleam@otp@actor:continue(State@2); + + {error, too_many_restarts} -> + {stop, + {abnormal, + <<"Child processes restarted too many times within allowed period"/utf8>>}} + end. + +-spec loop(message(), state(GPO)) -> gleam@otp@actor:next(message(), state(GPO)). +loop(Message, State) -> + case Message of + {exit, Exit_message} -> + handle_exit(erlang:element(2, Exit_message), State); + + {retry_restart, Pid} -> + handle_exit(Pid, State) + end. + +-spec start_spec(spec(any(), any())) -> {ok, + gleam@erlang@process:subject(message())} | + {error, gleam@otp@actor:start_error()}. +start_spec(Spec) -> + gleam@otp@actor:start_spec( + {spec, fun() -> init(Spec) end, 60000, fun loop/2} + ). + +-spec start(fun((children(nil)) -> children(any()))) -> {ok, + gleam@erlang@process:subject(message())} | + {error, gleam@otp@actor:start_error()}. +start(Init) -> + start_spec({spec, nil, 1, 5, Init}). + +-spec application_stopped() -> application_stop(). +application_stopped() -> + gleam_otp_external:application_stopped(). + +-spec to_erlang_start_result( + {ok, gleam@erlang@process:subject(any())} | + {error, gleam@otp@actor:start_error()} +) -> {ok, gleam@erlang@process:pid_()} | {error, gleam@dynamic:dynamic_()}. +to_erlang_start_result(Res) -> + gleam@otp@actor:to_erlang_start_result(Res). diff --git a/aoc2023/build/packages/gleam_otp/src/gleam@otp@system.erl b/aoc2023/build/packages/gleam_otp/src/gleam@otp@system.erl new file mode 100644 index 0000000..622e5ea --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam@otp@system.erl @@ -0,0 +1,43 @@ +-module(gleam@otp@system). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([debug_state/1, get_state/1, suspend/1, resume/1]). +-export_type([mode/0, debug_option/0, debug_state/0, status_info/0, system_message/0, do_not_leak/0]). + +-type mode() :: running | suspended. + +-type debug_option() :: no_debug. + +-type debug_state() :: any(). + +-type status_info() :: {status_info, + gleam@erlang@atom:atom_(), + gleam@erlang@process:pid_(), + mode(), + debug_state(), + gleam@dynamic:dynamic_()}. + +-type system_message() :: {resume, fun(() -> nil)} | + {suspend, fun(() -> nil)} | + {get_state, fun((gleam@dynamic:dynamic_()) -> nil)} | + {get_status, fun((status_info()) -> nil)}. + +-type do_not_leak() :: any(). + +-spec debug_state(list(debug_option())) -> debug_state(). +debug_state(A) -> + sys:debug_options(A). + +-spec get_state(gleam@erlang@process:pid_()) -> gleam@dynamic:dynamic_(). +get_state(From) -> + sys:get_state(From). + +-spec suspend(gleam@erlang@process:pid_()) -> nil. +suspend(Pid) -> + sys:suspend(Pid), + nil. + +-spec resume(gleam@erlang@process:pid_()) -> nil. +resume(Pid) -> + sys:resume(Pid), + nil. diff --git a/aoc2023/build/packages/gleam_otp/src/gleam@otp@task.erl b/aoc2023/build/packages/gleam_otp/src/gleam@otp@task.erl new file mode 100644 index 0000000..e004284 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam@otp@task.erl @@ -0,0 +1,111 @@ +-module(gleam@otp@task). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([async/1, try_await/2, await/2, try_await_forever/1, await_forever/1]). +-export_type([task/1, await_error/0, message/1]). + +-opaque task(FWJ) :: {task, + gleam@erlang@process:pid_(), + gleam@erlang@process:pid_(), + gleam@erlang@process:process_monitor(), + gleam@erlang@process:selector(message(FWJ))}. + +-type await_error() :: timeout | {exit, gleam@dynamic:dynamic_()}. + +-type message(FWK) :: {from_monitor, gleam@erlang@process:process_down()} | + {from_subject, FWK}. + +-spec async(fun(() -> FWL)) -> task(FWL). +async(Work) -> + Owner = erlang:self(), + Subject = gleam@erlang@process:new_subject(), + Pid = gleam@erlang@process:start( + fun() -> gleam@erlang@process:send(Subject, Work()) end, + true + ), + Monitor = gleam@erlang@process:monitor_process(Pid), + Selector = begin + _pipe = gleam_erlang_ffi:new_selector(), + _pipe@1 = gleam@erlang@process:selecting_process_down( + _pipe, + Monitor, + fun(Field@0) -> {from_monitor, Field@0} end + ), + gleam@erlang@process:selecting( + _pipe@1, + Subject, + fun(Field@0) -> {from_subject, Field@0} end + ) + end, + {task, Owner, Pid, Monitor, Selector}. + +-spec assert_owner(task(any())) -> nil. +assert_owner(Task) -> + Self = erlang:self(), + case erlang:element(2, Task) =:= Self of + true -> + nil; + + false -> + gleam@erlang@process:send_abnormal_exit( + Self, + <<"awaited on a task that does not belong to this process"/utf8>> + ) + end. + +-spec try_await(task(FWP), integer()) -> {ok, FWP} | {error, await_error()}. +try_await(Task, Timeout) -> + assert_owner(Task), + case gleam_erlang_ffi:select(erlang:element(5, Task), Timeout) of + {ok, {from_subject, X}} -> + gleam_erlang_ffi:demonitor(erlang:element(4, Task)), + {ok, X}; + + {ok, {from_monitor, {process_down, _, Reason}}} -> + {error, {exit, Reason}}; + + {error, nil} -> + {error, timeout} + end. + +-spec await(task(FWT), integer()) -> FWT. +await(Task, Timeout) -> + _assert_subject = try_await(Task, Timeout), + {ok, Value} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam/otp/task"/utf8>>, + function => <<"await"/utf8>>, + line => 117}) + end, + Value. + +-spec try_await_forever(task(FWV)) -> {ok, FWV} | {error, await_error()}. +try_await_forever(Task) -> + assert_owner(Task), + case gleam_erlang_ffi:select(erlang:element(5, Task)) of + {from_subject, X} -> + gleam_erlang_ffi:demonitor(erlang:element(4, Task)), + {ok, X}; + + {from_monitor, {process_down, _, Reason}} -> + {error, {exit, Reason}} + end. + +-spec await_forever(task(FWZ)) -> FWZ. +await_forever(Task) -> + _assert_subject = try_await_forever(Task), + {ok, Value} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"gleam/otp/task"/utf8>>, + function => <<"await_forever"/utf8>>, + line => 149}) + end, + Value. diff --git a/aoc2023/build/packages/gleam_otp/src/gleam_otp.app.src b/aoc2023/build/packages/gleam_otp/src/gleam_otp.app.src new file mode 100644 index 0000000..5c52295 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam_otp.app.src @@ -0,0 +1,15 @@ +{application, gleam_otp, [ + {vsn, "0.8.0"}, + {applications, [gleam_erlang, + gleam_stdlib, + gleeunit]}, + {description, "Fault tolerant multicore Gleam programs with OTP"}, + {modules, [gleam@otp@actor, + gleam@otp@intensity_tracker, + gleam@otp@port, + gleam@otp@supervisor, + gleam@otp@system, + gleam@otp@task, + gleam_otp]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/gleam_otp/src/gleam_otp.erl b/aoc2023/build/packages/gleam_otp/src/gleam_otp.erl new file mode 100644 index 0000000..9381ad2 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam_otp.erl @@ -0,0 +1,28 @@ +-module(gleam_otp). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([main/0]). + +-spec spawn_task(integer()) -> gleam@otp@task:task(nil). +spawn_task(I) -> + gleam@otp@task:async(fun() -> case (I rem 500) =:= 0 of + true -> + gleam@io:println( + <<"Hello from "/utf8, (gleam@int:to_string(I))/binary>> + ); + + false -> + nil + end end). + +-spec main() -> integer(). +main() -> + gleam@io:debug( + gleam_otp_test_external:get_message_queue_length(erlang:self()) + ), + _pipe = gleam@list:range(0, 1000000), + _pipe@1 = gleam@list:map(_pipe, fun spawn_task/1), + gleam@list:each(_pipe@1, fun gleam@otp@task:await_forever/1), + gleam@io:debug( + gleam_otp_test_external:get_message_queue_length(erlang:self()) + ). diff --git a/aoc2023/build/packages/gleam_otp/src/gleam_otp.gleam b/aoc2023/build/packages/gleam_otp/src/gleam_otp.gleam new file mode 100644 index 0000000..69cdd5b --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam_otp.gleam @@ -0,0 +1,27 @@ +import gleam/io +import gleam/int +import gleam/list +import gleam/otp/task +import gleam/erlang/process.{type Pid} + +@external(erlang, "gleam_otp_test_external", "get_message_queue_length") +fn get_message_queue_length(pid pid: Pid) -> Int + +fn spawn_task(i) { + task.async(fn() { + case i % 500 == 0 { + True -> io.println("Hello from " <> int.to_string(i)) + False -> Nil + } + }) +} + +pub fn main() { + io.debug(get_message_queue_length(process.self())) + + list.range(0, 1_000_000) + |> list.map(spawn_task) + |> list.each(task.await_forever) + + io.debug(get_message_queue_length(process.self())) +} diff --git a/aoc2023/build/packages/gleam_otp/src/gleam_otp_external.erl b/aoc2023/build/packages/gleam_otp/src/gleam_otp_external.erl new file mode 100644 index 0000000..8910a67 --- /dev/null +++ b/aoc2023/build/packages/gleam_otp/src/gleam_otp_external.erl @@ -0,0 +1,43 @@ +-module(gleam_otp_external). + +-export([application_stopped/0, convert_system_message/2]). + +% TODO: support other system messages +% {replace_state, StateFn} +% {change_code, Mod, Vsn, Extra} +% {terminate, Reason} +% {debug, {log, Flag}} +% {debug, {trace, Flag}} +% {debug, {log_to_file, FileName}} +% {debug, {statistics, Flag}} +% {debug, no_debug} +% {debug, {install, {Func, FuncState}}} +% {debug, {install, {FuncId, Func, FuncState}}} +% {debug, {remove, FuncOrId}} +% GetStatus(Subject(StatusInfo)) +convert_system_message({From, Ref}, Request) when is_pid(From) -> + Reply = fun(Msg) -> + erlang:send(From, {Ref, Msg}), + nil + end, + System = fun(Callback) -> + {system, {Request, Callback}} + end, + case Request of + get_status -> System(fun(Status) -> Reply(process_status(Status)) end); + get_state -> System(Reply); + suspend -> System(fun() -> Reply(ok) end); + resume -> System(fun() -> Reply(ok) end); + Other -> {unexpeceted, Other} + end. + +process_status({status_info, Module, Parent, Mode, DebugState, State}) -> + Data = [ + get(), Mode, Parent, DebugState, + [{header, "Status for Gleam process " ++ pid_to_list(self())}, + {data, [{'Status', Mode}, {'Parent', Parent}, {'State', State}]}] + ], + {status, self(), {module, Module}, Data}. + +application_stopped() -> + ok. diff --git a/aoc2023/build/packages/gleam_stdlib/LICENCE b/aoc2023/build/packages/gleam_stdlib/LICENCE new file mode 100644 index 0000000..c1dabd0 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/LICENCE @@ -0,0 +1,191 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2018, Louis Pilfold <louis@lpil.uk>. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/aoc2023/build/packages/gleam_stdlib/README.md b/aoc2023/build/packages/gleam_stdlib/README.md new file mode 100644 index 0000000..05c68ca --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/README.md @@ -0,0 +1,39 @@ +# stdlib + +<a href="https://github.com/gleam-lang/stdlib/releases"><img src="https://img.shields.io/github/release/gleam-lang/stdlib" alt="GitHub release"></a> +<a href="https://discord.gg/Fm8Pwmy"><img src="https://img.shields.io/discord/768594524158427167?color=blue" alt="Discord chat"></a> + + +Gleam's standard library! +Documentation available on [HexDocs](https://hexdocs.pm/gleam_stdlib/). + +## Installation + +Add `gleam_stdlib` to your Gleam project. + +```sh +gleam add gleam_stdlib +``` + +## Usage + +Import the modules you want to use and write some code! + +```gleam +import gleam/string + +pub fn greet(name: String) -> String { + string.concat(["Hello ", name, "!"]) +} +``` + +## Targets + +Gleam's standard library supports both targets: Erlang and JavaScript. + +### Compatibility + +This library is compatible with all versions of Erlang/OTP, NodeJS, and +major browsers that are currently supported by their maintainers. If you +have a compatibility issue with any platform open an issue and we'll see +what we can do to help. diff --git a/aoc2023/build/packages/gleam_stdlib/gleam.toml b/aoc2023/build/packages/gleam_stdlib/gleam.toml new file mode 100644 index 0000000..0cb0531 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/gleam.toml @@ -0,0 +1,16 @@ +name = "gleam_stdlib" +version = "0.33.0" +gleam = ">= 0.32.0" +licences = ["Apache-2.0"] +description = "A standard library for the Gleam programming language" + +repository = { type = "github", user = "gleam-lang", repo = "stdlib" } +links = [ + { title = "Website", href = "https://gleam.run" }, + { title = "Sponsor", href = "https://github.com/sponsors/lpil" }, +] + +[javascript.deno] +allow_read = [ + "./", +] diff --git a/aoc2023/build/packages/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl b/aoc2023/build/packages/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl new file mode 100644 index 0000000..b1135f2 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl @@ -0,0 +1,5 @@ +-record(decode_error, { + expected :: binary(), + found :: binary(), + path :: list(binary()) +}). diff --git a/aoc2023/build/packages/gleam_stdlib/include/gleam@iterator_Iterator.hrl b/aoc2023/build/packages/gleam_stdlib/include/gleam@iterator_Iterator.hrl new file mode 100644 index 0000000..b0d08dc --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/include/gleam@iterator_Iterator.hrl @@ -0,0 +1 @@ +-record(iterator, {continuation :: fun(() -> gleam@iterator:action(any()))}). diff --git a/aoc2023/build/packages/gleam_stdlib/include/gleam@iterator_Next.hrl b/aoc2023/build/packages/gleam_stdlib/include/gleam@iterator_Next.hrl new file mode 100644 index 0000000..1f61922 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/include/gleam@iterator_Next.hrl @@ -0,0 +1 @@ +-record(next, {element :: any(), accumulator :: any()}). diff --git a/aoc2023/build/packages/gleam_stdlib/include/gleam@queue_Queue.hrl b/aoc2023/build/packages/gleam_stdlib/include/gleam@queue_Queue.hrl new file mode 100644 index 0000000..88ac25e --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/include/gleam@queue_Queue.hrl @@ -0,0 +1 @@ +-record(queue, {in :: list(any()), out :: list(any())}). diff --git a/aoc2023/build/packages/gleam_stdlib/include/gleam@regex_CompileError.hrl b/aoc2023/build/packages/gleam_stdlib/include/gleam@regex_CompileError.hrl new file mode 100644 index 0000000..ad5511e --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/include/gleam@regex_CompileError.hrl @@ -0,0 +1 @@ +-record(compile_error, {error :: binary(), byte_index :: integer()}). diff --git a/aoc2023/build/packages/gleam_stdlib/include/gleam@regex_Match.hrl b/aoc2023/build/packages/gleam_stdlib/include/gleam@regex_Match.hrl new file mode 100644 index 0000000..4216619 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/include/gleam@regex_Match.hrl @@ -0,0 +1,4 @@ +-record(match, { + content :: binary(), + submatches :: list(gleam@option:option(binary())) +}). diff --git a/aoc2023/build/packages/gleam_stdlib/include/gleam@regex_Options.hrl b/aoc2023/build/packages/gleam_stdlib/include/gleam@regex_Options.hrl new file mode 100644 index 0000000..0074603 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/include/gleam@regex_Options.hrl @@ -0,0 +1 @@ +-record(options, {case_insensitive :: boolean(), multi_line :: boolean()}). diff --git a/aoc2023/build/packages/gleam_stdlib/include/gleam@set_Set.hrl b/aoc2023/build/packages/gleam_stdlib/include/gleam@set_Set.hrl new file mode 100644 index 0000000..6e1e226 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/include/gleam@set_Set.hrl @@ -0,0 +1 @@ +-record(set, {map :: gleam@dict:dict(any(), list(nil))}). diff --git a/aoc2023/build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl b/aoc2023/build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl new file mode 100644 index 0000000..50150f4 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl @@ -0,0 +1,9 @@ +-record(uri, { + scheme :: gleam@option:option(binary()), + userinfo :: gleam@option:option(binary()), + host :: gleam@option:option(binary()), + port :: gleam@option:option(integer()), + path :: binary(), + 'query' :: gleam@option:option(binary()), + fragment :: gleam@option:option(binary()) +}). diff --git a/aoc2023/build/packages/gleam_stdlib/src/dict.mjs b/aoc2023/build/packages/gleam_stdlib/src/dict.mjs new file mode 100644 index 0000000..a8309e0 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/dict.mjs @@ -0,0 +1,957 @@ +/** + * This file uses jsdoc to annotate types. + * These types can be checked using the typescript compiler with "checkjs" option. + */ + +import { isEqual } from "./gleam.mjs"; + +const referenceMap = new WeakMap(); +const tempDataView = new DataView(new ArrayBuffer(8)); +let referenceUID = 0; +/** + * hash the object by reference using a weak map and incrementing uid + * @param {any} o + * @returns {number} + */ +function hashByReference(o) { + const known = referenceMap.get(o); + if (known !== undefined) { + return known; + } + const hash = referenceUID++; + if (referenceUID === 0x7fffffff) { + referenceUID = 0; + } + referenceMap.set(o, hash); + return hash; +} +/** + * merge two hashes in an order sensitive way + * @param {number} a + * @param {number} b + * @returns {number} + */ +function hashMerge(a, b) { + return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; +} +/** + * standard string hash popularised by java + * @param {string} s + * @returns {number} + */ +function hashString(s) { + let hash = 0; + const len = s.length; + for (let i = 0; i < len; i++) { + hash = (Math.imul(31, hash) + s.charCodeAt(i)) | 0; + } + return hash; +} +/** + * hash a number by converting to two integers and do some jumbling + * @param {number} n + * @returns {number} + */ +function hashNumber(n) { + tempDataView.setFloat64(0, n); + const i = tempDataView.getInt32(0); + const j = tempDataView.getInt32(4); + return Math.imul(0x45d9f3b, (i >> 16) ^ i) ^ j; +} +/** + * hash a BigInt by converting it to a string and hashing that + * @param {BigInt} n + * @returns {number} + */ +function hashBigInt(n) { + return hashString(n.toString()); +} +/** + * hash any js object + * @param {any} o + * @returns {number} + */ +function hashObject(o) { + const proto = Object.getPrototypeOf(o); + if (proto !== null && typeof proto.hashCode === "function") { + try { + const code = o.hashCode(o); + if (typeof code === "number") { + return code; + } + } catch {} + } + if (o instanceof Promise || o instanceof WeakSet || o instanceof WeakMap) { + return hashByReference(o); + } + if (o instanceof Date) { + return hashNumber(o.getTime()); + } + let h = 0; + if (o instanceof ArrayBuffer) { + o = new Uint8Array(o); + } + if (Array.isArray(o) || o instanceof Uint8Array) { + for (let i = 0; i < o.length; i++) { + h = (Math.imul(31, h) + getHash(o[i])) | 0; + } + } else if (o instanceof Set) { + o.forEach((v) => { + h = (h + getHash(v)) | 0; + }); + } else if (o instanceof Map) { + o.forEach((v, k) => { + h = (h + hashMerge(getHash(v), getHash(k))) | 0; + }); + } else { + const keys = Object.keys(o); + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; + const v = o[k]; + h = (h + hashMerge(getHash(v), hashString(k))) | 0; + } + } + return h; +} +/** + * hash any js value + * @param {any} u + * @returns {number} + */ +export function getHash(u) { + if (u === null) return 0x42108422; + if (u === undefined) return 0x42108423; + if (u === true) return 0x42108421; + if (u === false) return 0x42108420; + switch (typeof u) { + case "number": + return hashNumber(u); + case "string": + return hashString(u); + case "bigint": + return hashBigInt(u); + case "object": + return hashObject(u); + case "symbol": + return hashByReference(u); + case "function": + return hashByReference(u); + default: + return 0; // should be unreachable + } +} +/** + * @template K,V + * @typedef {ArrayNode<K,V> | IndexNode<K,V> | CollisionNode<K,V>} Node + */ +/** + * @template K,V + * @typedef {{ type: typeof ENTRY, k: K, v: V }} Entry + */ +/** + * @template K,V + * @typedef {{ type: typeof ARRAY_NODE, size: number, array: (undefined | Entry<K,V> | Node<K,V>)[] }} ArrayNode + */ +/** + * @template K,V + * @typedef {{ type: typeof INDEX_NODE, bitmap: number, array: (Entry<K,V> | Node<K,V>)[] }} IndexNode + */ +/** + * @template K,V + * @typedef {{ type: typeof COLLISION_NODE, hash: number, array: Entry<K, V>[] }} CollisionNode + */ +/** + * @typedef {{ val: boolean }} Flag + */ +const SHIFT = 5; // number of bits you need to shift by to get the next bucket +const BUCKET_SIZE = Math.pow(2, SHIFT); +const MASK = BUCKET_SIZE - 1; // used to zero out all bits not in the bucket +const MAX_INDEX_NODE = BUCKET_SIZE / 2; // when does index node grow into array node +const MIN_ARRAY_NODE = BUCKET_SIZE / 4; // when does array node shrink to index node +const ENTRY = 0; +const ARRAY_NODE = 1; +const INDEX_NODE = 2; +const COLLISION_NODE = 3; +/** @type {IndexNode<any,any>} */ +const EMPTY = { + type: INDEX_NODE, + bitmap: 0, + array: [], +}; +/** + * Mask the hash to get only the bucket corresponding to shift + * @param {number} hash + * @param {number} shift + * @returns {number} + */ +function mask(hash, shift) { + return (hash >>> shift) & MASK; +} +/** + * Set only the Nth bit where N is the masked hash + * @param {number} hash + * @param {number} shift + * @returns {number} + */ +function bitpos(hash, shift) { + return 1 << mask(hash, shift); +} +/** + * Count the number of 1 bits in a number + * @param {number} x + * @returns {number} + */ +function bitcount(x) { + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0f0f0f0f; + x += x >> 8; + x += x >> 16; + return x & 0x7f; +} +/** + * Calculate the array index of an item in a bitmap index node + * @param {number} bitmap + * @param {number} bit + * @returns {number} + */ +function index(bitmap, bit) { + return bitcount(bitmap & (bit - 1)); +} +/** + * Efficiently copy an array and set one value at an index + * @template T + * @param {T[]} arr + * @param {number} at + * @param {T} val + * @returns {T[]} + */ +function cloneAndSet(arr, at, val) { + const len = arr.length; + const out = new Array(len); + for (let i = 0; i < len; ++i) { + out[i] = arr[i]; + } + out[at] = val; + return out; +} +/** + * Efficiently copy an array and insert one value at an index + * @template T + * @param {T[]} arr + * @param {number} at + * @param {T} val + * @returns {T[]} + */ +function spliceIn(arr, at, val) { + const len = arr.length; + const out = new Array(len + 1); + let i = 0; + let g = 0; + while (i < at) { + out[g++] = arr[i++]; + } + out[g++] = val; + while (i < len) { + out[g++] = arr[i++]; + } + return out; +} +/** + * Efficiently copy an array and remove one value at an index + * @template T + * @param {T[]} arr + * @param {number} at + * @returns {T[]} + */ +function spliceOut(arr, at) { + const len = arr.length; + const out = new Array(len - 1); + let i = 0; + let g = 0; + while (i < at) { + out[g++] = arr[i++]; + } + ++i; + while (i < len) { + out[g++] = arr[i++]; + } + return out; +} +/** + * Create a new node containing two entries + * @template K,V + * @param {number} shift + * @param {K} key1 + * @param {V} val1 + * @param {number} key2hash + * @param {K} key2 + * @param {V} val2 + * @returns {Node<K,V>} + */ +function createNode(shift, key1, val1, key2hash, key2, val2) { + const key1hash = getHash(key1); + if (key1hash === key2hash) { + return { + type: COLLISION_NODE, + hash: key1hash, + array: [ + { type: ENTRY, k: key1, v: val1 }, + { type: ENTRY, k: key2, v: val2 }, + ], + }; + } + const addedLeaf = { val: false }; + return assoc( + assocIndex(EMPTY, shift, key1hash, key1, val1, addedLeaf), + shift, + key2hash, + key2, + val2, + addedLeaf + ); +} +/** + * @template T,K,V + * @callback AssocFunction + * @param {T} root + * @param {number} shift + * @param {number} hash + * @param {K} key + * @param {V} val + * @param {Flag} addedLeaf + * @returns {Node<K,V>} + */ +/** + * Associate a node with a new entry, creating a new node + * @template T,K,V + * @type {AssocFunction<Node<K,V>,K,V>} + */ +function assoc(root, shift, hash, key, val, addedLeaf) { + switch (root.type) { + case ARRAY_NODE: + return assocArray(root, shift, hash, key, val, addedLeaf); + case INDEX_NODE: + return assocIndex(root, shift, hash, key, val, addedLeaf); + case COLLISION_NODE: + return assocCollision(root, shift, hash, key, val, addedLeaf); + } +} +/** + * @template T,K,V + * @type {AssocFunction<ArrayNode<K,V>,K,V>} + */ +function assocArray(root, shift, hash, key, val, addedLeaf) { + const idx = mask(hash, shift); + const node = root.array[idx]; + // if the corresponding index is empty set the index to a newly created node + if (node === undefined) { + addedLeaf.val = true; + return { + type: ARRAY_NODE, + size: root.size + 1, + array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }), + }; + } + if (node.type === ENTRY) { + // if keys are equal replace the entry + if (isEqual(key, node.k)) { + if (val === node.v) { + return root; + } + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet(root.array, idx, { + type: ENTRY, + k: key, + v: val, + }), + }; + } + // otherwise upgrade the entry to a node and insert + addedLeaf.val = true; + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet( + root.array, + idx, + createNode(shift + SHIFT, node.k, node.v, hash, key, val) + ), + }; + } + // otherwise call assoc on the child node + const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); + // if the child node hasn't changed just return the old root + if (n === node) { + return root; + } + // otherwise set the index to the new node + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet(root.array, idx, n), + }; +} +/** + * @template T,K,V + * @type {AssocFunction<IndexNode<K,V>,K,V>} + */ +function assocIndex(root, shift, hash, key, val, addedLeaf) { + const bit = bitpos(hash, shift); + const idx = index(root.bitmap, bit); + // if there is already a item at this hash index.. + if ((root.bitmap & bit) !== 0) { + // if there is a node at the index (not an entry), call assoc on the child node + const node = root.array[idx]; + if (node.type !== ENTRY) { + const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); + if (n === node) { + return root; + } + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet(root.array, idx, n), + }; + } + // otherwise there is an entry at the index + // if the keys are equal replace the entry with the updated value + const nodeKey = node.k; + if (isEqual(key, nodeKey)) { + if (val === node.v) { + return root; + } + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet(root.array, idx, { + type: ENTRY, + k: key, + v: val, + }), + }; + } + // if the keys are not equal, replace the entry with a new child node + addedLeaf.val = true; + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet( + root.array, + idx, + createNode(shift + SHIFT, nodeKey, node.v, hash, key, val) + ), + }; + } else { + // else there is currently no item at the hash index + const n = root.array.length; + // if the number of nodes is at the maximum, expand this node into an array node + if (n >= MAX_INDEX_NODE) { + // create a 32 length array for the new array node (one for each bit in the hash) + const nodes = new Array(32); + // create and insert a node for the new entry + const jdx = mask(hash, shift); + nodes[jdx] = assocIndex(EMPTY, shift + SHIFT, hash, key, val, addedLeaf); + let j = 0; + let bitmap = root.bitmap; + // place each item in the index node into the correct spot in the array node + // loop through all 32 bits / array positions + for (let i = 0; i < 32; i++) { + if ((bitmap & 1) !== 0) { + const node = root.array[j++]; + nodes[i] = node; + } + // shift the bitmap to process the next bit + bitmap = bitmap >>> 1; + } + return { + type: ARRAY_NODE, + size: n + 1, + array: nodes, + }; + } else { + // else there is still space in this index node + // simply insert a new entry at the hash index + const newArray = spliceIn(root.array, idx, { + type: ENTRY, + k: key, + v: val, + }); + addedLeaf.val = true; + return { + type: INDEX_NODE, + bitmap: root.bitmap | bit, + array: newArray, + }; + } + } +} +/** + * @template T,K,V + * @type {AssocFunction<CollisionNode<K,V>,K,V>} + */ +function assocCollision(root, shift, hash, key, val, addedLeaf) { + // if there is a hash collision + if (hash === root.hash) { + const idx = collisionIndexOf(root, key); + // if this key already exists replace the entry with the new value + if (idx !== -1) { + const entry = root.array[idx]; + if (entry.v === val) { + return root; + } + return { + type: COLLISION_NODE, + hash: hash, + array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }), + }; + } + // otherwise insert the entry at the end of the array + const size = root.array.length; + addedLeaf.val = true; + return { + type: COLLISION_NODE, + hash: hash, + array: cloneAndSet(root.array, size, { type: ENTRY, k: key, v: val }), + }; + } + // if there is no hash collision, upgrade to an index node + return assoc( + { + type: INDEX_NODE, + bitmap: bitpos(root.hash, shift), + array: [root], + }, + shift, + hash, + key, + val, + addedLeaf + ); +} +/** + * Find the index of a key in the collision node's array + * @template K,V + * @param {CollisionNode<K,V>} root + * @param {K} key + * @returns {number} + */ +function collisionIndexOf(root, key) { + const size = root.array.length; + for (let i = 0; i < size; i++) { + if (isEqual(key, root.array[i].k)) { + return i; + } + } + return -1; +} +/** + * @template T,K,V + * @callback FindFunction + * @param {T} root + * @param {number} shift + * @param {number} hash + * @param {K} key + * @returns {undefined | Entry<K,V>} + */ +/** + * Return the found entry or undefined if not present in the root + * @template K,V + * @type {FindFunction<Node<K,V>,K,V>} + */ +function find(root, shift, hash, key) { + switch (root.type) { + case ARRAY_NODE: + return findArray(root, shift, hash, key); + case INDEX_NODE: + return findIndex(root, shift, hash, key); + case COLLISION_NODE: + return findCollision(root, key); + } +} +/** + * @template K,V + * @type {FindFunction<ArrayNode<K,V>,K,V>} + */ +function findArray(root, shift, hash, key) { + const idx = mask(hash, shift); + const node = root.array[idx]; + if (node === undefined) { + return undefined; + } + if (node.type !== ENTRY) { + return find(node, shift + SHIFT, hash, key); + } + if (isEqual(key, node.k)) { + return node; + } + return undefined; +} +/** + * @template K,V + * @type {FindFunction<IndexNode<K,V>,K,V>} + */ +function findIndex(root, shift, hash, key) { + const bit = bitpos(hash, shift); + if ((root.bitmap & bit) === 0) { + return undefined; + } + const idx = index(root.bitmap, bit); + const node = root.array[idx]; + if (node.type !== ENTRY) { + return find(node, shift + SHIFT, hash, key); + } + if (isEqual(key, node.k)) { + return node; + } + return undefined; +} +/** + * @template K,V + * @param {CollisionNode<K,V>} root + * @param {K} key + * @returns {undefined | Entry<K,V>} + */ +function findCollision(root, key) { + const idx = collisionIndexOf(root, key); + if (idx < 0) { + return undefined; + } + return root.array[idx]; +} +/** + * @template T,K,V + * @callback WithoutFunction + * @param {T} root + * @param {number} shift + * @param {number} hash + * @param {K} key + * @returns {undefined | Node<K,V>} + */ +/** + * Remove an entry from the root, returning the updated root. + * Returns undefined if the node should be removed from the parent. + * @template K,V + * @type {WithoutFunction<Node<K,V>,K,V>} + * */ +function without(root, shift, hash, key) { + switch (root.type) { + case ARRAY_NODE: + return withoutArray(root, shift, hash, key); + case INDEX_NODE: + return withoutIndex(root, shift, hash, key); + case COLLISION_NODE: + return withoutCollision(root, key); + } +} +/** + * @template K,V + * @type {WithoutFunction<ArrayNode<K,V>,K,V>} + */ +function withoutArray(root, shift, hash, key) { + const idx = mask(hash, shift); + const node = root.array[idx]; + if (node === undefined) { + return root; // already empty + } + let n = undefined; + // if node is an entry and the keys are not equal there is nothing to remove + // if node is not an entry do a recursive call + if (node.type === ENTRY) { + if (!isEqual(node.k, key)) { + return root; // no changes + } + } else { + n = without(node, shift + SHIFT, hash, key); + if (n === node) { + return root; // no changes + } + } + // if the recursive call returned undefined the node should be removed + if (n === undefined) { + // if the number of child nodes is at the minimum, pack into an index node + if (root.size <= MIN_ARRAY_NODE) { + const arr = root.array; + const out = new Array(root.size - 1); + let i = 0; + let j = 0; + let bitmap = 0; + while (i < idx) { + const nv = arr[i]; + if (nv !== undefined) { + out[j] = nv; + bitmap |= 1 << i; + ++j; + } + ++i; + } + ++i; // skip copying the removed node + while (i < arr.length) { + const nv = arr[i]; + if (nv !== undefined) { + out[j] = nv; + bitmap |= 1 << i; + ++j; + } + ++i; + } + return { + type: INDEX_NODE, + bitmap: bitmap, + array: out, + }; + } + return { + type: ARRAY_NODE, + size: root.size - 1, + array: cloneAndSet(root.array, idx, n), + }; + } + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet(root.array, idx, n), + }; +} +/** + * @template K,V + * @type {WithoutFunction<IndexNode<K,V>,K,V>} + */ +function withoutIndex(root, shift, hash, key) { + const bit = bitpos(hash, shift); + if ((root.bitmap & bit) === 0) { + return root; // already empty + } + const idx = index(root.bitmap, bit); + const node = root.array[idx]; + // if the item is not an entry + if (node.type !== ENTRY) { + const n = without(node, shift + SHIFT, hash, key); + if (n === node) { + return root; // no changes + } + // if not undefined, the child node still has items, so update it + if (n !== undefined) { + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet(root.array, idx, n), + }; + } + // otherwise the child node should be removed + // if it was the only child node, remove this node from the parent + if (root.bitmap === bit) { + return undefined; + } + // otherwise just remove the child node + return { + type: INDEX_NODE, + bitmap: root.bitmap ^ bit, + array: spliceOut(root.array, idx), + }; + } + // otherwise the item is an entry, remove it if the key matches + if (isEqual(key, node.k)) { + if (root.bitmap === bit) { + return undefined; + } + return { + type: INDEX_NODE, + bitmap: root.bitmap ^ bit, + array: spliceOut(root.array, idx), + }; + } + return root; +} +/** + * @template K,V + * @param {CollisionNode<K,V>} root + * @param {K} key + * @returns {undefined | Node<K,V>} + */ +function withoutCollision(root, key) { + const idx = collisionIndexOf(root, key); + // if the key not found, no changes + if (idx < 0) { + return root; + } + // otherwise the entry was found, remove it + // if it was the only entry in this node, remove the whole node + if (root.array.length === 1) { + return undefined; + } + // otherwise just remove the entry + return { + type: COLLISION_NODE, + hash: root.hash, + array: spliceOut(root.array, idx), + }; +} +/** + * @template K,V + * @param {undefined | Node<K,V>} root + * @param {(value:V,key:K)=>void} fn + * @returns {void} + */ +function forEach(root, fn) { + if (root === undefined) { + return; + } + const items = root.array; + const size = items.length; + for (let i = 0; i < size; i++) { + const item = items[i]; + if (item === undefined) { + continue; + } + if (item.type === ENTRY) { + fn(item.v, item.k); + continue; + } + forEach(item, fn); + } +} +/** + * Extra wrapper to keep track of Dict size and clean up the API + * @template K,V + */ +export default class Dict { + /** + * @template V + * @param {Record<string,V>} o + * @returns {Dict<string,V>} + */ + static fromObject(o) { + const keys = Object.keys(o); + /** @type Dict<string,V> */ + let m = Dict.new(); + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; + m = m.set(k, o[k]); + } + return m; + } + /** + * @template K,V + * @param {Map<K,V>} o + * @returns {Dict<K,V>} + */ + static fromMap(o) { + /** @type Dict<K,V> */ + let m = Dict.new(); + o.forEach((v, k) => { + m = m.set(k, v); + }); + return m; + } + static new() { + return new Dict(undefined, 0); + } + /** + * @param {undefined | Node<K,V>} root + * @param {number} size + */ + constructor(root, size) { + this.root = root; + this.size = size; + } + /** + * @template NotFound + * @param {K} key + * @param {NotFound} notFound + * @returns {NotFound | V} + */ + get(key, notFound) { + if (this.root === undefined) { + return notFound; + } + const found = find(this.root, 0, getHash(key), key); + if (found === undefined) { + return notFound; + } + return found.v; + } + /** + * @param {K} key + * @param {V} val + * @returns {Dict<K,V>} + */ + set(key, val) { + const addedLeaf = { val: false }; + const root = this.root === undefined ? EMPTY : this.root; + const newRoot = assoc(root, 0, getHash(key), key, val, addedLeaf); + if (newRoot === this.root) { + return this; + } + return new Dict(newRoot, addedLeaf.val ? this.size + 1 : this.size); + } + /** + * @param {K} key + * @returns {Dict<K,V>} + */ + delete(key) { + if (this.root === undefined) { + return this; + } + const newRoot = without(this.root, 0, getHash(key), key); + if (newRoot === this.root) { + return this; + } + if (newRoot === undefined) { + return Dict.new(); + } + return new Dict(newRoot, this.size - 1); + } + /** + * @param {K} key + * @returns {boolean} + */ + has(key) { + if (this.root === undefined) { + return false; + } + return find(this.root, 0, getHash(key), key) !== undefined; + } + /** + * @returns {[K,V][]} + */ + entries() { + if (this.root === undefined) { + return []; + } + /** @type [K,V][] */ + const result = []; + this.forEach((v, k) => result.push([k, v])); + return result; + } + /** + * + * @param {(val:V,key:K)=>void} fn + */ + forEach(fn) { + forEach(this.root, fn); + } + hashCode() { + let h = 0; + this.forEach((v, k) => { + h = (h + hashMerge(getHash(v), getHash(k))) | 0; + }); + return h; + } + /** + * @param {unknown} o + * @returns {boolean} + */ + equals(o) { + if (!(o instanceof Dict) || this.size !== o.size) { + return false; + } + let equal = true; + this.forEach((v, k) => { + equal = equal && isEqual(o.get(k, !v), v); + }); + return equal; + } +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/base.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/base.gleam new file mode 100644 index 0000000..eab2f0b --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/base.gleam @@ -0,0 +1,21 @@ +import gleam/bit_array + +@deprecated("Please use `base64_encode` in the `gleam/bit_array` module instead.") +pub fn encode64(input: BitArray, padding: Bool) -> String { + bit_array.base64_encode(input, padding) +} + +@deprecated("Please use `base64_decode` in the `gleam/bit_array` module instead.") +pub fn decode64(encoded: String) -> Result(BitArray, Nil) { + bit_array.base64_decode(encoded) +} + +@deprecated("Please use `base64_url_encode` in the `gleam/bit_array` module instead.") +pub fn url_encode64(input: BitArray, padding: Bool) -> String { + bit_array.base64_url_encode(input, padding) +} + +@deprecated("Please use `base64_url_decode` in the `gleam/bit_array` module instead.") +pub fn url_decode64(encoded: String) -> Result(BitArray, Nil) { + bit_array.base64_url_decode(encoded) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/bit_array.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/bit_array.gleam new file mode 100644 index 0000000..79860e9 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/bit_array.gleam @@ -0,0 +1,157 @@ +//// BitArrays are a sequence of binary data of any length. + +import gleam/string + +/// Converts a UTF-8 `String` type into a `BitArray`. +/// +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "bit_array_from_string") +pub fn from_string(x: String) -> BitArray + +/// Returns an integer which is the number of bytes in the bit array. +/// +@external(erlang, "erlang", "byte_size") +@external(javascript, "../gleam_stdlib.mjs", "length") +pub fn byte_size(x: BitArray) -> Int + +/// Creates a new bit array by joining two bit arrays. +/// +/// ## Examples +/// +/// ```gleam +/// > append(to: from_string("butter"), suffix: from_string("fly")) +/// from_string("butterfly") +/// ``` +/// +pub fn append(to first: BitArray, suffix second: BitArray) -> BitArray { + concat([first, second]) +} + +/// Extracts a sub-section of a bit array. +/// +/// The slice will start at given position and continue up to specified +/// length. +/// A negative length can be used to extract bytes at the end of a bit array. +/// +/// This function runs in constant time. +/// +@external(erlang, "gleam_stdlib", "bit_array_slice") +@external(javascript, "../gleam_stdlib.mjs", "bit_array_slice") +pub fn slice( + from string: BitArray, + at position: Int, + take length: Int, +) -> Result(BitArray, Nil) + +/// Tests to see whether a bit array is valid UTF-8. +/// +pub fn is_utf8(bits: BitArray) -> Bool { + do_is_utf8(bits) +} + +@target(erlang) +fn do_is_utf8(bits: BitArray) -> Bool { + case bits { + <<>> -> True + <<_:utf8, rest:bytes>> -> do_is_utf8(rest) + _ -> False + } +} + +@target(javascript) +fn do_is_utf8(bits: BitArray) -> Bool { + case to_string(bits) { + Ok(_) -> True + _ -> False + } +} + +/// Converts a bit array to a string. +/// +/// Returns an error if the bit array is invalid UTF-8 data. +/// +pub fn to_string(bits: BitArray) -> Result(String, Nil) { + do_to_string(bits) +} + +@target(erlang) +@external(erlang, "gleam_stdlib", "identity") +fn unsafe_to_string(a: BitArray) -> String + +@target(erlang) +fn do_to_string(bits: BitArray) -> Result(String, Nil) { + case is_utf8(bits) { + True -> Ok(unsafe_to_string(bits)) + False -> Error(Nil) + } +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "bit_array_to_string") +fn do_to_string(a: BitArray) -> Result(String, Nil) + +/// Creates a new bit array by joining multiple binaries. +/// +/// ## Examples +/// +/// ```gleam +/// > concat([from_string("butter"), from_string("fly")]) +/// from_string("butterfly") +/// ``` +/// +@external(erlang, "gleam_stdlib", "bit_array_concat") +@external(javascript, "../gleam_stdlib.mjs", "bit_array_concat") +pub fn concat(bit_arrays: List(BitArray)) -> BitArray + +/// Encodes a BitArray into a base 64 encoded string. +/// +pub fn base64_encode(input: BitArray, padding: Bool) -> String { + let encoded = encode64(input) + case padding { + True -> encoded + False -> string.replace(encoded, "=", "") + } +} + +@external(erlang, "base64", "encode") +@external(javascript, "../gleam_stdlib.mjs", "encode64") +fn encode64(a: BitArray) -> String + +/// Decodes a base 64 encoded string into a `BitArray`. +/// +pub fn base64_decode(encoded: String) -> Result(BitArray, Nil) { + let padded = case byte_size(from_string(encoded)) % 4 { + 0 -> encoded + n -> string.append(encoded, string.repeat("=", 4 - n)) + } + decode64(padded) +} + +@external(erlang, "gleam_stdlib", "base_decode64") +@external(javascript, "../gleam_stdlib.mjs", "decode64") +fn decode64(a: String) -> Result(BitArray, Nil) + +/// Encodes a `BitArray` into a base 64 encoded string with URL and filename safe alphabet. +/// +pub fn base64_url_encode(input: BitArray, padding: Bool) -> String { + base64_encode(input, padding) + |> string.replace("+", "-") + |> string.replace("/", "_") +} + +/// Decodes a base 64 encoded string with URL and filename safe alphabet into a `BitArray`. +/// +pub fn base64_url_decode(encoded: String) -> Result(BitArray, Nil) { + encoded + |> string.replace("-", "+") + |> string.replace("_", "/") + |> base64_decode() +} + +@external(erlang, "binary", "encode_hex") +@external(javascript, "../gleam_stdlib.mjs", "base16_encode") +pub fn base16_encode(input: BitArray) -> String + +@external(erlang, "gleam_stdlib", "base16_decode") +@external(javascript, "../gleam_stdlib.mjs", "base16_decode") +pub fn base16_decode(input: String) -> Result(BitArray, Nil) diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/bit_builder.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/bit_builder.gleam new file mode 100644 index 0000000..ce6fe52 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/bit_builder.gleam @@ -0,0 +1,80 @@ +//// This module has been deprecated in favour of `gleam/bytes_builder`. + +import gleam/bytes_builder +import gleam/string_builder.{type StringBuilder} + +pub type BitBuilder = + bytes_builder.BytesBuilder + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn new() -> BitBuilder { + bytes_builder.new() +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn prepend(to: BitBuilder, prefix: BitArray) -> BitBuilder { + bytes_builder.prepend(to, prefix) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn append(to: BitBuilder, suffix: BitArray) -> BitBuilder { + bytes_builder.append(to, suffix) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn prepend_builder(to: BitBuilder, prefix: BitBuilder) -> BitBuilder { + bytes_builder.prepend_builder(to, prefix) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn append_builder( + to first: BitBuilder, + suffix second: BitBuilder, +) -> BitBuilder { + bytes_builder.append_builder(first, second) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn prepend_string(to: BitBuilder, prefix: String) -> BitBuilder { + bytes_builder.prepend_string(to, prefix) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn append_string(to: BitBuilder, suffix: String) -> BitBuilder { + bytes_builder.append_string(to, suffix) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn concat(builders: List(BitBuilder)) -> BitBuilder { + bytes_builder.concat(builders) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn concat_bit_strings(bits: List(BitArray)) -> BitBuilder { + bytes_builder.concat_bit_arrays(bits) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn from_string(string: String) -> BitBuilder { + bytes_builder.from_string(string) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn from_string_builder(builder: StringBuilder) -> BitBuilder { + bytes_builder.from_string_builder(builder) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn from_bit_string(bits: BitArray) -> BitBuilder { + bytes_builder.from_bit_array(bits) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn to_bit_string(builder: BitBuilder) -> BitArray { + bytes_builder.to_bit_array(builder) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn byte_size(builder: BitBuilder) -> Int { + bytes_builder.byte_size(builder) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/bit_string.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/bit_string.gleam new file mode 100644 index 0000000..b703da0 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/bit_string.gleam @@ -0,0 +1,43 @@ +//// This module has been deprecated. Please use the `gleam/bit_array` module +//// instead. + +import gleam/bit_array + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn from_string(x: String) -> BitArray { + bit_array.from_string(x) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn byte_size(x: BitArray) -> Int { + bit_array.byte_size(x) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn append(to first: BitArray, suffix second: BitArray) -> BitArray { + bit_array.append(first, second) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn slice( + from string: BitArray, + at position: Int, + take length: Int, +) -> Result(BitArray, Nil) { + bit_array.slice(string, position, length) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn is_utf8(bits: BitArray) -> Bool { + bit_array.is_utf8(bits) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn to_string(bits: BitArray) -> Result(String, Nil) { + bit_array.to_string(bits) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn concat(bit_strings: List(BitArray)) -> BitArray { + bit_array.concat(bit_strings) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/bool.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/bool.gleam new file mode 100644 index 0000000..91bd6b7 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/bool.gleam @@ -0,0 +1,428 @@ +//// A type with two possible values, `True` and `False`. Used to indicate whether +//// things are... true or false! +//// +//// Often is it clearer and offers more type safety to define a custom type +//// than to use `Bool`. For example, rather than having a `is_teacher: Bool` +//// field consider having a `role: SchoolRole` field where `SchoolRole` is a custom +//// type that can be either `Student` or `Teacher`. + +import gleam/order.{type Order} + +/// Returns the and of two bools, but it evaluates both arguments. +/// +/// It's the function equivalent of the `&&` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > and(True, True) +/// True +/// ``` +/// +/// ```gleam +/// > and(False, True) +/// False +/// ``` +/// +/// ```gleam +/// > False |> and(True) +/// False +/// ``` +/// +pub fn and(a: Bool, b: Bool) -> Bool { + a && b +} + +/// Returns the or of two bools, but it evaluates both arguments. +/// +/// It's the function equivalent of the `||` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > or(True, True) +/// True +/// ``` +/// +/// ```gleam +/// > or(False, True) +/// True +/// ``` +/// +/// ```gleam +/// > False |> or(True) +/// True +/// ``` +/// +pub fn or(a: Bool, b: Bool) -> Bool { + a || b +} + +/// Returns the opposite bool value. +/// +/// This is the same as the `!` or `not` operators in some other languages. +/// +/// ## Examples +/// +/// ```gleam +/// > negate(True) +/// False +/// ``` +/// +/// ```gleam +/// > negate(False) +/// True +/// ``` +/// +pub fn negate(bool: Bool) -> Bool { + case bool { + True -> False + False -> True + } +} + +/// Returns the nor of two bools. +/// +/// ## Examples +/// +/// ```gleam +/// > nor(False, False) +/// True +/// ``` +/// +/// ```gleam +/// > nor(False, True) +/// False +/// ``` +/// +/// ```gleam +/// > nor(True, False) +/// False +/// ``` +/// +/// ```gleam +/// > nor(True, True) +/// False +/// ``` +/// +pub fn nor(a: Bool, b: Bool) -> Bool { + case a, b { + False, False -> True + False, True -> False + True, False -> False + True, True -> False + } +} + +/// Returns the nand of two bools. +/// +/// ## Examples +/// +/// ```gleam +/// > nand(False, False) +/// True +/// ``` +/// +/// ```gleam +/// > nand(False, True) +/// True +/// ``` +/// +/// ```gleam +/// > nand(True, False) +/// True +/// ``` +/// +/// ```gleam +/// > nand(True, True) +/// False +/// ``` +/// +pub fn nand(a: Bool, b: Bool) -> Bool { + case a, b { + False, False -> True + False, True -> True + True, False -> True + True, True -> False + } +} + +/// Returns the exclusive or of two bools. +/// +/// ## Examples +/// +/// ```gleam +/// > exclusive_or(False, False) +/// False +/// ``` +/// +/// ```gleam +/// > exclusive_or(False, True) +/// True +/// ``` +/// +/// ```gleam +/// > exclusive_or(True, False) +/// True +/// ``` +/// +/// ```gleam +/// > exclusive_or(True, True) +/// False +/// ``` +/// +pub fn exclusive_or(a: Bool, b: Bool) -> Bool { + case a, b { + False, False -> False + False, True -> True + True, False -> True + True, True -> False + } +} + +/// Returns the exclusive nor of two bools. +/// +/// ## Examples +/// +/// ```gleam +/// > exclusive_nor(False, False) +/// True +/// ``` +/// +/// ```gleam +/// > exclusive_nor(False, True) +/// False +/// ``` +/// +/// ```gleam +/// > exclusive_nor(True, False) +/// False +/// ``` +/// +/// ```gleam +/// > exclusive_nor(True, True) +/// True +/// ``` +/// +pub fn exclusive_nor(a: Bool, b: Bool) -> Bool { + case a, b { + False, False -> True + False, True -> False + True, False -> False + True, True -> True + } +} + +/// Compares two bools and returns the first value's `Order` to the second. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/order +/// > compare(True, False) +/// order.Gt +/// ``` +/// +pub fn compare(a: Bool, with b: Bool) -> Order { + case a, b { + True, True -> order.Eq + True, False -> order.Gt + False, False -> order.Eq + False, True -> order.Lt + } +} + +/// Returns `True` if either argument's value is `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > max(True, False) +/// True +/// ``` +/// +/// ```gleam +/// > max(False, True) +/// True +/// ``` +/// +/// ```gleam +/// > max(False, False) +/// False +/// ``` +/// +pub fn max(a: Bool, b: Bool) -> Bool { + case a { + True -> True + False -> b + } +} + +/// Returns `False` if either bool value is `False`. +/// +/// ## Examples +/// +/// ```gleam +/// > min(True, False) +/// False +/// ``` +/// +/// ```gleam +/// > min(False, True) +/// False +/// +/// > min(False, False) +/// False +/// ``` +/// +pub fn min(a: Bool, b: Bool) -> Bool { + case a { + False -> False + True -> b + } +} + +/// Returns a numeric representation of the given bool. +/// +/// ## Examples +/// +/// ```gleam +/// > to_int(True) +/// 1 +/// +/// > to_int(False) +/// 0 +/// ``` +/// +pub fn to_int(bool: Bool) -> Int { + case bool { + False -> 0 + True -> 1 + } +} + +/// Returns a string representation of the given bool. +/// +/// ## Examples +/// +/// ```gleam +/// > to_string(True) +/// "True" +/// ``` +/// +/// ```gleam +/// > to_string(False) +/// "False" +/// ``` +/// +pub fn to_string(bool: Bool) -> String { + case bool { + False -> "False" + True -> "True" + } +} + +/// Run a callback function if the given bool is `False`, otherwise return a +/// default value. +/// +/// With a `use` expression this function can simulate the early-return pattern +/// found in some other programming languages. +/// +/// In a procedural language: +/// +/// ```js +/// if (predicate) return value; +/// // ... +/// ``` +/// +/// In Gleam with a `use` expression: +/// +/// ```gleam +/// use <- guard(when: predicate, return: value) +/// // ... +/// ``` +/// +/// Like everything in Gleam `use` is an expression, so it short circuits the +/// current block, not the entire function. As a result you can assign the value +/// to a variable: +/// +/// ```gleam +/// let x = { +/// use <- guard(when: predicate, return: value) +/// // ... +/// } +/// ``` +/// +/// Note that unlike in procedural languages the `return` value is evaluated +/// even when the predicate is `False`, so it is advisable not to perform +/// expensive computation there. +/// +/// +/// ## Examples +/// +/// ```gleam +/// > let name = "" +/// > use <- guard(when: name == "", return: "Welcome!") +/// > "Hello, " <> name +/// "Welcome!" +/// ``` +/// +/// ```gleam +/// > let name = "Kamaka" +/// > use <- guard(when: name == "", return: "Welcome!") +/// > "Hello, " <> name +/// "Hello, Kamaka" +/// ``` +/// +pub fn guard( + when requirement: Bool, + return consequence: t, + otherwise alternative: fn() -> t, +) -> t { + case requirement { + True -> consequence + False -> alternative() + } +} + +/// Runs a callback function if the given bool is `True`, otherwise runs an +/// alternative callback function. +/// +/// Useful when further computation should be delayed regardless of the given +/// bool's value. +/// +/// See [`guard`](#guard) for more info. +/// +/// ## Examples +/// +/// ```gleam +/// > let name = "Kamaka" +/// > let inquiry = fn() { "How may we address you?" } +/// > use <- lazy_guard(when: name == "", return: inquiry) +/// > "Hello, " <> name +/// "Hello, Kamaka" +/// ``` +/// +/// ```gleam +/// > import gleam/int +/// > let name = "" +/// > let greeting = fn() { "Hello, " <> name } +/// > use <- lazy_guard(when: name == "", otherwise: greeting) +/// > let number = int.random(1, 99) +/// > let name = "User " <> int.to_string(number) +/// > "Welcome, " <> name +/// "Welcome, User 54" +/// ``` +/// +pub fn lazy_guard( + when requirement: Bool, + return consequence: fn() -> a, + otherwise alternative: fn() -> a, +) -> a { + case requirement { + True -> consequence() + False -> alternative() + } +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/bytes_builder.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/bytes_builder.gleam new file mode 100644 index 0000000..20c145d --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/bytes_builder.gleam @@ -0,0 +1,197 @@ +//// BytesBuilder is a type used for efficiently concatenating bytes together +//// without copying. +//// +//// If we append one bit array to another the bit arrays must be copied to a +//// new location in memory so that they can sit together. This behaviour +//// enables efficient reading of the string but copying can be expensive, +//// especially if we want to join many bit arrays together. +//// +//// BytesBuilder is different in that it can be joined together in constant +//// time using minimal memory, and then can be efficiently converted to a +//// bit array using the `to_bit_array` function. +//// +//// Byte builders are always byte aligned, so that a number of bits that is not +//// divisible by 8 will be padded with 0s. +//// +//// On Erlang this type is compatible with Erlang's iolists. + +// TODO: pad bit arrays to byte boundaries when adding to a builder. +import gleam/string_builder.{type StringBuilder} +import gleam/list +import gleam/bit_array + +pub opaque type BytesBuilder { + Bytes(BitArray) + Text(StringBuilder) + Many(List(BytesBuilder)) +} + +/// Create an empty `BytesBuilder`. Useful as the start of a pipe chaining many +/// builders together. +/// +pub fn new() -> BytesBuilder { + concat([]) +} + +/// Prepends a bit array to the start of a builder. +/// +/// Runs in constant time. +/// +pub fn prepend(to second: BytesBuilder, prefix first: BitArray) -> BytesBuilder { + append_builder(from_bit_array(first), second) +} + +/// Appends a bit array to the end of a builder. +/// +/// Runs in constant time. +/// +pub fn append(to first: BytesBuilder, suffix second: BitArray) -> BytesBuilder { + append_builder(first, from_bit_array(second)) +} + +/// Prepends a builder onto the start of another. +/// +/// Runs in constant time. +/// +pub fn prepend_builder( + to second: BytesBuilder, + prefix first: BytesBuilder, +) -> BytesBuilder { + append_builder(first, second) +} + +/// Appends a builder onto the end of another. +/// +/// Runs in constant time. +/// +@external(erlang, "gleam_stdlib", "iodata_append") +pub fn append_builder( + to first: BytesBuilder, + suffix second: BytesBuilder, +) -> BytesBuilder { + case second { + Many(builders) -> Many([first, ..builders]) + _ -> Many([first, second]) + } +} + +/// Prepends a string onto the start of a builder. +/// +/// Runs in constant time when running on Erlang. +/// Runs in linear time with the length of the string otherwise. +/// +pub fn prepend_string( + to second: BytesBuilder, + prefix first: String, +) -> BytesBuilder { + append_builder(from_string(first), second) +} + +/// Appends a string onto the end of a builder. +/// +/// Runs in constant time when running on Erlang. +/// Runs in linear time with the length of the string otherwise. +/// +pub fn append_string( + to first: BytesBuilder, + suffix second: String, +) -> BytesBuilder { + append_builder(first, from_string(second)) +} + +/// Joins a list of builders into a single builder. +/// +/// Runs in constant time. +/// +@external(erlang, "gleam_stdlib", "identity") +pub fn concat(builders: List(BytesBuilder)) -> BytesBuilder { + Many(builders) +} + +/// Joins a list of bit arrays into a single builder. +/// +/// Runs in constant time. +/// +@external(erlang, "gleam_stdlib", "identity") +pub fn concat_bit_arrays(bits: List(BitArray)) -> BytesBuilder { + bits + |> list.map(fn(b) { from_bit_array(b) }) + |> concat() +} + +/// Creates a new builder from a string. +/// +/// Runs in constant time when running on Erlang. +/// Runs in linear time otherwise. +/// +@external(erlang, "gleam_stdlib", "wrap_list") +pub fn from_string(string: String) -> BytesBuilder { + Text(string_builder.from_string(string)) +} + +/// Creates a new builder from a string builder. +/// +/// Runs in constant time when running on Erlang. +/// Runs in linear time otherwise. +/// +@external(erlang, "gleam_stdlib", "wrap_list") +pub fn from_string_builder(builder: StringBuilder) -> BytesBuilder { + Text(builder) +} + +/// Creates a new builder from a bit array. +/// +/// Runs in constant time. +/// +@external(erlang, "gleam_stdlib", "wrap_list") +pub fn from_bit_array(bits: BitArray) -> BytesBuilder { + Bytes(bits) +} + +/// Turns an builder into a bit array. +/// +/// Runs in linear time. +/// +/// When running on Erlang this function is implemented natively by the +/// virtual machine and is highly optimised. +/// +@external(erlang, "erlang", "list_to_bitstring") +pub fn to_bit_array(builder: BytesBuilder) -> BitArray { + [[builder]] + |> to_list([]) + |> list.reverse + |> bit_array.concat +} + +fn to_list( + stack: List(List(BytesBuilder)), + acc: List(BitArray), +) -> List(BitArray) { + case stack { + [] -> acc + + [[], ..remaining_stack] -> to_list(remaining_stack, acc) + + [[Bytes(bits), ..rest], ..remaining_stack] -> + to_list([rest, ..remaining_stack], [bits, ..acc]) + + [[Text(builder), ..rest], ..remaining_stack] -> { + let bits = bit_array.from_string(string_builder.to_string(builder)) + to_list([rest, ..remaining_stack], [bits, ..acc]) + } + + [[Many(builders), ..rest], ..remaining_stack] -> + to_list([builders, rest, ..remaining_stack], acc) + } +} + +/// Returns the size of the builder's content in bytes. +/// +/// Runs in linear time. +/// +@external(erlang, "erlang", "iolist_size") +pub fn byte_size(builder: BytesBuilder) -> Int { + [[builder]] + |> to_list([]) + |> list.fold(0, fn(acc, builder) { bit_array.byte_size(builder) + acc }) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/dict.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/dict.gleam new file mode 100644 index 0000000..280bf9d --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/dict.gleam @@ -0,0 +1,544 @@ +import gleam/option.{type Option} + +/// A dictionary of keys and values. +/// +/// Any type can be used for the keys and values of a dict, but all the keys +/// must be of the same type and all the values must be of the same type. +/// +/// Each key can only be present in a dict once. +/// +/// Dicts are not ordered in any way, and any unintentional ordering is not to +/// be relied upon in your code as it may change in future versions of Erlang +/// or Gleam. +/// +/// See [the Erlang map module](https://erlang.org/doc/man/maps.html) for more +/// information. +/// +pub type Dict(key, value) + +/// Determines the number of key-value pairs in the dict. +/// This function runs in constant time and does not need to iterate the dict. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> size() +/// 0 +/// ``` +/// +/// ```gleam +/// > new() |> insert("key", "value") |> size() +/// 1 +/// ``` +/// +pub fn size(dict: Dict(k, v)) -> Int { + do_size(dict) +} + +@external(erlang, "maps", "size") +@external(javascript, "../gleam_stdlib.mjs", "map_size") +fn do_size(a: Dict(k, v)) -> Int + +/// Converts the dict to a list of 2-element tuples `#(key, value)`, one for +/// each key-value pair in the dict. +/// +/// The tuples in the list have no specific order. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> to_list() +/// [] +/// ``` +/// +/// ```gleam +/// > new() |> insert("key", 0) |> to_list() +/// [#("key", 0)] +/// ``` +/// +pub fn to_list(dict: Dict(key, value)) -> List(#(key, value)) { + do_to_list(dict) +} + +@external(erlang, "maps", "to_list") +@external(javascript, "../gleam_stdlib.mjs", "map_to_list") +fn do_to_list(a: Dict(key, value)) -> List(#(key, value)) + +/// Converts a list of 2-element tuples `#(key, value)` to a dict. +/// +/// If two tuples have the same key the last one in the list will be the one +/// that is present in the dict. +/// +pub fn from_list(list: List(#(k, v))) -> Dict(k, v) { + do_from_list(list) +} + +@target(erlang) +@external(erlang, "maps", "from_list") +fn do_from_list(a: List(#(key, value))) -> Dict(key, value) + +@target(javascript) +fn fold_list_of_pair( + over list: List(#(k, v)), + from initial: Dict(k, v), +) -> Dict(k, v) { + case list { + [] -> initial + [x, ..rest] -> fold_list_of_pair(rest, insert(initial, x.0, x.1)) + } +} + +@target(javascript) +fn do_from_list(list: List(#(k, v))) -> Dict(k, v) { + fold_list_of_pair(list, new()) +} + +/// Determines whether or not a value present in the dict for a given key. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> insert("a", 0) |> has_key("a") +/// True +/// ``` +/// +/// ```gleam +/// > new() |> insert("a", 0) |> has_key("b") +/// False +/// ``` +/// +pub fn has_key(dict: Dict(k, v), key: k) -> Bool { + do_has_key(key, dict) +} + +@target(erlang) +@external(erlang, "maps", "is_key") +fn do_has_key(a: key, b: Dict(key, v)) -> Bool + +@target(javascript) +fn do_has_key(key: k, dict: Dict(k, v)) -> Bool { + get(dict, key) != Error(Nil) +} + +/// Creates a fresh dict that contains no values. +/// +pub fn new() -> Dict(key, value) { + do_new() +} + +@external(erlang, "maps", "new") +@external(javascript, "../gleam_stdlib.mjs", "new_map") +fn do_new() -> Dict(key, value) + +/// Fetches a value from a dict for a given key. +/// +/// The dict may not have a value for the key, so the value is wrapped in a +/// `Result`. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> insert("a", 0) |> get("a") +/// Ok(0) +/// ``` +/// +/// ```gleam +/// > new() |> insert("a", 0) |> get("b") +/// Error(Nil) +/// ``` +/// +pub fn get(from: Dict(key, value), get: key) -> Result(value, Nil) { + do_get(from, get) +} + +@external(erlang, "gleam_stdlib", "map_get") +@external(javascript, "../gleam_stdlib.mjs", "map_get") +fn do_get(a: Dict(key, value), b: key) -> Result(value, Nil) + +/// Inserts a value into the dict with the given key. +/// +/// If the dict already has a value for the given key then the value is +/// replaced with the new value. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> insert("a", 0) |> to_list +/// [#("a", 0)] +/// ``` +/// +/// ```gleam +/// > new() |> insert("a", 0) |> insert("a", 5) |> to_list +/// [#("a", 5)] +/// ``` +/// +pub fn insert(into dict: Dict(k, v), for key: k, insert value: v) -> Dict(k, v) { + do_insert(key, value, dict) +} + +@external(erlang, "maps", "put") +@external(javascript, "../gleam_stdlib.mjs", "map_insert") +fn do_insert(a: key, b: value, c: Dict(key, value)) -> Dict(key, value) + +/// Updates all values in a given dict by calling a given function on each key +/// and value. +/// +/// ## Examples +/// +/// ```gleam +/// > [#(3, 3), #(2, 4)] +/// > |> from_list +/// > |> map_values(fn(key, value) { key * value }) +/// [#(3, 9), #(2, 8)] +/// ``` +/// +pub fn map_values(in dict: Dict(k, v), with fun: fn(k, v) -> w) -> Dict(k, w) { + do_map_values(fun, dict) +} + +@target(erlang) +@external(erlang, "maps", "map") +fn do_map_values(a: fn(key, value) -> b, b: Dict(key, value)) -> Dict(key, b) + +@target(javascript) +fn do_map_values(f: fn(key, value) -> b, dict: Dict(key, value)) -> Dict(key, b) { + let f = fn(dict, k, v) { insert(dict, k, f(k, v)) } + dict + |> fold(from: new(), with: f) +} + +/// Gets a list of all keys in a given dict. +/// +/// Dicts are not ordered so the keys are not returned in any specific order. Do +/// not write code that relies on the order keys are returned by this function +/// as it may change in later versions of Gleam or Erlang. +/// +/// ## Examples +/// +/// ```gleam +/// > keys([#("a", 0), #("b", 1)]) +/// ["a", "b"] +/// ``` +/// +pub fn keys(dict: Dict(keys, v)) -> List(keys) { + do_keys(dict) +} + +@target(erlang) +@external(erlang, "maps", "keys") +fn do_keys(a: Dict(keys, v)) -> List(keys) + +@target(javascript) +fn reverse_and_concat(remaining, accumulator) { + case remaining { + [] -> accumulator + [item, ..rest] -> reverse_and_concat(rest, [item, ..accumulator]) + } +} + +@target(javascript) +fn do_keys_acc(list: List(#(k, v)), acc: List(k)) -> List(k) { + case list { + [] -> reverse_and_concat(acc, []) + [x, ..xs] -> do_keys_acc(xs, [x.0, ..acc]) + } +} + +@target(javascript) +fn do_keys(dict: Dict(k, v)) -> List(k) { + let list_of_pairs = to_list(dict) + do_keys_acc(list_of_pairs, []) +} + +/// Gets a list of all values in a given dict. +/// +/// Dicts are not ordered so the values are not returned in any specific order. Do +/// not write code that relies on the order values are returned by this function +/// as it may change in later versions of Gleam or Erlang. +/// +/// ## Examples +/// +/// ```gleam +/// > values(from_list([#("a", 0), #("b", 1)])) +/// [0, 1] +/// ``` +/// +pub fn values(dict: Dict(k, values)) -> List(values) { + do_values(dict) +} + +@target(erlang) +@external(erlang, "maps", "values") +fn do_values(a: Dict(k, values)) -> List(values) + +@target(javascript) +fn do_values_acc(list: List(#(k, v)), acc: List(v)) -> List(v) { + case list { + [] -> reverse_and_concat(acc, []) + [x, ..xs] -> do_values_acc(xs, [x.1, ..acc]) + } +} + +@target(javascript) +fn do_values(dict: Dict(k, v)) -> List(v) { + let list_of_pairs = to_list(dict) + do_values_acc(list_of_pairs, []) +} + +/// Creates a new dict from a given dict, minus any entries that a given function +/// returns `False` for. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([#("a", 0), #("b", 1)]) +/// > |> filter(fn(key, value) { value != 0 }) +/// from_list([#("b", 1)]) +/// ``` +/// +/// ```gleam +/// > from_list([#("a", 0), #("b", 1)]) +/// > |> filter(fn(key, value) { True }) +/// from_list([#("a", 0), #("b", 1)]) +/// ``` +/// +pub fn filter( + in dict: Dict(k, v), + keeping predicate: fn(k, v) -> Bool, +) -> Dict(k, v) { + do_filter(predicate, dict) +} + +@target(erlang) +@external(erlang, "maps", "filter") +fn do_filter(a: fn(key, value) -> Bool, b: Dict(key, value)) -> Dict(key, value) + +@target(javascript) +fn do_filter( + f: fn(key, value) -> Bool, + dict: Dict(key, value), +) -> Dict(key, value) { + let insert = fn(dict, k, v) { + case f(k, v) { + True -> insert(dict, k, v) + _ -> dict + } + } + dict + |> fold(from: new(), with: insert) +} + +/// Creates a new dict from a given dict, only including any entries for which the +/// keys are in a given list. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([#("a", 0), #("b", 1)]) +/// > |> take(["b"]) +/// from_list([#("b", 1)]) +/// ``` +/// +/// ```gleam +/// > from_list([#("a", 0), #("b", 1)]) +/// > |> take(["a", "b", "c"]) +/// from_list([#("a", 0), #("b", 1)]) +/// ``` +/// +pub fn take(from dict: Dict(k, v), keeping desired_keys: List(k)) -> Dict(k, v) { + do_take(desired_keys, dict) +} + +@target(erlang) +@external(erlang, "maps", "with") +fn do_take(a: List(k), b: Dict(k, v)) -> Dict(k, v) + +@target(javascript) +fn insert_taken( + dict: Dict(k, v), + desired_keys: List(k), + acc: Dict(k, v), +) -> Dict(k, v) { + let insert = fn(taken, key) { + case get(dict, key) { + Ok(value) -> insert(taken, key, value) + _ -> taken + } + } + case desired_keys { + [] -> acc + [x, ..xs] -> insert_taken(dict, xs, insert(acc, x)) + } +} + +@target(javascript) +fn do_take(desired_keys: List(k), dict: Dict(k, v)) -> Dict(k, v) { + insert_taken(dict, desired_keys, new()) +} + +/// Creates a new dict from a pair of given dicts by combining their entries. +/// +/// If there are entries with the same keys in both dicts the entry from the +/// second dict takes precedence. +/// +/// ## Examples +/// +/// ```gleam +/// > let a = from_list([#("a", 0), #("b", 1)]) +/// > let b = from_list([#("b", 2), #("c", 3)]) +/// > merge(a, b) +/// from_list([#("a", 0), #("b", 2), #("c", 3)]) +/// ``` +/// +pub fn merge(into dict: Dict(k, v), from new_entries: Dict(k, v)) -> Dict(k, v) { + do_merge(dict, new_entries) +} + +@target(erlang) +@external(erlang, "maps", "merge") +fn do_merge(a: Dict(k, v), b: Dict(k, v)) -> Dict(k, v) + +@target(javascript) +fn insert_pair(dict: Dict(k, v), pair: #(k, v)) -> Dict(k, v) { + insert(dict, pair.0, pair.1) +} + +@target(javascript) +fn fold_inserts(new_entries: List(#(k, v)), dict: Dict(k, v)) -> Dict(k, v) { + case new_entries { + [] -> dict + [x, ..xs] -> fold_inserts(xs, insert_pair(dict, x)) + } +} + +@target(javascript) +fn do_merge(dict: Dict(k, v), new_entries: Dict(k, v)) -> Dict(k, v) { + new_entries + |> to_list + |> fold_inserts(dict) +} + +/// Creates a new dict from a given dict with all the same entries except for the +/// one with a given key, if it exists. +/// +/// ## Examples +/// +/// ```gleam +/// > delete([#("a", 0), #("b", 1)], "a") +/// from_list([#("b", 1)]) +/// ``` +/// +/// ```gleam +/// > delete([#("a", 0), #("b", 1)], "c") +/// from_list([#("a", 0), #("b", 1)]) +/// ``` +/// +pub fn delete(from dict: Dict(k, v), delete key: k) -> Dict(k, v) { + do_delete(key, dict) +} + +@external(erlang, "maps", "remove") +@external(javascript, "../gleam_stdlib.mjs", "map_remove") +fn do_delete(a: k, b: Dict(k, v)) -> Dict(k, v) + +/// Creates a new dict from a given dict with all the same entries except any with +/// keys found in a given list. +/// +/// ## Examples +/// +/// ```gleam +/// > drop([#("a", 0), #("b", 1)], ["a"]) +/// from_list([#("b", 2)]) +/// ``` +/// +/// ```gleam +/// > delete([#("a", 0), #("b", 1)], ["c"]) +/// from_list([#("a", 0), #("b", 1)]) +/// ``` +/// +/// ```gleam +/// > drop([#("a", 0), #("b", 1)], ["a", "b", "c"]) +/// from_list([]) +/// ``` +/// +pub fn drop(from dict: Dict(k, v), drop disallowed_keys: List(k)) -> Dict(k, v) { + case disallowed_keys { + [] -> dict + [x, ..xs] -> drop(delete(dict, x), xs) + } +} + +/// Creates a new dict with one entry updated using a given function. +/// +/// If there was not an entry in the dict for the given key then the function +/// gets `None` as its argument, otherwise it gets `Some(value)`. +/// +/// ## Example +/// +/// ```gleam +/// > let increment = fn(x) { +/// > case x { +/// > Some(i) -> i + 1 +/// > None -> 0 +/// > } +/// > } +/// > let dict = from_list([#("a", 0)]) +/// > +/// > update(dict, "a", increment) +/// from_list([#("a", 1)]) +/// ``` +/// +/// ```gleam +/// > update(dict, "b", increment) +/// from_list([#("a", 0), #("b", 0)]) +/// ``` +/// +pub fn update( + in dict: Dict(k, v), + update key: k, + with fun: fn(Option(v)) -> v, +) -> Dict(k, v) { + dict + |> get(key) + |> option.from_result + |> fun + |> insert(dict, key, _) +} + +fn do_fold(list: List(#(k, v)), initial: acc, fun: fn(acc, k, v) -> acc) -> acc { + case list { + [] -> initial + [#(k, v), ..rest] -> do_fold(rest, fun(initial, k, v), fun) + } +} + +/// Combines all entries into a single value by calling a given function on each +/// one. +/// +/// Dicts are not ordered so the values are not returned in any specific order. Do +/// not write code that relies on the order entries are used by this function +/// as it may change in later versions of Gleam or Erlang. +/// +/// # Examples +/// +/// ```gleam +/// > let dict = from_list([#("a", 1), #("b", 3), #("c", 9)]) +/// > fold(dict, 0, fn(accumulator, key, value) { accumulator + value }) +/// 13 +/// ``` +/// +/// ```gleam +/// > import gleam/string.{append} +/// > fold(dict, "", fn(accumulator, key, value) { append(accumulator, key) }) +/// "abc" +/// ``` +/// +pub fn fold( + over dict: Dict(k, v), + from initial: acc, + with fun: fn(acc, k, v) -> acc, +) -> acc { + dict + |> to_list + |> do_fold(initial, fun) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/dynamic.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/dynamic.gleam new file mode 100644 index 0000000..c71c6f3 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/dynamic.gleam @@ -0,0 +1,1508 @@ +import gleam/int +import gleam/list +import gleam/dict.{type Dict} +import gleam/option.{type Option} +import gleam/result +import gleam/string_builder +@target(erlang) +import gleam/bit_array + +/// `Dynamic` data is data that we don't know the type of yet. +/// We likely get data like this from interop with Erlang, or from +/// IO with the outside world. +/// +pub type Dynamic + +/// Error returned when unexpected data is encountered +/// +pub type DecodeError { + DecodeError(expected: String, found: String, path: List(String)) +} + +pub type DecodeErrors = + List(DecodeError) + +pub type Decoder(t) = + fn(Dynamic) -> Result(t, DecodeErrors) + +/// Converts any Gleam data into `Dynamic` data. +/// +pub fn from(a) -> Dynamic { + do_from(a) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_from(a: anything) -> Dynamic + +/// Unsafely casts a Dynamic value into any other type. +/// +/// This is an escape hatch for the type system that may be useful when wrapping +/// native Erlang APIs. It is to be used as a last measure only! +/// +/// If you can avoid using this function, do! +/// +pub fn unsafe_coerce(a: Dynamic) -> anything { + do_unsafe_coerce(a) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_unsafe_coerce(a: Dynamic) -> a + +/// Decodes a `Dynamic` value from a `Dynamic` value. +/// +/// This function doesn't seem very useful at first, but it can be convenient +/// when you need to give a decoder function but you don't actually care what +/// the to-decode value is. +/// +pub fn dynamic(value: Dynamic) -> Result(Dynamic, List(DecodeError)) { + Ok(value) +} + +/// Checks to see whether a `Dynamic` value is a bit array, and returns that bit +/// array if it is. +/// +/// ## Examples +/// +/// ```gleam +/// > bit_array(from("Hello")) == bit_array.from_string("Hello") +/// True +/// ``` +/// +/// ```gleam +/// > bit_array(from(123)) +/// Error([DecodeError(expected: "BitArray", found: "Int", path: [])]) +/// ``` +/// +pub fn bit_array(from data: Dynamic) -> Result(BitArray, DecodeErrors) { + decode_bit_array(data) +} + +@deprecated("Please use `bit_array` instead") +pub fn bit_string(from data: Dynamic) -> Result(BitArray, DecodeErrors) { + bit_array(data) +} + +@external(erlang, "gleam_stdlib", "decode_bit_array") +@external(javascript, "../gleam_stdlib.mjs", "decode_bit_array") +fn decode_bit_array(a: Dynamic) -> Result(BitArray, DecodeErrors) + +/// Checks to see whether a `Dynamic` value is a string, and returns that string if +/// it is. +/// +/// ## Examples +/// +/// ```gleam +/// > string(from("Hello")) +/// Ok("Hello") +/// ``` +/// +/// ```gleam +/// > string(from(123)) +/// Error([DecodeError(expected: "String", found: "Int", path: [])]) +/// ``` +/// +pub fn string(from data: Dynamic) -> Result(String, DecodeErrors) { + decode_string(data) +} + +fn map_errors( + result: Result(t, DecodeErrors), + f: fn(DecodeError) -> DecodeError, +) -> Result(t, DecodeErrors) { + result.map_error(result, list.map(_, f)) +} + +@target(erlang) +fn decode_string(data: Dynamic) -> Result(String, DecodeErrors) { + bit_array(data) + |> map_errors(put_expected(_, "String")) + |> result.try(fn(raw) { + case bit_array.to_string(raw) { + Ok(string) -> Ok(string) + Error(Nil) -> + Error([DecodeError(expected: "String", found: "BitArray", path: [])]) + } + }) +} + +@target(erlang) +fn put_expected(error: DecodeError, expected: String) -> DecodeError { + DecodeError(..error, expected: expected) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "decode_string") +fn decode_string(a: Dynamic) -> Result(String, DecodeErrors) + +/// Return a string indicating the type of the dynamic value. +/// +/// ```gleam +/// > classify(from("Hello")) +/// "String" +/// ``` +/// +pub fn classify(data: Dynamic) -> String { + do_classify(data) +} + +@external(erlang, "gleam_stdlib", "classify_dynamic") +@external(javascript, "../gleam_stdlib.mjs", "classify_dynamic") +fn do_classify(a: Dynamic) -> String + +/// Checks to see whether a `Dynamic` value is an int, and returns that int if it +/// is. +/// +/// ## Examples +/// +/// ```gleam +/// > int(from(123)) +/// Ok(123) +/// ``` +/// +/// ```gleam +/// > int(from("Hello")) +/// Error([DecodeError(expected: "Int", found: "String", path: [])]) +/// ``` +/// +pub fn int(from data: Dynamic) -> Result(Int, DecodeErrors) { + decode_int(data) +} + +@external(erlang, "gleam_stdlib", "decode_int") +@external(javascript, "../gleam_stdlib.mjs", "decode_int") +fn decode_int(a: Dynamic) -> Result(Int, DecodeErrors) + +/// Checks to see whether a `Dynamic` value is a float, and returns that float if +/// it is. +/// +/// ## Examples +/// +/// ```gleam +/// > float(from(2.0)) +/// Ok(2.0) +/// ``` +/// +/// ```gleam +/// > float(from(123)) +/// Error([DecodeError(expected: "Float", found: "Int", path: [])]) +/// ``` +/// +pub fn float(from data: Dynamic) -> Result(Float, DecodeErrors) { + decode_float(data) +} + +@external(erlang, "gleam_stdlib", "decode_float") +@external(javascript, "../gleam_stdlib.mjs", "decode_float") +fn decode_float(a: Dynamic) -> Result(Float, DecodeErrors) + +/// Checks to see whether a `Dynamic` value is a bool, and returns that bool if +/// it is. +/// +/// ## Examples +/// +/// ```gleam +/// > bool(from(True)) +/// Ok(True) +/// ``` +/// +/// ```gleam +/// > bool(from(123)) +/// Error([DecodeError(expected: "Bool", found: "Int", path: [])]) +/// ``` +/// +pub fn bool(from data: Dynamic) -> Result(Bool, DecodeErrors) { + decode_bool(data) +} + +@external(erlang, "gleam_stdlib", "decode_bool") +@external(javascript, "../gleam_stdlib.mjs", "decode_bool") +fn decode_bool(a: Dynamic) -> Result(Bool, DecodeErrors) + +/// Checks to see whether a `Dynamic` value is a list, and returns that list if it +/// is. The types of the elements are not checked. +/// +/// If you wish to decode all the elements in the list use the `list` function +/// instead. +/// +/// ## Examples +/// +/// ```gleam +/// > shallow_list(from(["a", "b", "c"])) +/// Ok([from("a"), from("b"), from("c")]) +/// ``` +/// +/// ```gleam +/// > shallow_list(1) +/// Error([DecodeError(expected: "List", found: "Int", path: [])]) +/// ``` +/// +pub fn shallow_list(from value: Dynamic) -> Result(List(Dynamic), DecodeErrors) { + decode_list(value) +} + +@external(erlang, "gleam_stdlib", "decode_list") +@external(javascript, "../gleam_stdlib.mjs", "decode_list") +fn decode_list(a: Dynamic) -> Result(List(Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_result") +@external(javascript, "../gleam_stdlib.mjs", "decode_result") +fn decode_result(a: Dynamic) -> Result(Result(a, e), DecodeErrors) + +/// Checks to see whether a `Dynamic` value is a result of a particular type, and +/// returns that result if it is. +/// +/// The `ok` and `error` arguments are decoders for decoding the `Ok` and +/// `Error` values of the result. +/// +/// ## Examples +/// +/// ```gleam +/// > from(Ok(1)) +/// > |> result(ok: int, error: string) +/// Ok(Ok(1)) +/// ``` +/// +/// ```gleam +/// > from(Error("boom")) +/// > |> result(ok: int, error: string) +/// Ok(Error("boom")) +/// ``` +/// +/// ```gleam +/// > from(123) +/// > |> result(ok: int, error: string) +/// Error([DecodeError(expected: "Result", found: "Int", path: [])]) +/// ``` +/// +pub fn result( + ok decode_ok: Decoder(a), + error decode_error: Decoder(e), +) -> Decoder(Result(a, e)) { + fn(value) { + use inner_result <- result.try(decode_result(value)) + + case inner_result { + Ok(raw) -> { + use value <- result.try( + decode_ok(raw) + |> map_errors(push_path(_, "ok")), + ) + Ok(Ok(value)) + } + Error(raw) -> { + use value <- result.try( + decode_error(raw) + |> map_errors(push_path(_, "error")), + ) + Ok(Error(value)) + } + } + } +} + +/// Checks to see whether a `Dynamic` value is a list of a particular type, and +/// returns that list if it is. +/// +/// The second argument is a decoder function used to decode the elements of +/// the list. The list is only decoded if all elements in the list can be +/// successfully decoded using this function. +/// +/// If you do not wish to decode all the elements in the list use the `shallow_list` +/// function instead. +/// +/// ## Examples +/// +/// ```gleam +/// > from(["a", "b", "c"]) +/// > |> list(of: string) +/// Ok(["a", "b", "c"]) +/// ``` +/// +/// ```gleam +/// > from([1, 2, 3]) +/// > |> list(of: string) +/// Error([DecodeError(expected: "String", found: "Int", path: ["*"])]) +/// ``` +/// +/// ```gleam +/// > from("ok") +/// > |> list(of: string) +/// Error([DecodeError(expected: "List", found: "String", path: [])]) +/// ``` +/// +pub fn list( + of decoder_type: fn(Dynamic) -> Result(inner, DecodeErrors), +) -> Decoder(List(inner)) { + fn(dynamic) { + use list <- result.try(shallow_list(dynamic)) + list + |> list.try_map(decoder_type) + |> map_errors(push_path(_, "*")) + } +} + +/// Checks to see if a `Dynamic` value is a nullable version of a particular +/// type, and returns a corresponding `Option` if it is. +/// +/// ## Examples +/// +/// ```gleam +/// > from("Hello") +/// > |> optional(string) +/// Ok(Some("Hello")) +/// ``` +/// +/// ```gleam +/// > from("Hello") +/// > |> optional(string) +/// Ok(Some("Hello")) +/// ``` +/// +/// ```gleam +/// > from(atom.from_string("null")) +/// > |> optional(string) +/// Ok(None) +/// ``` +/// +/// ```gleam +/// > from(atom.from_string("nil")) +/// > |> optional(string) +/// Ok(None) +/// ``` +/// +/// ```gleam +/// > from(atom.from_string("undefined")) +/// > |> optional(string) +/// Ok(None) +/// ``` +/// +/// ```gleam +/// > from(123) +/// > |> optional(string) +/// Error([DecodeError(expected: "String", found: "Int", path: [])]) +/// ``` +/// +pub fn optional(of decode: Decoder(inner)) -> Decoder(Option(inner)) { + fn(value) { decode_optional(value, decode) } +} + +@external(erlang, "gleam_stdlib", "decode_option") +@external(javascript, "../gleam_stdlib.mjs", "decode_option") +fn decode_optional(a: Dynamic, b: Decoder(a)) -> Result(Option(a), DecodeErrors) + +/// Checks to see if a `Dynamic` value is a map with a specific field, and returns +/// the value of that field if it is. +/// +/// This will not succeed on a record. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/dict +/// > dict.new() +/// > |> dict.insert("Hello", "World") +/// > |> from +/// > |> field(named: "Hello", of: string) +/// Ok("World") +/// ``` +/// +/// ```gleam +/// > from(123) +/// > |> field("Hello", string) +/// Error([DecodeError(expected: "Map", found: "Int", path: [])]) +/// ``` +/// +pub fn field(named name: a, of inner_type: Decoder(t)) -> Decoder(t) { + fn(value) { + let missing_field_error = + DecodeError(expected: "field", found: "nothing", path: []) + + use maybe_inner <- result.try(decode_field(value, name)) + maybe_inner + |> option.to_result([missing_field_error]) + |> result.try(inner_type) + |> map_errors(push_path(_, name)) + } +} + +/// Checks to see if a `Dynamic` value is a map with a specific field. +/// If the map does not have the specified field, returns an `Ok(None)` instead of failing; otherwise, +/// returns the decoded field wrapped in `Some(_)`. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/dict +/// > dict.new() +/// > |> dict.insert("Hello", "World") +/// > |> from +/// > |> field(named: "Hello", of: string) +/// Ok(Some("World")) +/// ``` +/// +/// ```gleam +/// > import gleam/dict +/// > dict.new() +/// > |> from +/// > |> field(named: "Hello", of: string) +/// Ok(None) +/// ``` +/// +/// ```gleam +/// > from(123) +/// > |> field("Hello", string) +/// Error([DecodeError(expected: "Map", found: "Int", path: [])]) +/// ``` +/// +pub fn optional_field( + named name: a, + of inner_type: Decoder(t), +) -> Decoder(Option(t)) { + fn(value) { + use maybe_inner <- result.try(decode_field(value, name)) + case maybe_inner { + option.None -> Ok(option.None) + option.Some(dynamic_inner) -> + dynamic_inner + |> decode_optional(inner_type) + |> map_errors(push_path(_, name)) + } + } +} + +@external(erlang, "gleam_stdlib", "decode_field") +@external(javascript, "../gleam_stdlib.mjs", "decode_field") +fn decode_field(a: Dynamic, b: name) -> Result(Option(Dynamic), DecodeErrors) + +/// Checks to see if a `Dynamic` value is a tuple large enough to have a certain +/// index, and returns the value of that index if it is. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> element(0, int) +/// Ok(from(1)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> element(2, int) +/// Error([ +/// DecodeError( +/// expected: "Tuple of at least 3 elements", +/// found: "Tuple of 2 elements", +/// path: [], +/// ), +/// ]) +/// ``` +/// +pub fn element(at index: Int, of inner_type: Decoder(t)) -> Decoder(t) { + fn(data: Dynamic) { + use tuple <- result.try(decode_tuple(data)) + let size = tuple_size(tuple) + use data <- result.try(case index >= 0 { + True -> + case index < size { + True -> tuple_get(tuple, index) + False -> at_least_decode_tuple_error(index + 1, data) + } + False -> + case int.absolute_value(index) <= size { + True -> tuple_get(tuple, size + index) + False -> at_least_decode_tuple_error(int.absolute_value(index), data) + } + }) + inner_type(data) + |> map_errors(push_path(_, index)) + } +} + +fn at_least_decode_tuple_error( + size: Int, + data: Dynamic, +) -> Result(a, DecodeErrors) { + let s = case size { + 1 -> "" + _ -> "s" + } + let error = + ["Tuple of at least ", int.to_string(size), " element", s] + |> string_builder.from_strings + |> string_builder.to_string + |> DecodeError(found: classify(data), path: []) + Error([error]) +} + +// A tuple of unknown size +type UnknownTuple + +@external(erlang, "gleam_stdlib", "decode_tuple") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple") +fn decode_tuple(a: Dynamic) -> Result(UnknownTuple, DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple2") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple2") +fn decode_tuple2(a: Dynamic) -> Result(#(Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple3") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple3") +fn decode_tuple3( + a: Dynamic, +) -> Result(#(Dynamic, Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple4") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple4") +fn decode_tuple4( + a: Dynamic, +) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple5") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple5") +fn decode_tuple5( + a: Dynamic, +) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple6") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple6") +fn decode_tuple6( + a: Dynamic, +) -> Result( + #(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), + DecodeErrors, +) + +@external(erlang, "gleam_stdlib", "tuple_get") +@external(javascript, "../gleam_stdlib.mjs", "tuple_get") +fn tuple_get(a: UnknownTuple, b: Int) -> Result(Dynamic, DecodeErrors) + +@external(erlang, "gleam_stdlib", "size_of_tuple") +@external(javascript, "../gleam_stdlib.mjs", "length") +fn tuple_size(a: UnknownTuple) -> Int + +fn tuple_errors( + result: Result(a, List(DecodeError)), + name: String, +) -> List(DecodeError) { + case result { + Ok(_) -> [] + Error(errors) -> list.map(errors, push_path(_, name)) + } +} + +fn push_path(error: DecodeError, name: t) -> DecodeError { + let name = from(name) + let decoder = any([string, fn(x) { result.map(int(x), int.to_string) }]) + let name = case decoder(name) { + Ok(name) -> name + Error(_) -> + ["<", classify(name), ">"] + |> string_builder.from_strings + |> string_builder.to_string + } + DecodeError(..error, path: [name, ..error.path]) +} + +/// Checks to see if a `Dynamic` value is a 2-element tuple, list or array containing +/// specifically typed elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> tuple2(int, int) +/// Ok(#(1, 2)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2.0)) +/// > |> tuple2(int, float) +/// Ok(#(1, 2.0)) +/// ``` +/// +/// ```gleam +/// > from([1, 2]) +/// > |> tuple2(int, int) +/// Ok(#(1, 2)) +/// ``` +/// +/// ```gleam +/// > from([from(1), from(2.0)]) +/// > |> tuple2(int, float) +/// Ok(#(1, 2.0)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2, 3)) +/// > |> tuple2(int, float) +/// Error([ +/// DecodeError(expected: "Tuple of 2 elements", found: "Tuple of 3 elements", path: []), +/// ]) +/// ``` +/// +/// ```gleam +/// > from("") +/// > |> tuple2(int, float) +/// Error([DecodeError(expected: "Tuple of 2 elements", found: "String", path: [])]) +/// ``` +/// +pub fn tuple2( + first decode1: Decoder(a), + second decode2: Decoder(b), +) -> Decoder(#(a, b)) { + fn(value) { + use #(a, b) <- result.try(decode_tuple2(value)) + case decode1(a), decode2(b) { + Ok(a), Ok(b) -> Ok(#(a, b)) + a, b -> + tuple_errors(a, "0") + |> list.append(tuple_errors(b, "1")) + |> Error + } + } +} + +/// Checks to see if a `Dynamic` value is a 3-element tuple, list or array containing +/// specifically typed elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2, 3)) +/// > |> tuple3(int, int, int) +/// Ok(#(1, 2, 3)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2.0, "3")) +/// > |> tuple3(int, float, string) +/// Ok(#(1, 2.0, "3")) +/// ``` +/// +/// ```gleam +/// > from([1, 2, 3]) +/// > |> tuple3(int, int, int) +/// Ok(#(1, 2, 3)) +/// ``` +/// +/// ```gleam +/// > from([from(1), from(2.0), from("3")]) +/// > |> tuple3(int, float, string) +/// Ok(#(1, 2.0, "3")) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> tuple3(int, float, string) +/// Error([ +/// DecodeError(expected: "Tuple of 3 elements", found: "Tuple of 2 elements", path: [])), +/// ]) +/// ``` +/// +/// ```gleam +/// > from("") +/// > |> tuple3(int, float, string) +/// Error([ +/// DecodeError(expected: "Tuple of 3 elements", found: "String", path: []), +/// ]) +/// ``` +/// +pub fn tuple3( + first decode1: Decoder(a), + second decode2: Decoder(b), + third decode3: Decoder(c), +) -> Decoder(#(a, b, c)) { + fn(value) { + use #(a, b, c) <- result.try(decode_tuple3(value)) + case decode1(a), decode2(b), decode3(c) { + Ok(a), Ok(b), Ok(c) -> Ok(#(a, b, c)) + a, b, c -> + tuple_errors(a, "0") + |> list.append(tuple_errors(b, "1")) + |> list.append(tuple_errors(c, "2")) + |> Error + } + } +} + +/// Checks to see if a `Dynamic` value is a 4-element tuple, list or array containing +/// specifically typed elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2, 3, 4)) +/// > |> tuple4(int, int, int, int) +/// Ok(#(1, 2, 3, 4)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2.0, "3", 4)) +/// > |> tuple4(int, float, string, int) +/// Ok(#(1, 2.0, "3", 4)) +/// ``` +/// +/// ```gleam +/// > from([1, 2, 3, 4]) +/// > |> tuple4(int, int, int, int) +/// Ok(#(1, 2, 3, 4)) +/// ``` +/// +/// ```gleam +/// > from([from(1), from(2.0), from("3"), from(4)]) +/// > |> tuple4(int, float, string, int) +/// Ok(#(1, 2.0, "3", 4)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> tuple4(int, float, string, int) +/// Error([ +/// DecodeError(expected: "Tuple of 4 elements", found: "Tuple of 2 elements", path: []), +/// ]) +/// ``` +/// +/// ```gleam +/// > from("") +/// > |> tuple4(int, float, string, int) +/// Error([ +/// DecodeError(expected: "Tuple of 4 elements", found: "String", path: []), +/// ]) +/// ``` +/// +pub fn tuple4( + first decode1: Decoder(a), + second decode2: Decoder(b), + third decode3: Decoder(c), + fourth decode4: Decoder(d), +) -> Decoder(#(a, b, c, d)) { + fn(value) { + use #(a, b, c, d) <- result.try(decode_tuple4(value)) + case decode1(a), decode2(b), decode3(c), decode4(d) { + Ok(a), Ok(b), Ok(c), Ok(d) -> Ok(#(a, b, c, d)) + a, b, c, d -> + tuple_errors(a, "0") + |> list.append(tuple_errors(b, "1")) + |> list.append(tuple_errors(c, "2")) + |> list.append(tuple_errors(d, "3")) + |> Error + } + } +} + +/// Checks to see if a `Dynamic` value is a 5-element tuple, list or array containing +/// specifically typed elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2, 3, 4, 5)) +/// > |> tuple5(int, int, int, int, int) +/// Ok(#(1, 2, 3, 4, 5)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2.0, "3", 4, 5)) +/// > |> tuple5(int, float, string, int, int) +/// Ok(#(1, 2.0, "3", 4, 5)) +/// ``` +/// +/// ```gleam +/// > from([1, 2, 3, 4, 5]) +/// > |> tuple5(int, int, int, int, int) +/// Ok(#(1, 2, 3, 4, 5)) +/// ``` +/// +/// ```gleam +/// > from([from(1), from(2.0), from("3"), from(4), from(True)]) +/// > |> tuple5(int, float, string, int, bool) +/// Ok(#(1, 2.0, "3", 4, True)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> tuple5(int, float, string, int, int) +/// Error([ +/// DecodeError(expected: "Tuple of 5 elements", found: "Tuple of 2 elements", path: [])), +/// ]) +/// ``` +/// +/// ```gleam +/// > from("") +/// > |> tuple5(int, float, string, int, int) +/// Error([DecodeError(expected: "Tuple of 5 elements", found: "String", path: [])]) +/// ``` +/// +pub fn tuple5( + first decode1: Decoder(a), + second decode2: Decoder(b), + third decode3: Decoder(c), + fourth decode4: Decoder(d), + fifth decode5: Decoder(e), +) -> Decoder(#(a, b, c, d, e)) { + fn(value) { + use #(a, b, c, d, e) <- result.try(decode_tuple5(value)) + case decode1(a), decode2(b), decode3(c), decode4(d), decode5(e) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e) -> Ok(#(a, b, c, d, e)) + a, b, c, d, e -> + tuple_errors(a, "0") + |> list.append(tuple_errors(b, "1")) + |> list.append(tuple_errors(c, "2")) + |> list.append(tuple_errors(d, "3")) + |> list.append(tuple_errors(e, "4")) + |> Error + } + } +} + +/// Checks to see if a `Dynamic` value is a 6-element tuple, list or array containing +/// specifically typed elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2, 3, 4, 5, 6)) +/// > |> tuple6(int, int, int, int, int, int) +/// Ok(#(1, 2, 3, 4, 5, 6)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2.0, "3", 4, 5, 6)) +/// > |> tuple6(int, float, string, int, int, int) +/// Ok(#(1, 2.0, "3", 4, 5, 6)) +/// ``` +/// +/// ```gleam +/// > from([1, 2, 3, 4, 5, 6]) +/// > |> tuple6(int, int, int, int, int, int) +/// Ok(#(1, 2, 3, 4, 5, 6)) +/// ``` +/// +/// ```gleam +/// > from([from(1), from(2.0), from("3"), from(4), from(True), from(False)]) +/// > |> tuple6(int, float, string, int, bool, bool) +/// Ok(#(1, 2.0, "3", 4, True, False)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> tuple6(int, float, string, int, int, int) +/// Error([ +/// DecodeError(expected: "Tuple of 6 elements", found: "Tuple of 2 elements", path: []), +/// ]) +/// ``` +/// +/// ```gleam +/// > from("") +/// > |> tuple6(int, float, string, int, int, int) +/// Error([DecodeError(expected: "Tuple of 6 elements", found: "String", path: [])]) +/// ``` +/// +pub fn tuple6( + first decode1: Decoder(a), + second decode2: Decoder(b), + third decode3: Decoder(c), + fourth decode4: Decoder(d), + fifth decode5: Decoder(e), + sixth decode6: Decoder(f), +) -> Decoder(#(a, b, c, d, e, f)) { + fn(value) { + use #(a, b, c, d, e, f) <- result.try(decode_tuple6(value)) + case + decode1(a), + decode2(b), + decode3(c), + decode4(d), + decode5(e), + decode6(f) + { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e), Ok(f) -> Ok(#(a, b, c, d, e, f)) + a, b, c, d, e, f -> + tuple_errors(a, "0") + |> list.append(tuple_errors(b, "1")) + |> list.append(tuple_errors(c, "2")) + |> list.append(tuple_errors(d, "3")) + |> list.append(tuple_errors(e, "4")) + |> list.append(tuple_errors(f, "5")) + |> Error + } + } +} + +/// Checks to see if a `Dynamic` value is a dict. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/dict +/// > dict.new() |> from |> map(string, int) +/// Ok(dict.new()) +/// ``` +/// +/// ```gleam +/// > from(1) |> map(string, int) +/// Error(DecodeError(expected: "Map", found: "Int", path: [])) +/// ``` +/// +/// ```gleam +/// > from("") |> map(string, int) +/// Error(DecodeError(expected: "Map", found: "String", path: [])) +/// ``` +/// +pub fn dict( + of key_type: Decoder(k), + to value_type: Decoder(v), +) -> Decoder(Dict(k, v)) { + fn(value) { + use map <- result.try(decode_map(value)) + use pairs <- result.try( + map + |> dict.to_list + |> list.try_map(fn(pair) { + let #(k, v) = pair + use k <- result.try( + key_type(k) + |> map_errors(push_path(_, "keys")), + ) + use v <- result.try( + value_type(v) + |> map_errors(push_path(_, "values")), + ) + Ok(#(k, v)) + }), + ) + Ok(dict.from_list(pairs)) + } +} + +@deprecated("Use `dict` instead") +pub fn map( + of key_type: Decoder(k), + to value_type: Decoder(v), +) -> Decoder(Dict(k, v)) { + dict(key_type, value_type) +} + +@external(erlang, "gleam_stdlib", "decode_map") +@external(javascript, "../gleam_stdlib.mjs", "decode_map") +fn decode_map(a: Dynamic) -> Result(Dict(Dynamic, Dynamic), DecodeErrors) + +/// Joins multiple decoders into one. When run they will each be tried in turn +/// until one succeeds, or they all fail. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/result +/// > let bool_or_string = any(of: [ +/// > string, +/// > fn(x) { result.map(bool(x), fn(_) { "a bool" }) } +/// > ]) +/// > bool_or_string(from("ok")) +/// Ok("ok") +/// ``` +/// +/// ```gleam +/// > bool_or_string(from(True)) +/// Ok("a bool") +/// ``` +/// +/// ```gleam +/// > bool_or_string(from(1)) +/// Error(DecodeError(expected: "another type", found: "Int", path: [])) +/// ``` +/// +pub fn any(of decoders: List(Decoder(t))) -> Decoder(t) { + fn(data) { + case decoders { + [] -> + Error([ + DecodeError(found: classify(data), expected: "another type", path: []), + ]) + + [decoder, ..decoders] -> + case decoder(data) { + Ok(decoded) -> Ok(decoded) + Error(_) -> any(decoders)(data) + } + } + } +} + +/// Decode 1 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.0, "3")) +/// > |> decode1(MyRecord, element(0, int)) +/// Ok(MyRecord(1)) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "")) +/// > |> decode1(MyRecord, element(0, int)) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// ]) +/// ``` +/// +pub fn decode1(constructor: fn(t1) -> t, t1: Decoder(t1)) -> Decoder(t) { + fn(value) { + case t1(value) { + Ok(a) -> Ok(constructor(a)) + a -> Error(all_errors(a)) + } + } +} + +/// Decode 2 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.0, "3")) +/// > |> decode2(MyRecord, element(0, int), element(1, float)) +/// Ok(MyRecord(1, 2.0)) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "")) +/// > |> decode2(MyRecord, element(0, int), element(1, float)) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode2( + constructor: fn(t1, t2) -> t, + t1: Decoder(t1), + t2: Decoder(t2), +) -> Decoder(t) { + fn(value) { + case t1(value), t2(value) { + Ok(a), Ok(b) -> Ok(constructor(a, b)) + a, b -> Error(list.concat([all_errors(a), all_errors(b)])) + } + } +} + +/// Decode 3 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.0, "3")) +/// > |> decode3(MyRecord, element(0, int), element(1, float), element(2, string)) +/// Ok(MyRecord(1, 2.0, "3")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "")) +/// > |> decode3(MyRecord, element(0, int), element(1, float), element(2, string)) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode3( + constructor: fn(t1, t2, t3) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), +) -> Decoder(t) { + fn(value) { + case t1(value), t2(value), t3(value) { + Ok(a), Ok(b), Ok(c) -> Ok(constructor(a, b, c)) + a, b, c -> + Error(list.concat([all_errors(a), all_errors(b), all_errors(c)])) + } + } +} + +/// Decode 4 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4")) +/// > |> decode4( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "")) +/// > |> decode4( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode4( + constructor: fn(t1, t2, t3, t4) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x) { + Ok(a), Ok(b), Ok(c), Ok(d) -> Ok(constructor(a, b, c, d)) + a, b, c, d -> + Error(list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + ])) + } + } +} + +/// Decode 5 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4", "5")) +/// > |> decode5( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4", "5")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "", "")) +/// > |> decode5( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode5( + constructor: fn(t1, t2, t3, t4, t5) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), + t5: Decoder(t5), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x), t5(x) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e) -> Ok(constructor(a, b, c, d, e)) + a, b, c, d, e -> + Error(list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + all_errors(e), + ])) + } + } +} + +/// Decode 6 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4", "5", "6")) +/// > |> decode6( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4", "5", "6")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "", "", "")) +/// > |> decode6( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode6( + constructor: fn(t1, t2, t3, t4, t5, t6) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), + t5: Decoder(t5), + t6: Decoder(t6), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x), t5(x), t6(x) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e), Ok(f) -> + Ok(constructor(a, b, c, d, e, f)) + a, b, c, d, e, f -> + Error(list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + all_errors(e), + all_errors(f), + ])) + } + } +} + +/// Decode 7 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4", "5", "6")) +/// > |> decode7( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4", "5", "6", "7")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "", "", "", "")) +/// > |> decode7( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode7( + constructor: fn(t1, t2, t3, t4, t5, t6, t7) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), + t5: Decoder(t5), + t6: Decoder(t6), + t7: Decoder(t7), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x), t5(x), t6(x), t7(x) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e), Ok(f), Ok(g) -> + Ok(constructor(a, b, c, d, e, f, g)) + a, b, c, d, e, f, g -> + Error(list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + all_errors(e), + all_errors(f), + all_errors(g), + ])) + } + } +} + +/// Decode 8 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4", "5", "6", "7", "8")) +/// > |> decode8( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > element(7, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4", "5", "6", "7", "8")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "", "", "", "", "")) +/// > |> decode8( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > element(7, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode8( + constructor: fn(t1, t2, t3, t4, t5, t6, t7, t8) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), + t5: Decoder(t5), + t6: Decoder(t6), + t7: Decoder(t7), + t8: Decoder(t8), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x), t5(x), t6(x), t7(x), t8(x) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e), Ok(f), Ok(g), Ok(h) -> + Ok(constructor(a, b, c, d, e, f, g, h)) + a, b, c, d, e, f, g, h -> + Error(list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + all_errors(e), + all_errors(f), + all_errors(g), + all_errors(h), + ])) + } + } +} + +/// Decode 9 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4", "5", "6", "7", "8", "9")) +/// > |> decode9( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > element(7, string), +/// > element(8, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4", "5", "6", "7", "8", "9")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "", "", "", "", "", "")) +/// > |> decode9( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > element(7, string), +/// > element(8, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode9( + constructor: fn(t1, t2, t3, t4, t5, t6, t7, t8, t9) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), + t5: Decoder(t5), + t6: Decoder(t6), + t7: Decoder(t7), + t8: Decoder(t8), + t9: Decoder(t9), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x), t5(x), t6(x), t7(x), t8(x), t9(x) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e), Ok(f), Ok(g), Ok(h), Ok(i) -> + Ok(constructor(a, b, c, d, e, f, g, h, i)) + a, b, c, d, e, f, g, h, i -> + Error(list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + all_errors(e), + all_errors(f), + all_errors(g), + all_errors(h), + all_errors(i), + ])) + } + } +} + +fn all_errors(result: Result(a, List(DecodeError))) -> List(DecodeError) { + case result { + Ok(_) -> [] + Error(errors) -> errors + } +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/float.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/float.gleam new file mode 100644 index 0000000..5d62419 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/float.gleam @@ -0,0 +1,546 @@ +//// Functions for working with floats. +//// +//// ## Division by zero +//// +//// Gleam runs on the Erlang virtual machine, which does not follow the IEEE +//// 754 standard for floating point arithmetic and does not have an `Infinity` +//// value. In Erlang division by zero results in a crash, however Gleam does +//// not have partial functions and operators in core so instead division by zero +//// returns zero, a behaviour taken from Pony, Coq, and Lean. +//// +//// This may seem unexpected at first, but it is no less mathematically valid +//// than crashing or returning a special value. Division by zero is undefined +//// in mathematics. + +import gleam/order.{type Order} + +/// Attempts to parse a string as a `Float`, returning `Error(Nil)` if it was +/// not possible. +/// +/// ## Examples +/// +/// ```gleam +/// > parse("2.3") +/// Ok(2.3) +/// ``` +/// +/// ```gleam +/// > parse("ABC") +/// Error(Nil) +/// ``` +/// +pub fn parse(string: String) -> Result(Float, Nil) { + do_parse(string) +} + +@external(erlang, "gleam_stdlib", "parse_float") +@external(javascript, "../gleam_stdlib.mjs", "parse_float") +fn do_parse(a: String) -> Result(Float, Nil) + +/// Returns the string representation of the provided `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > to_string(2.3) +/// "2.3" +/// ``` +/// +pub fn to_string(x: Float) -> String { + do_to_string(x) +} + +@external(erlang, "gleam_stdlib", "float_to_string") +@external(javascript, "../gleam_stdlib.mjs", "float_to_string") +fn do_to_string(a: Float) -> String + +/// Restricts a `Float` between a lower and upper bound. +/// +/// ## Examples +/// +/// ```gleam +/// > clamp(1.2, min: 1.4, max: 1.6) +/// 1.4 +/// ``` +/// +pub fn clamp(x: Float, min min_bound: Float, max max_bound: Float) -> Float { + x + |> min(max_bound) + |> max(min_bound) +} + +/// Compares two `Float`s, returning an `Order`: +/// `Lt` for lower than, `Eq` for equals, or `Gt` for greater than. +/// +/// ## Examples +/// +/// ```gleam +/// > compare(2.0, 2.3) +/// Lt +/// ``` +/// +/// To handle +/// [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems) +/// you may use [`loosely_compare`](#loosely_compare) instead. +/// +pub fn compare(a: Float, with b: Float) -> Order { + case a == b { + True -> order.Eq + False -> + case a <. b { + True -> order.Lt + False -> order.Gt + } + } +} + +/// Compares two `Float`s within a tolerance, returning an `Order`: +/// `Lt` for lower than, `Eq` for equals, or `Gt` for greater than. +/// +/// This function allows Float comparison while handling +/// [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems). +/// +/// Notice: For `Float`s the tolerance won't be exact: +/// `5.3 - 5.0` is not exactly `0.3`. +/// +/// ## Examples +/// +/// ```gleam +/// > loosely_compare(5.0, with: 5.3, tolerating: 0.5) +/// Eq +/// ``` +/// +/// If you want to check only for equality you may use +/// [`loosely_equals`](#loosely_equals) instead. +/// +pub fn loosely_compare( + a: Float, + with b: Float, + tolerating tolerance: Float, +) -> Order { + let difference = absolute_value(a -. b) + case difference <=. tolerance { + True -> order.Eq + False -> compare(a, b) + } +} + +/// Checks for equality of two `Float`s within a tolerance, +/// returning an `Bool`. +/// +/// This function allows Float comparison while handling +/// [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems). +/// +/// Notice: For `Float`s the tolerance won't be exact: +/// `5.3 - 5.0` is not exactly `0.3`. +/// +/// ## Examples +/// +/// ```gleam +/// > loosely_equals(5.0, with: 5.3, tolerating: 0.5) +/// True +/// ``` +/// +/// ```gleam +/// > loosely_equals(5.0, with: 5.1, tolerating: 0.1) +/// False +/// ``` +/// +pub fn loosely_equals( + a: Float, + with b: Float, + tolerating tolerance: Float, +) -> Bool { + let difference = absolute_value(a -. b) + difference <=. tolerance +} + +/// Compares two `Float`s, returning the smaller of the two. +/// +/// ## Examples +/// +/// ```gleam +/// > min(2.0, 2.3) +/// 2.0 +/// ``` +/// +pub fn min(a: Float, b: Float) -> Float { + case a <. b { + True -> a + False -> b + } +} + +/// Compares two `Float`s, returning the larger of the two. +/// +/// ## Examples +/// +/// ```gleam +/// > max(2.0, 2.3) +/// 2.3 +/// ``` +/// +pub fn max(a: Float, b: Float) -> Float { + case a >. b { + True -> a + False -> b + } +} + +/// Rounds the value to the next highest whole number as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > ceiling(2.3) +/// 3.0 +/// ``` +/// +pub fn ceiling(x: Float) -> Float { + do_ceiling(x) +} + +@external(erlang, "math", "ceil") +@external(javascript, "../gleam_stdlib.mjs", "ceiling") +fn do_ceiling(a: Float) -> Float + +/// Rounds the value to the next lowest whole number as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > floor(2.3) +/// 2.0 +/// ``` +/// +pub fn floor(x: Float) -> Float { + do_floor(x) +} + +@external(erlang, "math", "floor") +@external(javascript, "../gleam_stdlib.mjs", "floor") +fn do_floor(a: Float) -> Float + +/// Rounds the value to the nearest whole number as an `Int`. +/// +/// ## Examples +/// +/// ```gleam +/// > round(2.3) +/// 2 +/// ``` +/// +/// ```gleam +/// > round(2.5) +/// 3 +/// ``` +/// +pub fn round(x: Float) -> Int { + do_round(x) +} + +@target(erlang) +@external(erlang, "erlang", "round") +fn do_round(a: Float) -> Int + +@target(javascript) +fn do_round(x: Float) -> Int { + case x >=. 0.0 { + True -> js_round(x) + _ -> 0 - js_round(negate(x)) + } +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "round") +fn js_round(a: Float) -> Int + +/// Returns the value as an `Int`, truncating all decimal digits. +/// +/// ## Examples +/// +/// ```gleam +/// > truncate(2.4343434847383438) +/// 2 +/// ``` +/// +pub fn truncate(x: Float) -> Int { + do_truncate(x) +} + +@external(erlang, "erlang", "trunc") +@external(javascript, "../gleam_stdlib.mjs", "truncate") +fn do_truncate(a: Float) -> Int + +/// Returns the absolute value of the input as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > absolute_value(-12.5) +/// 12.5 +/// ``` +/// +/// ```gleam +/// > absolute_value(10.2) +/// 10.2 +/// ``` +/// +pub fn absolute_value(x: Float) -> Float { + case x >=. 0.0 { + True -> x + _ -> 0.0 -. x + } +} + +/// Returns the results of the base being raised to the power of the +/// exponent, as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > power(2.0, -1.0) +/// Ok(0.5) +/// ``` +/// +/// ```gleam +/// > power(2.0, 2.0) +/// Ok(4.0) +/// ``` +/// +/// ```gleam +/// > power(8.0, 1.5) +/// Ok(22.627416997969522) +/// ``` +/// +/// ```gleam +/// > 4.0 |> power(of: 2.0) +/// Ok(16.0) +/// ``` +/// +/// ```gleam +/// > power(-1.0, 0.5) +/// Error(Nil) +/// ``` +/// +pub fn power(base: Float, of exponent: Float) -> Result(Float, Nil) { + let fractional: Bool = ceiling(exponent) -. exponent >. 0.0 + // In the following check: + // 1. If the base is negative and the exponent is fractional then + // return an error as it will otherwise be an imaginary number + // 2. If the base is 0 and the exponent is negative then the expression + // is equivalent to the exponent divided by 0 and an error should be + // returned + case base <. 0.0 && fractional || base == 0.0 && exponent <. 0.0 { + True -> Error(Nil) + False -> Ok(do_power(base, exponent)) + } +} + +@external(erlang, "math", "pow") +@external(javascript, "../gleam_stdlib.mjs", "power") +fn do_power(a: Float, b: Float) -> Float + +/// Returns the square root of the input as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > square_root(4.0) +/// Ok(2.0) +/// ``` +/// +/// ```gleam +/// > square_root(-16.0) +/// Error(Nil) +/// ``` +/// +pub fn square_root(x: Float) -> Result(Float, Nil) { + power(x, 0.5) +} + +/// Returns the negative of the value provided. +/// +/// ## Examples +/// +/// ```gleam +/// > negate(1.0) +/// -1.0 +/// ``` +/// +pub fn negate(x: Float) -> Float { + -1.0 *. x +} + +/// Sums a list of `Float`s. +/// +/// ## Example +/// +/// ```gleam +/// > sum([1.0, 2.2, 3.3]) +/// 6.5 +/// ``` +/// +pub fn sum(numbers: List(Float)) -> Float { + numbers + |> do_sum(0.0) +} + +fn do_sum(numbers: List(Float), initial: Float) -> Float { + case numbers { + [] -> initial + [x, ..rest] -> do_sum(rest, x +. initial) + } +} + +/// Multiplies a list of `Float`s and returns the product. +/// +/// ## Example +/// +/// ```gleam +/// > product([2.5, 3.2, 4.2]) +/// 33.6 +/// ``` +/// +pub fn product(numbers: List(Float)) -> Float { + case numbers { + [] -> 1.0 + _ -> do_product(numbers, 1.0) + } +} + +fn do_product(numbers: List(Float), initial: Float) -> Float { + case numbers { + [] -> initial + [x, ..rest] -> do_product(rest, x *. initial) + } +} + +/// Generates a random float between the given minimum and maximum values. +/// +/// +/// ## Examples +/// +/// ```gleam +/// > random(1.0, 5.0) +/// 2.646355926896028 +/// ``` +/// +pub fn random(min: Float, max: Float) -> Float { + do_random_uniform() *. { max -. min } +. min +} + +/// Returns a random float uniformly distributed in the value range +/// 0.0 =< X < 1.0 and updates the state in the process dictionary. +/// See: <https://www.erlang.org/doc/man/rand.html#uniform-0> +/// +@external(erlang, "rand", "uniform") +@external(javascript, "../gleam_stdlib.mjs", "random_uniform") +fn do_random_uniform() -> Float + +/// Returns division of the inputs as a `Result`. +/// +/// ## Examples +/// +/// ```gleam +/// > divide(0.0, 1.0) +/// Ok(1.0) +/// ``` +/// +/// ```gleam +/// > divide(1.0, 0.0) +/// Error(Nil) +/// ``` +/// +pub fn divide(a: Float, by b: Float) -> Result(Float, Nil) { + case b { + 0.0 -> Error(Nil) + b -> Ok(a /. b) + } +} + +/// Adds two floats together. +/// +/// It's the function equivalent of the `+.` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > add(1.0, 2.0) +/// 3.0 +/// ``` +/// +/// ```gleam +/// > import gleam/list +/// > list.fold([1.0, 2.0, 3.0], 0.0, add) +/// 6.0 +/// ``` +/// +/// ```gleam +/// > 3.0 |> add(2.0) +/// 5.0 +/// ``` +/// +pub fn add(a: Float, b: Float) -> Float { + a +. b +} + +/// Multiplies two floats together. +/// +/// It's the function equivalent of the `*.` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > multiply(2.0, 4.0) +/// 8.0 +/// ``` +/// +/// ```gleam +/// import gleam/list +/// > list.fold([2.0, 3.0, 4.0], 1.0, multiply) +/// 24.0 +/// ``` +/// +/// ```gleam +/// > 3.0 |> multiply(2.0) +/// 6.0 +/// ``` +/// +pub fn multiply(a: Float, b: Float) -> Float { + a *. b +} + +/// Subtracts one float from another. +/// +/// It's the function equivalent of the `-.` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > subtract(3.0, 1.0) +/// 2.0 +/// ``` +/// +/// ```gleam +/// > import gleam/list +/// > list.fold([1.0, 2.0, 3.0], 10.0, subtract) +/// 4.0 +/// ``` +/// +/// ```gleam +/// > 3.0 |> subtract(_, 2.0) +/// 1.0 +/// ``` +/// +/// ```gleam +/// > 3.0 |> subtract(2.0, _) +/// -1.0 +/// ``` +/// +pub fn subtract(a: Float, b: Float) -> Float { + a -. b +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/function.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/function.gleam new file mode 100644 index 0000000..daa997d --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/function.gleam @@ -0,0 +1,162 @@ +/// Takes two functions and chains them together to form one function that +/// takes the input from the first and returns the output of the second. +/// +pub fn compose(fun1: fn(a) -> b, fun2: fn(b) -> c) -> fn(a) -> c { + fn(a) { fun2(fun1(a)) } +} + +/// Takes a function with `2` arguments (an arity of `2`), and returns the +/// curried equivalent. +/// +/// `fn(a, b) -> c` becomes `fn(a) -> fn(b) -> c`. +/// +/// ## Examples +/// +/// *Currying* creates a new function that is identical to the given function +/// except that arguments must now be supplied one by one over several function +/// calls. It thus is the process of taking a function with `n` arguments +/// and producing a sequence of `n` single-argument functions. Given: +/// +/// ```gleam +/// > fn my_fun(i: Int, s: String) -> String { ... } +/// ``` +/// +/// …calling `curry2(my_fun)` would return the curried equivalent, like so: +/// +/// ```gleam +/// > curry2(my_fun) +/// fn(Int) -> fn(String) -> String +/// ``` +/// +/// Currying is useful when you want to partially apply a function with +/// some arguments and then pass it somewhere else, for example: +/// +/// ```gleam +/// > import gleam/list +/// > let multiply = curry2(fn(x, y) { x * y }) +/// > let doubles = list.map([1, 2, 3], multiply(2)) +/// [2, 4, 6] +/// ``` +/// +pub fn curry2(fun: fn(a, b) -> value) { + fn(a) { fn(b) { fun(a, b) } } +} + +/// Takes a function with `3` arguments (an arity of `3`), and returns the +/// curried equivalent. +/// +/// `fn(a, b, c) -> d` becomes `fn(a) -> fn(b) -> fn(c) -> d`. +/// +/// See [`curry2`](#curry2) for a detailed explanation. +/// +pub fn curry3(fun: fn(a, b, c) -> value) { + fn(a) { fn(b) { fn(c) { fun(a, b, c) } } } +} + +/// Takes a function with `4` arguments (an arity of `4`), and returns the +/// curried equivalent. +/// +/// `fn(a, b, c, d) -> e` becomes `fn(a) -> fn(b) -> fn(c) -> fn(d) -> e`. +/// +/// See [`curry2`](#curry2) for a detailed explanation. +/// +pub fn curry4(fun: fn(a, b, c, d) -> value) { + fn(a) { fn(b) { fn(c) { fn(d) { fun(a, b, c, d) } } } } +} + +/// Takes a function with `5` arguments (an arity of `5`), and returns the +/// curried equivalent. +/// +/// `fn(a, b, c, d, e) -> f` becomes +/// `fn(a) -> fn(b) -> fn(c) -> fn(d) -> fn(e) -> f`. +/// +/// See [`curry2`](#curry2) for a detailed explanation. +/// +pub fn curry5(fun: fn(a, b, c, d, e) -> value) { + fn(a) { fn(b) { fn(c) { fn(d) { fn(e) { fun(a, b, c, d, e) } } } } } +} + +/// Takes a function with `6` arguments (an arity of `6`), and returns the +/// curried equivalent. +/// +/// `fn(a, b, c, d, e, f) -> g` becomes +/// `fn(a) -> fn(b) -> fn(c) -> fn(d) -> fn(e) -> fn(f) -> g`. +/// +/// See [`curry2`](#curry2) for a detailed explanation. +/// +pub fn curry6(fun: fn(a, b, c, d, e, f) -> value) { + fn(a) { + fn(b) { fn(c) { fn(d) { fn(e) { fn(f) { fun(a, b, c, d, e, f) } } } } } + } +} + +/// Takes a function that takes two arguments and returns a new function that +/// takes the same two arguments, but in reverse order. +/// +pub fn flip(fun: fn(a, b) -> c) -> fn(b, a) -> c { + fn(b, a) { fun(a, b) } +} + +/// Takes a single argument and always returns its input value. +/// +pub fn identity(x: a) -> a { + x +} + +/// Takes a single argument and returns a new function that +/// ignores its argument and always returns the input value. +/// +pub fn constant(value: a) -> fn(b) -> a { + fn(_) { value } +} + +/// Takes an argument and a single function, +/// calls that function with that argument +/// and returns that argument instead of the function return value. +/// Useful for running synchronous side effects in a pipeline. +/// +pub fn tap(arg: a, effect: fn(a) -> b) -> a { + effect(arg) + arg +} + +/// Takes a function with arity one and an argument, +/// calls that function with the argument and returns the function return value. +/// +/// Useful for concisely calling functions returned as a part of a pipeline. +/// +/// ## Example +/// +/// ```gleam +/// > let doubler = fn() { +/// > fn(x: Int) { x * 2 } +/// > } +/// > +/// > doubler() +/// > |> apply1(2) +/// 4 +/// ``` +/// +pub fn apply1(fun: fn(a) -> value, arg1: a) -> value { + fun(arg1) +} + +/// Takes a function with arity two and two arguments, +/// calls that function with the arguments +/// and returns the function return value. +/// +/// See [`apply1`](#apply1) for more details. +/// +pub fn apply2(fun: fn(a, b) -> value, arg1: a, arg2: b) -> value { + fun(arg1, arg2) +} + +/// Takes a function with arity three and three arguments, +/// calls that function with the arguments +/// and returns the function return value. +/// +/// See [`apply1`](#apply1) for more details. +/// +pub fn apply3(fun: fn(a, b, c) -> value, arg1: a, arg2: b, arg3: c) -> value { + fun(arg1, arg2, arg3) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/int.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/int.gleam new file mode 100644 index 0000000..d93c16a --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/int.gleam @@ -0,0 +1,874 @@ +//// Functions for working with integers. +//// +//// ## Division by zero +//// +//// In Erlang division by zero results in a crash, however Gleam does not have +//// partial functions and operators in core so instead division by zero returns +//// zero, a behaviour taken from Pony, Coq, and Lean. +//// +//// This may seem unexpected at first, but it is no less mathematically valid +//// than crashing or returning a special value. Division by zero is undefined +//// in mathematics. + +import gleam/float +import gleam/order.{type Order} + +/// Returns the absolute value of the input. +/// +/// ## Examples +/// +/// ```gleam +/// > absolute_value(-12) +/// 12 +/// ``` +/// +/// ```gleam +/// > absolute_value(10) +/// 10 +/// ``` +/// +pub fn absolute_value(x: Int) -> Int { + case x >= 0 { + True -> x + False -> x * -1 + } +} + +/// Returns the results of the base being raised to the power of the +/// exponent, as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > power(2, -1.0) +/// Ok(0.5) +/// ``` +/// +/// ```gleam +/// > power(2, 2.0) +/// Ok(4.0) +/// ``` +/// +/// ```gleam +/// > power(8, 1.5) +/// Ok(22.627416997969522) +/// ``` +/// +/// ```gleam +/// > 4 |> power(of: 2.0) +/// Ok(16.0) +/// ``` +/// +/// ```gleam +/// > power(-1, 0.5) +/// Error(Nil) +/// ``` +/// +pub fn power(base: Int, of exponent: Float) -> Result(Float, Nil) { + base + |> to_float() + |> float.power(exponent) +} + +/// Returns the square root of the input as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > square_root(4) +/// Ok(2.0) +/// ``` +/// +/// ```gleam +/// > square_root(-16) +/// Error(Nil) +/// ``` +/// +pub fn square_root(x: Int) -> Result(Float, Nil) { + x + |> to_float() + |> float.square_root() +} + +/// Parses a given string as an int if possible. +/// +/// ## Examples +/// +/// ```gleam +/// > parse("2") +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > parse("ABC") +/// Error(Nil) +/// ``` +/// +pub fn parse(string: String) -> Result(Int, Nil) { + do_parse(string) +} + +@external(erlang, "gleam_stdlib", "parse_int") +@external(javascript, "../gleam_stdlib.mjs", "parse_int") +fn do_parse(a: String) -> Result(Int, Nil) + +/// Parses a given string as an int in a given base if possible. +/// Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`. +/// +/// ## Examples +/// +/// ```gleam +/// > base_parse("10", 2) +/// Ok(2) +/// +/// > base_parse("30", 16) +/// Ok(48) +/// +/// > base_parse("1C", 36) +/// Ok(48) +/// +/// > base_parse("48", 1) +/// Error(Nil) +/// +/// > base_parse("48", 37) +/// Error(Nil) +/// ``` +/// +pub fn base_parse(string: String, base: Int) -> Result(Int, Nil) { + case base >= 2 && base <= 36 { + True -> do_base_parse(string, base) + False -> Error(Nil) + } +} + +@external(erlang, "gleam_stdlib", "int_from_base_string") +@external(javascript, "../gleam_stdlib.mjs", "int_from_base_string") +fn do_base_parse(a: String, b: Int) -> Result(Int, Nil) + +/// Prints a given int to a string. +/// +/// ## Examples +/// +/// ```gleam +/// > to_string(2) +/// "2" +/// ``` +/// +pub fn to_string(x: Int) { + do_to_string(x) +} + +@external(erlang, "erlang", "integer_to_binary") +@external(javascript, "../gleam_stdlib.mjs", "to_string") +fn do_to_string(a: Int) -> String + +/// Error value when trying to operate with a base out of the allowed range. +/// +pub type InvalidBase { + InvalidBase +} + +/// Prints a given int to a string using the base number provided. +/// Supports only bases 2 to 36, for values outside of which this function returns an `Error(InvalidBase)`. +/// For common bases (2, 8, 16, 36), use the `to_baseN` functions. +/// +/// ## Examples +/// +/// ```gleam +/// > to_base_string(2, 2) +/// Ok("10") +/// ``` +/// +/// ```gleam +/// > to_base_string(48, 16) +/// Ok("30") +/// ``` +/// +/// ```gleam +/// > to_base_string(48, 36) +/// Ok("1C") +/// ``` +/// +/// ```gleam +/// > to_base_string(48, 1) +/// Error(InvalidBase) +/// ``` +/// +/// ```gleam +/// > to_base_string(48, 37) +/// Error(InvalidBase) +/// ``` +/// +pub fn to_base_string(x: Int, base: Int) -> Result(String, InvalidBase) { + case base >= 2 && base <= 36 { + True -> Ok(do_to_base_string(x, base)) + False -> Error(InvalidBase) + } +} + +@external(erlang, "erlang", "integer_to_binary") +@external(javascript, "../gleam_stdlib.mjs", "int_to_base_string") +fn do_to_base_string(a: Int, b: Int) -> String + +/// Prints a given int to a string using base-2. +/// +/// ## Examples +/// +/// ```gleam +/// > to_base2(2) +/// "10" +/// ``` +/// +pub fn to_base2(x: Int) -> String { + do_to_base_string(x, 2) +} + +/// Prints a given int to a string using base-8. +/// +/// ## Examples +/// +/// ```gleam +/// > to_base8(15) +/// "17" +/// ``` +/// +pub fn to_base8(x: Int) -> String { + do_to_base_string(x, 8) +} + +/// Prints a given int to a string using base-16. +/// +/// ## Examples +/// +/// ```gleam +/// > to_base16(48) +/// "30" +/// ``` +/// +pub fn to_base16(x: Int) -> String { + do_to_base_string(x, 16) +} + +/// Prints a given int to a string using base-36. +/// +/// ## Examples +/// +/// ```gleam +/// > to_base36(48) +/// "1C" +/// ``` +/// +pub fn to_base36(x: Int) -> String { + do_to_base_string(x, 36) +} + +/// Takes an int and returns its value as a float. +/// +/// ## Examples +/// +/// ```gleam +/// > to_float(5) +/// 5.0 +/// ``` +/// +/// ```gleam +/// > to_float(0) +/// 0.0 +/// ``` +/// +/// ```gleam +/// > to_float(-3) +/// -3.0 +/// ``` +/// +pub fn to_float(x: Int) -> Float { + do_to_float(x) +} + +@external(erlang, "erlang", "float") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_to_float(a: Int) -> Float + +/// Restricts an int between a lower and upper bound. +/// +/// ## Examples +/// +/// ```gleam +/// > clamp(40, min: 50, max: 60) +/// 50 +/// ``` +/// +pub fn clamp(x: Int, min min_bound: Int, max max_bound: Int) -> Int { + x + |> min(max_bound) + |> max(min_bound) +} + +/// Compares two ints, returning an order. +/// +/// ## Examples +/// +/// ```gleam +/// > compare(2, 3) +/// Lt +/// ``` +/// +/// ```gleam +/// > compare(4, 3) +/// Gt +/// ``` +/// +/// ```gleam +/// > compare(3, 3) +/// Eq +/// ``` +/// +pub fn compare(a: Int, with b: Int) -> Order { + case a == b { + True -> order.Eq + False -> + case a < b { + True -> order.Lt + False -> order.Gt + } + } +} + +/// Compares two ints, returning the smaller of the two. +/// +/// ## Examples +/// +/// ```gleam +/// > min(2, 3) +/// 2 +/// ``` +/// +pub fn min(a: Int, b: Int) -> Int { + case a < b { + True -> a + False -> b + } +} + +/// Compares two ints, returning the larger of the two. +/// +/// ## Examples +/// +/// ```gleam +/// > max(2, 3) +/// 3 +/// ``` +/// +pub fn max(a: Int, b: Int) -> Int { + case a > b { + True -> a + False -> b + } +} + +/// Returns whether the value provided is even. +/// +/// ## Examples +/// +/// ```gleam +/// > is_even(2) +/// True +/// ``` +/// +/// ```gleam +/// > is_even(3) +/// False +/// ``` +/// +pub fn is_even(x: Int) -> Bool { + x % 2 == 0 +} + +/// Returns whether the value provided is odd. +/// +/// ## Examples +/// +/// ```gleam +/// > is_odd(3) +/// True +/// ``` +/// +/// ```gleam +/// > is_odd(2) +/// False +/// ``` +/// +pub fn is_odd(x: Int) -> Bool { + x % 2 != 0 +} + +/// Returns the negative of the value provided. +/// +/// ## Examples +/// +/// ```gleam +/// > negate(1) +/// -1 +/// ``` +/// +pub fn negate(x: Int) -> Int { + -1 * x +} + +/// Sums a list of ints. +/// +/// ## Example +/// +/// ```gleam +/// > sum([1, 2, 3]) +/// 6 +/// ``` +/// +pub fn sum(numbers: List(Int)) -> Int { + numbers + |> do_sum(0) +} + +fn do_sum(numbers: List(Int), initial: Int) -> Int { + case numbers { + [] -> initial + [x, ..rest] -> do_sum(rest, x + initial) + } +} + +/// Multiplies a list of ints and returns the product. +/// +/// ## Example +/// +/// ```gleam +/// > product([2, 3, 4]) +/// 24 +/// ``` +/// +pub fn product(numbers: List(Int)) -> Int { + case numbers { + [] -> 1 + _ -> do_product(numbers, 1) + } +} + +fn do_product(numbers: List(Int), initial: Int) -> Int { + case numbers { + [] -> initial + [x, ..rest] -> do_product(rest, x * initial) + } +} + +/// Splits an integer into its digit representation in the specified base +/// +/// ## Examples +/// +/// ```gleam +/// > digits(234, 10) +/// Ok([2,3,4]) +/// ``` +/// +/// ```gleam +/// > digits(234, 1) +/// Error(InvalidBase) +/// ``` +/// +pub fn digits(x: Int, base: Int) -> Result(List(Int), InvalidBase) { + case base < 2 { + True -> Error(InvalidBase) + False -> Ok(do_digits(x, base, [])) + } +} + +fn do_digits(x: Int, base: Int, acc: List(Int)) -> List(Int) { + case absolute_value(x) < base { + True -> [x, ..acc] + False -> do_digits(x / base, base, [x % base, ..acc]) + } +} + +/// Joins a list of digits into a single value. +/// Returns an error if the base is less than 2 or if the list contains a digit greater than or equal to the specified base. +/// +/// ## Examples +/// +/// ```gleam +/// > undigits([2,3,4], 10) +/// Ok(234) +/// ``` +/// +/// ```gleam +/// > undigits([2,3,4], 1) +/// Error(InvalidBase) +/// ``` +/// +/// ```gleam +/// > undigits([2,3,4], 2) +/// Error(InvalidBase) +/// ``` +/// +pub fn undigits(numbers: List(Int), base: Int) -> Result(Int, InvalidBase) { + case base < 2 { + True -> Error(InvalidBase) + False -> do_undigits(numbers, base, 0) + } +} + +fn do_undigits( + numbers: List(Int), + base: Int, + acc: Int, +) -> Result(Int, InvalidBase) { + case numbers { + [] -> Ok(acc) + [digit, ..] if digit >= base -> Error(InvalidBase) + [digit, ..rest] -> do_undigits(rest, base, acc * base + digit) + } +} + +/// Generates a random int between the given minimum and maximum values. +/// +/// ## Examples +/// +/// ```gleam +/// > random(1, 5) +/// 2 +/// ``` +/// +pub fn random(min: Int, max: Int) -> Int { + float.random(to_float(min), to_float(max)) + |> float.floor() + |> float.round() +} + +/// Performs a truncated integer division. +/// +/// Returns division of the inputs as a `Result`: If the given divisor equals +/// `0`, this function returns an `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > divide(0, 1) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > divide(1, 0) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > divide(5, 2) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > divide(-99, 2) +/// Ok(-49) +/// ``` +/// +pub fn divide(dividend: Int, by divisor: Int) -> Result(Int, Nil) { + case divisor { + 0 -> Error(Nil) + divisor -> Ok(dividend / divisor) + } +} + +/// Computes the remainder of an integer division of inputs as a `Result`. +/// +/// Returns division of the inputs as a `Result`: If the given divisor equals +/// `0`, this function returns an `Error`. +/// +/// Most the time you will want to use the `%` operator instead of this +/// function. +/// +/// ## Examples +/// +/// ```gleam +/// > remainder(3, 2) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > remainder(1, 0) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > remainder(10, -1) +/// Ok(0) +/// ``` +/// +/// ```gleam +/// > remainder(13, by: 3) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > remainder(-13, by: 3) +/// Ok(-1) +/// ``` +/// +/// ```gleam +/// > remainder(13, by: -3) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > remainder(-13, by: -3) +/// Ok(-1) +/// ``` +/// +pub fn remainder(dividend: Int, by divisor: Int) -> Result(Int, Nil) { + case divisor { + 0 -> Error(Nil) + divisor -> Ok(dividend % divisor) + } +} + +/// Computes the modulo of an integer division of inputs as a `Result`. +/// +/// Returns division of the inputs as a `Result`: If the given divisor equals +/// `0`, this function returns an `Error`. +/// +/// Most the time you will want to use the `%` operator instead of this +/// function. +/// +/// ## Examples +/// +/// ```gleam +/// > modulo(3, 2) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > modulo(1, 0) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > modulo(10, -1) +/// Ok(0) +/// ``` +/// +/// ```gleam +/// > modulo(13, by: 3) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > modulo(-13, by: 3) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > modulo(13, by: -3) +/// Ok(-2) +/// ``` +/// +/// ```gleam +/// > modulo(-13, by: -3) +/// Ok(-1) +/// ``` +/// +pub fn modulo(dividend: Int, by divisor: Int) -> Result(Int, Nil) { + case divisor { + 0 -> Error(Nil) + _ -> { + let remainder = dividend % divisor + case remainder * divisor < 0 { + True -> Ok(remainder + divisor) + False -> Ok(remainder) + } + } + } +} + +/// Performs a *floored* integer division, which means that the result will +/// always be rounded towards negative infinity. +/// +/// If you want to perform truncated integer division (rounding towards zero), +/// use `int.divide()` or the `/` operator instead. +/// +/// Returns division of the inputs as a `Result`: If the given divisor equals +/// `0`, this function returns an `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > floor_divide(1, 0) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > floor_divide(5, 2) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > floor_divide(6, -4) +/// Ok(-2) +/// ``` +/// +/// ```gleam +/// > floor_divide(-99, 2) +/// Ok(-50) +/// ``` +/// +pub fn floor_divide(dividend: Int, by divisor: Int) -> Result(Int, Nil) { + case divisor { + 0 -> Error(Nil) + divisor -> + case dividend * divisor < 0 && dividend % divisor != 0 { + True -> Ok(dividend / divisor - 1) + False -> Ok(dividend / divisor) + } + } +} + +/// Adds two integers together. +/// +/// It's the function equivalent of the `+` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > add(1, 2) +/// 3 +/// ``` +/// +/// ```gleam +/// import gleam/list +/// > list.fold([1, 2, 3], 0, add) +/// 6 +/// ``` +/// +/// ```gleam +/// > 3 |> add(2) +/// 5 +/// ``` +/// +pub fn add(a: Int, b: Int) -> Int { + a + b +} + +/// Multiplies two integers together. +/// +/// It's the function equivalent of the `*` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > multiply(2, 4) +/// 8 +/// ``` +/// +/// ```gleam +/// import gleam/list +/// > list.fold([2, 3, 4], 1, multiply) +/// 24 +/// ``` +/// +/// ```gleam +/// > 3 |> multiply(2) +/// 6 +/// ``` +/// +pub fn multiply(a: Int, b: Int) -> Int { + a * b +} + +/// Subtracts one int from another. +/// +/// It's the function equivalent of the `-` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > subtract(3, 1) +/// 2.0 +/// ``` +/// +/// ```gleam +/// import gleam/list +/// > list.fold([1, 2, 3], 10, subtract) +/// 4 +/// ``` +/// +/// ```gleam +/// > 3 |> subtract(2) +/// 1 +/// ``` +/// +/// ```gleam +/// > 3 |> subtract(2, _) +/// -1 +/// ``` +/// +pub fn subtract(a: Int, b: Int) -> Int { + a - b +} + +/// Calculates the bitwise AND of its arguments. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "band") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_and") +pub fn bitwise_and(x: Int, y: Int) -> Int + +/// Calculates the bitwise NOT of its argument. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "bnot") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_not") +pub fn bitwise_not(x: Int) -> Int + +/// Calculates the bitwise OR of its arguments. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "bor") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_or") +pub fn bitwise_or(x: Int, y: Int) -> Int + +/// Calculates the bitwise XOR of its arguments. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "bxor") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_exclusive_or") +pub fn bitwise_exclusive_or(x: Int, y: Int) -> Int + +/// Calculates the result of an arithmetic left bitshift. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "bsl") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_shift_left") +pub fn bitwise_shift_left(x: Int, y: Int) -> Int + +/// Calculates the result of an arithmetic right bitshift. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "bsr") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_shift_right") +pub fn bitwise_shift_right(x: Int, y: Int) -> Int diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/io.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/io.gleam new file mode 100644 index 0000000..0c0a3ee --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/io.gleam @@ -0,0 +1,117 @@ +import gleam/string + +/// Writes a string to standard output. +/// +/// If you want your output to be printed on its own line see `println`. +/// +/// ## Example +/// +/// ```gleam +/// > io.print("Hi mum") +/// // -> Hi mum +/// Nil +/// ``` +/// +pub fn print(string: String) -> Nil { + do_print(string) +} + +@external(erlang, "gleam_stdlib", "print") +@external(javascript, "../gleam_stdlib.mjs", "print") +fn do_print(string string: String) -> Nil + +/// Writes a string to standard error. +/// +/// If you want your output to be printed on its own line see `println_error`. +/// +/// ## Example +/// +/// ``` +/// > io.print_error("Hi pop") +/// // -> Hi pop +/// Nil +/// ``` +/// +pub fn print_error(string: String) -> Nil { + do_print_error(string) +} + +@external(erlang, "gleam_stdlib", "print_error") +@external(javascript, "../gleam_stdlib.mjs", "print_error") +fn do_print_error(string string: String) -> Nil + +/// Writes a string to standard output, appending a newline to the end. +/// +/// ## Example +/// +/// ```gleam +/// > io.println("Hi mum") +/// // -> Hi mum +/// Nil +/// ``` +/// +pub fn println(string: String) -> Nil { + do_println(string) +} + +@external(erlang, "gleam_stdlib", "println") +@external(javascript, "../gleam_stdlib.mjs", "console_log") +fn do_println(string string: String) -> Nil + +/// Writes a string to standard error, appending a newline to the end. +/// +/// ## Example +/// +/// ```gleam +/// > io.println_error("Hi pop") +/// // -> Hi mum +/// Nil +/// ``` +/// +pub fn println_error(string: String) -> Nil { + do_println_error(string) +} + +@external(erlang, "gleam_stdlib", "println_error") +@external(javascript, "../gleam_stdlib.mjs", "console_error") +fn do_println_error(string string: String) -> Nil + +/// Prints a value to standard error (stderr) yielding Gleam syntax. +/// +/// The value is returned after being printed so it can be used in pipelines. +/// +/// ## Example +/// +/// ```gleam +/// > debug("Hi mum") +/// // -> <<"Hi mum">> +/// "Hi mum" +/// ``` +/// +/// ```gleam +/// > debug(Ok(1)) +/// // -> {ok, 1} +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > import list +/// > [1, 2] +/// > |> list.map(fn(x) { x + 1 }) +/// > |> debug +/// > |> list.map(fn(x) { x * 2 }) +/// // -> [2, 3] +/// [4, 6] +/// ``` +/// +pub fn debug(term: anything) -> anything { + term + |> string.inspect + |> do_debug_println + + term +} + +@external(erlang, "gleam_stdlib", "println_error") +@external(javascript, "../gleam_stdlib.mjs", "print_debug") +fn do_debug_println(string string: String) -> Nil diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/iterator.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/iterator.gleam new file mode 100644 index 0000000..c57e7fd --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/iterator.gleam @@ -0,0 +1,1530 @@ +import gleam/result +import gleam/int +import gleam/list +import gleam/dict.{type Dict} +import gleam/option.{type Option, None, Some} +import gleam/order + +// Internal private representation of an Iterator +type Action(element) { + // Dedicated to Electric Six + // https://youtu.be/_30t2dzEgiw?t=162 + Stop + Continue(element, fn() -> Action(element)) +} + +/// An iterator is a lazily evaluated sequence of element. +/// +/// Iterators are useful when working with collections that are too large to +/// fit in memory (or those that are infinite in size) as they only require the +/// elements currently being processed to be in memory. +/// +/// As a lazy data structure no work is done when an iterator is filters, +/// mapped, etc, instead a new iterator is returned with these transformations +/// applied to the stream. Once the stream has all the required transformations +/// applied it can be evaluated using functions such as `fold` and `to_list`. +/// +pub opaque type Iterator(element) { + Iterator(continuation: fn() -> Action(element)) +} + +// Public API for iteration +pub type Step(element, accumulator) { + Next(element: element, accumulator: accumulator) + Done +} + +// Shortcut for an empty iterator. +fn stop() -> Action(element) { + Stop +} + +// Creating Iterators +fn do_unfold( + initial: acc, + f: fn(acc) -> Step(element, acc), +) -> fn() -> Action(element) { + fn() { + case f(initial) { + Next(x, acc) -> Continue(x, do_unfold(acc, f)) + Done -> Stop + } + } +} + +/// Creates an iterator from a given function and accumulator. +/// +/// The function is called on the accumulator and returns either `Done`, +/// indicating the iterator has no more elements, or `Next` which contains a +/// new element and accumulator. The element is yielded by the iterator and the +/// new accumulator is used with the function to compute the next element in +/// the sequence. +/// +/// ## Examples +/// +/// ```gleam +/// > unfold(from: 5, with: fn(n) { +/// > case n { +/// > 0 -> Done +/// > n -> Next(element: n, accumulator: n - 1) +/// > } +/// > }) +/// > |> to_list +/// [5, 4, 3, 2, 1] +/// ``` +/// +pub fn unfold( + from initial: acc, + with f: fn(acc) -> Step(element, acc), +) -> Iterator(element) { + initial + |> do_unfold(f) + |> Iterator +} + +// TODO: test +/// Creates an iterator that yields values created by calling a given function +/// repeatedly. +/// +pub fn repeatedly(f: fn() -> element) -> Iterator(element) { + unfold(Nil, fn(_) { Next(f(), Nil) }) +} + +/// Creates an iterator that returns the same value infinitely. +/// +/// ## Examples +/// +/// ```gleam +/// > repeat(10) +/// > |> take(4) +/// > |> to_list +/// [10, 10, 10, 10] +/// ``` +/// +pub fn repeat(x: element) -> Iterator(element) { + repeatedly(fn() { x }) +} + +/// Creates an iterator that yields each element from the given list. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) +/// > |> to_list +/// [1, 2, 3, 4] +/// ``` +/// +pub fn from_list(list: List(element)) -> Iterator(element) { + let yield = fn(acc) { + case acc { + [] -> Done + [head, ..tail] -> Next(head, tail) + } + } + unfold(list, yield) +} + +// Consuming Iterators +fn do_transform( + continuation: fn() -> Action(a), + state: acc, + f: fn(acc, a) -> Step(b, acc), +) -> fn() -> Action(b) { + fn() { + case continuation() { + Stop -> Stop + Continue(el, next) -> + case f(state, el) { + Done -> Stop + Next(yield, next_state) -> + Continue(yield, do_transform(next, next_state, f)) + } + } + } +} + +/// Creates an iterator from an existing iterator +/// and a stateful function that may short-circuit. +/// +/// `f` takes arguments `acc` for current state and `el` for current element from underlying iterator, +/// and returns either `Next` with yielded element and new state value, or `Done` to halt the iterator. +/// +/// ## Examples +/// +/// Approximate implementation of `index` in terms of `transform`: +/// +/// ```gleam +/// > from_list(["a", "b", "c"]) +/// > |> transform(0, fn(i, el) { Next(#(i, el), i + 1) }) +/// > |> to_list +/// [#(0, "a"), #(1, "b"), #(2, "c")] +/// ``` +pub fn transform( + over iterator: Iterator(a), + from initial: acc, + with f: fn(acc, a) -> Step(b, acc), +) -> Iterator(b) { + do_transform(iterator.continuation, initial, f) + |> Iterator +} + +fn do_fold( + continuation: fn() -> Action(e), + f: fn(acc, e) -> acc, + accumulator: acc, +) -> acc { + case continuation() { + Continue(elem, next) -> do_fold(next, f, f(accumulator, elem)) + Stop -> accumulator + } +} + +/// Reduces an iterator of elements into a single value by calling a given +/// function on each element in turn. +/// +/// If called on an iterator of infinite length then this function will never +/// return. +/// +/// If you do not care about the end value and only wish to evaluate the +/// iterator for side effects consider using the `run` function instead. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4] +/// > |> from_list +/// > |> fold(from: 0, with: fn(acc, element) { element + acc }) +/// 10 +/// ``` +/// +pub fn fold( + over iterator: Iterator(e), + from initial: acc, + with f: fn(acc, e) -> acc, +) -> acc { + iterator.continuation + |> do_fold(f, initial) +} + +// TODO: test +/// Evaluates all elements emitted by the given iterator. This function is useful for when +/// you wish to trigger any side effects that would occur when evaluating +/// the iterator. +/// +pub fn run(iterator: Iterator(e)) -> Nil { + fold(iterator, Nil, fn(_, _) { Nil }) +} + +/// Evaluates an iterator and returns all the elements as a list. +/// +/// If called on an iterator of infinite length then this function will never +/// return. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3] +/// > |> from_list +/// > |> map(fn(x) { x * 2 }) +/// > |> to_list +/// [2, 4, 6] +/// ``` +/// +pub fn to_list(iterator: Iterator(element)) -> List(element) { + iterator + |> fold([], fn(acc, e) { [e, ..acc] }) + |> list.reverse +} + +/// Eagerly accesses the first value of an iterator, returning a `Next` +/// that contains the first value and the rest of the iterator. +/// +/// If called on an empty iterator, `Done` is returned. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Next(first, rest) = [1, 2, 3, 4] +/// > |> from_list +/// > |> step +/// > first +/// 1 +/// ``` +/// +/// ```gleam +/// > rest |> to_list +/// [2, 3, 4] +/// ``` +/// +/// ```gleam +/// > empty() |> step +/// Done +/// ``` +/// +pub fn step(iterator: Iterator(e)) -> Step(e, Iterator(e)) { + case iterator.continuation() { + Stop -> Done + Continue(e, a) -> Next(e, Iterator(a)) + } +} + +fn do_take(continuation: fn() -> Action(e), desired: Int) -> fn() -> Action(e) { + fn() { + case desired > 0 { + False -> Stop + True -> + case continuation() { + Stop -> Stop + Continue(e, next) -> Continue(e, do_take(next, desired - 1)) + } + } + } +} + +/// Creates an iterator that only yields the first `desired` elements. +/// +/// If the iterator does not have enough elements all of them are yielded. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4, 5] +/// > |> from_list +/// > |> take(up_to: 3) +/// > |> to_list +/// [1, 2, 3] +/// ``` +/// +/// ```gleam +/// > [1, 2] +/// > |> from_list +/// > |> take(up_to: 3) +/// > |> to_list +/// [1, 2] +/// ``` +/// +pub fn take(from iterator: Iterator(e), up_to desired: Int) -> Iterator(e) { + iterator.continuation + |> do_take(desired) + |> Iterator +} + +fn do_drop(continuation: fn() -> Action(e), desired: Int) -> Action(e) { + case continuation() { + Stop -> Stop + Continue(e, next) -> + case desired > 0 { + True -> do_drop(next, desired - 1) + False -> Continue(e, next) + } + } +} + +/// Evaluates and discards the first N elements in an iterator, returning a new +/// iterator. +/// +/// If the iterator does not have enough elements an empty iterator is +/// returned. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4, 5] +/// > |> from_list +/// > |> drop(up_to: 3) +/// > |> to_list +/// [4, 5] +/// ``` +/// +/// ```gleam +/// > [1, 2] +/// > |> from_list +/// > |> drop(up_to: 3) +/// > |> to_list +/// [] +/// ``` +/// +pub fn drop(from iterator: Iterator(e), up_to desired: Int) -> Iterator(e) { + fn() { do_drop(iterator.continuation, desired) } + |> Iterator +} + +fn do_map(continuation: fn() -> Action(a), f: fn(a) -> b) -> fn() -> Action(b) { + fn() { + case continuation() { + Stop -> Stop + Continue(e, continuation) -> Continue(f(e), do_map(continuation, f)) + } + } +} + +/// Creates an iterator from an existing iterator and a transformation function. +/// +/// Each element in the new iterator will be the result of calling the given +/// function on the elements in the given iterator. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3] +/// > |> from_list +/// > |> map(fn(x) { x * 2 }) +/// > |> to_list +/// [2, 4, 6] +/// ``` +/// +pub fn map(over iterator: Iterator(a), with f: fn(a) -> b) -> Iterator(b) { + iterator.continuation + |> do_map(f) + |> Iterator +} + +fn do_map2( + continuation1: fn() -> Action(a), + continuation2: fn() -> Action(b), + with fun: fn(a, b) -> c, +) -> fn() -> Action(c) { + fn() { + case continuation1() { + Stop -> Stop + Continue(a, next_a) -> + case continuation2() { + Stop -> Stop + Continue(b, next_b) -> + Continue(fun(a, b), do_map2(next_a, next_b, fun)) + } + } + } +} + +/// Combines two interators into a single one using the given function. +/// +/// If an iterator is longer than the other the extra elements are dropped. +/// +/// This function does not evaluate the elements of the two iterators, the +/// computation is performed when the resulting iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// let first = from_list([1, 2, 3]) +/// let second = from_list([4, 5, 6]) +/// map2(first, second, fn(x, y) { x + y }) |> to_list +/// // -> [5, 7, 9] +/// ``` +/// +/// ```gleam +/// let first = from_list([1, 2]) +/// let second = from_list(["a", "b", "c"]) +/// map2(first, second, fn(i, x) { #(i, x) }) |> to_list +/// // -> [#(1, "a"), #(2, "b")] +/// ``` +/// +pub fn map2( + iterator1: Iterator(a), + iterator2: Iterator(b), + with fun: fn(a, b) -> c, +) -> Iterator(c) { + do_map2(iterator1.continuation, iterator2.continuation, fun) + |> Iterator +} + +fn do_append(first: fn() -> Action(a), second: fn() -> Action(a)) -> Action(a) { + case first() { + Continue(e, first) -> Continue(e, fn() { do_append(first, second) }) + Stop -> second() + } +} + +/// Appends two iterators, producing a new iterator. +/// +/// This function does not evaluate the elements of the iterators, the +/// computation is performed when the resulting iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2] +/// > |> from_list +/// > |> append([3, 4] |> from_list) +/// > |> to_list +/// [1, 2, 3, 4] +/// ``` +/// +pub fn append(to first: Iterator(a), suffix second: Iterator(a)) -> Iterator(a) { + fn() { do_append(first.continuation, second.continuation) } + |> Iterator +} + +fn do_flatten(flattened: fn() -> Action(Iterator(a))) -> Action(a) { + case flattened() { + Stop -> Stop + Continue(it, next_iterator) -> + do_append(it.continuation, fn() { do_flatten(next_iterator) }) + } +} + +/// Flattens an iterator of iterators, creating a new iterator. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([[1, 2], [3, 4]]) +/// > |> map(from_list) +/// > |> flatten +/// > |> to_list +/// [1, 2, 3, 4] +/// ``` +/// +pub fn flatten(iterator: Iterator(Iterator(a))) -> Iterator(a) { + fn() { do_flatten(iterator.continuation) } + |> Iterator +} + +/// Joins a list of iterators into a single iterator. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > [[1, 2], [3, 4]] +/// > |> map(from_list) +/// > |> concat +/// > |> to_list +/// [1, 2, 3, 4] +/// ``` +/// +pub fn concat(iterators: List(Iterator(a))) -> Iterator(a) { + flatten(from_list(iterators)) +} + +/// Creates an iterator from an existing iterator and a transformation function. +/// +/// Each element in the new iterator will be the result of calling the given +/// function on the elements in the given iterator and then flattening the +/// results. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2] +/// > |> from_list +/// > |> flat_map(fn(x) { from_list([x, x + 1]) }) +/// > |> to_list +/// [1, 2, 2, 3] +/// ``` +/// +pub fn flat_map( + over iterator: Iterator(a), + with f: fn(a) -> Iterator(b), +) -> Iterator(b) { + iterator + |> map(f) + |> flatten +} + +fn do_filter( + continuation: fn() -> Action(e), + predicate: fn(e) -> Bool, +) -> Action(e) { + case continuation() { + Stop -> Stop + Continue(e, iterator) -> + case predicate(e) { + True -> Continue(e, fn() { do_filter(iterator, predicate) }) + False -> do_filter(iterator, predicate) + } + } +} + +/// Creates an iterator from an existing iterator and a predicate function. +/// +/// The new iterator will contain elements from the first iterator for which +/// the given function returns `True`. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/int +/// > [1, 2, 3, 4] +/// > |> from_list +/// > |> filter(int.is_even) +/// > |> to_list +/// [2, 4] +/// ``` +/// +pub fn filter( + iterator: Iterator(a), + keeping predicate: fn(a) -> Bool, +) -> Iterator(a) { + fn() { do_filter(iterator.continuation, predicate) } + |> Iterator +} + +/// Creates an iterator that repeats a given iterator infinitely. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2] +/// > |> from_list +/// > |> cycle +/// > |> take(6) +/// > |> to_list +/// [1, 2, 1, 2, 1, 2] +/// ``` +/// +pub fn cycle(iterator: Iterator(a)) -> Iterator(a) { + repeat(iterator) + |> flatten +} + +/// Creates an iterator of ints, starting at a given start int and stepping by +/// one to a given end int. +/// +/// ## Examples +/// +/// ```gleam +/// > range(from: 1, to: 5) |> to_list +/// [1, 2, 3, 4, 5] +/// ``` +/// +/// ```gleam +/// > range(from: 1, to: -2) |> to_list +/// [1, 0, -1, -2] +/// ``` +/// +/// ```gleam +/// > range(from: 0, to: 0) |> to_list +/// [0] +/// ``` +/// +pub fn range(from start: Int, to stop: Int) -> Iterator(Int) { + case int.compare(start, stop) { + order.Eq -> once(fn() { start }) + order.Gt -> + unfold( + from: start, + with: fn(current) { + case current < stop { + False -> Next(current, current - 1) + True -> Done + } + }, + ) + + order.Lt -> + unfold( + from: start, + with: fn(current) { + case current > stop { + False -> Next(current, current + 1) + True -> Done + } + }, + ) + } +} + +fn do_find(continuation: fn() -> Action(a), f: fn(a) -> Bool) -> Result(a, Nil) { + case continuation() { + Stop -> Error(Nil) + Continue(e, next) -> + case f(e) { + True -> Ok(e) + False -> do_find(next, f) + } + } +} + +/// Finds the first element in a given iterator for which the given function returns +/// `True`. +/// +/// Returns `Error(Nil)` if the function does not return `True` for any of the +/// elements. +/// +/// ## Examples +/// +/// ```gleam +/// > find(from_list([1, 2, 3]), fn(x) { x > 2 }) +/// Ok(3) +/// ``` +/// +/// ```gleam +/// > find(from_list([1, 2, 3]), fn(x) { x > 4 }) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > find(empty(), fn(_) { True }) +/// Error(Nil) +/// ``` +/// +pub fn find( + in haystack: Iterator(a), + one_that is_desired: fn(a) -> Bool, +) -> Result(a, Nil) { + haystack.continuation + |> do_find(is_desired) +} + +fn do_index( + continuation: fn() -> Action(element), + next: Int, +) -> fn() -> Action(#(Int, element)) { + fn() { + case continuation() { + Stop -> Stop + Continue(e, continuation) -> + Continue(#(next, e), do_index(continuation, next + 1)) + } + } +} + +/// Wraps values yielded from an iterator with indices, starting from 0. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list(["a", "b", "c"]) |> index |> to_list +/// [#(0, "a"), #(1, "b"), #(2, "c")] +/// ``` +/// +pub fn index(over iterator: Iterator(element)) -> Iterator(#(Int, element)) { + iterator.continuation + |> do_index(0) + |> Iterator +} + +/// Creates an iterator that inifinitely applies a function to a value. +/// +/// ## Examples +/// +/// ```gleam +/// > iterate(1, fn(n) { n * 3 }) |> take(5) |> to_list +/// [1, 3, 9, 27, 81] +/// ``` +/// +pub fn iterate( + from initial: element, + with f: fn(element) -> element, +) -> Iterator(element) { + unfold(initial, fn(element) { Next(element, f(element)) }) +} + +fn do_take_while( + continuation: fn() -> Action(element), + predicate: fn(element) -> Bool, +) -> fn() -> Action(element) { + fn() { + case continuation() { + Stop -> Stop + Continue(e, next) -> + case predicate(e) { + False -> Stop + True -> Continue(e, do_take_while(next, predicate)) + } + } + } +} + +/// Creates an iterator that yields elements while the predicate returns `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 2, 4]) +/// > |> take_while(satisfying: fn(x) { x < 3 }) +/// > |> to_list +/// [1, 2] +/// ``` +/// +pub fn take_while( + in iterator: Iterator(element), + satisfying predicate: fn(element) -> Bool, +) -> Iterator(element) { + iterator.continuation + |> do_take_while(predicate) + |> Iterator +} + +fn do_drop_while( + continuation: fn() -> Action(element), + predicate: fn(element) -> Bool, +) -> Action(element) { + case continuation() { + Stop -> Stop + Continue(e, next) -> + case predicate(e) { + False -> Continue(e, next) + True -> do_drop_while(next, predicate) + } + } +} + +/// Creates an iterator that drops elements while the predicate returns `True`, +/// and then yields the remaining elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4, 2, 5]) +/// > |> drop_while(satisfying: fn(x) { x < 4 }) +/// > |> to_list +/// [4, 2, 5] +/// ``` +/// +pub fn drop_while( + in iterator: Iterator(element), + satisfying predicate: fn(element) -> Bool, +) -> Iterator(element) { + fn() { do_drop_while(iterator.continuation, predicate) } + |> Iterator +} + +fn do_scan( + continuation: fn() -> Action(element), + f: fn(acc, element) -> acc, + accumulator: acc, +) -> fn() -> Action(acc) { + fn() { + case continuation() { + Stop -> Stop + Continue(el, next) -> { + let accumulated = f(accumulator, el) + Continue(accumulated, do_scan(next, f, accumulated)) + } + } + } +} + +/// Creates an iterator from an existing iterator and a stateful function. +/// +/// Specifically, this behaves like `fold`, but yields intermediate results. +/// +/// ## Examples +/// +/// ```gleam +/// // Generate a sequence of partial sums +/// > from_list([1, 2, 3, 4, 5]) +/// > |> scan(from: 0, with: fn(acc, el) { acc + el }) +/// > |> to_list +/// [1, 3, 6, 10, 15] +/// ``` +/// +pub fn scan( + over iterator: Iterator(element), + from initial: acc, + with f: fn(acc, element) -> acc, +) -> Iterator(acc) { + iterator.continuation + |> do_scan(f, initial) + |> Iterator +} + +fn do_zip( + left: fn() -> Action(a), + right: fn() -> Action(b), +) -> fn() -> Action(#(a, b)) { + fn() { + case left() { + Stop -> Stop + Continue(el_left, next_left) -> + case right() { + Stop -> Stop + Continue(el_right, next_right) -> + Continue(#(el_left, el_right), do_zip(next_left, next_right)) + } + } + } +} + +/// Zips two iterators together, emitting values from both +/// until the shorter one runs out. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list(["a", "b", "c"]) +/// > |> zip(range(20, 30)) +/// > |> to_list +/// [#("a", 20), #("b", 21), #("c", 22)] +/// ``` +/// +pub fn zip(left: Iterator(a), right: Iterator(b)) -> Iterator(#(a, b)) { + do_zip(left.continuation, right.continuation) + |> Iterator +} + +// Result of collecting a single chunk by key +type Chunk(element, key) { + AnotherBy(List(element), key, element, fn() -> Action(element)) + LastBy(List(element)) +} + +fn next_chunk( + continuation: fn() -> Action(element), + f: fn(element) -> key, + previous_key: key, + current_chunk: List(element), +) -> Chunk(element, key) { + case continuation() { + Stop -> LastBy(list.reverse(current_chunk)) + Continue(e, next) -> { + let key = f(e) + case key == previous_key { + True -> next_chunk(next, f, key, [e, ..current_chunk]) + False -> AnotherBy(list.reverse(current_chunk), key, e, next) + } + } + } +} + +fn do_chunk( + continuation: fn() -> Action(element), + f: fn(element) -> key, + previous_key: key, + previous_element: element, +) -> Action(List(element)) { + case next_chunk(continuation, f, previous_key, [previous_element]) { + LastBy(chunk) -> Continue(chunk, stop) + AnotherBy(chunk, key, el, next) -> + Continue(chunk, fn() { do_chunk(next, f, key, el) }) + } +} + +/// Creates an iterator that emits chunks of elements +/// for which `f` returns the same value. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 2, 3, 4, 4, 6, 7, 7]) +/// > |> chunk(by: fn(n) { n % 2 }) +/// > |> to_list +/// [[1], [2, 2], [3], [4, 4, 6], [7, 7]] +/// ``` +/// +pub fn chunk( + over iterator: Iterator(element), + by f: fn(element) -> key, +) -> Iterator(List(element)) { + fn() { + case iterator.continuation() { + Stop -> Stop + Continue(e, next) -> do_chunk(next, f, f(e), e) + } + } + |> Iterator +} + +// Result of collecting a single sized chunk +type SizedChunk(element) { + Another(List(element), fn() -> Action(element)) + Last(List(element)) + NoMore +} + +fn next_sized_chunk( + continuation: fn() -> Action(element), + left: Int, + current_chunk: List(element), +) -> SizedChunk(element) { + case continuation() { + Stop -> + case current_chunk { + [] -> NoMore + remaining -> Last(list.reverse(remaining)) + } + Continue(e, next) -> { + let chunk = [e, ..current_chunk] + case left > 1 { + False -> Another(list.reverse(chunk), next) + True -> next_sized_chunk(next, left - 1, chunk) + } + } + } +} + +fn do_sized_chunk( + continuation: fn() -> Action(element), + count: Int, +) -> fn() -> Action(List(element)) { + fn() { + case next_sized_chunk(continuation, count, []) { + NoMore -> Stop + Last(chunk) -> Continue(chunk, stop) + Another(chunk, next_element) -> + Continue(chunk, do_sized_chunk(next_element, count)) + } + } +} + +/// Creates an iterator that emits chunks of given size. +/// +/// If the last chunk does not have `count` elements, it is yielded +/// as a partial chunk, with less than `count` elements. +/// +/// For any `count` less than 1 this function behaves as if it was set to 1. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4, 5, 6]) +/// > |> sized_chunk(into: 2) +/// > |> to_list +/// [[1, 2], [3, 4], [5, 6]] +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 3, 4, 5, 6, 7, 8]) +/// > |> sized_chunk(into: 3) +/// > |> to_list +/// [[1, 2, 3], [4, 5, 6], [7, 8]] +/// ``` +/// +pub fn sized_chunk( + over iterator: Iterator(element), + into count: Int, +) -> Iterator(List(element)) { + iterator.continuation + |> do_sized_chunk(count) + |> Iterator +} + +fn do_intersperse( + continuation: fn() -> Action(element), + separator: element, +) -> Action(element) { + case continuation() { + Stop -> Stop + Continue(e, next) -> { + let next_interspersed = fn() { do_intersperse(next, separator) } + Continue(separator, fn() { Continue(e, next_interspersed) }) + } + } +} + +/// Creates an iterator that yields the given `elem` element +/// between elements emitted by the underlying iterator. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() +/// > |> intersperse(with: 0) +/// > |> to_list +/// [] +/// +/// > from_list([1]) +/// > |> intersperse(with: 0) +/// > |> to_list +/// [1] +/// +/// > from_list([1, 2, 3, 4, 5]) +/// > |> intersperse(with: 0) +/// > |> to_list +/// [1, 0, 2, 0, 3, 0, 4, 0, 5] +/// ``` +/// +pub fn intersperse( + over iterator: Iterator(element), + with elem: element, +) -> Iterator(element) { + fn() { + case iterator.continuation() { + Stop -> Stop + Continue(e, next) -> Continue(e, fn() { do_intersperse(next, elem) }) + } + } + |> Iterator +} + +fn do_any( + continuation: fn() -> Action(element), + predicate: fn(element) -> Bool, +) -> Bool { + case continuation() { + Stop -> False + Continue(e, next) -> + case predicate(e) { + True -> True + False -> do_any(next, predicate) + } + } +} + +/// Returns `True` if any element emitted by the iterator satisfies the given predicate, +/// `False` otherwise. +/// +/// This function short-circuits once it finds a satisfying element. +/// +/// An empty iterator results in `False`. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> any(fn(n) { n % 2 == 0 }) +/// False +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 5, 7, 9]) |> any(fn(n) { n % 2 == 0 }) +/// True +/// ``` +/// +/// ```gleam +/// > from_list([1, 3, 5, 7, 9]) |> any(fn(n) { n % 2 == 0 }) +/// False +/// ``` +/// +pub fn any( + in iterator: Iterator(element), + satisfying predicate: fn(element) -> Bool, +) -> Bool { + iterator.continuation + |> do_any(predicate) +} + +fn do_all( + continuation: fn() -> Action(element), + predicate: fn(element) -> Bool, +) -> Bool { + case continuation() { + Stop -> True + Continue(e, next) -> + case predicate(e) { + True -> do_all(next, predicate) + False -> False + } + } +} + +/// Returns `True` if all elements emitted by the iterator satisfy the given predicate, +/// `False` otherwise. +/// +/// This function short-circuits once it finds a non-satisfying element. +/// +/// An empty iterator results in `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> all(fn(n) { n % 2 == 0 }) +/// True +/// ``` +/// +/// ```gleam +/// > from_list([2, 4, 6, 8]) |> all(fn(n) { n % 2 == 0 }) +/// True +/// ``` +/// +/// ```gleam +/// > from_list([2, 4, 5, 8]) |> all(fn(n) { n % 2 == 0 }) +/// False +/// ``` +/// +pub fn all( + in iterator: Iterator(element), + satisfying predicate: fn(element) -> Bool, +) -> Bool { + iterator.continuation + |> do_all(predicate) +} + +fn update_group_with(el: element) -> fn(Option(List(element))) -> List(element) { + fn(maybe_group) { + case maybe_group { + Some(group) -> [el, ..group] + None -> [el] + } + } +} + +fn group_updater( + f: fn(element) -> key, +) -> fn(Dict(key, List(element)), element) -> Dict(key, List(element)) { + fn(groups, elem) { + groups + |> dict.update(f(elem), update_group_with(elem)) + } +} + +/// Returns a `Dict(k, List(element))` of elements from the given iterator +/// grouped with the given key function. +/// +/// The order within each group is preserved from the iterator. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4, 5, 6]) |> group(by: fn(n) { n % 3 }) +/// dict.from_list([#(0, [3, 6]), #(1, [1, 4]), #(2, [2, 5])]) +/// ``` +/// +pub fn group( + in iterator: Iterator(element), + by key: fn(element) -> key, +) -> Dict(key, List(element)) { + iterator + |> fold(dict.new(), group_updater(key)) + |> dict.map_values(fn(_, group) { list.reverse(group) }) +} + +/// This function acts similar to fold, but does not take an initial state. +/// Instead, it starts from the first yielded element +/// and combines it with each subsequent element in turn using the given function. +/// The function is called as `f(accumulator, current_element)`. +/// +/// Returns `Ok` to indicate a successful run, and `Error` if called on an empty iterator. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([]) |> reduce(fn(acc, x) { acc + x }) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 3, 4, 5]) |> reduce(fn(acc, x) { acc + x }) +/// Ok(15) +/// ``` +/// +pub fn reduce( + over iterator: Iterator(e), + with f: fn(e, e) -> e, +) -> Result(e, Nil) { + case iterator.continuation() { + Stop -> Error(Nil) + Continue(e, next) -> + do_fold(next, f, e) + |> Ok + } +} + +/// Returns the last element in the given iterator. +/// +/// Returns `Error(Nil)` if the iterator is empty. +/// +/// This function runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> last +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > range(1, 10) |> last +/// Ok(9) +/// ``` +/// +pub fn last(iterator: Iterator(element)) -> Result(element, Nil) { + iterator + |> reduce(fn(_, elem) { elem }) +} + +/// Creates an iterator that yields no elements. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> to_list +/// [] +/// ``` +/// +pub fn empty() -> Iterator(element) { + Iterator(stop) +} + +/// Creates an iterator that yields exactly one element provided by calling the given function. +/// +/// ## Examples +/// +/// ```gleam +/// > once(fn() { 1 }) |> to_list +/// [1] +/// ``` +/// +pub fn once(f: fn() -> element) -> Iterator(element) { + fn() { Continue(f(), stop) } + |> Iterator +} + +/// Creates an iterator that yields the given element exactly once. +/// +/// ## Examples +/// +/// ```gleam +/// > single(1) |> to_list +/// [1] +/// ``` +/// +pub fn single(elem: element) -> Iterator(element) { + once(fn() { elem }) +} + +fn do_interleave( + current: fn() -> Action(element), + next: fn() -> Action(element), +) -> Action(element) { + case current() { + Stop -> next() + Continue(e, next_other) -> + Continue(e, fn() { do_interleave(next, next_other) }) + } +} + +/// Creates an iterator that alternates between the two given iterators +/// until both have run out. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) |> interleave(from_list([11, 12, 13, 14])) |> to_list +/// [1, 11, 2, 12, 3, 13, 4, 14] +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) |> interleave(from_list([100])) |> to_list +/// [1, 100, 2, 3, 4] +/// ``` +/// +pub fn interleave( + left: Iterator(element), + with right: Iterator(element), +) -> Iterator(element) { + fn() { do_interleave(left.continuation, right.continuation) } + |> Iterator +} + +fn do_fold_until( + continuation: fn() -> Action(e), + f: fn(acc, e) -> list.ContinueOrStop(acc), + accumulator: acc, +) -> acc { + case continuation() { + Stop -> accumulator + Continue(elem, next) -> + case f(accumulator, elem) { + list.Continue(accumulator) -> do_fold_until(next, f, accumulator) + list.Stop(accumulator) -> accumulator + } + } +} + +/// Like `fold`, `fold_until` reduces an iterator of elements into a single value by calling a given +/// function on each element in turn, but uses `list.ContinueOrStop` to determine +/// whether or not to keep iterating. +/// +/// If called on an iterator of infinite length then this function will only ever +/// return if the function returns `list.Stop`. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/list +/// > let f = fn(acc, e) { +/// > case e { +/// > _ if e < 4 -> list.Continue(e + acc) +/// > _ -> list.Stop(acc) +/// > } +/// > } +/// > +/// > [1, 2, 3, 4] +/// > |> from_list +/// > |> fold_until(from: acc, with: f) +/// 6 +/// ``` +/// +pub fn fold_until( + over iterator: Iterator(e), + from initial: acc, + with f: fn(acc, e) -> list.ContinueOrStop(acc), +) -> acc { + iterator.continuation + |> do_fold_until(f, initial) +} + +fn do_try_fold( + over continuation: fn() -> Action(a), + with f: fn(acc, a) -> Result(acc, err), + from accumulator: acc, +) -> Result(acc, err) { + case continuation() { + Stop -> Ok(accumulator) + Continue(elem, next) -> { + use accumulator <- result.try(f(accumulator, elem)) + do_try_fold(next, f, accumulator) + } + } +} + +/// A variant of fold that might fail. +/// +/// The folding function should return `Result(accumulator, error)`. +/// If the returned value is `Ok(accumulator)` try_fold will try the next value in the iterator. +/// If the returned value is `Error(error)` try_fold will stop and return that error. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4] +/// > |> iterator.from_list() +/// > |> try_fold(0, fn(acc, i) { +/// > case i < 3 { +/// > True -> Ok(acc + i) +/// > False -> Error(Nil) +/// > } +/// > }) +/// Error(Nil) +/// ``` +/// +pub fn try_fold( + over iterator: Iterator(e), + from initial: acc, + with f: fn(acc, e) -> Result(acc, err), +) -> Result(acc, err) { + iterator.continuation + |> do_try_fold(f, initial) +} + +/// Returns the first element yielded by the given iterator, if it exists, +/// or `Error(Nil)` otherwise. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3]) |> first +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > empty() |> first +/// Error(Nil) +/// ``` +pub fn first(from iterator: Iterator(e)) -> Result(e, Nil) { + case iterator.continuation() { + Stop -> Error(Nil) + Continue(e, _) -> Ok(e) + } +} + +/// Returns nth element yielded by the given iterator, where `0` means the first element. +/// +/// If there are not enough elements in the iterator, `Error(Nil)` is returned. +/// +/// For any `index` less than `0` this function behaves as if it was set to `0`. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) |> at(2) +/// Ok(3) +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) |> at(4) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > empty() |> at(0) +/// Error(Nil) +/// ``` +/// +pub fn at(in iterator: Iterator(e), get index: Int) -> Result(e, Nil) { + iterator + |> drop(index) + |> first +} + +fn do_length(over continuation: fn() -> Action(e), with length: Int) -> Int { + case continuation() { + Stop -> length + Continue(_, next) -> do_length(next, length + 1) + } +} + +/// Counts the number of elements in the given iterator. +/// +/// This function has to traverse the entire iterator to count its elements, +/// so it runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> length +/// 0 +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) |> length +/// 4 +/// ``` +/// +pub fn length(over iterator: Iterator(e)) -> Int { + iterator.continuation + |> do_length(0) +} + +/// Traverse an iterator, calling a function on each element. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> each(io.println) +/// Nil +/// ``` +/// +/// ```gleam +/// > from_list(["Tom", "Malory", "Louis"]) |> each(io.println) +/// // -> Tom +/// // -> Malory +/// // -> Louis +/// Nil +/// ``` +/// +pub fn each(over iterator: Iterator(a), with f: fn(a) -> b) -> Nil { + iterator + |> map(f) + |> run +} + +/// Add a new element to the start of an iterator. +/// +/// This function is for use with `use` expressions, to replicate the behaviour +/// of the `yield` keyword found in other languages. +/// +/// ## Examples +/// +/// ```gleam +/// > use <- iterator.yield(1) +/// > use <- iterator.yield(2) +/// > use <- iterator.yield(3) +/// > iterator.empty() +/// iterator.from_list([1, 2, 3]) +/// ``` +/// +pub fn yield(element: a, next: fn() -> Iterator(a)) -> Iterator(a) { + Iterator(fn() { Continue(element, next().continuation) }) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/list.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/list.gleam new file mode 100644 index 0000000..a5cffa9 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/list.gleam @@ -0,0 +1,2154 @@ +//// Lists are an ordered sequence of elements and are one of the most common +//// data types in Gleam. +//// +//// New elements can be added and removed from the front of a list in +//// constant time, while adding and removing from the end requires traversing +//// the copying the whole list, so keep this in mind when designing your +//// programs. +//// +//// There is a dedicated syntax for prefixing to a list: +//// +//// ```gleam +//// let new_list = [1, 2, ..existing_list] +//// ``` +//// +//// And a matching syntax for getting the first elements of a list: +//// +//// ```gleam +//// case list { +//// [first_element, ..rest] -> first_element +//// _ -> "this pattern matches when the list is empty" +//// } +//// ``` +//// + +import gleam/int +import gleam/float +import gleam/order.{type Order} +import gleam/pair +import gleam/dict.{type Dict} + +/// An error value returned by the `strict_zip` function. +/// +pub type LengthMismatch { + LengthMismatch +} + +/// Counts the number of elements in a given list. +/// +/// This function has to traverse the list to determine the number of elements, +/// so it runs in linear time. +/// +/// This function is natively implemented by the virtual machine and is highly +/// optimised. +/// +/// ## Examples +/// +/// ```gleam +/// > length([]) +/// 0 +/// ``` +/// +/// ```gleam +/// > length([1]) +/// 1 +/// ``` +/// +/// ```gleam +/// > length([1, 2]) +/// 2 +/// ``` +/// +pub fn length(of list: List(a)) -> Int { + do_length(list) +} + +@target(erlang) +@external(erlang, "erlang", "length") +fn do_length(a: List(a)) -> Int + +@target(javascript) +fn do_length(list: List(a)) -> Int { + do_length_acc(list, 0) +} + +@target(javascript) +fn do_length_acc(list: List(a), count: Int) -> Int { + case list { + [_, ..list] -> do_length_acc(list, count + 1) + _ -> count + } +} + +/// Creates a new list from a given list containing the same elements but in the +/// opposite order. +/// +/// This function has to traverse the list to create the new reversed list, so +/// it runs in linear time. +/// +/// This function is natively implemented by the virtual machine and is highly +/// optimised. +/// +/// ## Examples +/// +/// ```gleam +/// > reverse([]) +/// [] +/// ``` +/// +/// ```gleam +/// > reverse([1]) +/// [1] +/// ``` +/// +/// ```gleam +/// > reverse([1, 2]) +/// [2, 1] +/// ``` +/// +pub fn reverse(xs: List(a)) -> List(a) { + do_reverse(xs) +} + +@target(erlang) +@external(erlang, "lists", "reverse") +fn do_reverse(a: List(a)) -> List(a) + +@target(javascript) +fn do_reverse(list) { + do_reverse_acc(list, []) +} + +@target(javascript) +fn do_reverse_acc(remaining, accumulator) { + case remaining { + [] -> accumulator + [item, ..rest] -> do_reverse_acc(rest, [item, ..accumulator]) + } +} + +/// Determines whether or not the list is empty. +/// +/// This function runs in constant time. +/// +/// ## Examples +/// +/// ```gleam +/// > is_empty([]) +/// True +/// ``` +/// +/// ```gleam +/// > is_empty([1]) +/// False +/// ``` +/// +/// ```gleam +/// > is_empty([1, 1]) +/// False +/// ``` +/// +pub fn is_empty(list: List(a)) -> Bool { + list == [] +} + +/// Determines whether or not a given element exists within a given list. +/// +/// This function traverses the list to find the element, so it runs in linear +/// time. +/// +/// ## Examples +/// +/// ```gleam +/// > [] |> contains(any: 0) +/// False +/// ``` +/// +/// ```gleam +/// > [0] |> contains(any: 0) +/// True +/// ``` +/// +/// ```gleam +/// > [1] |> contains(any: 0) +/// False +/// ``` +/// +/// ```gleam +/// > [1, 1] |> contains(any: 0) +/// False +/// ``` +/// +/// ```gleam +/// > [1, 0] |> contains(any: 0) +/// True +/// ``` +/// +pub fn contains(list: List(a), any elem: a) -> Bool { + case list { + [] -> False + [first, ..] if first == elem -> True + [_, ..rest] -> contains(rest, elem) + } +} + +/// Gets the first element from the start of the list, if there is one. +/// +/// ## Examples +/// +/// ```gleam +/// > first([]) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > first([0]) +/// Ok(0) +/// ``` +/// +/// ```gleam +/// > first([1, 2]) +/// Ok(1) +/// ``` +/// +pub fn first(list: List(a)) -> Result(a, Nil) { + case list { + [] -> Error(Nil) + [x, ..] -> Ok(x) + } +} + +/// Returns the list minus the first element. If the list is empty, `Error(Nil)` is +/// returned. +/// +/// This function runs in constant time and does not make a copy of the list. +/// +/// ## Examples +/// +/// ```gleam +/// > rest([]) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > rest([0]) +/// Ok([]) +/// ``` +/// +/// ```gleam +/// > rest([1, 2]) +/// Ok([2]) +/// ``` +/// +pub fn rest(list: List(a)) -> Result(List(a), Nil) { + case list { + [] -> Error(Nil) + [_, ..xs] -> Ok(xs) + } +} + +fn update_group( + f: fn(element) -> key, +) -> fn(Dict(key, List(element)), element) -> Dict(key, List(element)) { + fn(groups, elem) { + case dict.get(groups, f(elem)) { + Ok(existing) -> dict.insert(groups, f(elem), [elem, ..existing]) + Error(_) -> dict.insert(groups, f(elem), [elem]) + } + } +} + +/// Takes a list and groups the values by a key +/// which is built from a key function. +/// +/// Does not preserve the initial value order. +/// +/// ## Examples +/// +/// ```gleam +/// > [Ok(3), Error("Wrong"), Ok(200), Ok(73)] +/// |> group(by: fn(i) { +/// case i { +/// Ok(_) -> "Successful" +/// Error(_) -> "Failed" +/// } +/// }) +/// |> dict.to_list +/// +/// [ +/// #("Failed", [Error("Wrong")]), +/// #("Successful", [Ok(73), Ok(200), Ok(3)]) +/// ] +/// +/// > group([1,2,3,4,5], by: fn(i) { i - i / 3 * 3 }) +/// |> dict.to_list +/// [#(0, [3]), #(1, [4, 1]), #(2, [5, 2])] +/// ``` +/// +pub fn group(list: List(v), by key: fn(v) -> k) -> Dict(k, List(v)) { + fold(list, dict.new(), update_group(key)) +} + +fn do_filter(list: List(a), fun: fn(a) -> Bool, acc: List(a)) -> List(a) { + case list { + [] -> reverse(acc) + [x, ..xs] -> { + let new_acc = case fun(x) { + True -> [x, ..acc] + False -> acc + } + do_filter(xs, fun, new_acc) + } + } +} + +/// Returns a new list containing only the elements from the first list for +/// which the given functions returns `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > filter([2, 4, 6, 1], fn(x) { x > 2 }) +/// [4, 6] +/// ``` +/// +/// ```gleam +/// > filter([2, 4, 6, 1], fn(x) { x > 6 }) +/// [] +/// ``` +/// +pub fn filter(list: List(a), keeping predicate: fn(a) -> Bool) -> List(a) { + do_filter(list, predicate, []) +} + +fn do_filter_map( + list: List(a), + fun: fn(a) -> Result(b, e), + acc: List(b), +) -> List(b) { + case list { + [] -> reverse(acc) + [x, ..xs] -> { + let new_acc = case fun(x) { + Ok(x) -> [x, ..acc] + Error(_) -> acc + } + do_filter_map(xs, fun, new_acc) + } + } +} + +/// Returns a new list containing only the elements from the first list for +/// which the given functions returns `Ok(_)`. +/// +/// ## Examples +/// +/// ```gleam +/// > filter_map([2, 4, 6, 1], Error) +/// [] +/// ``` +/// +/// ```gleam +/// > filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) }) +/// [3, 5, 7, 2] +/// ``` +/// +pub fn filter_map(list: List(a), with fun: fn(a) -> Result(b, e)) -> List(b) { + do_filter_map(list, fun, []) +} + +fn do_map(list: List(a), fun: fn(a) -> b, acc: List(b)) -> List(b) { + case list { + [] -> reverse(acc) + [x, ..xs] -> do_map(xs, fun, [fun(x), ..acc]) + } +} + +/// Returns a new list containing only the elements of the first list after the +/// function has been applied to each one. +/// +/// ## Examples +/// +/// ```gleam +/// > map([2, 4, 6], fn(x) { x * 2 }) +/// [4, 8, 12] +/// ``` +/// +pub fn map(list: List(a), with fun: fn(a) -> b) -> List(b) { + do_map(list, fun, []) +} + +/// Combines two lists into a single list using the given function. +/// +/// If a list is longer than the other the extra elements are dropped. +/// +/// ## Examples +/// +/// ```gleam +/// > map2([1, 2, 3], [4, 5, 6], fn(x, y) { x + y }) +/// [5, 7, 9] +/// ``` +/// +/// ```gleam +/// > map2([1, 2], ["a", "b", "c"], fn(i, x) { #(i, x) }) +/// [#(1, "a"), #(2, "b")] +/// ``` +/// +pub fn map2(list1: List(a), list2: List(b), with fun: fn(a, b) -> c) -> List(c) { + do_map2(list1, list2, fun, []) +} + +fn do_map2( + list1: List(a), + list2: List(b), + fun: fn(a, b) -> c, + acc: List(c), +) -> List(c) { + case list1, list2 { + [], _ | _, [] -> reverse(acc) + [a, ..as_], [b, ..bs] -> do_map2(as_, bs, fun, [fun(a, b), ..acc]) + } +} + +/// Similar to `map` but also lets you pass around an accumulated value. +/// +/// ## Examples +/// +/// ```gleam +/// > map_fold( +/// over: [1, 2, 3], +/// from: 100, +/// with: fn(memo, i) { #(memo + i, i * 2) } +/// ) +/// #(106, [2, 4, 6]) +/// ``` +/// +pub fn map_fold( + over list: List(a), + from acc: acc, + with fun: fn(acc, a) -> #(acc, b), +) -> #(acc, List(b)) { + fold( + over: list, + from: #(acc, []), + with: fn(acc, item) { + let #(current_acc, items) = acc + let #(next_acc, next_item) = fun(current_acc, item) + #(next_acc, [next_item, ..items]) + }, + ) + |> pair.map_second(reverse) +} + +fn do_index_map( + list: List(a), + fun: fn(Int, a) -> b, + index: Int, + acc: List(b), +) -> List(b) { + case list { + [] -> reverse(acc) + [x, ..xs] -> { + let acc = [fun(index, x), ..acc] + do_index_map(xs, fun, index + 1, acc) + } + } +} + +/// Returns a new list containing only the elements of the first list after the +/// function has been applied to each one and their index. +/// +/// The index starts at 0, so the first element is 0, the second is 1, and so +/// on. +/// +/// ## Examples +/// +/// ```gleam +/// > index_map(["a", "b"], fn(i, x) { #(i, x) }) +/// [#(0, "a"), #(1, "b")] +/// ``` +/// +pub fn index_map(list: List(a), with fun: fn(Int, a) -> b) -> List(b) { + do_index_map(list, fun, 0, []) +} + +fn do_try_map( + list: List(a), + fun: fn(a) -> Result(b, e), + acc: List(b), +) -> Result(List(b), e) { + case list { + [] -> Ok(reverse(acc)) + [x, ..xs] -> + case fun(x) { + Ok(y) -> do_try_map(xs, fun, [y, ..acc]) + Error(error) -> Error(error) + } + } +} + +/// Takes a function that returns a `Result` and applies it to each element in a +/// given list in turn. +/// +/// If the function returns `Ok(new_value)` for all elements in the list then a +/// list of the new values is returned. +/// +/// If the function returns `Error(reason)` for any of the elements then it is +/// returned immediately. None of the elements in the list are processed after +/// one returns an `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > try_map([1, 2, 3], fn(x) { Ok(x + 2) }) +/// Ok([3, 4, 5]) +/// ``` +/// +/// ```gleam +/// > try_map([1, 2, 3], fn(_) { Error(0) }) +/// Error(0) +/// ``` +/// +/// ```gleam +/// > try_map([[1], [2, 3]], first) +/// Ok([1, 2]) +/// ``` +/// +/// ```gleam +/// > try_map([[1], [], [2]], first) +/// Error(Nil) +/// ``` +/// +pub fn try_map( + over list: List(a), + with fun: fn(a) -> Result(b, e), +) -> Result(List(b), e) { + do_try_map(list, fun, []) +} + +/// Returns a list that is the given list with up to the given number of +/// elements removed from the front of the list. +/// +/// If the element has less than the number of elements an empty list is +/// returned. +/// +/// This function runs in linear time but does not copy the list. +/// +/// ## Examples +/// +/// ```gleam +/// > drop([1, 2, 3, 4], 2) +/// [3, 4] +/// ``` +/// +/// ```gleam +/// > drop([1, 2, 3, 4], 9) +/// [] +/// ``` +/// +pub fn drop(from list: List(a), up_to n: Int) -> List(a) { + case n <= 0 { + True -> list + False -> + case list { + [] -> [] + [_, ..xs] -> drop(xs, n - 1) + } + } +} + +fn do_take(list: List(a), n: Int, acc: List(a)) -> List(a) { + case n <= 0 { + True -> reverse(acc) + False -> + case list { + [] -> reverse(acc) + [x, ..xs] -> do_take(xs, n - 1, [x, ..acc]) + } + } +} + +/// Returns a list containing the first given number of elements from the given +/// list. +/// +/// If the element has less than the number of elements then the full list is +/// returned. +/// +/// This function runs in linear time but does not copy the list. +/// +/// ## Examples +/// +/// ```gleam +/// > take([1, 2, 3, 4], 2) +/// [1, 2] +/// ``` +/// +/// ```gleam +/// > take([1, 2, 3, 4], 9) +/// [1, 2, 3, 4] +/// ``` +/// +pub fn take(from list: List(a), up_to n: Int) -> List(a) { + do_take(list, n, []) +} + +/// Returns a new empty list. +/// +/// ## Examples +/// +/// ```gleam +/// > new() +/// [] +/// ``` +/// +pub fn new() -> List(a) { + [] +} + +/// Joins one list onto the end of another. +/// +/// This function runs in linear time, and it traverses and copies the first +/// list. +/// +/// ## Examples +/// +/// ```gleam +/// > append([1, 2], [3]) +/// [1, 2, 3] +/// ``` +/// +pub fn append(first: List(a), second: List(a)) -> List(a) { + do_append(first, second) +} + +@target(erlang) +@external(erlang, "lists", "append") +fn do_append(a: List(a), b: List(a)) -> List(a) + +@target(javascript) +fn do_append(first: List(a), second: List(a)) -> List(a) { + do_append_acc(reverse(first), second) +} + +@target(javascript) +fn do_append_acc(first: List(a), second: List(a)) -> List(a) { + case first { + [] -> second + [item, ..rest] -> do_append_acc(rest, [item, ..second]) + } +} + +/// Prefixes an item to a list. This can also be done using the dedicated +/// syntax instead +/// +/// ```gleam +/// let new_list = [1, ..existing_list] +/// ``` +/// +pub fn prepend(to list: List(a), this item: a) -> List(a) { + [item, ..list] +} + +// Reverses a list and prepends it to another list +fn reverse_and_prepend(list prefix: List(a), to suffix: List(a)) -> List(a) { + case prefix { + [] -> suffix + [first, ..rest] -> reverse_and_prepend(list: rest, to: [first, ..suffix]) + } +} + +fn do_concat(lists: List(List(a)), acc: List(a)) -> List(a) { + case lists { + [] -> reverse(acc) + [list, ..further_lists] -> + do_concat(further_lists, reverse_and_prepend(list: list, to: acc)) + } +} + +/// Joins a list of lists into a single list. +/// +/// This function traverses all elements twice. +/// +/// ## Examples +/// +/// ```gleam +/// > concat([[1], [2, 3], []]) +/// [1, 2, 3] +/// ``` +/// +pub fn concat(lists: List(List(a))) -> List(a) { + do_concat(lists, []) +} + +/// This is the same as `concat`: it joins a list of lists into a single +/// list. +/// +/// This function traverses all elements twice. +/// +/// ## Examples +/// +/// ```gleam +/// > flatten([[1], [2, 3], []]) +/// [1, 2, 3] +/// ``` +/// +pub fn flatten(lists: List(List(a))) -> List(a) { + do_concat(lists, []) +} + +/// Maps the list with the given function into a list of lists, and then flattens it. +/// +/// ## Examples +/// +/// ```gleam +/// > flat_map([2, 4, 6], fn(x) { [x, x + 1] }) +/// [2, 3, 4, 5, 6, 7] +/// ``` +/// +pub fn flat_map(over list: List(a), with fun: fn(a) -> List(b)) -> List(b) { + map(list, fun) + |> concat +} + +/// Reduces a list of elements into a single value by calling a given function +/// on each element, going from left to right. +/// +/// `fold([1, 2, 3], 0, add)` is the equivalent of +/// `add(add(add(0, 1), 2), 3)`. +/// +/// This function runs in linear time. +/// +pub fn fold( + over list: List(a), + from initial: acc, + with fun: fn(acc, a) -> acc, +) -> acc { + case list { + [] -> initial + [x, ..rest] -> fold(rest, fun(initial, x), fun) + } +} + +/// Reduces a list of elements into a single value by calling a given function +/// on each element, going from right to left. +/// +/// `fold_right([1, 2, 3], 0, add)` is the equivalent of +/// `add(add(add(0, 3), 2), 1)`. +/// +/// This function runs in linear time. +/// +/// Unlike `fold` this function is not tail recursive. Where possible use +/// `fold` instead as it will use less memory. +/// +pub fn fold_right( + over list: List(a), + from initial: acc, + with fun: fn(acc, a) -> acc, +) -> acc { + case list { + [] -> initial + [x, ..rest] -> fun(fold_right(rest, initial, fun), x) + } +} + +fn do_index_fold( + over: List(a), + acc: acc, + with: fn(acc, a, Int) -> acc, + index: Int, +) -> acc { + case over { + [] -> acc + [first, ..rest] -> + do_index_fold(rest, with(acc, first, index), with, index + 1) + } +} + +/// Like fold but the folding function also receives the index of the current element. +/// +/// ## Examples +/// +/// ```gleam +/// ["a", "b", "c"] +/// |> index_fold([], fn(acc, item, index) { ... }) +/// ``` +/// +pub fn index_fold( + over over: List(a), + from initial: acc, + with fun: fn(acc, a, Int) -> acc, +) -> acc { + do_index_fold(over, initial, fun, 0) +} + +/// A variant of fold that might fail. +/// +/// The folding function should return `Result(accumulator, error)`. +/// If the returned value is `Ok(accumulator)` try_fold will try the next value in the list. +/// If the returned value is `Error(error)` try_fold will stop and return that error. +/// +/// ## Examples +/// +/// ```gleam +/// [1, 2, 3, 4] +/// |> try_fold(0, fn(acc, i) { +/// case i < 3 { +/// True -> Ok(acc + i) +/// False -> Error(Nil) +/// } +/// }) +/// ``` +/// +pub fn try_fold( + over collection: List(a), + from accumulator: acc, + with fun: fn(acc, a) -> Result(acc, e), +) -> Result(acc, e) { + case collection { + [] -> Ok(accumulator) + [first, ..rest] -> + case fun(accumulator, first) { + Ok(result) -> try_fold(rest, result, fun) + Error(_) as error -> error + } + } +} + +pub type ContinueOrStop(a) { + Continue(a) + Stop(a) +} + +/// A variant of fold that allows to stop folding earlier. +/// +/// The folding function should return `ContinueOrStop(accumulator)`. +/// If the returned value is `Continue(accumulator)` fold_until will try the next value in the list. +/// If the returned value is `Stop(accumulator)` fold_until will stop and return that accumulator. +/// +/// ## Examples +/// +/// ```gleam +/// [1, 2, 3, 4] +/// |> fold_until(0, fn(acc, i) { +/// case i < 3 { +/// True -> Continue(acc + i) +/// False -> Stop(acc) +/// } +/// }) +/// ``` +/// +pub fn fold_until( + over collection: List(a), + from accumulator: acc, + with fun: fn(acc, a) -> ContinueOrStop(acc), +) -> acc { + case collection { + [] -> accumulator + [first, ..rest] -> + case fun(accumulator, first) { + Continue(next_accumulator) -> fold_until(rest, next_accumulator, fun) + Stop(b) -> b + } + } +} + +/// Finds the first element in a given list for which the given function returns +/// `True`. +/// +/// Returns `Error(Nil)` if no such element is found. +/// +/// ## Examples +/// +/// ```gleam +/// > find([1, 2, 3], fn(x) { x > 2 }) +/// Ok(3) +/// ``` +/// +/// ```gleam +/// > find([1, 2, 3], fn(x) { x > 4 }) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > find([], fn(_) { True }) +/// Error(Nil) +/// ``` +/// +pub fn find( + in haystack: List(a), + one_that is_desired: fn(a) -> Bool, +) -> Result(a, Nil) { + case haystack { + [] -> Error(Nil) + [x, ..rest] -> + case is_desired(x) { + True -> Ok(x) + _ -> find(in: rest, one_that: is_desired) + } + } +} + +/// Finds the first element in a given list for which the given function returns +/// `Ok(new_value)`, then returns the wrapped `new_value`. +/// +/// Returns `Error(Nil)` if no such element is found. +/// +/// ## Examples +/// +/// ```gleam +/// > find_map([[], [2], [3]], first) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > find_map([[], []], first) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > find_map([], first) +/// Error(Nil) +/// ``` +/// +pub fn find_map( + in haystack: List(a), + with fun: fn(a) -> Result(b, c), +) -> Result(b, Nil) { + case haystack { + [] -> Error(Nil) + [x, ..rest] -> + case fun(x) { + Ok(x) -> Ok(x) + _ -> find_map(in: rest, with: fun) + } + } +} + +/// Returns `True` if the given function returns `True` for all the elements in +/// the given list. If the function returns `False` for any of the elements it +/// immediately returns `False` without checking the rest of the list. +/// +/// ## Examples +/// +/// ```gleam +/// > all([], fn(x) { x > 3 }) +/// True +/// ``` +/// +/// ```gleam +/// > all([4, 5], fn(x) { x > 3 }) +/// True +/// ``` +/// +/// ```gleam +/// > all([4, 3], fn(x) { x > 3 }) +/// False +/// ``` +/// +pub fn all(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool { + case list { + [] -> True + [first, ..rest] -> + case predicate(first) { + True -> all(rest, predicate) + False -> False + } + } +} + +/// Returns `True` if the given function returns `True` for any the elements in +/// the given list. If the function returns `True` for any of the elements it +/// immediately returns `True` without checking the rest of the list. +/// +/// ## Examples +/// +/// ```gleam +/// > any([], fn(x) { x > 3 }) +/// False +/// ``` +/// +/// ```gleam +/// > any([4, 5], fn(x) { x > 3 }) +/// True +/// ``` +/// +/// ```gleam +/// > any([4, 3], fn(x) { x > 4 }) +/// False +/// ``` +/// +/// ```gleam +/// > any([3, 4], fn(x) { x > 3 }) +/// True +/// ``` +/// +pub fn any(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool { + case list { + [] -> False + [first, ..rest] -> + case predicate(first) { + True -> True + False -> any(rest, predicate) + } + } +} + +fn do_zip(xs: List(a), ys: List(b), acc: List(#(a, b))) -> List(#(a, b)) { + case xs, ys { + [x, ..xs], [y, ..ys] -> do_zip(xs, ys, [#(x, y), ..acc]) + _, _ -> reverse(acc) + } +} + +/// Takes two lists and returns a single list of 2-element tuples. +/// +/// If one of the lists is longer than the other, the remaining elements from +/// the longer list are not used. +/// +/// ## Examples +/// +/// ```gleam +/// > zip([], []) +/// [] +/// ``` +/// +/// ```gleam +/// > zip([1, 2], [3]) +/// [#(1, 3)] +/// ``` +/// +/// ```gleam +/// > zip([1], [3, 4]) +/// [#(1, 3)] +/// ``` +/// +/// ```gleam +/// > zip([1, 2], [3, 4]) +/// [#(1, 3), #(2, 4)] +/// ``` +/// +pub fn zip(list: List(a), with other: List(b)) -> List(#(a, b)) { + do_zip(list, other, []) +} + +/// Takes two lists and returns a single list of 2-element tuples. +/// +/// If one of the lists is longer than the other, an `Error` is returned. +/// +/// ## Examples +/// +/// ```gleam +/// > strict_zip([], []) +/// Ok([]) +/// ``` +/// +/// ```gleam +/// > strict_zip([1, 2], [3]) +/// Error(LengthMismatch) +/// ``` +/// +/// ```gleam +/// > strict_zip([1], [3, 4]) +/// Error(LengthMismatch) +/// ``` +/// +/// ```gleam +/// > strict_zip([1, 2], [3, 4]) +/// Ok([#(1, 3), #(2, 4)]) +/// ``` +/// +pub fn strict_zip( + list: List(a), + with other: List(b), +) -> Result(List(#(a, b)), LengthMismatch) { + case length(of: list) == length(of: other) { + True -> Ok(zip(list, other)) + False -> Error(LengthMismatch) + } +} + +fn do_unzip(input, xs, ys) { + case input { + [] -> #(reverse(xs), reverse(ys)) + [#(x, y), ..rest] -> do_unzip(rest, [x, ..xs], [y, ..ys]) + } +} + +/// Takes a single list of 2-element tuples and returns two lists. +/// +/// ## Examples +/// +/// ```gleam +/// > unzip([#(1, 2), #(3, 4)]) +/// #([1, 3], [2, 4]) +/// ``` +/// +/// ```gleam +/// > unzip([]) +/// #([], []) +/// ``` +/// +pub fn unzip(input: List(#(a, b))) -> #(List(a), List(b)) { + do_unzip(input, [], []) +} + +fn do_intersperse(list: List(a), separator: a, acc: List(a)) -> List(a) { + case list { + [] -> reverse(acc) + [x, ..rest] -> do_intersperse(rest, separator, [x, separator, ..acc]) + } +} + +/// Inserts a given value between each existing element in a given list. +/// +/// This function runs in linear time and copies the list. +/// +/// ## Examples +/// +/// ```gleam +/// > intersperse([1, 1, 1], 2) +/// [1, 2, 1, 2, 1] +/// ``` +/// +/// ```gleam +/// > intersperse([], 2) +/// [] +/// ``` +/// +pub fn intersperse(list: List(a), with elem: a) -> List(a) { + case list { + [] | [_] -> list + [x, ..rest] -> do_intersperse(rest, elem, [x]) + } +} + +/// Returns the element in the Nth position in the list, with 0 being the first +/// position. +/// +/// `Error(Nil)` is returned if the list is not long enough for the given index +/// or if the index is less than 0. +/// +/// ## Examples +/// +/// ```gleam +/// > at([1, 2, 3], 1) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > at([1, 2, 3], 5) +/// Error(Nil) +/// ``` +/// +pub fn at(in list: List(a), get index: Int) -> Result(a, Nil) { + case index >= 0 { + True -> + list + |> drop(index) + |> first + False -> Error(Nil) + } +} + +/// Removes any duplicate elements from a given list. +/// +/// This function returns in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > unique([1, 1, 1, 4, 7, 3, 3, 4]) +/// [1, 4, 7, 3] +/// ``` +/// +pub fn unique(list: List(a)) -> List(a) { + case list { + [] -> [] + [x, ..rest] -> [x, ..unique(filter(rest, fn(y) { y != x }))] + } +} + +/// Merge lists `a` and `b` in ascending order +/// but only up to `na` and `nb` number of items respectively. +/// +fn merge_up( + na: Int, + nb: Int, + a: List(a), + b: List(a), + acc: List(a), + compare: fn(a, a) -> Order, +) { + case na, nb, a, b { + 0, 0, _, _ -> acc + _, 0, [ax, ..ar], _ -> merge_up(na - 1, nb, ar, b, [ax, ..acc], compare) + 0, _, _, [bx, ..br] -> merge_up(na, nb - 1, a, br, [bx, ..acc], compare) + _, _, [ax, ..ar], [bx, ..br] -> + case compare(ax, bx) { + order.Gt -> merge_up(na, nb - 1, a, br, [bx, ..acc], compare) + _ -> merge_up(na - 1, nb, ar, b, [ax, ..acc], compare) + } + _, _, _, _ -> acc + } +} + +/// Merge lists `a` and `b` in descending order +/// but only up to `na` and `nb` number of items respectively. +/// +fn merge_down( + na: Int, + nb: Int, + a: List(a), + b: List(a), + acc: List(a), + compare: fn(a, a) -> Order, +) { + case na, nb, a, b { + 0, 0, _, _ -> acc + _, 0, [ax, ..ar], _ -> merge_down(na - 1, nb, ar, b, [ax, ..acc], compare) + 0, _, _, [bx, ..br] -> merge_down(na, nb - 1, a, br, [bx, ..acc], compare) + _, _, [ax, ..ar], [bx, ..br] -> + case compare(bx, ax) { + order.Lt -> merge_down(na - 1, nb, ar, b, [ax, ..acc], compare) + _ -> merge_down(na, nb - 1, a, br, [bx, ..acc], compare) + } + _, _, _, _ -> acc + } +} + +/// Merge sort that alternates merging in ascending and descending order +/// because the merge process also reverses the list. +/// +/// Some copying is avoided by merging only a subset of the lists +/// instead of creating and merging new smaller lists. +/// +fn merge_sort( + l: List(a), + ln: Int, + compare: fn(a, a) -> Order, + down: Bool, +) -> List(a) { + let n = ln / 2 + let a = l + let b = drop(l, n) + case ln < 3 { + True -> + case down { + True -> merge_down(n, ln - n, a, b, [], compare) + False -> merge_up(n, ln - n, a, b, [], compare) + } + False -> + case down { + True -> + merge_down( + n, + ln - n, + merge_sort(a, n, compare, False), + merge_sort(b, ln - n, compare, False), + [], + compare, + ) + False -> + merge_up( + n, + ln - n, + merge_sort(a, n, compare, True), + merge_sort(b, ln - n, compare, True), + [], + compare, + ) + } + } +} + +/// Sorts from smallest to largest based upon the ordering specified by a given +/// function. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/int +/// > list.sort([4, 3, 6, 5, 4, 1, 2], by: int.compare) +/// [1, 2, 3, 4, 4, 5, 6] +/// ``` +/// +pub fn sort(list: List(a), by compare: fn(a, a) -> Order) -> List(a) { + merge_sort(list, length(list), compare, True) +} + +/// Creates a list of ints ranging from a given start and finish. +/// +/// ## Examples +/// +/// ```gleam +/// > range(0, 0) +/// [0] +/// ``` +/// +/// ```gleam +/// > range(0, 5) +/// [0, 1, 2, 3, 4, 5] +/// ``` +/// +/// ```gleam +/// > range(1, -5) +/// [1, 0, -1, -2, -3, -4, -5] +/// ``` +/// +pub fn range(from start: Int, to stop: Int) -> List(Int) { + tail_recursive_range(start, stop, []) +} + +fn tail_recursive_range(start: Int, stop: Int, acc: List(Int)) -> List(Int) { + case int.compare(start, stop) { + order.Eq -> [stop, ..acc] + order.Gt -> tail_recursive_range(start, stop + 1, [stop, ..acc]) + order.Lt -> tail_recursive_range(start, stop - 1, [stop, ..acc]) + } +} + +fn do_repeat(a: a, times: Int, acc: List(a)) -> List(a) { + case times <= 0 { + True -> acc + False -> do_repeat(a, times - 1, [a, ..acc]) + } +} + +/// Builds a list of a given value a given number of times. +/// +/// ## Examples +/// +/// ```gleam +/// > repeat("a", times: 0) +/// [] +/// ``` +/// +/// ```gleam +/// > repeat("a", times: 5) +/// ["a", "a", "a", "a", "a"] +/// ``` +/// +pub fn repeat(item a: a, times times: Int) -> List(a) { + do_repeat(a, times, []) +} + +fn do_split(list: List(a), n: Int, taken: List(a)) -> #(List(a), List(a)) { + case n <= 0 { + True -> #(reverse(taken), list) + False -> + case list { + [] -> #(reverse(taken), []) + [x, ..xs] -> do_split(xs, n - 1, [x, ..taken]) + } + } +} + +/// Splits a list in two before the given index. +/// +/// If the list is not long enough to have the given index the before list will +/// be the input list, and the after list will be empty. +/// +/// ## Examples +/// +/// ```gleam +/// > split([6, 7, 8, 9], 0) +/// #([], [6, 7, 8, 9]) +/// ``` +/// +/// ```gleam +/// > split([6, 7, 8, 9], 2) +/// #([6, 7], [8, 9]) +/// ``` +/// +/// ```gleam +/// > split([6, 7, 8, 9], 4) +/// #([6, 7, 8, 9], []) +/// ``` +/// +pub fn split(list list: List(a), at index: Int) -> #(List(a), List(a)) { + do_split(list, index, []) +} + +fn do_split_while( + list: List(a), + f: fn(a) -> Bool, + acc: List(a), +) -> #(List(a), List(a)) { + case list { + [] -> #(reverse(acc), []) + [x, ..xs] -> + case f(x) { + False -> #(reverse(acc), list) + _ -> do_split_while(xs, f, [x, ..acc]) + } + } +} + +/// Splits a list in two before the first element that a given function returns +/// `False` for. +/// +/// If the function returns `True` for all elements the first list will be the +/// input list, and the second list will be empty. +/// +/// ## Examples +/// +/// ```gleam +/// > split_while([1, 2, 3, 4, 5], fn(x) { x <= 3 }) +/// #([1, 2, 3], [4, 5]) +/// ``` +/// +/// ```gleam +/// > split_while([1, 2, 3, 4, 5], fn(x) { x <= 5 }) +/// #([1, 2, 3, 4, 5], []) +/// ``` +/// +pub fn split_while( + list list: List(a), + satisfying predicate: fn(a) -> Bool, +) -> #(List(a), List(a)) { + do_split_while(list, predicate, []) +} + +/// Given a list of 2-element tuples, finds the first tuple that has a given +/// key as the first element and returns the second element. +/// +/// If no tuple is found with the given key then `Error(Nil)` is returned. +/// +/// This function may be useful for interacting with Erlang code where lists of +/// tuples are common. +/// +/// ## Examples +/// +/// ```gleam +/// > key_find([#("a", 0), #("b", 1)], "a") +/// Ok(0) +/// ``` +/// +/// ```gleam +/// > key_find([#("a", 0), #("b", 1)], "b") +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > key_find([#("a", 0), #("b", 1)], "c") +/// Error(Nil) +/// ``` +/// +pub fn key_find( + in keyword_list: List(#(k, v)), + find desired_key: k, +) -> Result(v, Nil) { + find_map( + keyword_list, + fn(keyword) { + let #(key, value) = keyword + case key == desired_key { + True -> Ok(value) + False -> Error(Nil) + } + }, + ) +} + +/// Given a list of 2-element tuples, finds all tuples that have a given +/// key as the first element and returns the second element. +/// +/// This function may be useful for interacting with Erlang code where lists of +/// tuples are common. +/// +/// ## Examples +/// +/// ```gleam +/// > key_filter([#("a", 0), #("b", 1), #("a", 2)], "a") +/// [0, 2] +/// ``` +/// +/// ```gleam +/// > key_filter([#("a", 0), #("b", 1)], "c") +/// [] +/// ``` +/// +pub fn key_filter( + in keyword_list: List(#(k, v)), + find desired_key: k, +) -> List(v) { + filter_map( + keyword_list, + fn(keyword) { + let #(key, value) = keyword + case key == desired_key { + True -> Ok(value) + False -> Error(Nil) + } + }, + ) +} + +fn do_pop(haystack, predicate, checked) { + case haystack { + [] -> Error(Nil) + [x, ..rest] -> + case predicate(x) { + True -> Ok(#(x, append(reverse(checked), rest))) + False -> do_pop(rest, predicate, [x, ..checked]) + } + } +} + +/// Removes the first element in a given list for which the predicate function returns `True`. +/// +/// Returns `Error(Nil)` if no such element is found. +/// +/// ## Examples +/// +/// ```gleam +/// > pop([1, 2, 3], fn(x) { x > 2 }) +/// Ok(#(3, [1, 2])) +/// ``` +/// +/// ```gleam +/// > pop([1, 2, 3], fn(x) { x > 4 }) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > pop([], fn(_) { True }) +/// Error(Nil) +/// ``` +/// +pub fn pop( + in haystack: List(a), + one_that is_desired: fn(a) -> Bool, +) -> Result(#(a, List(a)), Nil) { + do_pop(haystack, is_desired, []) +} + +fn do_pop_map(haystack, mapper, checked) { + case haystack { + [] -> Error(Nil) + [x, ..rest] -> + case mapper(x) { + Ok(y) -> Ok(#(y, append(reverse(checked), rest))) + Error(_) -> do_pop_map(rest, mapper, [x, ..checked]) + } + } +} + +/// Removes the first element in a given list for which the given function returns +/// `Ok(new_value)`, then returns the wrapped `new_value` as well as list with the value removed. +/// +/// Returns `Error(Nil)` if no such element is found. +/// +/// ## Examples +/// +/// ```gleam +/// > pop_map([[], [2], [3]], first) +/// Ok(#(2, [[], [3]])) +/// ``` +/// +/// ```gleam +/// > pop_map([[], []], first) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > pop_map([], first) +/// Error(Nil) +/// ``` +/// +pub fn pop_map( + in haystack: List(a), + one_that is_desired: fn(a) -> Result(b, c), +) -> Result(#(b, List(a)), Nil) { + do_pop_map(haystack, is_desired, []) +} + +/// Given a list of 2-element tuples, finds the first tuple that has a given +/// key as the first element. This function will return the second element +/// of the found tuple and list with tuple removed. +/// +/// If no tuple is found with the given key then `Error(Nil)` is returned. +/// +/// ## Examples +/// +/// ```gleam +/// > key_pop([#("a", 0), #("b", 1)], "a") +/// Ok(#(0, [#("b", 1)])) +/// ``` +/// +/// ```gleam +/// > key_pop([#("a", 0), #("b", 1)], "b") +/// Ok(#(1, [#("a", 0)])) +/// ``` +/// +/// ```gleam +/// > key_pop([#("a", 0), #("b", 1)], "c") +/// Error(Nil) +/// ``` +/// +pub fn key_pop( + haystack: List(#(k, v)), + key: k, +) -> Result(#(v, List(#(k, v))), Nil) { + pop_map( + haystack, + fn(entry) { + let #(k, v) = entry + case k { + k if k == key -> Ok(v) + _ -> Error(Nil) + } + }, + ) +} + +/// Given a list of 2-element tuples, inserts a key and value into the list. +/// +/// If there was already a tuple with the key then it is replaced, otherwise it +/// is added to the end of the list. +/// +/// ## Examples +/// +/// ```gleam +/// > key_set([#(5, 0), #(4, 1)], 4, 100) +/// [#(5, 0), #(4, 100)] +/// ``` +/// +/// ```gleam +/// > key_set([#(5, 0), #(4, 1)], 1, 100) +/// [#(5, 0), #(4, 1), #(1, 100)] +/// ``` +/// +pub fn key_set(list: List(#(a, b)), key: a, value: b) -> List(#(a, b)) { + case list { + [] -> [#(key, value)] + [#(k, _), ..rest] if k == key -> [#(key, value), ..rest] + [first, ..rest] -> [first, ..key_set(rest, key, value)] + } +} + +/// Calls a function for each element in a list, discarding the return value. +/// +/// Useful for calling a side effect for every item of a list. +/// +/// ```gleam +/// > list.each([1, 2, 3], io.println) +/// Nil +/// ``` +/// +pub fn each(list: List(a), f: fn(a) -> b) -> Nil { + case list { + [] -> Nil + [x, ..xs] -> { + f(x) + each(xs, f) + } + } +} + +/// Calls a `Result` returning function for each element in a list, discarding +/// the return value. If the function returns `Error` then the iteration is +/// stopped and the error is returned. +/// +/// Useful for calling a side effect for every item of a list. +/// +/// ## Examples +/// +/// ```gleam +/// > try_each( +/// > over: [1, 2, 3], +/// > with: function_that_might_fail, +/// > ) +/// Ok(Nil) +/// ``` +/// +pub fn try_each( + over list: List(a), + with fun: fn(a) -> Result(b, e), +) -> Result(Nil, e) { + case list { + [] -> Ok(Nil) + [x, ..xs] -> + case fun(x) { + Ok(_) -> try_each(over: xs, with: fun) + Error(e) -> Error(e) + } + } +} + +fn do_partition(list, categorise, trues, falses) { + case list { + [] -> #(reverse(trues), reverse(falses)) + [x, ..xs] -> + case categorise(x) { + True -> do_partition(xs, categorise, [x, ..trues], falses) + False -> do_partition(xs, categorise, trues, [x, ..falses]) + } + } +} + +/// Partitions a list into a tuple/pair of lists +/// by a given categorisation function. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4, 5] |> list.partition(int.is_odd) +/// #([1, 3, 5], [2, 4]) +/// ``` +/// +pub fn partition( + list: List(a), + with categorise: fn(a) -> Bool, +) -> #(List(a), List(a)) { + do_partition(list, categorise, [], []) +} + +/// Returns all the permutations of a list. +/// +/// ## Examples +/// +/// ```gleam +/// > permutations([1, 2]) +/// [[1, 2], [2, 1]] +/// ``` +/// +pub fn permutations(l: List(a)) -> List(List(a)) { + case l { + [] -> [[]] + _ -> + l + |> index_map(fn(i_idx, i) { + l + |> index_fold( + [], + fn(acc, j, j_idx) { + case i_idx == j_idx { + True -> acc + False -> [j, ..acc] + } + }, + ) + |> reverse + |> permutations + |> map(fn(permutation) { [i, ..permutation] }) + }) + |> concat + } +} + +fn do_window(acc: List(List(a)), l: List(a), n: Int) -> List(List(a)) { + let window = take(l, n) + + case length(window) == n { + True -> do_window([window, ..acc], drop(l, 1), n) + False -> acc + } +} + +/// Returns a list of sliding windows. +/// +/// ## Examples +/// +/// ```gleam +/// > window([1,2,3,4,5], 3) +/// [[1, 2, 3], [2, 3, 4], [3, 4, 5]] +/// ``` +/// +/// ```gleam +/// > window([1, 2], 4) +/// [] +/// ``` +/// +pub fn window(l: List(a), by n: Int) -> List(List(a)) { + do_window([], l, n) + |> reverse +} + +/// Returns a list of tuples containing two contiguous elements. +/// +/// ## Examples +/// +/// ```gleam +/// > window_by_2([1,2,3,4]) +/// [#(1, 2), #(2, 3), #(3, 4)] +/// ``` +/// +/// ```gleam +/// > window_by_2([1]) +/// [] +/// ``` +/// +pub fn window_by_2(l: List(a)) -> List(#(a, a)) { + zip(l, drop(l, 1)) +} + +/// Drops the first elements in a given list for which the predicate function returns `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > drop_while([1, 2, 3, 4], fn (x) { x < 3 }) +/// [3, 4] +/// ``` +/// +pub fn drop_while( + in list: List(a), + satisfying predicate: fn(a) -> Bool, +) -> List(a) { + case list { + [] -> [] + [x, ..xs] -> + case predicate(x) { + True -> drop_while(xs, predicate) + False -> [x, ..xs] + } + } +} + +fn do_take_while( + list: List(a), + predicate: fn(a) -> Bool, + acc: List(a), +) -> List(a) { + case list { + [] -> reverse(acc) + [first, ..rest] -> + case predicate(first) { + True -> do_take_while(rest, predicate, [first, ..acc]) + False -> reverse(acc) + } + } +} + +/// Takes the first elements in a given list for which the predicate function returns `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > take_while([1, 2, 3, 2, 4], fn (x) { x < 3 }) +/// [1, 2] +/// ``` +/// +pub fn take_while( + in list: List(a), + satisfying predicate: fn(a) -> Bool, +) -> List(a) { + do_take_while(list, predicate, []) +} + +fn do_chunk( + list: List(a), + f: fn(a) -> key, + previous_key: key, + current_chunk: List(a), + acc: List(List(a)), +) -> List(List(a)) { + case list { + [first, ..rest] -> { + let key = f(first) + case key == previous_key { + False -> { + let new_acc = [reverse(current_chunk), ..acc] + do_chunk(rest, f, key, [first], new_acc) + } + _true -> do_chunk(rest, f, key, [first, ..current_chunk], acc) + } + } + _empty -> reverse([reverse(current_chunk), ..acc]) + } +} + +/// Returns a list of chunks in which +/// the return value of calling `f` on each element is the same. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk(by: fn(n) { n % 2 }) +/// [[1], [2, 2], [3], [4, 4, 6], [7, 7]] +/// ``` +/// +pub fn chunk(in list: List(a), by f: fn(a) -> key) -> List(List(a)) { + case list { + [] -> [] + [first, ..rest] -> do_chunk(rest, f, f(first), [first], []) + } +} + +fn do_sized_chunk( + list: List(a), + count: Int, + left: Int, + current_chunk: List(a), + acc: List(List(a)), +) -> List(List(a)) { + case list { + [] -> + case current_chunk { + [] -> reverse(acc) + remaining -> reverse([reverse(remaining), ..acc]) + } + [first, ..rest] -> { + let chunk = [first, ..current_chunk] + case left > 1 { + False -> do_sized_chunk(rest, count, count, [], [reverse(chunk), ..acc]) + True -> do_sized_chunk(rest, count, left - 1, chunk, acc) + } + } + } +} + +/// Returns a list of chunks containing `count` elements each. +/// +/// If the last chunk does not have `count` elements, it is instead +/// a partial chunk, with less than `count` elements. +/// +/// For any `count` less than 1 this function behaves as if it was set to 1. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4, 5, 6] |> sized_chunk(into: 2) +/// [[1, 2], [3, 4], [5, 6]] +/// ``` +/// +/// ```gleam +/// > [1, 2, 3, 4, 5, 6, 7, 8] |> sized_chunk(into: 3) +/// [[1, 2, 3], [4, 5, 6], [7, 8]] +/// ``` +/// +pub fn sized_chunk(in list: List(a), into count: Int) -> List(List(a)) { + do_sized_chunk(list, count, count, [], []) +} + +/// This function acts similar to fold, but does not take an initial state. +/// Instead, it starts from the first element in the list +/// and combines it with each subsequent element in turn using the given +/// function. The function is called as `fun(accumulator, current_element)`. +/// +/// Returns `Ok` to indicate a successful run, and `Error` if called on an +/// empty list. +/// +/// ## Examples +/// +/// ```gleam +/// > [] |> reduce(fn(acc, x) { acc + x }) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > [1, 2, 3, 4, 5] |> reduce(fn(acc, x) { acc + x }) +/// Ok(15) +/// ``` +/// +pub fn reduce(over list: List(a), with fun: fn(a, a) -> a) -> Result(a, Nil) { + case list { + [] -> Error(Nil) + [first, ..rest] -> Ok(fold(rest, first, fun)) + } +} + +fn do_scan( + list: List(a), + accumulator: acc, + accumulated: List(acc), + fun: fn(acc, a) -> acc, +) -> List(acc) { + case list { + [] -> reverse(accumulated) + [x, ..xs] -> { + let next = fun(accumulator, x) + do_scan(xs, next, [next, ..accumulated], fun) + } + } +} + +/// Similar to `fold`, but yields the state of the accumulator at each stage. +/// +/// ## Examples +/// +/// ```gleam +/// > scan(over: [1, 2, 3], from: 100, with: fn(acc, i) { acc + i }) +/// [101, 103, 106] +/// ``` +/// +pub fn scan( + over list: List(a), + from initial: acc, + with fun: fn(acc, a) -> acc, +) -> List(acc) { + do_scan(list, initial, [], fun) +} + +/// Returns the last element in the given list. +/// +/// Returns `Error(Nil)` if the list is empty. +/// +/// This function runs in linear time. +/// For a collection oriented around performant access at either end, +/// see `gleam/queue.Queue`. +/// +/// ## Examples +/// +/// ```gleam +/// > last([]) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > last([1, 2, 3, 4, 5]) +/// Ok(5) +/// ``` +/// +pub fn last(list: List(a)) -> Result(a, Nil) { + list + |> reduce(fn(_, elem) { elem }) +} + +/// Return unique combinations of elements in the list. +/// +/// ## Examples +/// +/// ```gleam +/// > combinations([1, 2, 3], 2) +/// [[1, 2], [1, 3], [2, 3]] +/// ``` +/// +/// ```gleam +/// > combinations([1, 2, 3, 4], 3) +/// [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]] +/// ``` +/// +pub fn combinations(items: List(a), by n: Int) -> List(List(a)) { + case n { + 0 -> [[]] + _ -> + case items { + [] -> [] + [x, ..xs] -> { + let first_combinations = + map(combinations(xs, n - 1), with: fn(com) { [x, ..com] }) + |> reverse + fold( + first_combinations, + combinations(xs, n), + fn(acc, c) { [c, ..acc] }, + ) + } + } + } +} + +fn do_combination_pairs(items: List(a)) -> List(List(#(a, a))) { + case items { + [] -> [] + [x, ..xs] -> { + let first_combinations = map(xs, with: fn(other) { #(x, other) }) + [first_combinations, ..do_combination_pairs(xs)] + } + } +} + +/// Return unique pair combinations of elements in the list +/// +/// ## Examples +/// +/// ```gleam +/// > combination_pairs([1, 2, 3]) +/// [#(1, 2), #(1, 3), #(2, 3)] +/// ``` +/// +pub fn combination_pairs(items: List(a)) -> List(#(a, a)) { + do_combination_pairs(items) + |> concat +} + +/// Make a list alternating the elements from the given lists +/// +/// ## Examples +/// +/// ```gleam +/// > list.interleave([[1, 2], [101, 102], [201, 202]]) +/// [1, 101, 201, 2, 102, 202] +/// ``` +/// +pub fn interleave(list: List(List(a))) -> List(a) { + transpose(list) + |> concat +} + +/// Transpose rows and columns of the list of lists. +/// +/// Notice: This function is not tail recursive, +/// and thus may exceed stack size if called, +/// with large lists (on target JavaScript). +/// +/// ## Examples +/// +/// ```gleam +/// > transpose([[1, 2, 3], [101, 102, 103]]) +/// [[1, 101], [2, 102], [3, 103]] +/// ``` +/// +pub fn transpose(list_of_list: List(List(a))) -> List(List(a)) { + let take_first = fn(list) { + case list { + [] -> [] + [f] -> [f] + [f, ..] -> [f] + } + } + + case list_of_list { + [] -> [] + [[], ..xss] -> transpose(xss) + rows -> { + let firsts = + rows + |> map(take_first) + |> concat + let rest = transpose(map(rows, drop(_, 1))) + [firsts, ..rest] + } + } +} + +fn do_shuffle_pair_unwrap(list: List(#(Float, a)), acc: List(a)) -> List(a) { + case list { + [] -> acc + [elem_pair, ..enumerable] -> + do_shuffle_pair_unwrap(enumerable, [elem_pair.1, ..acc]) + } +} + +fn do_shuffle_by_pair_indexes( + list_of_pairs: List(#(Float, a)), +) -> List(#(Float, a)) { + sort( + list_of_pairs, + fn(a_pair: #(Float, a), b_pair: #(Float, a)) -> Order { + float.compare(a_pair.0, b_pair.0) + }, + ) +} + +/// Takes a list, randomly sorts all items and returns the shuffled list. +/// +/// This function uses Erlang's `:rand` module or Javascript's +/// `Math.random()` to calculate the index shuffling. +/// +/// ## Example +/// +/// ```gleam +/// > range(1, 10) +/// > |> shuffle() +/// [1, 6, 9, 10, 3, 8, 4, 2, 7, 5] +/// ``` +/// +pub fn shuffle(list: List(a)) -> List(a) { + list + |> fold(from: [], with: fn(acc, a) { [#(float.random(0.0, 1.0), a), ..acc] }) + |> do_shuffle_by_pair_indexes() + |> do_shuffle_pair_unwrap([]) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/map.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/map.gleam new file mode 100644 index 0000000..1f8b228 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/map.gleam @@ -0,0 +1,127 @@ +import gleam/option.{type Option} +import gleam/dict + +@deprecated("Please use the `gleam/dict` module instead") +pub type Map(key, value) = + dict.Dict(key, value) + +@deprecated("Please use the `gleam/dict` module instead") +pub fn size(map) -> Int { + dict.size(map) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn to_list(map) -> List(#(key, value)) { + dict.to_list(map) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn from_list(list: List(#(k, v))) { + dict.from_list(list) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn has_key(map, key: k) -> Bool { + dict.has_key(map, key) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn new() { + dict.new() +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn get(from, get: key) -> Result(value, Nil) { + dict.get(from, get) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn insert(into map, for key: k, insert value: v) { + dict.insert(map, key, value) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn map_values(in map, with fun: fn(k, v) -> w) { + dict.map_values(map, fun) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn keys(map) -> List(keys) { + dict.keys(map) +} + +@target(javascript) +fn reverse_and_concat(remaining, accumulator) { + case remaining { + [] -> accumulator + [item, ..rest] -> reverse_and_concat(rest, [item, ..accumulator]) + } +} + +@target(javascript) +fn do_keys_acc(list: List(#(k, v)), acc: List(k)) -> List(k) { + case list { + [] -> reverse_and_concat(acc, []) + [x, ..xs] -> do_keys_acc(xs, [x.0, ..acc]) + } +} + +@target(javascript) +fn do_keys(map) -> List(k) { + let list_of_pairs = + map + |> to_list + do_keys_acc(list_of_pairs, []) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn values(map) -> List(values) { + dict.values(map) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn filter(in map, keeping predicate: fn(k, v) -> Bool) { + dict.filter(map, predicate) +} + +@target(javascript) +fn do_filter(f: fn(key, value) -> Bool, map) { + let insert = fn(map, k, v) { + case f(k, v) { + True -> insert(map, k, v) + _ -> map + } + } + map + |> fold(from: new(), with: insert) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn take(from map, keeping desired_keys: List(k)) { + dict.take(map, desired_keys) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn merge(into map, from new_entries) { + dict.merge(map, new_entries) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn delete(from map, delete key: k) { + dict.delete(map, key) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn drop(from map, drop disallowed_keys: List(k)) { + dict.drop(map, disallowed_keys) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn update(in map, update key: k, with fun: fn(Option(v)) -> v) { + dict.update(map, key, fun) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn fold(over map, from initial: acc, with fun: fn(acc, k, v) -> acc) -> acc { + dict.fold(map, initial, fun) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/option.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/option.gleam new file mode 100644 index 0000000..6015c0f --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/option.gleam @@ -0,0 +1,346 @@ +/// `Option` represents a value that may be present or not. `Some` means the value is +/// present, `None` means the value is not. +/// +/// This is Gleam's alternative to having a value that could be Null, as is +/// possible in some other languages. +/// +pub type Option(a) { + Some(a) + None +} + +fn do_all(list: List(Option(a)), acc: List(a)) -> Option(List(a)) { + case list { + [] -> Some(acc) + [x, ..rest] -> { + let accumulate = fn(acc, item) { + case acc, item { + Some(values), Some(value) -> Some([value, ..values]) + _, _ -> None + } + } + accumulate(do_all(rest, acc), x) + } + } +} + +/// Combines a list of `Option`s into a single `Option`. +/// If all elements in the list are `Some` then returns a `Some` holding the list of values. +/// If any element is `None` then returns`None`. +/// +/// ## Examples +/// +/// ```gleam +/// > all([Some(1), Some(2)]) +/// Some([1, 2]) +/// ``` +/// +/// ```gleam +/// > all([Some(1), None]) +/// None +/// ``` +/// +pub fn all(list: List(Option(a))) -> Option(List(a)) { + do_all(list, []) +} + +/// Checks whether the `Option` is a `Some` value. +/// +/// ## Examples +/// +/// ```gleam +/// > is_some(Some(1)) +/// True +/// ``` +/// +/// ```gleam +/// > is_some(None) +/// False +/// ``` +/// +pub fn is_some(option: Option(a)) -> Bool { + option != None +} + +/// Checks whether the `Option` is a `None` value. +/// +/// ## Examples +/// +/// ```gleam +/// > is_none(Some(1)) +/// False +/// ``` +/// +/// ```gleam +/// > is_none(None) +/// True +/// ``` +/// +pub fn is_none(option: Option(a)) -> Bool { + option == None +} + +/// Converts an `Option` type to a `Result` type. +/// +/// ## Examples +/// +/// ```gleam +/// > to_result(Some(1), "some_error") +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > to_result(None, "some_error") +/// Error("some_error") +/// ``` +/// +pub fn to_result(option: Option(a), e) -> Result(a, e) { + case option { + Some(a) -> Ok(a) + _ -> Error(e) + } +} + +/// Converts a `Result` type to an `Option` type. +/// +/// ## Examples +/// +/// ```gleam +/// > from_result(Ok(1)) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > from_result(Error("some_error")) +/// None +/// ``` +/// +pub fn from_result(result: Result(a, e)) -> Option(a) { + case result { + Ok(a) -> Some(a) + _ -> None + } +} + +/// Extracts the value from an `Option`, returning a default value if there is none. +/// +/// ## Examples +/// +/// ```gleam +/// > unwrap(Some(1), 0) +/// 1 +/// ``` +/// +/// ```gleam +/// > unwrap(None, 0) +/// 0 +/// ``` +/// +pub fn unwrap(option: Option(a), or default: a) -> a { + case option { + Some(x) -> x + None -> default + } +} + +/// Extracts the value from an `Option`, evaluating the default function if the option is `None`. +/// +/// ## Examples +/// +/// ```gleam +/// > lazy_unwrap(Some(1), fn() { 0 }) +/// 1 +/// ``` +/// +/// ```gleam +/// > lazy_unwrap(None, fn() { 0 }) +/// 0 +/// ``` +/// +pub fn lazy_unwrap(option: Option(a), or default: fn() -> a) -> a { + case option { + Some(x) -> x + None -> default() + } +} + +/// Updates a value held within the `Some` of an `Option` by calling a given function +/// on it. +/// +/// If the `Option` is a `None` rather than `Some`, the function is not called and the +/// `Option` stays the same. +/// +/// ## Examples +/// +/// ```gleam +/// > map(over: Some(1), with: fn(x) { x + 1 }) +/// Some(2) +/// ``` +/// +/// ```gleam +/// > map(over: None, with: fn(x) { x + 1 }) +/// None +/// ``` +/// +pub fn map(over option: Option(a), with fun: fn(a) -> b) -> Option(b) { + case option { + Some(x) -> Some(fun(x)) + None -> None + } +} + +/// Merges a nested `Option` into a single layer. +/// +/// ## Examples +/// +/// ```gleam +/// > flatten(Some(Some(1))) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > flatten(Some(None)) +/// None +/// ``` +/// +/// ```gleam +/// > flatten(None) +/// None +/// ``` +/// +pub fn flatten(option: Option(Option(a))) -> Option(a) { + case option { + Some(x) -> x + None -> None + } +} + +/// Updates a value held within the `Some` of an `Option` by calling a given function +/// on it, where the given function also returns an `Option`. The two options are +/// then merged together into one `Option`. +/// +/// If the `Option` is a `None` rather than `Some` the function is not called and the +/// option stays the same. +/// +/// This function is the equivalent of calling `map` followed by `flatten`, and +/// it is useful for chaining together multiple functions that return `Option`. +/// +/// ## Examples +/// +/// ```gleam +/// > then(Some(1), fn(x) { Some(x + 1) }) +/// Some(2) +/// ``` +/// +/// ```gleam +/// > then(Some(1), fn(x) { Some(#("a", x)) }) +/// Some(#("a", 1)) +/// ``` +/// +/// ```gleam +/// > then(Some(1), fn(_) { None }) +/// None +/// ``` +/// +/// ```gleam +/// > then(None, fn(x) { Some(x + 1) }) +/// None +/// ``` +/// +pub fn then(option: Option(a), apply fun: fn(a) -> Option(b)) -> Option(b) { + case option { + Some(x) -> fun(x) + None -> None + } +} + +/// Returns the first value if it is `Some`, otherwise returns the second value. +/// +/// ## Examples +/// +/// ```gleam +/// > or(Some(1), Some(2)) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > or(Some(1), None) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > or(None, Some(2)) +/// Some(2) +/// ``` +/// +/// ```gleam +/// > or(None, None) +/// None +/// ``` +/// +pub fn or(first: Option(a), second: Option(a)) -> Option(a) { + case first { + Some(_) -> first + None -> second + } +} + +/// Returns the first value if it is `Some`, otherwise evaluates the given function for a fallback value. +/// +/// ## Examples +/// +/// ```gleam +/// > lazy_or(Some(1), fn() { Some(2) }) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > lazy_or(Some(1), fn() { None }) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > lazy_or(None, fn() { Some(2) }) +/// Some(2) +/// ``` +/// +/// ```gleam +/// > lazy_or(None, fn() { None }) +/// None +/// ``` +/// +pub fn lazy_or(first: Option(a), second: fn() -> Option(a)) -> Option(a) { + case first { + Some(_) -> first + None -> second() + } +} + +fn do_values(list: List(Option(a)), acc: List(a)) -> List(a) { + case list { + [] -> acc + [x, ..xs] -> { + let accumulate = fn(acc, item) { + case item { + Some(value) -> [value, ..acc] + None -> acc + } + } + accumulate(do_values(xs, acc), x) + } + } +} + +/// Given a list of `Option`s, +/// returns only the values inside `Some`. +/// +/// ## Examples +/// +/// ```gleam +/// > values([Some(1), None, Some(3)]) +/// [1, 3] +/// ``` +/// +pub fn values(options: List(Option(a))) -> List(a) { + do_values(options, []) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/order.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/order.gleam new file mode 100644 index 0000000..12ce011 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/order.gleam @@ -0,0 +1,133 @@ +/// Represents the result of a single comparison to determine the precise +/// ordering of two values. +/// +pub type Order { + /// Less-than + Lt + + /// Equal + Eq + + /// Greater than + Gt +} + +/// Inverts an order, so less-than becomes greater-than and greater-than +/// becomes less-than. +/// +/// ## Examples +/// +/// ```gleam +/// > negate(Lt) +/// Gt +/// ``` +/// +/// ```gleam +/// > negate(Eq) +/// Eq +/// ``` +/// +/// ```gleam +/// > negate(Lt) +/// Gt +/// ``` +/// +pub fn negate(order: Order) -> Order { + case order { + Lt -> Gt + Eq -> Eq + Gt -> Lt + } +} + +/// Produces a numeric representation of the order. +/// +/// ## Examples +/// +/// ```gleam +/// > to_int(Lt) +/// -1 +/// ``` +/// +/// ```gleam +/// > to_int(Eq) +/// 0 +/// ``` +/// +/// ```gleam +/// > to_int(Gt) +/// 1 +/// ``` +/// +pub fn to_int(order: Order) -> Int { + case order { + Lt -> -1 + Eq -> 0 + Gt -> 1 + } +} + +/// Compares two `Order` values to one another, producing a new `Order`. +/// +/// ## Examples +/// +/// ```gleam +/// > compare(Eq, with: Lt) +/// Gt +/// ``` +/// +pub fn compare(a: Order, with b: Order) -> Order { + case a, b { + x, y if x == y -> Eq + Lt, _ | Eq, Gt -> Lt + _, _ -> Gt + } +} + +/// Returns the largest of two orders given that `Gt > Eq > Lt`. +/// +/// ## Examples +/// +/// ```gleam +/// > max(Eq, Lt) +/// Eq +/// ``` +/// +pub fn max(a: Order, b: Order) -> Order { + case a, b { + Gt, _ -> Gt + Eq, Lt -> Eq + _, _ -> b + } +} + +/// Returns the smallest of two orders given that `Gt > Eq > Lt`. +/// +/// ## Examples +/// +/// ```gleam +/// > min(Eq, Lt) +/// Lt +/// ``` +/// +pub fn min(a: Order, b: Order) -> Order { + case a, b { + Lt, _ -> Lt + Eq, Gt -> Eq + _, _ -> b + } +} + +/// Inverts an ordering function, so less-than becomes greater-than and greater-than +/// becomes less-than. +/// +/// ## Examples +/// +/// ```gleam +/// > list.sort([1, 5, 4], by: reverse(int.compare)) +/// [5, 4, 1] +/// ``` +/// +pub fn reverse(orderer: fn(a, a) -> Order) -> fn(a, a) -> Order { + fn(a, b) { orderer(b, a) } +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/pair.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/pair.gleam new file mode 100644 index 0000000..894e6a8 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/pair.gleam @@ -0,0 +1,85 @@ +/// Returns the first element in a pair. +/// +/// ## Examples +/// +/// ```gleam +/// > first(#(1, 2)) +/// 1 +/// ``` +/// +pub fn first(pair: #(a, b)) -> a { + let #(a, _) = pair + a +} + +/// Returns the second element in a pair. +/// +/// ## Examples +/// +/// ```gleam +/// > second(#(1, 2)) +/// 2 +/// ``` +/// +pub fn second(pair: #(a, b)) -> b { + let #(_, a) = pair + a +} + +/// Returns a new pair with the elements swapped. +/// +/// ## Examples +/// +/// ```gleam +/// > swap(#(1, 2)) +/// #(2, 1) +/// ``` +/// +pub fn swap(pair: #(a, b)) -> #(b, a) { + let #(a, b) = pair + #(b, a) +} + +/// Returns a new pair with the first element having had `with` applied to +/// it. +/// +/// ## Examples +/// +/// ```gleam +/// > #(1, 2) |> map_first(fn(n) { n * 2 }) +/// #(2, 2) +/// ``` +/// +pub fn map_first(of pair: #(a, b), with fun: fn(a) -> c) -> #(c, b) { + let #(a, b) = pair + #(fun(a), b) +} + +/// Returns a new pair with the second element having had `with` applied to +/// it. +/// +/// ## Examples +/// +/// ```gleam +/// > #(1, 2) |> map_second(fn(n) { n * 2 }) +/// #(1, 4) +/// ``` +/// +pub fn map_second(of pair: #(a, b), with fun: fn(b) -> c) -> #(a, c) { + let #(a, b) = pair + #(a, fun(b)) +} + +/// Returns a new pair with the given elements. This can also be done using the dedicated +/// syntax instead: `new(1, 2) == #(1, 2)`. +/// +/// ## Examples +/// +/// ```gleam +/// > new(1, 2) +/// #(1, 2) +/// ``` +/// +pub fn new(first: a, second: b) -> #(a, b) { + #(first, second) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/queue.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/queue.gleam new file mode 100644 index 0000000..5bf60c8 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/queue.gleam @@ -0,0 +1,292 @@ +import gleam/list + +/// A queue is an ordered collection of elements. It is similar to a list, but +/// unlike a list elements can be added to or removed from either the front or +/// the back in a performant fashion. +/// +/// The internal representation may be different for two queues with the same +/// elements in the same order if the queues were constructed in different +/// ways. This is the price paid for a queue's fast access at both the front +/// and the back. +/// +/// Because of unpredictable internal representation the equality operator `==` +/// may return surprising results, and the `is_equal` and `is_logically_equal` +/// functions are the recommended way to test queues for equality. +/// +pub opaque type Queue(element) { + Queue(in: List(element), out: List(element)) +} + +/// Creates a fresh queue that contains no values. +/// +pub fn new() -> Queue(a) { + Queue(in: [], out: []) +} + +/// Converts a list of elements into a queue of the same elements in the same +/// order. The first element in the list becomes the front element in the queue. +/// +/// This function runs in constant time. +/// +/// # Examples +/// +/// ```gleam +/// > [1, 2, 3] |> from_list |> length +/// 3 +/// ``` +/// +pub fn from_list(list: List(a)) -> Queue(a) { + Queue(in: [], out: list) +} + +/// Converts a queue of elements into a list of the same elements in the same +/// order. The front element in the queue becomes the first element in the list. +/// +/// This function runs in linear time. +/// +/// # Examples +/// +/// ```gleam +/// > new() |> push_back(1) |> push_back(2) |> to_list +/// [1, 2] +/// ``` +/// +pub fn to_list(queue: Queue(a)) -> List(a) { + queue.out + |> list.append(list.reverse(queue.in)) +} + +/// Determines whether or not the queue is empty. +/// +/// This function runs in constant time. +/// +/// ## Examples +/// +/// ```gleam +/// > [] |> from_list |> is_empty +/// True +/// ``` +/// +/// ```gleam +/// > [1] |> from_list |> is_empty +/// False +/// ``` +/// +/// ```gleam +/// > [1, 2] |> from_list |> is_empty +/// False +/// ``` +/// +pub fn is_empty(queue: Queue(a)) -> Bool { + queue.in == [] && queue.out == [] +} + +/// Counts the number of elements in a given queue. +/// +/// This function has to traverse the queue to determine the number of elements, +/// so it runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > length(from_list([])) +/// 0 +/// ``` +/// +/// ```gleam +/// > length(from_list([1])) +/// 1 +/// ``` +/// +/// ```gleam +/// > length(from_list([1, 2])) +/// 2 +/// ``` +/// +pub fn length(queue: Queue(a)) -> Int { + list.length(queue.in) + list.length(queue.out) +} + +/// Pushes an element onto the back of the queue. +/// +/// # Examples +/// +/// ```gleam +/// > [1, 2] |> from_list |> push_back(3) |> to_list +/// [1, 2, 3] +/// ``` +/// +pub fn push_back(onto queue: Queue(a), this item: a) -> Queue(a) { + Queue(in: [item, ..queue.in], out: queue.out) +} + +/// Pushes an element onto the front of the queue. +/// +/// # Examples +/// +/// ```gleam +/// > [0, 0] |> from_list |> push_front(1) |> to_list +/// [1, 0, 0] +/// ``` +/// +pub fn push_front(onto queue: Queue(a), this item: a) -> Queue(a) { + Queue(in: queue.in, out: [item, ..queue.out]) +} + +/// Gets the last element from the queue, returning the +/// element and a new queue without that element. +/// +/// This function typically runs in constant time, but will occasionally run in +/// linear time. +/// +/// # Examples +/// +/// ```gleam +/// > new() +/// > |> push_back(0) +/// > |> push_back(1) +/// > |> pop_back() +/// Ok(#(1, push_front(new(), 0))) +/// ``` +/// +/// ```gleam +/// > new() +/// > |> push_front(0) +/// > |> pop_back() +/// Ok(#(0, new())) +/// ``` +/// +/// ```gleam +/// > new() +/// > |> pop_back() +/// Error(Nil) +/// ``` +/// +pub fn pop_back(from queue: Queue(a)) -> Result(#(a, Queue(a)), Nil) { + case queue { + Queue(in: [], out: []) -> Error(Nil) + Queue(in: [], out: out) -> pop_back(Queue(in: list.reverse(out), out: [])) + Queue(in: [first, ..rest], out: out) -> { + let queue = Queue(in: rest, out: out) + Ok(#(first, queue)) + } + } +} + +/// Gets the first element from the queue, returning the +/// element and a new queue without that element. +/// +/// This function typically runs in constant time, but will occasionally run in +/// linear time. +/// +/// # Examples +/// +/// ```gleam +/// > queue.new() +/// > |> queue.push_front(1) +/// > |> queue.push_front(0) +/// > |> queue.pop_front() +/// Ok(#(0, queue.push_back(queue.new(), 1))) +/// ``` +/// +/// ```gleam +/// > queue.new() +/// > |> queue.push_back(0) +/// > |> queue.pop_front() +/// Ok(#(0, queue.new())) +/// ``` +/// +/// ```gleam +/// > queue.new() +/// > |> queue.pop_back() +/// Error(Nil) +/// ``` +/// +pub fn pop_front(from queue: Queue(a)) -> Result(#(a, Queue(a)), Nil) { + case queue { + Queue(in: [], out: []) -> Error(Nil) + Queue(in: in, out: []) -> pop_front(Queue(in: [], out: list.reverse(in))) + Queue(in: in, out: [first, ..rest]) -> { + let queue = Queue(in: in, out: rest) + Ok(#(first, queue)) + } + } +} + +/// Creates a new queue from a given queue containing the same elements, but in +/// the opposite order. +/// +/// This function runs in constant time. +/// +/// ## Examples +/// +/// ```gleam +/// > [] |> from_list |> reverse |> to_list +/// [] +/// ``` +/// +/// ```gleam +/// > [1] |> from_list |> reverse |> to_list +/// [1] +/// ``` +/// +/// ```gleam +/// > [1, 2] |> from_list |> reverse |> to_list +/// [2, 1] +/// ``` +/// +pub fn reverse(queue: Queue(a)) -> Queue(a) { + Queue(in: queue.out, out: queue.in) +} + +fn check_equal( + xs: List(t), + x_tail: List(t), + ys: List(t), + y_tail: List(t), + eq: fn(t, t) -> Bool, +) -> Bool { + case xs, x_tail, ys, y_tail { + [], [], [], [] -> True + [x, ..xs], _, [y, ..ys], _ -> + case eq(x, y) { + False -> False + True -> check_equal(xs, x_tail, ys, y_tail, eq) + } + [], [_, ..], _, _ -> check_equal(list.reverse(x_tail), [], ys, y_tail, eq) + _, _, [], [_, ..] -> check_equal(xs, x_tail, list.reverse(y_tail), [], eq) + _, _, _, _ -> False + } +} + +/// Checks whether two queues have equal elements in the same order, where the +/// equality of elements is determined by a given equality checking function. +/// +/// This function is useful as the internal representation may be different for +/// two queues with the same elements in the same order depending on how they +/// were constructed, so the equality operator `==` may return surprising +/// results. +/// +/// This function runs in linear time multiplied by the time taken by the +/// element equality checking function. +/// +pub fn is_logically_equal( + a: Queue(t), + to b: Queue(t), + checking element_is_equal: fn(t, t) -> Bool, +) -> Bool { + check_equal(a.out, a.in, b.out, b.in, element_is_equal) +} + +/// Checks whether two queues have the same elements in the same order. +/// +/// This function is useful as the internal representation may be different for +/// two queues with the same elements in the same order depending on how they +/// were constructed, so the equality operator `==` may return surprising +/// results. +/// +/// This function runs in linear time. +/// +pub fn is_equal(a: Queue(t), to b: Queue(t)) -> Bool { + check_equal(a.out, a.in, b.out, b.in, fn(a, b) { a == b }) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/regex.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/regex.gleam new file mode 100644 index 0000000..9ffda78 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/regex.gleam @@ -0,0 +1,214 @@ +//// This module contains regular expression matching functions for strings. +//// The matching algorithms of the library are based on the PCRE library, but not +//// all of the PCRE library is interfaced and some parts of the library go beyond +//// what PCRE offers. Currently PCRE version 8.40 (release date 2017-01-11) is used. + +import gleam/option.{type Option} + +pub type Regex + +/// The details about a particular match: +/// +pub type Match { + Match( + /// The full string of the match. + content: String, + /// A `Regex` can have subpatterns, sup-parts that are in parentheses. + submatches: List(Option(String)), + ) +} + +/// When a regular expression fails to compile: +/// +pub type CompileError { + CompileError( + /// The problem encountered that caused the compilation to fail + error: String, + /// The byte index into the string to where the problem was found + /// This value may not be correct in JavaScript environments. + byte_index: Int, + ) +} + +pub type Options { + Options(case_insensitive: Bool, multi_line: Bool) +} + +/// Creates a `Regex` with some additional options. +/// +/// ## Examples +/// +/// ```gleam +/// > let options = Options(case_insensitive: False, multi_line: True) +/// > let assert Ok(re) = compile("^[0-9]", with: options) +/// > check(re, "abc\n123") +/// True +/// ``` +/// +/// ```gleam +/// > let options = Options(case_insensitive: True, multi_line: False) +/// > let assert Ok(re) = compile("[A-Z]", with: options) +/// > check(re, "abc123") +/// True +/// ``` +/// +pub fn compile( + pattern: String, + with options: Options, +) -> Result(Regex, CompileError) { + do_compile(pattern, options) +} + +@external(erlang, "gleam_stdlib", "compile_regex") +@external(javascript, "../gleam_stdlib.mjs", "compile_regex") +fn do_compile(a: String, with with: Options) -> Result(Regex, CompileError) + +/// Creates a new `Regex`. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Ok(re) = from_string("[0-9]") +/// > check(re, "abc123") +/// True +/// ``` +/// +/// ```gleam +/// > check(re, "abcxyz") +/// False +/// ``` +/// +/// ```gleam +/// > from_string("[0-9") +/// Error( +/// CompileError( +/// error: "missing terminating ] for character class", +/// byte_index: 4 +/// ) +/// ) +/// ``` +/// +pub fn from_string(pattern: String) -> Result(Regex, CompileError) { + compile(pattern, Options(case_insensitive: False, multi_line: False)) +} + +/// Returns a boolean indicating whether there was a match or not. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Ok(re) = from_string("^f.o.?") +/// > check(with: re, content: "foo") +/// True +/// ``` +/// +/// ```gleam +/// > check(with: re, content: "boo") +/// False +/// ``` +/// +pub fn check(with regex: Regex, content content: String) -> Bool { + do_check(regex, content) +} + +@external(erlang, "gleam_stdlib", "regex_check") +@external(javascript, "../gleam_stdlib.mjs", "regex_check") +fn do_check(a: Regex, b: String) -> Bool + +/// Splits a string. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Ok(re) = from_string(" *, *") +/// > split(with: re, content: "foo,32, 4, 9 ,0") +/// ["foo", "32", "4", "9", "0"] +/// ``` +/// +pub fn split(with regex: Regex, content string: String) -> List(String) { + do_split(regex, string) +} + +@target(erlang) +@external(erlang, "gleam_stdlib", "regex_split") +fn do_split(a: Regex, b: String) -> List(String) + +@target(javascript) +fn do_split(regex, string) -> List(String) { + js_split(string, regex) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "split") +fn js_split(a: String, b: Regex) -> List(String) + +/// Collects all matches of the regular expression. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Ok(re) = from_string("[oi]n a (\\w+)") +/// > scan(with: re, content: "I am on a boat in a lake.") +/// [ +/// Match( +/// content: "on a boat", +/// submatches: [Some("boat")] +/// ), +/// Match( +/// content: "in a lake", +/// submatches: [Some("lake")] +/// ) +/// ] +/// ``` +/// +/// ```gleam +/// > let assert Ok(re) = regex.from_string("([+|\\-])?(\\d+)(\\w+)?") +/// > scan(with: re, content: "-36") +/// [ +/// Match( +/// content: "-36", +/// submatches: [Some("-"), Some("36")] +/// ) +/// ] +/// +/// > scan(with: re, content: "36") +/// [ +/// Match( +/// content: "36", +/// submatches: [None, Some("36")] +/// ) +/// ] +/// ``` +/// +/// ```gleam +/// > let assert Ok(re) = regex.from_string("var\\s*(\\w+)\\s*(int|string)?\\s*=\\s*(.*)") +/// > scan(with: re, content: "var age = 32") +/// [ +/// Match( +/// content: "var age = 32", +/// submatches: [Some("age"), None, Some("32")] +/// ) +/// ] +/// ``` +/// +/// ```gleam +/// > let assert Ok(re) = regex.from_string("let (\\w+) = (\\w+)") +/// > scan(with: re, content: "let age = 32") +/// [ +/// Match( +/// content: "let age = 32", +/// submatches: [Some("age"), Some("32")] +/// ) +/// ] +/// +/// > scan(with: re, content: "const age = 32") +/// [] +/// ``` +/// +pub fn scan(with regex: Regex, content string: String) -> List(Match) { + do_scan(regex, string) +} + +@external(erlang, "gleam_stdlib", "regex_scan") +@external(javascript, "../gleam_stdlib.mjs", "regex_scan") +fn do_scan(a: Regex, b: String) -> List(Match) diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/result.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/result.gleam new file mode 100644 index 0000000..fb6dddb --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/result.gleam @@ -0,0 +1,482 @@ +//// Result represents the result of something that may succeed or not. +//// `Ok` means it was successful, `Error` means it was not successful. + +import gleam/list + +/// Checks whether the result is an `Ok` value. +/// +/// ## Examples +/// +/// ```gleam +/// > is_ok(Ok(1)) +/// True +/// ``` +/// +/// ```gleam +/// > is_ok(Error(Nil)) +/// False +/// ``` +/// +pub fn is_ok(result: Result(a, e)) -> Bool { + case result { + Error(_) -> False + Ok(_) -> True + } +} + +/// Checks whether the result is an `Error` value. +/// +/// ## Examples +/// +/// ```gleam +/// > is_error(Ok(1)) +/// False +/// ``` +/// +/// ```gleam +/// > is_error(Error(Nil)) +/// True +/// ``` +/// +pub fn is_error(result: Result(a, e)) -> Bool { + case result { + Ok(_) -> False + Error(_) -> True + } +} + +/// Updates a value held within the `Ok` of a result by calling a given function +/// on it. +/// +/// If the result is an `Error` rather than `Ok` the function is not called and the +/// result stays the same. +/// +/// ## Examples +/// +/// ```gleam +/// > map(over: Ok(1), with: fn(x) { x + 1 }) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > map(over: Error(1), with: fn(x) { x + 1 }) +/// Error(1) +/// ``` +/// +pub fn map(over result: Result(a, e), with fun: fn(a) -> b) -> Result(b, e) { + case result { + Ok(x) -> Ok(fun(x)) + Error(e) -> Error(e) + } +} + +/// Updates a value held within the `Error` of a result by calling a given function +/// on it. +/// +/// If the result is `Ok` rather than `Error` the function is not called and the +/// result stays the same. +/// +/// ## Examples +/// +/// ```gleam +/// > map_error(over: Error(1), with: fn(x) { x + 1 }) +/// Error(2) +/// ``` +/// +/// ```gleam +/// > map_error(over: Ok(1), with: fn(x) { x + 1 }) +/// Ok(1) +/// ``` +/// +pub fn map_error( + over result: Result(a, e), + with fun: fn(e) -> f, +) -> Result(a, f) { + case result { + Ok(x) -> Ok(x) + Error(error) -> Error(fun(error)) + } +} + +/// Merges a nested `Result` into a single layer. +/// +/// ## Examples +/// +/// ```gleam +/// > flatten(Ok(Ok(1))) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > flatten(Ok(Error(""))) +/// Error("") +/// ``` +/// +/// ```gleam +/// > flatten(Error(Nil)) +/// Error(Nil) +/// ``` +/// +pub fn flatten(result: Result(Result(a, e), e)) -> Result(a, e) { + case result { + Ok(x) -> x + Error(error) -> Error(error) + } +} + +/// "Updates" an `Ok` result by passing its value to a function that yields a result, +/// and returning the yielded result. (This may "replace" the `Ok` with an `Error`.) +/// +/// If the input is an `Error` rather than an `Ok`, the function is not called and +/// the original `Error` is returned. +/// +/// This function is the equivalent of calling `map` followed by `flatten`, and +/// it is useful for chaining together multiple functions that may fail. +/// +/// ## Examples +/// +/// ```gleam +/// > try(Ok(1), fn(x) { Ok(x + 1) }) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > try(Ok(1), fn(x) { Ok(#("a", x)) }) +/// Ok(#("a", 1)) +/// ``` +/// +/// ```gleam +/// > try(Ok(1), fn(_) { Error("Oh no") }) +/// Error("Oh no") +/// ``` +/// +/// ```gleam +/// > try(Error(Nil), fn(x) { Ok(x + 1) }) +/// Error(Nil) +/// ``` +/// +pub fn try( + result: Result(a, e), + apply fun: fn(a) -> Result(b, e), +) -> Result(b, e) { + case result { + Ok(x) -> fun(x) + Error(e) -> Error(e) + } +} + +/// An alias for `try`. See the documentation for that function for more information. +/// +pub fn then( + result: Result(a, e), + apply fun: fn(a) -> Result(b, e), +) -> Result(b, e) { + try(result, fun) +} + +/// Extracts the `Ok` value from a result, returning a default value if the result +/// is an `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > unwrap(Ok(1), 0) +/// 1 +/// ``` +/// +/// ```gleam +/// > unwrap(Error(""), 0) +/// 0 +/// ``` +/// +pub fn unwrap(result: Result(a, e), or default: a) -> a { + case result { + Ok(v) -> v + Error(_) -> default + } +} + +/// Extracts the `Ok` value from a result, evaluating the default function if the result +/// is an `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > lazy_unwrap(Ok(1), fn() { 0 }) +/// 1 +/// ``` +/// +/// ```gleam +/// > lazy_unwrap(Error(""), fn() { 0 }) +/// 0 +/// ``` +/// +pub fn lazy_unwrap(result: Result(a, e), or default: fn() -> a) -> a { + case result { + Ok(v) -> v + Error(_) -> default() + } +} + +/// Extracts the `Error` value from a result, returning a default value if the result +/// is an `Ok`. +/// +/// ## Examples +/// +/// ```gleam +/// > unwrap_error(Error(1), 0) +/// 1 +/// ``` +/// +/// ```gleam +/// > unwrap_error(Ok(""), 0) +/// 0 +/// ``` +/// +pub fn unwrap_error(result: Result(a, e), or default: e) -> e { + case result { + Ok(_) -> default + Error(e) -> e + } +} + +/// Extracts the inner value from a result. Both the value and error must be of +/// the same type. +/// +/// ## Examples +/// +/// ```gleam +/// > unwrap_both(Error(1)) +/// 1 +/// ``` +/// +/// ```gleam +/// > unwrap_both(Ok(2)) +/// 2 +/// ``` +/// +pub fn unwrap_both(result: Result(a, a)) -> a { + case result { + Ok(a) -> a + Error(a) -> a + } +} + +/// Transforms any error into `Error(Nil)`. +/// +/// ## Examples +/// +/// ```gleam +/// > nil_error(Error(1)) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > nil_error(Ok(1)) +/// Ok(1) +/// ``` +/// +pub fn nil_error(result: Result(a, e)) -> Result(a, Nil) { + map_error(result, fn(_) { Nil }) +} + +/// Returns the first value if it is `Ok`, otherwise returns the second value. +/// +/// ## Examples +/// +/// ```gleam +/// > or(Ok(1), Ok(2)) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > or(Ok(1), Error("Error 2")) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > or(Error("Error 1"), Ok(2)) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > or(Error("Error 1"), Error("Error 2")) +/// Error("Error 2") +/// ``` +/// +pub fn or(first: Result(a, e), second: Result(a, e)) -> Result(a, e) { + case first { + Ok(_) -> first + Error(_) -> second + } +} + +/// Returns the first value if it is `Ok`, otherwise evaluates the given function for a fallback value. +/// +/// ## Examples +/// +/// ```gleam +/// > lazy_or(Ok(1), fn() { Ok(2) }) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > lazy_or(Ok(1), fn() { Error("Error 2") }) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > lazy_or(Error("Error 1"), fn() { Ok(2) }) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > lazy_or(Error("Error 1"), fn() { Error("Error 2") }) +/// Error("Error 2") +/// ``` +/// +pub fn lazy_or( + first: Result(a, e), + second: fn() -> Result(a, e), +) -> Result(a, e) { + case first { + Ok(_) -> first + Error(_) -> second() + } +} + +/// Combines a list of results into a single result. +/// If all elements in the list are `Ok` then returns an `Ok` holding the list of values. +/// If any element is `Error` then returns the first error. +/// +/// ## Examples +/// +/// ```gleam +/// > all([Ok(1), Ok(2)]) +/// Ok([1, 2]) +/// ``` +/// +/// ```gleam +/// > all([Ok(1), Error("e")]) +/// Error("e") +/// ``` +/// +pub fn all(results: List(Result(a, e))) -> Result(List(a), e) { + list.try_map(results, fn(x) { x }) +} + +/// Given a list of results, returns a pair where the first element is a list +/// of all the values inside `Ok` and the second element is a list with all the +/// values inside `Error`. The values in both lists appear in reverse order with +/// respect to their position in the original list of results. +/// +/// ## Examples +/// +/// ```gleam +/// > partition([Ok(1), Error("a"), Error("b"), Ok(2)]) +/// #([2, 1], ["b", "a"]) +/// ``` +/// +pub fn partition(results: List(Result(a, e))) -> #(List(a), List(e)) { + do_partition(results, [], []) +} + +fn do_partition(results: List(Result(a, e)), oks: List(a), errors: List(e)) { + case results { + [] -> #(oks, errors) + [Ok(a), ..rest] -> do_partition(rest, [a, ..oks], errors) + [Error(e), ..rest] -> do_partition(rest, oks, [e, ..errors]) + } +} + +/// Replace the value within a result +/// +/// ## Examples +/// +/// ```gleam +/// > replace(Ok(1), Nil) +/// Ok(Nil) +/// ``` +/// +/// ```gleam +/// > replace(Error(1), Nil) +/// Error(1) +/// ``` +/// +pub fn replace(result: Result(a, e), value: b) -> Result(b, e) { + case result { + Ok(_) -> Ok(value) + Error(error) -> Error(error) + } +} + +/// Replace the error within a result +/// +/// ## Examples +/// +/// ```gleam +/// > replace_error(Error(1), Nil) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > replace_error(Ok(1), Nil) +/// Ok(1) +/// ``` +/// +pub fn replace_error(result: Result(a, e1), error: e2) -> Result(a, e2) { + case result { + Ok(x) -> Ok(x) + Error(_) -> Error(error) + } +} + +/// Given a list of results, returns only the values inside `Ok`. +/// +/// ## Examples +/// +/// ```gleam +/// > values([Ok(1), Error("a"), Ok(3)]) +/// [1, 3] +/// ``` +/// +pub fn values(results: List(Result(a, e))) -> List(a) { + list.filter_map(results, fn(r) { r }) +} + +/// Updates a value held within the `Error` of a result by calling a given function +/// on it, where the given function also returns a result. The two results are +/// then merged together into one result. +/// +/// If the result is an `Ok` rather than `Error` the function is not called and the +/// result stays the same. +/// +/// This function is useful for chaining together computations that may fail +/// and trying to recover from possible errors. +/// +/// ## Examples +/// +/// ```gleam +/// > Ok(1) |> try_recover(with: fn(_) { Error("failed to recover") }) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > Error(1) |> try_recover(with: fn(error) { Ok(error + 1) }) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > Error(1) |> try_recover(with: fn(error) { Error("failed to recover") }) +/// Error("failed to recover") +/// ``` +/// +pub fn try_recover( + result: Result(a, e), + with fun: fn(e) -> Result(a, f), +) -> Result(a, f) { + case result { + Ok(value) -> Ok(value) + Error(error) -> fun(error) + } +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/set.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/set.gleam new file mode 100644 index 0000000..df8d500 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/set.gleam @@ -0,0 +1,264 @@ +import gleam/list +import gleam/dict.{type Dict} +import gleam/result + +// A list is used as the map value as an empty list has the smallest +// representation in Erlang's binary format +@target(erlang) +type Token = + List(Nil) + +@target(erlang) +const token = [] + +@target(javascript) +type Token = + Nil + +@target(javascript) +const token = Nil + +/// A set is a collection of unique members of the same type. +/// +/// It is implemented using the `gleam/map` module, so inserts and lookups have +/// logarithmic time complexity. +/// +pub opaque type Set(member) { + Set(map: Dict(member, Token)) +} + +/// Creates a new empty set. +/// +pub fn new() -> Set(member) { + Set(dict.new()) +} + +/// Gets the number of members in a set. +/// +/// This function runs in constant time. +/// +/// ## Examples +/// +/// ```gleam +/// > new() +/// > |> insert(1) +/// > |> insert(2) +/// > |> size +/// 2 +/// ``` +/// +pub fn size(set: Set(member)) -> Int { + dict.size(set.map) +} + +/// Inserts an member into the set. +/// +/// This function runs in logarithmic time. +/// +/// ## Examples +/// +/// ```gleam +/// > new() +/// > |> insert(1) +/// > |> insert(2) +/// > |> size +/// 2 +/// ``` +/// +pub fn insert(into set: Set(member), this member: member) -> Set(member) { + Set(map: dict.insert(set.map, member, token)) +} + +/// Checks whether a set contains a given member. +/// +/// This function runs in logarithmic time. +/// +/// ## Examples +/// +/// ```gleam +/// > new() +/// > |> insert(2) +/// > |> contains(2) +/// True +/// ``` +/// +/// ```gleam +/// > new() +/// > |> insert(2) +/// > |> contains(1) +/// False +/// ``` +/// +pub fn contains(in set: Set(member), this member: member) -> Bool { + set.map + |> dict.get(member) + |> result.is_ok +} + +/// Removes a member from a set. If the set does not contain the member then +/// the set is returned unchanged. +/// +/// This function runs in logarithmic time. +/// +/// ## Examples +/// +/// ```gleam +/// > new() +/// > |> insert(2) +/// > |> delete(2) +/// > |> contains(1) +/// False +/// ``` +/// +pub fn delete(from set: Set(member), this member: member) -> Set(member) { + Set(map: dict.delete(set.map, member)) +} + +/// Converts the set into a list of the contained members. +/// +/// The list has no specific ordering, any unintentional ordering may change in +/// future versions of Gleam or Erlang. +/// +/// This function runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> insert(2) |> to_list +/// [2] +/// ``` +/// +pub fn to_list(set: Set(member)) -> List(member) { + dict.keys(set.map) +} + +/// Creates a new set of the members in a given list. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/list +/// > [1, 1, 2, 4, 3, 2] |> from_list |> to_list |> list.sort +/// [1, 3, 3, 4] +/// ``` +/// +pub fn from_list(members: List(member)) -> Set(member) { + let map = + list.fold( + over: members, + from: dict.new(), + with: fn(m, k) { dict.insert(m, k, token) }, + ) + Set(map) +} + +/// Combines all entries into a single value by calling a given function on each +/// one. +/// +/// Sets are not ordered so the values are not returned in any specific order. +/// Do not write code that relies on the order entries are used by this +/// function as it may change in later versions of Gleam or Erlang. +/// +/// # Examples +/// +/// ```gleam +/// > from_list([1, 3, 9]) +/// > |> fold(0, fn(member, accumulator) { accumulator + member }) +/// 13 +/// ``` +/// +pub fn fold( + over set: Set(member), + from initial: acc, + with reducer: fn(acc, member) -> acc, +) -> acc { + dict.fold(over: set.map, from: initial, with: fn(a, k, _) { reducer(a, k) }) +} + +/// Creates a new set from an existing set, minus any members that a given +/// function returns `False` for. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/int +/// > from_list([1, 4, 6, 3, 675, 44, 67]) +/// > |> filter(for: int.is_even) +/// > |> to_list +/// [4, 6, 44] +/// ``` +/// +pub fn filter( + in set: Set(member), + keeping predicate: fn(member) -> Bool, +) -> Set(member) { + Set(dict.filter(in: set.map, keeping: fn(m, _) { predicate(m) })) +} + +pub fn drop(from set: Set(member), drop disallowed: List(member)) -> Set(member) { + list.fold(over: disallowed, from: set, with: delete) +} + +/// Creates a new map from a given map, only including any members which are in +/// a given list. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3]) +/// > |> take([1, 3, 5]) +/// > |> to_list +/// [1, 3] +/// ``` +/// +pub fn take(from set: Set(member), keeping desired: List(member)) -> Set(member) { + Set(dict.take(from: set.map, keeping: desired)) +} + +fn order(first: Set(member), second: Set(member)) -> #(Set(member), Set(member)) { + case dict.size(first.map) > dict.size(second.map) { + True -> #(first, second) + False -> #(second, first) + } +} + +/// Creates a new set that contains all members of both given sets. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > union(from_list([1, 2]), from_list([2, 3])) |> to_list +/// [1, 2, 3] +/// ``` +/// +pub fn union(of first: Set(member), and second: Set(member)) -> Set(member) { + let #(larger, smaller) = order(first, second) + fold(over: smaller, from: larger, with: insert) +} + +/// Creates a new set that contains members that are present in both given sets. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > intersection(from_list([1, 2]), from_list([2, 3])) |> to_list +/// [2] +/// ``` +/// +pub fn intersection( + of first: Set(member), + and second: Set(member), +) -> Set(member) { + let #(larger, smaller) = order(first, second) + take(from: larger, keeping: to_list(smaller)) +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/string.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/string.gleam new file mode 100644 index 0000000..d4496f3 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/string.gleam @@ -0,0 +1,906 @@ +//// Strings in Gleam are UTF-8 binaries. They can be written in your code as +//// text surrounded by `"double quotes"`. + +import gleam/iterator.{type Iterator} +import gleam/list +import gleam/option.{type Option, None, Some} +import gleam/order +import gleam/string_builder.{type StringBuilder} + +/// Determines if a `String` is empty. +/// +/// ## Examples +/// +/// ```gleam +/// > is_empty("") +/// True +/// ``` +/// +/// ```gleam +/// > is_empty("the world") +/// False +/// ``` +/// +pub fn is_empty(str: String) -> Bool { + str == "" +} + +/// Gets the number of grapheme clusters in a given `String`. +/// +/// This function has to iterate across the whole string to count the number of +/// graphemes, so it runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > length("Gleam") +/// 5 +/// ``` +/// +/// ```gleam +/// > length("ß↑e̊") +/// 3 +/// ``` +/// +/// ```gleam +/// > length("") +/// 0 +/// ``` +/// +pub fn length(string: String) -> Int { + do_length(string) +} + +@external(erlang, "string", "length") +@external(javascript, "../gleam_stdlib.mjs", "string_length") +fn do_length(a: String) -> Int + +/// Reverses a `String`. +/// +/// This function has to iterate across the whole `String` so it runs in linear +/// time. +/// +/// ## Examples +/// +/// ```gleam +/// > reverse("stressed") +/// "desserts" +/// ``` +/// +pub fn reverse(string: String) -> String { + do_reverse(string) +} + +@target(erlang) +fn do_reverse(string: String) -> String { + string + |> string_builder.from_string + |> string_builder.reverse + |> string_builder.to_string +} + +@target(javascript) +fn do_reverse(string: String) -> String { + string + |> to_graphemes + |> list.reverse + |> concat +} + +/// Creates a new `String` by replacing all occurrences of a given substring. +/// +/// ## Examples +/// +/// ```gleam +/// > replace("www.example.com", each: ".", with: "-") +/// "www-example-com" +/// ``` +/// +/// ```gleam +/// > replace("a,b,c,d,e", each: ",", with: "/") +/// "a/b/c/d/e" +/// ``` +/// +pub fn replace( + in string: String, + each pattern: String, + with substitute: String, +) -> String { + string + |> string_builder.from_string + |> string_builder.replace(each: pattern, with: substitute) + |> string_builder.to_string +} + +/// Creates a new `String` with all the graphemes in the input `String` converted to +/// lowercase. +/// +/// Useful for case-insensitive comparisons. +/// +/// ## Examples +/// +/// ```gleam +/// > lowercase("X-FILES") +/// "x-files" +/// ``` +/// +pub fn lowercase(string: String) -> String { + do_lowercase(string) +} + +@external(erlang, "string", "lowercase") +@external(javascript, "../gleam_stdlib.mjs", "lowercase") +fn do_lowercase(a: String) -> String + +/// Creates a new `String` with all the graphemes in the input `String` converted to +/// uppercase. +/// +/// Useful for case-insensitive comparisons and VIRTUAL YELLING. +/// +/// ## Examples +/// +/// ```gleam +/// > uppercase("skinner") +/// "SKINNER" +/// ``` +/// +pub fn uppercase(string: String) -> String { + do_uppercase(string) +} + +@external(erlang, "string", "uppercase") +@external(javascript, "../gleam_stdlib.mjs", "uppercase") +fn do_uppercase(a: String) -> String + +/// Compares two `String`s to see which is "larger" by comparing their graphemes. +/// +/// This does not compare the size or length of the given `String`s. +/// +/// ## Examples +/// +/// ```gleam +/// > compare("Anthony", "Anthony") +/// order.Eq +/// ``` +/// +/// ```gleam +/// > compare("A", "B") +/// order.Lt +/// ``` +/// +pub fn compare(a: String, b: String) -> order.Order { + case a == b { + True -> order.Eq + _ -> + case less_than(a, b) { + True -> order.Lt + _ -> order.Gt + } + } +} + +@external(erlang, "gleam_stdlib", "less_than") +@external(javascript, "../gleam_stdlib.mjs", "less_than") +fn less_than(a: String, b: String) -> Bool + +/// Takes a substring given a start grapheme index and a length. Negative indexes +/// are taken starting from the *end* of the list. +/// +/// ## Examples +/// +/// ```gleam +/// > slice(from: "gleam", at_index: 1, length: 2) +/// "le" +/// ``` +/// +/// ```gleam +/// > slice(from: "gleam", at_index: 1, length: 10) +/// "leam" +/// ``` +/// +/// ```gleam +/// > slice(from: "gleam", at_index: 10, length: 3) +/// "" +/// ``` +/// +/// ```gleam +/// > slice(from: "gleam", at_index: -2, length: 2) +/// "am" +/// ``` +/// +/// ```gleam +/// > slice(from: "gleam", at_index: -12, length: 2) +/// "" +/// ``` +/// +pub fn slice(from string: String, at_index idx: Int, length len: Int) -> String { + case len < 0 { + True -> "" + False -> + case idx < 0 { + True -> { + let translated_idx = length(string) + idx + case translated_idx < 0 { + True -> "" + False -> do_slice(string, translated_idx, len) + } + } + False -> do_slice(string, idx, len) + } + } +} + +@target(erlang) +@external(erlang, "string", "slice") +fn do_slice(a: String, b: Int, c: Int) -> String + +@target(javascript) +fn do_slice(string: String, idx: Int, len: Int) -> String { + string + |> to_graphemes + |> list.drop(idx) + |> list.take(len) + |> concat +} + +/// Drops contents of the first `String` that occur before the second `String`. +/// If the `from` string does not contain the `before` string, `from` is returned unchanged. +/// +/// ## Examples +/// +/// ```gleam +/// > crop(from: "The Lone Gunmen", before: "Lone") +/// "Lone Gunmen" +/// ``` +/// +@external(erlang, "gleam_stdlib", "crop_string") +@external(javascript, "../gleam_stdlib.mjs", "crop_string") +pub fn crop(from string: String, before substring: String) -> String + +/// Drops *n* graphemes from the left side of a `String`. +/// +/// ## Examples +/// +/// ```gleam +/// > drop_left(from: "The Lone Gunmen", up_to: 2) +/// "e Lone Gunmen" +/// ``` +/// +pub fn drop_left(from string: String, up_to num_graphemes: Int) -> String { + case num_graphemes < 0 { + True -> string + False -> slice(string, num_graphemes, length(string) - num_graphemes) + } +} + +/// Drops *n* graphemes from the right side of a `String`. +/// +/// ## Examples +/// +/// ```gleam +/// > drop_right(from: "Cigarette Smoking Man", up_to: 2) +/// "Cigarette Smoking M" +/// ``` +/// +pub fn drop_right(from string: String, up_to num_graphemes: Int) -> String { + case num_graphemes < 0 { + True -> string + False -> slice(string, 0, length(string) - num_graphemes) + } +} + +/// Checks if the first `String` contains the second. +/// +/// ## Examples +/// +/// ```gleam +/// > contains(does: "theory", contain: "ory") +/// True +/// ``` +/// +/// ```gleam +/// > contains(does: "theory", contain: "the") +/// True +/// ``` +/// +/// ```gleam +/// > contains(does: "theory", contain: "THE") +/// False +/// ``` +/// +@external(erlang, "gleam_stdlib", "contains_string") +@external(javascript, "../gleam_stdlib.mjs", "contains_string") +pub fn contains(does haystack: String, contain needle: String) -> Bool + +/// Checks whether the first `String` starts with the second one. +/// +/// ## Examples +/// +/// ```gleam +/// > starts_with("theory", "ory") +/// False +/// ``` +/// +pub fn starts_with(string: String, prefix: String) -> Bool { + do_starts_with(string, prefix) +} + +@external(erlang, "gleam_stdlib", "string_starts_with") +@external(javascript, "../gleam_stdlib.mjs", "starts_with") +fn do_starts_with(a: String, b: String) -> Bool + +/// Checks whether the first `String` ends with the second one. +/// +/// ## Examples +/// +/// ```gleam +/// > ends_with("theory", "ory") +/// True +/// ``` +/// +pub fn ends_with(string: String, suffix: String) -> Bool { + do_ends_with(string, suffix) +} + +@external(erlang, "gleam_stdlib", "string_ends_with") +@external(javascript, "../gleam_stdlib.mjs", "ends_with") +fn do_ends_with(a: String, b: String) -> Bool + +/// Creates a list of `String`s by splitting a given string on a given substring. +/// +/// ## Examples +/// +/// ```gleam +/// > split("home/gleam/desktop/", on: "/") +/// ["home", "gleam", "desktop", ""] +/// ``` +/// +pub fn split(x: String, on substring: String) -> List(String) { + case substring { + "" -> to_graphemes(x) + _ -> + x + |> string_builder.from_string + |> string_builder.split(on: substring) + |> list.map(with: string_builder.to_string) + } +} + +/// Splits a `String` a single time on the given substring. +/// +/// Returns an `Error` if substring not present. +/// +/// ## Examples +/// +/// ```gleam +/// > split_once("home/gleam/desktop/", on: "/") +/// Ok(#("home", "gleam/desktop/")) +/// ``` +/// +/// ```gleam +/// > split_once("home/gleam/desktop/", on: "?") +/// Error(Nil) +/// ``` +/// +pub fn split_once( + x: String, + on substring: String, +) -> Result(#(String, String), Nil) { + do_split_once(x, substring) +} + +@target(erlang) +@external(erlang, "string", "split") +fn erl_split(a: String, b: String) -> List(String) + +@target(erlang) +fn do_split_once(x: String, substring: String) -> Result(#(String, String), Nil) { + case erl_split(x, substring) { + [first, rest] -> Ok(#(first, rest)) + _ -> Error(Nil) + } +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "split_once") +fn do_split_once( + x x: String, + substring substring: String, +) -> Result(#(String, String), Nil) + +/// Creates a new `String` by joining two `String`s together. +/// +/// This function copies both `String`s and runs in linear time. If you find +/// yourself joining `String`s frequently consider using the [`string_builder`](../gleam/string_builder.html) +/// module as it can append `String`s much faster! +/// +/// ## Examples +/// +/// ```gleam +/// > append(to: "butter", suffix: "fly") +/// "butterfly" +/// ``` +/// +pub fn append(to first: String, suffix second: String) -> String { + first + |> string_builder.from_string + |> string_builder.append(second) + |> string_builder.to_string +} + +/// Creates a new `String` by joining many `String`s together. +/// +/// This function copies both `String`s and runs in linear time. If you find +/// yourself joining `String`s frequently consider using the [`string_builder`](../gleam/string_builder.html) +/// module as it can append `String`s much faster! +/// +/// ## Examples +/// +/// ```gleam +/// > concat(["never", "the", "less"]) +/// "nevertheless" +/// ``` +/// +pub fn concat(strings: List(String)) -> String { + strings + |> string_builder.from_strings + |> string_builder.to_string +} + +/// Creates a new `String` by repeating a `String` a given number of times. +/// +/// This function runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > repeat("ha", times: 3) +/// "hahaha" +/// ``` +/// +pub fn repeat(string: String, times times: Int) -> String { + iterator.repeat(string) + |> iterator.take(times) + |> iterator.to_list + |> concat +} + +/// Joins many `String`s together with a given separator. +/// +/// This function runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > join(["home","evan","Desktop"], with: "/") +/// "home/evan/Desktop" +/// ``` +/// +pub fn join(strings: List(String), with separator: String) -> String { + do_join(strings, separator) +} + +@target(erlang) +fn do_join(strings: List(String), separator: String) -> String { + strings + |> list.intersperse(with: separator) + |> concat +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "join") +fn do_join(strings strings: List(String), string string: String) -> String + +/// Pads a `String` on the left until it has at least given number of graphemes. +/// +/// ## Examples +/// +/// ```gleam +/// > pad_left("121", to: 5, with: ".") +/// "..121" +/// ``` +/// +/// ```gleam +/// > pad_left("121", to: 3, with: ".") +/// "121" +/// ``` +/// +/// ```gleam +/// > pad_left("121", to: 2, with: ".") +/// "121" +/// ``` +/// +pub fn pad_left(string: String, to desired_length: Int, with pad_string: String) { + let current_length = length(string) + let to_pad_length = desired_length - current_length + padding(to_pad_length, pad_string) + |> iterator.append(iterator.single(string)) + |> iterator.to_list + |> concat +} + +/// Pads a `String` on the right until it has a given length. +/// +/// ## Examples +/// +/// ```gleam +/// > pad_right("123", to: 5, with: ".") +/// "123.." +/// ``` +/// +/// ```gleam +/// > pad_right("123", to: 3, with: ".") +/// "123" +/// ``` +/// +/// ```gleam +/// > pad_right("123", to: 2, with: ".") +/// "123" +/// ``` +/// +pub fn pad_right( + string: String, + to desired_length: Int, + with pad_string: String, +) { + let current_length = length(string) + let to_pad_length = desired_length - current_length + iterator.single(string) + |> iterator.append(padding(to_pad_length, pad_string)) + |> iterator.to_list + |> concat +} + +fn padding(size: Int, pad_string: String) -> Iterator(String) { + let pad_length = length(pad_string) + let num_pads = size / pad_length + let extra = size % pad_length + iterator.repeat(pad_string) + |> iterator.take(num_pads) + |> iterator.append(iterator.single(slice(pad_string, 0, extra))) +} + +/// Removes whitespace on both sides of a `String`. +/// +/// ## Examples +/// +/// ```gleam +/// > trim(" hats \n") +/// "hats" +/// ``` +/// +pub fn trim(string: String) -> String { + do_trim(string) +} + +@target(erlang) +fn do_trim(string: String) -> String { + erl_trim(string, Both) +} + +@target(erlang) +type Direction { + Leading + Trailing + Both +} + +@target(erlang) +@external(erlang, "string", "trim") +fn erl_trim(a: String, b: Direction) -> String + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "trim") +fn do_trim(string string: String) -> String + +/// Removes whitespace on the left of a `String`. +/// +/// ## Examples +/// +/// ```gleam +/// > trim_left(" hats \n") +/// "hats \n" +/// ``` +/// +pub fn trim_left(string: String) -> String { + do_trim_left(string) +} + +@target(erlang) +fn do_trim_left(string: String) -> String { + erl_trim(string, Leading) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "trim_left") +fn do_trim_left(string string: String) -> String + +/// Removes whitespace on the right of a `String`. +/// +/// ## Examples +/// +/// ```gleam +/// > trim_right(" hats \n") +/// " hats" +/// ``` +/// +pub fn trim_right(string: String) -> String { + do_trim_right(string) +} + +@target(erlang) +fn do_trim_right(string: String) -> String { + erl_trim(string, Trailing) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "trim_right") +fn do_trim_right(string string: String) -> String + +/// Splits a non-empty `String` into its first element (head) and rest (tail). +/// This lets you pattern match on `String`s exactly as you would with lists. +/// +/// Note on JavaScript using the function to iterate over a string will likely +/// be slower than using `to_graphemes` due to string slicing being more +/// expensive on JavaScript than Erlang. +/// +/// ## Examples +/// +/// ```gleam +/// > pop_grapheme("gleam") +/// Ok(#("g", "leam")) +/// ``` +/// +/// ```gleam +/// > pop_grapheme("") +/// Error(Nil) +/// ``` +/// +pub fn pop_grapheme(string: String) -> Result(#(String, String), Nil) { + do_pop_grapheme(string) +} + +@external(erlang, "gleam_stdlib", "string_pop_grapheme") +@external(javascript, "../gleam_stdlib.mjs", "pop_grapheme") +fn do_pop_grapheme(string string: String) -> Result(#(String, String), Nil) + +/// Converts a `String` to a list of +/// [graphemes](https://en.wikipedia.org/wiki/Grapheme). +/// +/// ```gleam +/// > to_graphemes("abc") +/// ["a", "b", "c"] +/// ``` +/// +@external(javascript, "../gleam_stdlib.mjs", "graphemes") +pub fn to_graphemes(string: String) -> List(String) { + do_to_graphemes(string, []) + |> list.reverse +} + +fn do_to_graphemes(string: String, acc: List(String)) -> List(String) { + case pop_grapheme(string) { + Ok(#(grapheme, rest)) -> do_to_graphemes(rest, [grapheme, ..acc]) + _ -> acc + } +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "codepoint") +fn unsafe_int_to_utf_codepoint(a: Int) -> UtfCodepoint + +/// Converts a `String` to a `List` of `UtfCodepoint`. +/// +/// See <https://en.wikipedia.org/wiki/Code_point> and +/// <https://en.wikipedia.org/wiki/Unicode#Codespace_and_Code_Points> for an +/// explanation on code points. +/// +/// ## Examples +/// +/// ```gleam +/// > "a" |> to_utf_codepoints +/// [UtfCodepoint(97)] +/// ``` +/// +/// ```gleam +/// // Semantically the same as: +/// // ["🏳", "️", "", "🌈"] or: +/// // [waving_white_flag, variant_selector_16, zero_width_joiner, rainbow] +/// > "🏳️🌈" |> to_utf_codepoints +/// [UtfCodepoint(127987), UtfCodepoint(65039), UtfCodepoint(8205), UtfCodepoint(127752)] +/// ``` +/// +pub fn to_utf_codepoints(string: String) -> List(UtfCodepoint) { + do_to_utf_codepoints(string) +} + +@target(erlang) +fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) { + do_to_utf_codepoints_impl(<<string:utf8>>, []) + |> list.reverse +} + +@target(erlang) +fn do_to_utf_codepoints_impl( + bit_array: BitArray, + acc: List(UtfCodepoint), +) -> List(UtfCodepoint) { + case bit_array { + <<first:utf8_codepoint, rest:bytes>> -> + do_to_utf_codepoints_impl(rest, [first, ..acc]) + _ -> acc + } +} + +@target(javascript) +fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) { + string + |> string_to_codepoint_integer_list + |> list.map(unsafe_int_to_utf_codepoint) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "string_to_codepoint_integer_list") +fn string_to_codepoint_integer_list(a: String) -> List(Int) + +/// Converts a `List` of `UtfCodepoint`s to a `String`. +/// +/// See <https://en.wikipedia.org/wiki/Code_point> and +/// <https://en.wikipedia.org/wiki/Unicode#Codespace_and_Code_Points> for an +/// explanation on code points. +/// +/// ## Examples +/// +/// ```gleam +/// > { +/// > let assert #(Ok(a), Ok(b), Ok(c)) = #( +/// > utf_codepoint(97), +/// > utf_codepoint(98), +/// > utf_codepoint(99), +/// > ) +/// > [a, b, c] +/// > } +/// > |> from_utf_codepoints +/// "abc" +/// ``` +/// +@external(erlang, "gleam_stdlib", "utf_codepoint_list_to_string") +@external(javascript, "../gleam_stdlib.mjs", "utf_codepoint_list_to_string") +pub fn from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String + +/// Converts an integer to a `UtfCodepoint`. +/// +/// Returns an `Error` if the integer does not represent a valid UTF codepoint. +/// +pub fn utf_codepoint(value: Int) -> Result(UtfCodepoint, Nil) { + case value { + i if i > 1_114_111 -> Error(Nil) + 65_534 | 65_535 -> Error(Nil) + i if i >= 55_296 && i <= 57_343 -> Error(Nil) + i -> Ok(unsafe_int_to_utf_codepoint(i)) + } +} + +/// Converts an UtfCodepoint to its ordinal code point value. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert [utf_codepoint, ..] = to_utf_codepoints("💜") +/// > utf_codepoint_to_int(utf_codepoint) +/// 128156 +/// ``` +/// +pub fn utf_codepoint_to_int(cp: UtfCodepoint) -> Int { + do_utf_codepoint_to_int(cp) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "utf_codepoint_to_int") +fn do_utf_codepoint_to_int(cp cp: UtfCodepoint) -> Int + +/// Converts a `String` into `Option(String)` where an empty `String` becomes +/// `None`. +/// +/// ## Examples +/// +/// ```gleam +/// > to_option("") +/// None +/// ``` +/// +/// ```gleam +/// > to_option("hats") +/// Some("hats") +/// ``` +/// +pub fn to_option(s: String) -> Option(String) { + case s { + "" -> None + _ -> Some(s) + } +} + +/// Returns the first grapheme cluster in a given `String` and wraps it in a +/// `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`. +/// Otherwise, it returns `Ok(String)`. +/// +/// ## Examples +/// +/// ```gleam +/// > first("") +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > first("icecream") +/// Ok("i") +/// ``` +/// +pub fn first(s: String) -> Result(String, Nil) { + case pop_grapheme(s) { + Ok(#(first, _)) -> Ok(first) + Error(e) -> Error(e) + } +} + +/// Returns the last grapheme cluster in a given `String` and wraps it in a +/// `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`. +/// Otherwise, it returns `Ok(String)`. +/// +/// ## Examples +/// +/// ```gleam +/// > last("") +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > last("icecream") +/// Ok("m") +/// ``` +/// +pub fn last(s: String) -> Result(String, Nil) { + case pop_grapheme(s) { + Ok(#(first, "")) -> Ok(first) + Ok(#(_, rest)) -> Ok(slice(rest, -1, 1)) + Error(e) -> Error(e) + } +} + +/// Creates a new `String` with the first grapheme in the input `String` +/// converted to uppercase and the remaining graphemes to lowercase. +/// +/// ## Examples +/// +/// ```gleam +/// > capitalise("mamouna") +/// "Mamouna" +/// ``` +/// +pub fn capitalise(s: String) -> String { + case pop_grapheme(s) { + Ok(#(first, rest)) -> append(to: uppercase(first), suffix: lowercase(rest)) + _ -> "" + } +} + +/// Returns a `String` representation of a term in Gleam syntax. +/// +pub fn inspect(term: anything) -> String { + do_inspect(term) + |> string_builder.to_string +} + +@external(erlang, "gleam_stdlib", "inspect") +@external(javascript, "../gleam_stdlib.mjs", "inspect") +fn do_inspect(term term: anything) -> StringBuilder + +/// Returns the number of bytes in a `String`. +/// +/// This function runs in constant time on Erlang and in linear time on +/// JavaScript. +/// +@external(erlang, "erlang", "byte_size") +@external(javascript, "../gleam_stdlib.mjs", "byte_size") +pub fn byte_size(string: String) -> Int diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/string_builder.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/string_builder.gleam new file mode 100644 index 0000000..5792ca8 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/string_builder.gleam @@ -0,0 +1,298 @@ +import gleam/list + +/// `StringBuilder` is a type used for efficiently building strings. +/// +/// When we append one string to another the strings must be copied to a +/// new location in memory so that they can sit together. This behaviour +/// enables efficient reading of the string but copying can be expensive, +/// especially if we want to join many strings together. +/// +/// `StringBuilder` is different in that it can be joined together in constant time +/// using minimal memory, and then can be efficiently converted to a string +/// using the `to_string` function. +/// +/// On Erlang this type is compatible with Erlang's iodata. On JavaScript this +/// type is compatible with normal strings. +/// +pub type StringBuilder + +/// Create an empty `StringBuilder`. Useful as the start of a pipe chaining many +/// builders together. +/// +pub fn new() -> StringBuilder { + do_from_strings([]) +} + +/// Prepends a `String` onto the start of some `StringBuilder`. +/// +/// Runs in constant time. +/// +pub fn prepend( + to builder: StringBuilder, + prefix prefix: String, +) -> StringBuilder { + append_builder(from_string(prefix), builder) +} + +/// Appends a `String` onto the end of some `StringBuilder`. +/// +/// Runs in constant time. +/// +pub fn append(to builder: StringBuilder, suffix second: String) -> StringBuilder { + append_builder(builder, from_string(second)) +} + +/// Prepends some `StringBuilder` onto the start of another. +/// +/// Runs in constant time. +/// +pub fn prepend_builder( + to builder: StringBuilder, + prefix prefix: StringBuilder, +) -> StringBuilder { + do_append(prefix, builder) +} + +/// Appends some `StringBuilder` onto the end of another. +/// +/// Runs in constant time. +/// +pub fn append_builder( + to builder: StringBuilder, + suffix suffix: StringBuilder, +) -> StringBuilder { + do_append(builder, suffix) +} + +@external(erlang, "gleam_stdlib", "iodata_append") +@external(javascript, "../gleam_stdlib.mjs", "add") +fn do_append(a: StringBuilder, b: StringBuilder) -> StringBuilder + +/// Converts a list of strings into a builder. +/// +/// Runs in constant time. +/// +pub fn from_strings(strings: List(String)) -> StringBuilder { + do_from_strings(strings) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "concat") +fn do_from_strings(a: List(String)) -> StringBuilder + +/// Joins a list of builders into a single builder. +/// +/// Runs in constant time. +/// +pub fn concat(builders: List(StringBuilder)) -> StringBuilder { + do_concat(builders) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "concat") +fn do_concat(a: List(StringBuilder)) -> StringBuilder + +/// Converts a string into a builder. +/// +/// Runs in constant time. +/// +pub fn from_string(string: String) -> StringBuilder { + do_from_string(string) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_from_string(a: String) -> StringBuilder + +/// Turns an `StringBuilder` into a `String` +/// +/// This function is implemented natively by the virtual machine and is highly +/// optimised. +/// +pub fn to_string(builder: StringBuilder) -> String { + do_to_string(builder) +} + +@external(erlang, "unicode", "characters_to_binary") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_to_string(a: StringBuilder) -> String + +/// Returns the size of the `StringBuilder` in bytes. +/// +pub fn byte_size(builder: StringBuilder) -> Int { + do_byte_size(builder) +} + +@external(erlang, "erlang", "iolist_size") +@external(javascript, "../gleam_stdlib.mjs", "length") +fn do_byte_size(a: StringBuilder) -> Int + +/// Joins the given builders into a new builder separated with the given string +/// +pub fn join(builders: List(StringBuilder), with sep: String) -> StringBuilder { + builders + |> list.intersperse(from_string(sep)) + |> concat +} + +/// Converts a builder to a new builder where the contents have been +/// lowercased. +/// +pub fn lowercase(builder: StringBuilder) -> StringBuilder { + do_lowercase(builder) +} + +@external(erlang, "string", "lowercase") +@external(javascript, "../gleam_stdlib.mjs", "lowercase") +fn do_lowercase(a: StringBuilder) -> StringBuilder + +/// Converts a builder to a new builder where the contents have been +/// uppercased. +/// +pub fn uppercase(builder: StringBuilder) -> StringBuilder { + do_uppercase(builder) +} + +@external(erlang, "string", "uppercase") +@external(javascript, "../gleam_stdlib.mjs", "uppercase") +fn do_uppercase(a: StringBuilder) -> StringBuilder + +/// Converts a builder to a new builder with the contents reversed. +/// +pub fn reverse(builder: StringBuilder) -> StringBuilder { + do_reverse(builder) +} + +@target(erlang) +@external(erlang, "string", "reverse") +fn do_reverse(a: StringBuilder) -> StringBuilder + +@target(javascript) +fn do_reverse(builder: StringBuilder) -> StringBuilder { + builder + |> to_string + |> do_to_graphemes + |> list.reverse + |> from_strings +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "graphemes") +fn do_to_graphemes(string string: String) -> List(String) + +/// Splits a builder on a given pattern into a list of builders. +/// +pub fn split(iodata: StringBuilder, on pattern: String) -> List(StringBuilder) { + do_split(iodata, pattern) +} + +@target(erlang) +type Direction { + All +} + +@target(erlang) +@external(erlang, "string", "split") +fn erl_split(a: StringBuilder, b: String, c: Direction) -> List(StringBuilder) + +@target(erlang) +fn do_split(iodata: StringBuilder, pattern: String) -> List(StringBuilder) { + erl_split(iodata, pattern, All) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "split") +fn do_split( + builder builder: StringBuilder, + pattern pattern: String, +) -> List(StringBuilder) + +/// Replaces all instances of a pattern with a given string substitute. +/// +pub fn replace( + in builder: StringBuilder, + each pattern: String, + with substitute: String, +) -> StringBuilder { + do_replace(builder, pattern, substitute) +} + +@target(erlang) +fn do_replace( + iodata: StringBuilder, + pattern: String, + substitute: String, +) -> StringBuilder { + erl_replace(iodata, pattern, substitute, All) +} + +@target(erlang) +@external(erlang, "string", "replace") +fn erl_replace( + a: StringBuilder, + b: String, + c: String, + d: Direction, +) -> StringBuilder + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "string_replace") +fn do_replace(a: StringBuilder, b: String, c: String) -> StringBuilder + +/// Compares two builders to determine if they have the same textual content. +/// +/// Comparing two iodata using the `==` operator may return `False` even if they +/// have the same content as they may have been build in different ways, so +/// using this function is often preferred. +/// +/// ## Examples +/// +/// ```gleam +/// > from_strings(["a", "b"]) == from_string("ab") +/// False +/// ``` +/// +/// ```gleam +/// > is_equal(from_strings(["a", "b"]), from_string("ab")) +/// True +/// ``` +/// +pub fn is_equal(a: StringBuilder, b: StringBuilder) -> Bool { + do_is_equal(a, b) +} + +@external(erlang, "string", "equal") +@external(javascript, "../gleam_stdlib.mjs", "equal") +fn do_is_equal(a: StringBuilder, b: StringBuilder) -> Bool + +/// Inspects a builder to determine if it is equivalent to an empty string. +/// +/// ## Examples +/// +/// ```gleam +/// > from_string("ok") |> is_empty +/// False +/// ``` +/// +/// ```gleam +/// > from_string("") |> is_empty +/// True +/// ``` +/// +/// ```gleam +/// > from_strings([]) |> is_empty +/// True +/// ``` +/// +pub fn is_empty(builder: StringBuilder) -> Bool { + do_is_empty(builder) +} + +@target(erlang) +@external(erlang, "string", "is_empty") +fn do_is_empty(a: StringBuilder) -> Bool + +@target(javascript) +fn do_is_empty(builder: StringBuilder) -> Bool { + from_string("") == builder +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam/uri.gleam b/aoc2023/build/packages/gleam_stdlib/src/gleam/uri.gleam new file mode 100644 index 0000000..11f6ea6 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam/uri.gleam @@ -0,0 +1,462 @@ +//// Utilities for working with URIs +//// +//// This module provides functions for working with URIs (for example, parsing +//// URIs or encoding query strings). The functions in this module are implemented +//// according to [RFC 3986](https://tools.ietf.org/html/rfc3986). +//// +//// Query encoding (Form encoding) is defined in the +//// [W3C specification](https://www.w3.org/TR/html52/sec-forms.html#urlencoded-form-data). + +import gleam/int +import gleam/list +import gleam/option.{type Option, None, Some} +import gleam/string +import gleam/string_builder.{type StringBuilder} +@target(javascript) +import gleam/pair +@target(javascript) +import gleam/regex +@target(javascript) +import gleam/result + +/// Type representing holding the parsed components of an URI. +/// All components of a URI are optional, except the path. +/// +pub type Uri { + Uri( + scheme: Option(String), + userinfo: Option(String), + host: Option(String), + port: Option(Int), + path: String, + query: Option(String), + fragment: Option(String), + ) +} + +/// Parses a compliant URI string into the `Uri` Type. +/// If the string is not a valid URI string then an error is returned. +/// +/// The opposite operation is `uri.to_string`. +/// +/// ## Examples +/// +/// ```gleam +/// > parse("https://example.com:1234/a/b?query=true#fragment") +/// Ok( +/// Uri( +/// scheme: Some("https"), +/// userinfo: None, +/// host: Some("example.com"), +/// port: Some(1234), +/// path: "/a/b", +/// query: Some("query=true"), +/// fragment: Some("fragment") +/// ) +/// ) +/// ``` +/// +pub fn parse(uri_string: String) -> Result(Uri, Nil) { + do_parse(uri_string) +} + +@target(erlang) +@external(erlang, "gleam_stdlib", "uri_parse") +fn do_parse(a: String) -> Result(Uri, Nil) + +@target(javascript) +fn do_parse(uri_string: String) -> Result(Uri, Nil) { + // From https://tools.ietf.org/html/rfc3986#appendix-B + let pattern = + // 12 3 4 5 6 7 8 + "^(([a-z][a-z0-9\\+\\-\\.]*):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#.*)?" + let matches = + pattern + |> regex_submatches(uri_string) + |> pad_list(8) + + let #(scheme, authority, path, query, fragment) = case matches { + [ + _scheme_with_colon, + scheme, + authority_with_slashes, + _authority, + path, + query_with_question_mark, + _query, + fragment, + ] -> #( + scheme, + authority_with_slashes, + path, + query_with_question_mark, + fragment, + ) + _ -> #(None, None, None, None, None) + } + + let scheme = noneify_empty_string(scheme) + let path = option.unwrap(path, "") + let query = noneify_query(query) + let #(userinfo, host, port) = split_authority(authority) + let fragment = + fragment + |> option.to_result(Nil) + |> result.try(string.pop_grapheme) + |> result.map(pair.second) + |> option.from_result + let scheme = + scheme + |> noneify_empty_string + |> option.map(string.lowercase) + Ok(Uri( + scheme: scheme, + userinfo: userinfo, + host: host, + port: port, + path: path, + query: query, + fragment: fragment, + )) +} + +@target(javascript) +fn regex_submatches(pattern: String, string: String) -> List(Option(String)) { + pattern + |> regex.compile(regex.Options(case_insensitive: True, multi_line: False)) + |> result.nil_error + |> result.map(regex.scan(_, string)) + |> result.try(list.first) + |> result.map(fn(m: regex.Match) { m.submatches }) + |> result.unwrap([]) +} + +@target(javascript) +fn noneify_query(x: Option(String)) -> Option(String) { + case x { + None -> None + Some(x) -> + case string.pop_grapheme(x) { + Ok(#("?", query)) -> Some(query) + _ -> None + } + } +} + +@target(javascript) +fn noneify_empty_string(x: Option(String)) -> Option(String) { + case x { + Some("") | None -> None + Some(_) -> x + } +} + +// Split an authority into its userinfo, host and port parts. +@target(javascript) +fn split_authority( + authority: Option(String), +) -> #(Option(String), Option(String), Option(Int)) { + case option.unwrap(authority, "") { + "" -> #(None, None, None) + "//" -> #(None, Some(""), None) + authority -> { + let matches = + "^(//)?((.*)@)?(\\[[a-zA-Z0-9:.]*\\]|[^:]*)(:(\\d*))?" + |> regex_submatches(authority) + |> pad_list(6) + case matches { + [_, _, userinfo, host, _, port] -> { + let userinfo = noneify_empty_string(userinfo) + let host = noneify_empty_string(host) + let port = + port + |> option.unwrap("") + |> int.parse + |> option.from_result + #(userinfo, host, port) + } + _ -> #(None, None, None) + } + } + } +} + +@target(javascript) +fn pad_list(list: List(Option(a)), size: Int) -> List(Option(a)) { + list + |> list.append(list.repeat(None, extra_required(list, size))) +} + +@target(javascript) +fn extra_required(list: List(a), remaining: Int) -> Int { + case list { + _ if remaining == 0 -> 0 + [] -> remaining + [_, ..xs] -> extra_required(xs, remaining - 1) + } +} + +/// Parses an urlencoded query string into a list of key value pairs. +/// Returns an error for invalid encoding. +/// +/// The opposite operation is `uri.query_to_string`. +/// +/// ## Examples +/// +/// ```gleam +/// > parse_query("a=1&b=2") +/// Ok([#("a", "1"), #("b", "2")]) +/// ``` +/// +pub fn parse_query(query: String) -> Result(List(#(String, String)), Nil) { + do_parse_query(query) +} + +@external(erlang, "gleam_stdlib", "parse_query") +@external(javascript, "../gleam_stdlib.mjs", "parse_query") +fn do_parse_query(a: String) -> Result(List(#(String, String)), Nil) + +/// Encodes a list of key value pairs as a URI query string. +/// +/// The opposite operation is `uri.parse_query`. +/// +/// ## Examples +/// +/// ```gleam +/// > query_to_string([#("a", "1"), #("b", "2")]) +/// "a=1&b=2" +/// ``` +/// +pub fn query_to_string(query: List(#(String, String))) -> String { + query + |> list.map(query_pair) + |> list.intersperse(string_builder.from_string("&")) + |> string_builder.concat + |> string_builder.to_string +} + +fn query_pair(pair: #(String, String)) -> StringBuilder { + string_builder.from_strings([ + percent_encode(pair.0), + "=", + percent_encode(pair.1), + ]) +} + +/// Encodes a string into a percent encoded representation. +/// +/// ## Examples +/// +/// ```gleam +/// > percent_encode("100% great") +/// "100%25%20great" +/// ``` +/// +pub fn percent_encode(value: String) -> String { + do_percent_encode(value) +} + +@external(erlang, "gleam_stdlib", "percent_encode") +@external(javascript, "../gleam_stdlib.mjs", "percent_encode") +fn do_percent_encode(a: String) -> String + +/// Decodes a percent encoded string. +/// +/// ## Examples +/// +/// ```gleam +/// > percent_decode("100%25+great") +/// Ok("100% great") +/// ``` +/// +pub fn percent_decode(value: String) -> Result(String, Nil) { + do_percent_decode(value) +} + +@external(erlang, "gleam_stdlib", "percent_decode") +@external(javascript, "../gleam_stdlib.mjs", "percent_decode") +fn do_percent_decode(a: String) -> Result(String, Nil) + +fn do_remove_dot_segments( + input: List(String), + accumulator: List(String), +) -> List(String) { + case input { + [] -> list.reverse(accumulator) + [segment, ..rest] -> { + let accumulator = case segment, accumulator { + "", accumulator -> accumulator + ".", accumulator -> accumulator + "..", [] -> [] + "..", [_, ..accumulator] -> accumulator + segment, accumulator -> [segment, ..accumulator] + } + do_remove_dot_segments(rest, accumulator) + } + } +} + +fn remove_dot_segments(input: List(String)) -> List(String) { + do_remove_dot_segments(input, []) +} + +/// Splits the path section of a URI into it's constituent segments. +/// +/// Removes empty segments and resolves dot-segments as specified in +/// [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC. +/// +/// ## Examples +/// +/// ```gleam +/// > path_segments("/users/1") +/// ["users" ,"1"] +/// ``` +/// +pub fn path_segments(path: String) -> List(String) { + remove_dot_segments(string.split(path, "/")) +} + +/// Encodes a `Uri` value as a URI string. +/// +/// The opposite operation is `uri.parse`. +/// +/// ## Examples +/// +/// ```gleam +/// > let uri = Uri(Some("http"), None, Some("example.com"), ...) +/// > to_string(uri) +/// "http://example.com" +/// ``` +/// +pub fn to_string(uri: Uri) -> String { + let parts = case uri.fragment { + Some(fragment) -> ["#", fragment] + _ -> [] + } + let parts = case uri.query { + Some(query) -> ["?", query, ..parts] + _ -> parts + } + let parts = [uri.path, ..parts] + let parts = case uri.host, string.starts_with(uri.path, "/") { + Some(host), False if host != "" -> ["/", ..parts] + _, _ -> parts + } + let parts = case uri.host, uri.port { + Some(_), Some(port) -> [":", int.to_string(port), ..parts] + _, _ -> parts + } + let parts = case uri.scheme, uri.userinfo, uri.host { + Some(s), Some(u), Some(h) -> [s, "://", u, "@", h, ..parts] + Some(s), None, Some(h) -> [s, "://", h, ..parts] + Some(s), Some(_), None | Some(s), None, None -> [s, ":", ..parts] + None, None, Some(h) -> ["//", h, ..parts] + _, _, _ -> parts + } + string.concat(parts) +} + +/// Fetches the origin of a URI. +/// +/// Returns the origin of a uri as defined in +/// [RFC 6454](https://tools.ietf.org/html/rfc6454) +/// +/// The supported URI schemes are `http` and `https`. +/// URLs without a scheme will return `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Ok(uri) = parse("http://example.com/path?foo#bar") +/// > origin(uri) +/// Ok("http://example.com") +/// ``` +/// +pub fn origin(uri: Uri) -> Result(String, Nil) { + let Uri(scheme: scheme, host: host, port: port, ..) = uri + case scheme { + Some("https") if port == Some(443) -> { + let origin = Uri(scheme, None, host, None, "", None, None) + Ok(to_string(origin)) + } + Some("http") if port == Some(80) -> { + let origin = Uri(scheme, None, host, None, "", None, None) + Ok(to_string(origin)) + } + Some(s) if s == "http" || s == "https" -> { + let origin = Uri(scheme, None, host, port, "", None, None) + Ok(to_string(origin)) + } + _ -> Error(Nil) + } +} + +fn drop_last(elements: List(a)) -> List(a) { + list.take(from: elements, up_to: list.length(elements) - 1) +} + +fn join_segments(segments: List(String)) -> String { + string.join(["", ..segments], "/") +} + +/// Resolves a URI with respect to the given base URI. +/// +/// The base URI must be an absolute URI or this function will return an error. +/// The algorithm for merging uris is described in +/// [RFC 3986](https://tools.ietf.org/html/rfc3986#section-5.2). +/// +pub fn merge(base: Uri, relative: Uri) -> Result(Uri, Nil) { + case base { + Uri(scheme: Some(_), host: Some(_), ..) -> + case relative { + Uri(host: Some(_), ..) -> { + let path = + string.split(relative.path, "/") + |> remove_dot_segments() + |> join_segments() + let resolved = + Uri( + option.or(relative.scheme, base.scheme), + None, + relative.host, + option.or(relative.port, base.port), + path, + relative.query, + relative.fragment, + ) + Ok(resolved) + } + _ -> { + let #(new_path, new_query) = case relative.path { + "" -> #(base.path, option.or(relative.query, base.query)) + _ -> { + let path_segments = case string.starts_with(relative.path, "/") { + True -> string.split(relative.path, "/") + False -> + string.split(base.path, "/") + |> drop_last() + |> list.append(string.split(relative.path, "/")) + } + let path = + path_segments + |> remove_dot_segments() + |> join_segments() + #(path, relative.query) + } + } + let resolved = + Uri( + base.scheme, + None, + base.host, + base.port, + new_path, + new_query, + relative.fragment, + ) + Ok(resolved) + } + } + _ -> Error(Nil) + } +} diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@base.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@base.erl new file mode 100644 index 0000000..65bc3f6 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@base.erl @@ -0,0 +1,20 @@ +-module(gleam@base). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([encode64/2, decode64/1, url_encode64/2, url_decode64/1]). + +-spec encode64(bitstring(), boolean()) -> binary(). +encode64(Input, Padding) -> + gleam@bit_array:base64_encode(Input, Padding). + +-spec decode64(binary()) -> {ok, bitstring()} | {error, nil}. +decode64(Encoded) -> + gleam@bit_array:base64_decode(Encoded). + +-spec url_encode64(bitstring(), boolean()) -> binary(). +url_encode64(Input, Padding) -> + gleam@bit_array:base64_url_encode(Input, Padding). + +-spec url_decode64(binary()) -> {ok, bitstring()} | {error, nil}. +url_decode64(Encoded) -> + gleam@bit_array:base64_url_decode(Encoded). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@bit_array.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@bit_array.erl new file mode 100644 index 0000000..ba18dfa --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@bit_array.erl @@ -0,0 +1,102 @@ +-module(gleam@bit_array). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([from_string/1, byte_size/1, slice/3, is_utf8/1, to_string/1, concat/1, append/2, base64_encode/2, base64_decode/1, base64_url_encode/2, base64_url_decode/1, base16_encode/1, base16_decode/1]). + +-spec from_string(binary()) -> bitstring(). +from_string(X) -> + gleam_stdlib:identity(X). + +-spec byte_size(bitstring()) -> integer(). +byte_size(X) -> + erlang:byte_size(X). + +-spec slice(bitstring(), integer(), integer()) -> {ok, bitstring()} | + {error, nil}. +slice(String, Position, Length) -> + gleam_stdlib:bit_array_slice(String, Position, Length). + +-spec do_is_utf8(bitstring()) -> boolean(). +do_is_utf8(Bits) -> + case Bits of + <<>> -> + true; + + <<_/utf8, Rest/binary>> -> + do_is_utf8(Rest); + + _ -> + false + end. + +-spec is_utf8(bitstring()) -> boolean(). +is_utf8(Bits) -> + do_is_utf8(Bits). + +-spec do_to_string(bitstring()) -> {ok, binary()} | {error, nil}. +do_to_string(Bits) -> + case is_utf8(Bits) of + true -> + {ok, gleam_stdlib:identity(Bits)}; + + false -> + {error, nil} + end. + +-spec to_string(bitstring()) -> {ok, binary()} | {error, nil}. +to_string(Bits) -> + do_to_string(Bits). + +-spec concat(list(bitstring())) -> bitstring(). +concat(Bit_arrays) -> + gleam_stdlib:bit_array_concat(Bit_arrays). + +-spec append(bitstring(), bitstring()) -> bitstring(). +append(First, Second) -> + gleam_stdlib:bit_array_concat([First, Second]). + +-spec base64_encode(bitstring(), boolean()) -> binary(). +base64_encode(Input, Padding) -> + Encoded = base64:encode(Input), + case Padding of + true -> + Encoded; + + false -> + gleam@string:replace(Encoded, <<"="/utf8>>, <<""/utf8>>) + end. + +-spec base64_decode(binary()) -> {ok, bitstring()} | {error, nil}. +base64_decode(Encoded) -> + Padded = case erlang:byte_size(gleam_stdlib:identity(Encoded)) rem 4 of + 0 -> + Encoded; + + N -> + gleam@string:append( + Encoded, + gleam@string:repeat(<<"="/utf8>>, 4 - N) + ) + end, + gleam_stdlib:base_decode64(Padded). + +-spec base64_url_encode(bitstring(), boolean()) -> binary(). +base64_url_encode(Input, Padding) -> + _pipe = base64_encode(Input, Padding), + _pipe@1 = gleam@string:replace(_pipe, <<"+"/utf8>>, <<"-"/utf8>>), + gleam@string:replace(_pipe@1, <<"/"/utf8>>, <<"_"/utf8>>). + +-spec base64_url_decode(binary()) -> {ok, bitstring()} | {error, nil}. +base64_url_decode(Encoded) -> + _pipe = Encoded, + _pipe@1 = gleam@string:replace(_pipe, <<"-"/utf8>>, <<"+"/utf8>>), + _pipe@2 = gleam@string:replace(_pipe@1, <<"_"/utf8>>, <<"/"/utf8>>), + base64_decode(_pipe@2). + +-spec base16_encode(bitstring()) -> binary(). +base16_encode(Input) -> + binary:encode_hex(Input). + +-spec base16_decode(binary()) -> {ok, bitstring()} | {error, nil}. +base16_decode(Input) -> + gleam_stdlib:base16_decode(Input). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@bit_builder.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@bit_builder.erl new file mode 100644 index 0000000..284c6d4 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@bit_builder.erl @@ -0,0 +1,66 @@ +-module(gleam@bit_builder). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([new/0, prepend/2, append/2, prepend_builder/2, append_builder/2, prepend_string/2, append_string/2, concat/1, concat_bit_strings/1, from_string/1, from_string_builder/1, from_bit_string/1, to_bit_string/1, byte_size/1]). + +-spec new() -> gleam@bytes_builder:bytes_builder(). +new() -> + gleam@bytes_builder:new(). + +-spec prepend(gleam@bytes_builder:bytes_builder(), bitstring()) -> gleam@bytes_builder:bytes_builder(). +prepend(To, Prefix) -> + gleam@bytes_builder:prepend(To, Prefix). + +-spec append(gleam@bytes_builder:bytes_builder(), bitstring()) -> gleam@bytes_builder:bytes_builder(). +append(To, Suffix) -> + gleam@bytes_builder:append(To, Suffix). + +-spec prepend_builder( + gleam@bytes_builder:bytes_builder(), + gleam@bytes_builder:bytes_builder() +) -> gleam@bytes_builder:bytes_builder(). +prepend_builder(To, Prefix) -> + gleam@bytes_builder:prepend_builder(To, Prefix). + +-spec append_builder( + gleam@bytes_builder:bytes_builder(), + gleam@bytes_builder:bytes_builder() +) -> gleam@bytes_builder:bytes_builder(). +append_builder(First, Second) -> + gleam_stdlib:iodata_append(First, Second). + +-spec prepend_string(gleam@bytes_builder:bytes_builder(), binary()) -> gleam@bytes_builder:bytes_builder(). +prepend_string(To, Prefix) -> + gleam@bytes_builder:prepend_string(To, Prefix). + +-spec append_string(gleam@bytes_builder:bytes_builder(), binary()) -> gleam@bytes_builder:bytes_builder(). +append_string(To, Suffix) -> + gleam@bytes_builder:append_string(To, Suffix). + +-spec concat(list(gleam@bytes_builder:bytes_builder())) -> gleam@bytes_builder:bytes_builder(). +concat(Builders) -> + gleam_stdlib:identity(Builders). + +-spec concat_bit_strings(list(bitstring())) -> gleam@bytes_builder:bytes_builder(). +concat_bit_strings(Bits) -> + gleam_stdlib:identity(Bits). + +-spec from_string(binary()) -> gleam@bytes_builder:bytes_builder(). +from_string(String) -> + gleam_stdlib:wrap_list(String). + +-spec from_string_builder(gleam@string_builder:string_builder()) -> gleam@bytes_builder:bytes_builder(). +from_string_builder(Builder) -> + gleam_stdlib:wrap_list(Builder). + +-spec from_bit_string(bitstring()) -> gleam@bytes_builder:bytes_builder(). +from_bit_string(Bits) -> + gleam_stdlib:wrap_list(Bits). + +-spec to_bit_string(gleam@bytes_builder:bytes_builder()) -> bitstring(). +to_bit_string(Builder) -> + erlang:list_to_bitstring(Builder). + +-spec byte_size(gleam@bytes_builder:bytes_builder()) -> integer(). +byte_size(Builder) -> + erlang:iolist_size(Builder). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@bit_string.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@bit_string.erl new file mode 100644 index 0000000..7dabaa3 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@bit_string.erl @@ -0,0 +1,33 @@ +-module(gleam@bit_string). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([from_string/1, byte_size/1, append/2, slice/3, is_utf8/1, to_string/1, concat/1]). + +-spec from_string(binary()) -> bitstring(). +from_string(X) -> + gleam_stdlib:identity(X). + +-spec byte_size(bitstring()) -> integer(). +byte_size(X) -> + erlang:byte_size(X). + +-spec append(bitstring(), bitstring()) -> bitstring(). +append(First, Second) -> + gleam@bit_array:append(First, Second). + +-spec slice(bitstring(), integer(), integer()) -> {ok, bitstring()} | + {error, nil}. +slice(String, Position, Length) -> + gleam_stdlib:bit_array_slice(String, Position, Length). + +-spec is_utf8(bitstring()) -> boolean(). +is_utf8(Bits) -> + gleam@bit_array:is_utf8(Bits). + +-spec to_string(bitstring()) -> {ok, binary()} | {error, nil}. +to_string(Bits) -> + gleam@bit_array:to_string(Bits). + +-spec concat(list(bitstring())) -> bitstring(). +concat(Bit_strings) -> + gleam_stdlib:bit_array_concat(Bit_strings). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@bool.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@bool.erl new file mode 100644 index 0000000..cd55358 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@bool.erl @@ -0,0 +1,162 @@ +-module(gleam@bool). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export(['and'/2, 'or'/2, negate/1, nor/2, nand/2, exclusive_or/2, exclusive_nor/2, compare/2, max/2, min/2, to_int/1, to_string/1, guard/3, lazy_guard/3]). + +-spec 'and'(boolean(), boolean()) -> boolean(). +'and'(A, B) -> + A andalso B. + +-spec 'or'(boolean(), boolean()) -> boolean(). +'or'(A, B) -> + A orelse B. + +-spec negate(boolean()) -> boolean(). +negate(Bool) -> + case Bool of + true -> + false; + + false -> + true + end. + +-spec nor(boolean(), boolean()) -> boolean(). +nor(A, B) -> + case {A, B} of + {false, false} -> + true; + + {false, true} -> + false; + + {true, false} -> + false; + + {true, true} -> + false + end. + +-spec nand(boolean(), boolean()) -> boolean(). +nand(A, B) -> + case {A, B} of + {false, false} -> + true; + + {false, true} -> + true; + + {true, false} -> + true; + + {true, true} -> + false + end. + +-spec exclusive_or(boolean(), boolean()) -> boolean(). +exclusive_or(A, B) -> + case {A, B} of + {false, false} -> + false; + + {false, true} -> + true; + + {true, false} -> + true; + + {true, true} -> + false + end. + +-spec exclusive_nor(boolean(), boolean()) -> boolean(). +exclusive_nor(A, B) -> + case {A, B} of + {false, false} -> + true; + + {false, true} -> + false; + + {true, false} -> + false; + + {true, true} -> + true + end. + +-spec compare(boolean(), boolean()) -> gleam@order:order(). +compare(A, B) -> + case {A, B} of + {true, true} -> + eq; + + {true, false} -> + gt; + + {false, false} -> + eq; + + {false, true} -> + lt + end. + +-spec max(boolean(), boolean()) -> boolean(). +max(A, B) -> + case A of + true -> + true; + + false -> + B + end. + +-spec min(boolean(), boolean()) -> boolean(). +min(A, B) -> + case A of + false -> + false; + + true -> + B + end. + +-spec to_int(boolean()) -> integer(). +to_int(Bool) -> + case Bool of + false -> + 0; + + true -> + 1 + end. + +-spec to_string(boolean()) -> binary(). +to_string(Bool) -> + case Bool of + false -> + <<"False"/utf8>>; + + true -> + <<"True"/utf8>> + end. + +-spec guard(boolean(), DDZ, fun(() -> DDZ)) -> DDZ. +guard(Requirement, Consequence, Alternative) -> + case Requirement of + true -> + Consequence; + + false -> + Alternative() + end. + +-spec lazy_guard(boolean(), fun(() -> DEA), fun(() -> DEA)) -> DEA. +lazy_guard(Requirement, Consequence, Alternative) -> + case Requirement of + true -> + Consequence(); + + false -> + Alternative() + end. diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@bytes_builder.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@bytes_builder.erl new file mode 100644 index 0000000..2f6dd93 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@bytes_builder.erl @@ -0,0 +1,87 @@ +-module(gleam@bytes_builder). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([append_builder/2, prepend_builder/2, concat/1, new/0, from_string/1, prepend_string/2, append_string/2, from_string_builder/1, from_bit_array/1, prepend/2, append/2, concat_bit_arrays/1, to_bit_array/1, byte_size/1]). +-export_type([bytes_builder/0]). + +-opaque bytes_builder() :: {bytes, bitstring()} | + {text, gleam@string_builder:string_builder()} | + {many, list(bytes_builder())}. + +-spec append_builder(bytes_builder(), bytes_builder()) -> bytes_builder(). +append_builder(First, Second) -> + gleam_stdlib:iodata_append(First, Second). + +-spec prepend_builder(bytes_builder(), bytes_builder()) -> bytes_builder(). +prepend_builder(Second, First) -> + gleam_stdlib:iodata_append(First, Second). + +-spec concat(list(bytes_builder())) -> bytes_builder(). +concat(Builders) -> + gleam_stdlib:identity(Builders). + +-spec new() -> bytes_builder(). +new() -> + gleam_stdlib:identity([]). + +-spec from_string(binary()) -> bytes_builder(). +from_string(String) -> + gleam_stdlib:wrap_list(String). + +-spec prepend_string(bytes_builder(), binary()) -> bytes_builder(). +prepend_string(Second, First) -> + gleam_stdlib:iodata_append(gleam_stdlib:wrap_list(First), Second). + +-spec append_string(bytes_builder(), binary()) -> bytes_builder(). +append_string(First, Second) -> + gleam_stdlib:iodata_append(First, gleam_stdlib:wrap_list(Second)). + +-spec from_string_builder(gleam@string_builder:string_builder()) -> bytes_builder(). +from_string_builder(Builder) -> + gleam_stdlib:wrap_list(Builder). + +-spec from_bit_array(bitstring()) -> bytes_builder(). +from_bit_array(Bits) -> + gleam_stdlib:wrap_list(Bits). + +-spec prepend(bytes_builder(), bitstring()) -> bytes_builder(). +prepend(Second, First) -> + gleam_stdlib:iodata_append(gleam_stdlib:wrap_list(First), Second). + +-spec append(bytes_builder(), bitstring()) -> bytes_builder(). +append(First, Second) -> + gleam_stdlib:iodata_append(First, gleam_stdlib:wrap_list(Second)). + +-spec concat_bit_arrays(list(bitstring())) -> bytes_builder(). +concat_bit_arrays(Bits) -> + gleam_stdlib:identity(Bits). + +-spec to_list(list(list(bytes_builder())), list(bitstring())) -> list(bitstring()). +to_list(Stack, Acc) -> + case Stack of + [] -> + Acc; + + [[] | Remaining_stack] -> + to_list(Remaining_stack, Acc); + + [[{bytes, Bits} | Rest] | Remaining_stack@1] -> + to_list([Rest | Remaining_stack@1], [Bits | Acc]); + + [[{text, Builder} | Rest@1] | Remaining_stack@2] -> + Bits@1 = gleam_stdlib:identity( + gleam@string_builder:to_string(Builder) + ), + to_list([Rest@1 | Remaining_stack@2], [Bits@1 | Acc]); + + [[{many, Builders} | Rest@2] | Remaining_stack@3] -> + to_list([Builders, Rest@2 | Remaining_stack@3], Acc) + end. + +-spec to_bit_array(bytes_builder()) -> bitstring(). +to_bit_array(Builder) -> + erlang:list_to_bitstring(Builder). + +-spec byte_size(bytes_builder()) -> integer(). +byte_size(Builder) -> + erlang:iolist_size(Builder). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@dict.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@dict.erl new file mode 100644 index 0000000..44b89ea --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@dict.erl @@ -0,0 +1,97 @@ +-module(gleam@dict). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([size/1, to_list/1, from_list/1, has_key/2, new/0, get/2, insert/3, map_values/2, keys/1, values/1, filter/2, take/2, merge/2, delete/2, drop/2, update/3, fold/3]). +-export_type([dict/2]). + +-type dict(KS, KT) :: any() | {gleam_phantom, KS, KT}. + +-spec size(dict(any(), any())) -> integer(). +size(Dict) -> + maps:size(Dict). + +-spec to_list(dict(LC, LD)) -> list({LC, LD}). +to_list(Dict) -> + maps:to_list(Dict). + +-spec from_list(list({LM, LN})) -> dict(LM, LN). +from_list(List) -> + maps:from_list(List). + +-spec has_key(dict(LW, any()), LW) -> boolean(). +has_key(Dict, Key) -> + maps:is_key(Key, Dict). + +-spec new() -> dict(any(), any()). +new() -> + maps:new(). + +-spec get(dict(MM, MN), MM) -> {ok, MN} | {error, nil}. +get(From, Get) -> + gleam_stdlib:map_get(From, Get). + +-spec insert(dict(MY, MZ), MY, MZ) -> dict(MY, MZ). +insert(Dict, Key, Value) -> + maps:put(Key, Value, Dict). + +-spec map_values(dict(NK, NL), fun((NK, NL) -> NO)) -> dict(NK, NO). +map_values(Dict, Fun) -> + maps:map(Fun, Dict). + +-spec keys(dict(NY, any())) -> list(NY). +keys(Dict) -> + maps:keys(Dict). + +-spec values(dict(any(), OJ)) -> list(OJ). +values(Dict) -> + maps:values(Dict). + +-spec filter(dict(OS, OT), fun((OS, OT) -> boolean())) -> dict(OS, OT). +filter(Dict, Predicate) -> + maps:filter(Predicate, Dict). + +-spec take(dict(PE, PF), list(PE)) -> dict(PE, PF). +take(Dict, Desired_keys) -> + maps:with(Desired_keys, Dict). + +-spec merge(dict(PS, PT), dict(PS, PT)) -> dict(PS, PT). +merge(Dict, New_entries) -> + maps:merge(Dict, New_entries). + +-spec delete(dict(QI, QJ), QI) -> dict(QI, QJ). +delete(Dict, Key) -> + maps:remove(Key, Dict). + +-spec drop(dict(QU, QV), list(QU)) -> dict(QU, QV). +drop(Dict, Disallowed_keys) -> + case Disallowed_keys of + [] -> + Dict; + + [X | Xs] -> + drop(delete(Dict, X), Xs) + end. + +-spec update(dict(RB, RC), RB, fun((gleam@option:option(RC)) -> RC)) -> dict(RB, RC). +update(Dict, Key, Fun) -> + _pipe = Dict, + _pipe@1 = get(_pipe, Key), + _pipe@2 = gleam@option:from_result(_pipe@1), + _pipe@3 = Fun(_pipe@2), + insert(Dict, Key, _pipe@3). + +-spec do_fold(list({RI, RJ}), RL, fun((RL, RI, RJ) -> RL)) -> RL. +do_fold(List, Initial, Fun) -> + case List of + [] -> + Initial; + + [{K, V} | Rest] -> + do_fold(Rest, Fun(Initial, K, V), Fun) + end. + +-spec fold(dict(RM, RN), RQ, fun((RQ, RM, RN) -> RQ)) -> RQ. +fold(Dict, Initial, Fun) -> + _pipe = Dict, + _pipe@1 = to_list(_pipe), + do_fold(_pipe@1, Initial, Fun). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@dynamic.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@dynamic.erl new file mode 100644 index 0000000..38f4b4e --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@dynamic.erl @@ -0,0 +1,808 @@ +-module(gleam@dynamic). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([from/1, unsafe_coerce/1, dynamic/1, bit_array/1, bit_string/1, classify/1, int/1, float/1, bool/1, shallow_list/1, optional/1, any/1, decode1/2, result/2, list/1, string/1, field/2, optional_field/2, element/2, tuple2/2, tuple3/3, tuple4/4, tuple5/5, tuple6/6, dict/2, map/2, decode2/3, decode3/4, decode4/5, decode5/6, decode6/7, decode7/8, decode8/9, decode9/10]). +-export_type([dynamic_/0, decode_error/0, unknown_tuple/0]). + +-type dynamic_() :: any(). + +-type decode_error() :: {decode_error, binary(), binary(), list(binary())}. + +-type unknown_tuple() :: any(). + +-spec from(any()) -> dynamic_(). +from(A) -> + gleam_stdlib:identity(A). + +-spec unsafe_coerce(dynamic_()) -> any(). +unsafe_coerce(A) -> + gleam_stdlib:identity(A). + +-spec dynamic(dynamic_()) -> {ok, dynamic_()} | {error, list(decode_error())}. +dynamic(Value) -> + {ok, Value}. + +-spec bit_array(dynamic_()) -> {ok, bitstring()} | {error, list(decode_error())}. +bit_array(Data) -> + gleam_stdlib:decode_bit_array(Data). + +-spec bit_string(dynamic_()) -> {ok, bitstring()} | + {error, list(decode_error())}. +bit_string(Data) -> + bit_array(Data). + +-spec put_expected(decode_error(), binary()) -> decode_error(). +put_expected(Error, Expected) -> + erlang:setelement(2, Error, Expected). + +-spec classify(dynamic_()) -> binary(). +classify(Data) -> + gleam_stdlib:classify_dynamic(Data). + +-spec int(dynamic_()) -> {ok, integer()} | {error, list(decode_error())}. +int(Data) -> + gleam_stdlib:decode_int(Data). + +-spec float(dynamic_()) -> {ok, float()} | {error, list(decode_error())}. +float(Data) -> + gleam_stdlib:decode_float(Data). + +-spec bool(dynamic_()) -> {ok, boolean()} | {error, list(decode_error())}. +bool(Data) -> + gleam_stdlib:decode_bool(Data). + +-spec shallow_list(dynamic_()) -> {ok, list(dynamic_())} | + {error, list(decode_error())}. +shallow_list(Value) -> + gleam_stdlib:decode_list(Value). + +-spec optional(fun((dynamic_()) -> {ok, DZX} | {error, list(decode_error())})) -> fun((dynamic_()) -> {ok, + gleam@option:option(DZX)} | + {error, list(decode_error())}). +optional(Decode) -> + fun(Value) -> gleam_stdlib:decode_option(Value, Decode) end. + +-spec at_least_decode_tuple_error(integer(), dynamic_()) -> {ok, any()} | + {error, list(decode_error())}. +at_least_decode_tuple_error(Size, Data) -> + S = case Size of + 1 -> + <<""/utf8>>; + + _ -> + <<"s"/utf8>> + end, + Error = begin + _pipe = [<<"Tuple of at least "/utf8>>, + gleam@int:to_string(Size), + <<" element"/utf8>>, + S], + _pipe@1 = gleam@string_builder:from_strings(_pipe), + _pipe@2 = gleam@string_builder:to_string(_pipe@1), + {decode_error, _pipe@2, classify(Data), []} + end, + {error, [Error]}. + +-spec any(list(fun((dynamic_()) -> {ok, EEE} | {error, list(decode_error())}))) -> fun((dynamic_()) -> {ok, + EEE} | + {error, list(decode_error())}). +any(Decoders) -> + fun(Data) -> case Decoders of + [] -> + {error, + [{decode_error, <<"another type"/utf8>>, classify(Data), []}]}; + + [Decoder | Decoders@1] -> + case Decoder(Data) of + {ok, Decoded} -> + {ok, Decoded}; + + {error, _} -> + (any(Decoders@1))(Data) + end + end end. + +-spec all_errors({ok, any()} | {error, list(decode_error())}) -> list(decode_error()). +all_errors(Result) -> + case Result of + {ok, _} -> + []; + + {error, Errors} -> + Errors + end. + +-spec decode1( + fun((EEI) -> EEJ), + fun((dynamic_()) -> {ok, EEI} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EEJ} | {error, list(decode_error())}). +decode1(Constructor, T1) -> + fun(Value) -> case T1(Value) of + {ok, A} -> + {ok, Constructor(A)}; + + A@1 -> + {error, all_errors(A@1)} + end end. + +-spec push_path(decode_error(), any()) -> decode_error(). +push_path(Error, Name) -> + Name@1 = from(Name), + Decoder = any( + [fun string/1, + fun(X) -> gleam@result:map(int(X), fun gleam@int:to_string/1) end] + ), + Name@3 = case Decoder(Name@1) of + {ok, Name@2} -> + Name@2; + + {error, _} -> + _pipe = [<<"<"/utf8>>, classify(Name@1), <<">"/utf8>>], + _pipe@1 = gleam@string_builder:from_strings(_pipe), + gleam@string_builder:to_string(_pipe@1) + end, + erlang:setelement(4, Error, [Name@3 | erlang:element(4, Error)]). + +-spec result( + fun((dynamic_()) -> {ok, DZL} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DZN} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {ok, DZL} | {error, DZN}} | + {error, list(decode_error())}). +result(Decode_ok, Decode_error) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_result(Value), + fun(Inner_result) -> case Inner_result of + {ok, Raw} -> + gleam@result:'try'( + begin + _pipe = Decode_ok(Raw), + map_errors( + _pipe, + fun(_capture) -> + push_path(_capture, <<"ok"/utf8>>) + end + ) + end, + fun(Value@1) -> {ok, {ok, Value@1}} end + ); + + {error, Raw@1} -> + gleam@result:'try'( + begin + _pipe@1 = Decode_error(Raw@1), + map_errors( + _pipe@1, + fun(_capture@1) -> + push_path(_capture@1, <<"error"/utf8>>) + end + ) + end, + fun(Value@2) -> {ok, {error, Value@2}} end + ) + end end + ) + end. + +-spec list(fun((dynamic_()) -> {ok, DZS} | {error, list(decode_error())})) -> fun((dynamic_()) -> {ok, + list(DZS)} | + {error, list(decode_error())}). +list(Decoder_type) -> + fun(Dynamic) -> + gleam@result:'try'(shallow_list(Dynamic), fun(List) -> _pipe = List, + _pipe@1 = gleam@list:try_map(_pipe, Decoder_type), + map_errors( + _pipe@1, + fun(_capture) -> push_path(_capture, <<"*"/utf8>>) end + ) end) + end. + +-spec map_errors( + {ok, DYG} | {error, list(decode_error())}, + fun((decode_error()) -> decode_error()) +) -> {ok, DYG} | {error, list(decode_error())}. +map_errors(Result, F) -> + gleam@result:map_error( + Result, + fun(_capture) -> gleam@list:map(_capture, F) end + ). + +-spec decode_string(dynamic_()) -> {ok, binary()} | + {error, list(decode_error())}. +decode_string(Data) -> + _pipe = bit_array(Data), + _pipe@1 = map_errors( + _pipe, + fun(_capture) -> put_expected(_capture, <<"String"/utf8>>) end + ), + gleam@result:'try'( + _pipe@1, + fun(Raw) -> case gleam@bit_array:to_string(Raw) of + {ok, String} -> + {ok, String}; + + {error, nil} -> + {error, + [{decode_error, + <<"String"/utf8>>, + <<"BitArray"/utf8>>, + []}]} + end end + ). + +-spec string(dynamic_()) -> {ok, binary()} | {error, list(decode_error())}. +string(Data) -> + decode_string(Data). + +-spec field( + any(), + fun((dynamic_()) -> {ok, EAH} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EAH} | {error, list(decode_error())}). +field(Name, Inner_type) -> + fun(Value) -> + Missing_field_error = {decode_error, + <<"field"/utf8>>, + <<"nothing"/utf8>>, + []}, + gleam@result:'try'( + gleam_stdlib:decode_field(Value, Name), + fun(Maybe_inner) -> _pipe = Maybe_inner, + _pipe@1 = gleam@option:to_result(_pipe, [Missing_field_error]), + _pipe@2 = gleam@result:'try'(_pipe@1, Inner_type), + map_errors( + _pipe@2, + fun(_capture) -> push_path(_capture, Name) end + ) end + ) + end. + +-spec optional_field( + any(), + fun((dynamic_()) -> {ok, EAL} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, gleam@option:option(EAL)} | + {error, list(decode_error())}). +optional_field(Name, Inner_type) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_field(Value, Name), + fun(Maybe_inner) -> case Maybe_inner of + none -> + {ok, none}; + + {some, Dynamic_inner} -> + _pipe = Dynamic_inner, + _pipe@1 = gleam_stdlib:decode_option(_pipe, Inner_type), + map_errors( + _pipe@1, + fun(_capture) -> push_path(_capture, Name) end + ) + end end + ) + end. + +-spec element( + integer(), + fun((dynamic_()) -> {ok, EAT} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EAT} | {error, list(decode_error())}). +element(Index, Inner_type) -> + fun(Data) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple(Data), + fun(Tuple) -> + Size = gleam_stdlib:size_of_tuple(Tuple), + gleam@result:'try'(case Index >= 0 of + true -> + case Index < Size of + true -> + gleam_stdlib:tuple_get(Tuple, Index); + + false -> + at_least_decode_tuple_error(Index + 1, Data) + end; + + false -> + case gleam@int:absolute_value(Index) =< Size of + true -> + gleam_stdlib:tuple_get(Tuple, Size + Index); + + false -> + at_least_decode_tuple_error( + gleam@int:absolute_value(Index), + Data + ) + end + end, fun(Data@1) -> _pipe = Inner_type(Data@1), + map_errors( + _pipe, + fun(_capture) -> push_path(_capture, Index) end + ) end) + end + ) + end. + +-spec tuple_errors({ok, any()} | {error, list(decode_error())}, binary()) -> list(decode_error()). +tuple_errors(Result, Name) -> + case Result of + {ok, _} -> + []; + + {error, Errors} -> + gleam@list:map( + Errors, + fun(_capture) -> push_path(_capture, Name) end + ) + end. + +-spec tuple2( + fun((dynamic_()) -> {ok, EBT} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EBV} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {EBT, EBV}} | {error, list(decode_error())}). +tuple2(Decode1, Decode2) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple2(Value), + fun(_use0) -> + {A, B} = _use0, + case {Decode1(A), Decode2(B)} of + {{ok, A@1}, {ok, B@1}} -> + {ok, {A@1, B@1}}; + + {A@2, B@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + {error, _pipe@1} + end + end + ) + end. + +-spec tuple3( + fun((dynamic_()) -> {ok, EBY} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECA} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECC} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {EBY, ECA, ECC}} | {error, list(decode_error())}). +tuple3(Decode1, Decode2, Decode3) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple3(Value), + fun(_use0) -> + {A, B, C} = _use0, + case {Decode1(A), Decode2(B), Decode3(C)} of + {{ok, A@1}, {ok, B@1}, {ok, C@1}} -> + {ok, {A@1, B@1, C@1}}; + + {A@2, B@2, C@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + {error, _pipe@2} + end + end + ) + end. + +-spec tuple4( + fun((dynamic_()) -> {ok, ECF} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECH} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECJ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECL} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {ECF, ECH, ECJ, ECL}} | + {error, list(decode_error())}). +tuple4(Decode1, Decode2, Decode3, Decode4) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple4(Value), + fun(_use0) -> + {A, B, C, D} = _use0, + case {Decode1(A), Decode2(B), Decode3(C), Decode4(D)} of + {{ok, A@1}, {ok, B@1}, {ok, C@1}, {ok, D@1}} -> + {ok, {A@1, B@1, C@1, D@1}}; + + {A@2, B@2, C@2, D@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + _pipe@3 = gleam@list:append( + _pipe@2, + tuple_errors(D@2, <<"3"/utf8>>) + ), + {error, _pipe@3} + end + end + ) + end. + +-spec tuple5( + fun((dynamic_()) -> {ok, ECO} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECQ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECS} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECU} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, ECW} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {ECO, ECQ, ECS, ECU, ECW}} | + {error, list(decode_error())}). +tuple5(Decode1, Decode2, Decode3, Decode4, Decode5) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple5(Value), + fun(_use0) -> + {A, B, C, D, E} = _use0, + case {Decode1(A), + Decode2(B), + Decode3(C), + Decode4(D), + Decode5(E)} of + {{ok, A@1}, {ok, B@1}, {ok, C@1}, {ok, D@1}, {ok, E@1}} -> + {ok, {A@1, B@1, C@1, D@1, E@1}}; + + {A@2, B@2, C@2, D@2, E@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + _pipe@3 = gleam@list:append( + _pipe@2, + tuple_errors(D@2, <<"3"/utf8>>) + ), + _pipe@4 = gleam@list:append( + _pipe@3, + tuple_errors(E@2, <<"4"/utf8>>) + ), + {error, _pipe@4} + end + end + ) + end. + +-spec tuple6( + fun((dynamic_()) -> {ok, ECZ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EDB} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EDD} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EDF} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EDH} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EDJ} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {ECZ, EDB, EDD, EDF, EDH, EDJ}} | + {error, list(decode_error())}). +tuple6(Decode1, Decode2, Decode3, Decode4, Decode5, Decode6) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple6(Value), + fun(_use0) -> + {A, B, C, D, E, F} = _use0, + case {Decode1(A), + Decode2(B), + Decode3(C), + Decode4(D), + Decode5(E), + Decode6(F)} of + {{ok, A@1}, + {ok, B@1}, + {ok, C@1}, + {ok, D@1}, + {ok, E@1}, + {ok, F@1}} -> + {ok, {A@1, B@1, C@1, D@1, E@1, F@1}}; + + {A@2, B@2, C@2, D@2, E@2, F@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + _pipe@3 = gleam@list:append( + _pipe@2, + tuple_errors(D@2, <<"3"/utf8>>) + ), + _pipe@4 = gleam@list:append( + _pipe@3, + tuple_errors(E@2, <<"4"/utf8>>) + ), + _pipe@5 = gleam@list:append( + _pipe@4, + tuple_errors(F@2, <<"5"/utf8>>) + ), + {error, _pipe@5} + end + end + ) + end. + +-spec dict( + fun((dynamic_()) -> {ok, EDM} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EDO} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, gleam@dict:dict(EDM, EDO)} | + {error, list(decode_error())}). +dict(Key_type, Value_type) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_map(Value), + fun(Map) -> + gleam@result:'try'( + begin + _pipe = Map, + _pipe@1 = gleam@dict:to_list(_pipe), + gleam@list:try_map( + _pipe@1, + fun(Pair) -> + {K, V} = Pair, + gleam@result:'try'( + begin + _pipe@2 = Key_type(K), + map_errors( + _pipe@2, + fun(_capture) -> + push_path( + _capture, + <<"keys"/utf8>> + ) + end + ) + end, + fun(K@1) -> + gleam@result:'try'( + begin + _pipe@3 = Value_type(V), + map_errors( + _pipe@3, + fun(_capture@1) -> + push_path( + _capture@1, + <<"values"/utf8>> + ) + end + ) + end, + fun(V@1) -> {ok, {K@1, V@1}} end + ) + end + ) + end + ) + end, + fun(Pairs) -> {ok, gleam@dict:from_list(Pairs)} end + ) + end + ) + end. + +-spec map( + fun((dynamic_()) -> {ok, EDT} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EDV} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, gleam@dict:dict(EDT, EDV)} | + {error, list(decode_error())}). +map(Key_type, Value_type) -> + dict(Key_type, Value_type). + +-spec decode2( + fun((EEM, EEN) -> EEO), + fun((dynamic_()) -> {ok, EEM} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EEN} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EEO} | {error, list(decode_error())}). +decode2(Constructor, T1, T2) -> + fun(Value) -> case {T1(Value), T2(Value)} of + {{ok, A}, {ok, B}} -> + {ok, Constructor(A, B)}; + + {A@1, B@1} -> + {error, gleam@list:concat([all_errors(A@1), all_errors(B@1)])} + end end. + +-spec decode3( + fun((EES, EET, EEU) -> EEV), + fun((dynamic_()) -> {ok, EES} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EET} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EEU} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EEV} | {error, list(decode_error())}). +decode3(Constructor, T1, T2, T3) -> + fun(Value) -> case {T1(Value), T2(Value), T3(Value)} of + {{ok, A}, {ok, B}, {ok, C}} -> + {ok, Constructor(A, B, C)}; + + {A@1, B@1, C@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), all_errors(B@1), all_errors(C@1)] + )} + end end. + +-spec decode4( + fun((EFA, EFB, EFC, EFD) -> EFE), + fun((dynamic_()) -> {ok, EFA} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EFB} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EFC} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EFD} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EFE} | {error, list(decode_error())}). +decode4(Constructor, T1, T2, T3, T4) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}} -> + {ok, Constructor(A, B, C, D)}; + + {A@1, B@1, C@1, D@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1)] + )} + end end. + +-spec decode5( + fun((EFK, EFL, EFM, EFN, EFO) -> EFP), + fun((dynamic_()) -> {ok, EFK} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EFL} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EFM} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EFN} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EFO} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EFP} | {error, list(decode_error())}). +decode5(Constructor, T1, T2, T3, T4, T5) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}, {ok, E}} -> + {ok, Constructor(A, B, C, D, E)}; + + {A@1, B@1, C@1, D@1, E@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1)] + )} + end end. + +-spec decode6( + fun((EFW, EFX, EFY, EFZ, EGA, EGB) -> EGC), + fun((dynamic_()) -> {ok, EFW} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EFX} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EFY} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EFZ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EGA} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EGB} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EGC} | {error, list(decode_error())}). +decode6(Constructor, T1, T2, T3, T4, T5, T6) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}, {ok, E}, {ok, F}} -> + {ok, Constructor(A, B, C, D, E, F)}; + + {A@1, B@1, C@1, D@1, E@1, F@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1)] + )} + end end. + +-spec decode7( + fun((EGK, EGL, EGM, EGN, EGO, EGP, EGQ) -> EGR), + fun((dynamic_()) -> {ok, EGK} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EGL} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EGM} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EGN} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EGO} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EGP} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EGQ} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EGR} | {error, list(decode_error())}). +decode7(Constructor, T1, T2, T3, T4, T5, T6, T7) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X), T7(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}, {ok, E}, {ok, F}, {ok, G}} -> + {ok, Constructor(A, B, C, D, E, F, G)}; + + {A@1, B@1, C@1, D@1, E@1, F@1, G@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1), + all_errors(G@1)] + )} + end end. + +-spec decode8( + fun((EHA, EHB, EHC, EHD, EHE, EHF, EHG, EHH) -> EHI), + fun((dynamic_()) -> {ok, EHA} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHB} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHC} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHD} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHE} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHF} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHG} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHH} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EHI} | {error, list(decode_error())}). +decode8(Constructor, T1, T2, T3, T4, T5, T6, T7, T8) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X), T7(X), T8(X)} of + {{ok, A}, + {ok, B}, + {ok, C}, + {ok, D}, + {ok, E}, + {ok, F}, + {ok, G}, + {ok, H}} -> + {ok, Constructor(A, B, C, D, E, F, G, H)}; + + {A@1, B@1, C@1, D@1, E@1, F@1, G@1, H@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1), + all_errors(G@1), + all_errors(H@1)] + )} + end end. + +-spec decode9( + fun((EHS, EHT, EHU, EHV, EHW, EHX, EHY, EHZ, EIA) -> EIB), + fun((dynamic_()) -> {ok, EHS} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHT} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHU} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHV} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHW} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHX} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHY} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EHZ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, EIA} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, EIB} | {error, list(decode_error())}). +decode9(Constructor, T1, T2, T3, T4, T5, T6, T7, T8, T9) -> + fun(X) -> + case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X), T7(X), T8(X), T9(X)} of + {{ok, A}, + {ok, B}, + {ok, C}, + {ok, D}, + {ok, E}, + {ok, F}, + {ok, G}, + {ok, H}, + {ok, I}} -> + {ok, Constructor(A, B, C, D, E, F, G, H, I)}; + + {A@1, B@1, C@1, D@1, E@1, F@1, G@1, H@1, I@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1), + all_errors(G@1), + all_errors(H@1), + all_errors(I@1)] + )} + end + end. diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@float.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@float.erl new file mode 100644 index 0000000..33b3d4a --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@float.erl @@ -0,0 +1,181 @@ +-module(gleam@float). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([parse/1, to_string/1, compare/2, min/2, max/2, clamp/3, ceiling/1, floor/1, round/1, truncate/1, absolute_value/1, loosely_compare/3, loosely_equals/3, power/2, square_root/1, negate/1, sum/1, product/1, random/2, divide/2, add/2, multiply/2, subtract/2]). + +-spec parse(binary()) -> {ok, float()} | {error, nil}. +parse(String) -> + gleam_stdlib:parse_float(String). + +-spec to_string(float()) -> binary(). +to_string(X) -> + gleam_stdlib:float_to_string(X). + +-spec compare(float(), float()) -> gleam@order:order(). +compare(A, B) -> + case A =:= B of + true -> + eq; + + false -> + case A < B of + true -> + lt; + + false -> + gt + end + end. + +-spec min(float(), float()) -> float(). +min(A, B) -> + case A < B of + true -> + A; + + false -> + B + end. + +-spec max(float(), float()) -> float(). +max(A, B) -> + case A > B of + true -> + A; + + false -> + B + end. + +-spec clamp(float(), float(), float()) -> float(). +clamp(X, Min_bound, Max_bound) -> + _pipe = X, + _pipe@1 = min(_pipe, Max_bound), + max(_pipe@1, Min_bound). + +-spec ceiling(float()) -> float(). +ceiling(X) -> + math:ceil(X). + +-spec floor(float()) -> float(). +floor(X) -> + math:floor(X). + +-spec round(float()) -> integer(). +round(X) -> + erlang:round(X). + +-spec truncate(float()) -> integer(). +truncate(X) -> + erlang:trunc(X). + +-spec absolute_value(float()) -> float(). +absolute_value(X) -> + case X >= +0.0 of + true -> + X; + + _ -> + +0.0 - X + end. + +-spec loosely_compare(float(), float(), float()) -> gleam@order:order(). +loosely_compare(A, B, Tolerance) -> + Difference = absolute_value(A - B), + case Difference =< Tolerance of + true -> + eq; + + false -> + compare(A, B) + end. + +-spec loosely_equals(float(), float(), float()) -> boolean(). +loosely_equals(A, B, Tolerance) -> + Difference = absolute_value(A - B), + Difference =< Tolerance. + +-spec power(float(), float()) -> {ok, float()} | {error, nil}. +power(Base, Exponent) -> + Fractional = (ceiling(Exponent) - Exponent) > +0.0, + case ((Base < +0.0) andalso Fractional) orelse ((Base =:= +0.0) andalso (Exponent + < +0.0)) of + true -> + {error, nil}; + + false -> + {ok, math:pow(Base, Exponent)} + end. + +-spec square_root(float()) -> {ok, float()} | {error, nil}. +square_root(X) -> + power(X, 0.5). + +-spec negate(float()) -> float(). +negate(X) -> + -1.0 * X. + +-spec do_sum(list(float()), float()) -> float(). +do_sum(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_sum(Rest, X + Initial) + end. + +-spec sum(list(float())) -> float(). +sum(Numbers) -> + _pipe = Numbers, + do_sum(_pipe, +0.0). + +-spec do_product(list(float()), float()) -> float(). +do_product(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_product(Rest, X * Initial) + end. + +-spec product(list(float())) -> float(). +product(Numbers) -> + case Numbers of + [] -> + 1.0; + + _ -> + do_product(Numbers, 1.0) + end. + +-spec random(float(), float()) -> float(). +random(Min, Max) -> + (rand:uniform() * (Max - Min)) + Min. + +-spec divide(float(), float()) -> {ok, float()} | {error, nil}. +divide(A, B) -> + case B of + +0.0 -> + {error, nil}; + + B@1 -> + {ok, case B@1 of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> A / Gleam@denominator + end} + end. + +-spec add(float(), float()) -> float(). +add(A, B) -> + A + B. + +-spec multiply(float(), float()) -> float(). +multiply(A, B) -> + A * B. + +-spec subtract(float(), float()) -> float(). +subtract(A, B) -> + A - B. diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@function.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@function.erl new file mode 100644 index 0000000..3496318 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@function.erl @@ -0,0 +1,67 @@ +-module(gleam@function). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([compose/2, curry2/1, curry3/1, curry4/1, curry5/1, curry6/1, flip/1, identity/1, constant/1, tap/2, apply1/2, apply2/3, apply3/4]). + +-spec compose(fun((DOO) -> DOP), fun((DOP) -> DOQ)) -> fun((DOO) -> DOQ). +compose(Fun1, Fun2) -> + fun(A) -> Fun2(Fun1(A)) end. + +-spec curry2(fun((DOR, DOS) -> DOT)) -> fun((DOR) -> fun((DOS) -> DOT)). +curry2(Fun) -> + fun(A) -> fun(B) -> Fun(A, B) end end. + +-spec curry3(fun((DOV, DOW, DOX) -> DOY)) -> fun((DOV) -> fun((DOW) -> fun((DOX) -> DOY))). +curry3(Fun) -> + fun(A) -> fun(B) -> fun(C) -> Fun(A, B, C) end end end. + +-spec curry4(fun((DPA, DPB, DPC, DPD) -> DPE)) -> fun((DPA) -> fun((DPB) -> fun((DPC) -> fun((DPD) -> DPE)))). +curry4(Fun) -> + fun(A) -> fun(B) -> fun(C) -> fun(D) -> Fun(A, B, C, D) end end end end. + +-spec curry5(fun((DPG, DPH, DPI, DPJ, DPK) -> DPL)) -> fun((DPG) -> fun((DPH) -> fun((DPI) -> fun((DPJ) -> fun((DPK) -> DPL))))). +curry5(Fun) -> + fun(A) -> + fun(B) -> + fun(C) -> fun(D) -> fun(E) -> Fun(A, B, C, D, E) end end end + end + end. + +-spec curry6(fun((DPN, DPO, DPP, DPQ, DPR, DPS) -> DPT)) -> fun((DPN) -> fun((DPO) -> fun((DPP) -> fun((DPQ) -> fun((DPR) -> fun((DPS) -> DPT)))))). +curry6(Fun) -> + fun(A) -> + fun(B) -> + fun(C) -> + fun(D) -> fun(E) -> fun(F) -> Fun(A, B, C, D, E, F) end end end + end + end + end. + +-spec flip(fun((DPV, DPW) -> DPX)) -> fun((DPW, DPV) -> DPX). +flip(Fun) -> + fun(B, A) -> Fun(A, B) end. + +-spec identity(DPY) -> DPY. +identity(X) -> + X. + +-spec constant(DPZ) -> fun((any()) -> DPZ). +constant(Value) -> + fun(_) -> Value end. + +-spec tap(DQB, fun((DQB) -> any())) -> DQB. +tap(Arg, Effect) -> + Effect(Arg), + Arg. + +-spec apply1(fun((DQD) -> DQE), DQD) -> DQE. +apply1(Fun, Arg1) -> + Fun(Arg1). + +-spec apply2(fun((DQF, DQG) -> DQH), DQF, DQG) -> DQH. +apply2(Fun, Arg1, Arg2) -> + Fun(Arg1, Arg2). + +-spec apply3(fun((DQI, DQJ, DQK) -> DQL), DQI, DQJ, DQK) -> DQL. +apply3(Fun, Arg1, Arg2, Arg3) -> + Fun(Arg1, Arg2, Arg3). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@int.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@int.erl new file mode 100644 index 0000000..2a5dd2c --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@int.erl @@ -0,0 +1,332 @@ +-module(gleam@int). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([absolute_value/1, parse/1, base_parse/2, to_string/1, to_base_string/2, to_base2/1, to_base8/1, to_base16/1, to_base36/1, to_float/1, power/2, square_root/1, compare/2, min/2, max/2, clamp/3, is_even/1, is_odd/1, negate/1, sum/1, product/1, digits/2, undigits/2, random/2, divide/2, remainder/2, modulo/2, floor_divide/2, add/2, multiply/2, subtract/2, bitwise_and/2, bitwise_not/1, bitwise_or/2, bitwise_exclusive_or/2, bitwise_shift_left/2, bitwise_shift_right/2]). +-export_type([invalid_base/0]). + +-type invalid_base() :: invalid_base. + +-spec absolute_value(integer()) -> integer(). +absolute_value(X) -> + case X >= 0 of + true -> + X; + + false -> + X * -1 + end. + +-spec parse(binary()) -> {ok, integer()} | {error, nil}. +parse(String) -> + gleam_stdlib:parse_int(String). + +-spec base_parse(binary(), integer()) -> {ok, integer()} | {error, nil}. +base_parse(String, Base) -> + case (Base >= 2) andalso (Base =< 36) of + true -> + gleam_stdlib:int_from_base_string(String, Base); + + false -> + {error, nil} + end. + +-spec to_string(integer()) -> binary(). +to_string(X) -> + erlang:integer_to_binary(X). + +-spec to_base_string(integer(), integer()) -> {ok, binary()} | + {error, invalid_base()}. +to_base_string(X, Base) -> + case (Base >= 2) andalso (Base =< 36) of + true -> + {ok, erlang:integer_to_binary(X, Base)}; + + false -> + {error, invalid_base} + end. + +-spec to_base2(integer()) -> binary(). +to_base2(X) -> + erlang:integer_to_binary(X, 2). + +-spec to_base8(integer()) -> binary(). +to_base8(X) -> + erlang:integer_to_binary(X, 8). + +-spec to_base16(integer()) -> binary(). +to_base16(X) -> + erlang:integer_to_binary(X, 16). + +-spec to_base36(integer()) -> binary(). +to_base36(X) -> + erlang:integer_to_binary(X, 36). + +-spec to_float(integer()) -> float(). +to_float(X) -> + erlang:float(X). + +-spec power(integer(), float()) -> {ok, float()} | {error, nil}. +power(Base, Exponent) -> + _pipe = Base, + _pipe@1 = to_float(_pipe), + gleam@float:power(_pipe@1, Exponent). + +-spec square_root(integer()) -> {ok, float()} | {error, nil}. +square_root(X) -> + _pipe = X, + _pipe@1 = to_float(_pipe), + gleam@float:square_root(_pipe@1). + +-spec compare(integer(), integer()) -> gleam@order:order(). +compare(A, B) -> + case A =:= B of + true -> + eq; + + false -> + case A < B of + true -> + lt; + + false -> + gt + end + end. + +-spec min(integer(), integer()) -> integer(). +min(A, B) -> + case A < B of + true -> + A; + + false -> + B + end. + +-spec max(integer(), integer()) -> integer(). +max(A, B) -> + case A > B of + true -> + A; + + false -> + B + end. + +-spec clamp(integer(), integer(), integer()) -> integer(). +clamp(X, Min_bound, Max_bound) -> + _pipe = X, + _pipe@1 = min(_pipe, Max_bound), + max(_pipe@1, Min_bound). + +-spec is_even(integer()) -> boolean(). +is_even(X) -> + (X rem 2) =:= 0. + +-spec is_odd(integer()) -> boolean(). +is_odd(X) -> + (X rem 2) /= 0. + +-spec negate(integer()) -> integer(). +negate(X) -> + -1 * X. + +-spec do_sum(list(integer()), integer()) -> integer(). +do_sum(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_sum(Rest, X + Initial) + end. + +-spec sum(list(integer())) -> integer(). +sum(Numbers) -> + _pipe = Numbers, + do_sum(_pipe, 0). + +-spec do_product(list(integer()), integer()) -> integer(). +do_product(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_product(Rest, X * Initial) + end. + +-spec product(list(integer())) -> integer(). +product(Numbers) -> + case Numbers of + [] -> + 1; + + _ -> + do_product(Numbers, 1) + end. + +-spec do_digits(integer(), integer(), list(integer())) -> list(integer()). +do_digits(X, Base, Acc) -> + case absolute_value(X) < Base of + true -> + [X | Acc]; + + false -> + do_digits(case Base of + 0 -> 0; + Gleam@denominator -> X div Gleam@denominator + end, Base, [case Base of + 0 -> 0; + Gleam@denominator@1 -> X rem Gleam@denominator@1 + end | Acc]) + end. + +-spec digits(integer(), integer()) -> {ok, list(integer())} | + {error, invalid_base()}. +digits(X, Base) -> + case Base < 2 of + true -> + {error, invalid_base}; + + false -> + {ok, do_digits(X, Base, [])} + end. + +-spec do_undigits(list(integer()), integer(), integer()) -> {ok, integer()} | + {error, invalid_base()}. +do_undigits(Numbers, Base, Acc) -> + case Numbers of + [] -> + {ok, Acc}; + + [Digit | _] when Digit >= Base -> + {error, invalid_base}; + + [Digit@1 | Rest] -> + do_undigits(Rest, Base, (Acc * Base) + Digit@1) + end. + +-spec undigits(list(integer()), integer()) -> {ok, integer()} | + {error, invalid_base()}. +undigits(Numbers, Base) -> + case Base < 2 of + true -> + {error, invalid_base}; + + false -> + do_undigits(Numbers, Base, 0) + end. + +-spec random(integer(), integer()) -> integer(). +random(Min, Max) -> + _pipe = gleam@float:random(to_float(Min), to_float(Max)), + _pipe@1 = gleam@float:floor(_pipe), + gleam@float:round(_pipe@1). + +-spec divide(integer(), integer()) -> {ok, integer()} | {error, nil}. +divide(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + Divisor@1 -> + {ok, case Divisor@1 of + 0 -> 0; + Gleam@denominator -> Dividend div Gleam@denominator + end} + end. + +-spec remainder(integer(), integer()) -> {ok, integer()} | {error, nil}. +remainder(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + Divisor@1 -> + {ok, case Divisor@1 of + 0 -> 0; + Gleam@denominator -> Dividend rem Gleam@denominator + end} + end. + +-spec modulo(integer(), integer()) -> {ok, integer()} | {error, nil}. +modulo(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + _ -> + Remainder = case Divisor of + 0 -> 0; + Gleam@denominator -> Dividend rem Gleam@denominator + end, + case (Remainder * Divisor) < 0 of + true -> + {ok, Remainder + Divisor}; + + false -> + {ok, Remainder} + end + end. + +-spec floor_divide(integer(), integer()) -> {ok, integer()} | {error, nil}. +floor_divide(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + Divisor@1 -> + case ((Dividend * Divisor@1) < 0) andalso ((case Divisor@1 of + 0 -> 0; + Gleam@denominator -> Dividend rem Gleam@denominator + end) /= 0) of + true -> + {ok, (case Divisor@1 of + 0 -> 0; + Gleam@denominator@1 -> Dividend div Gleam@denominator@1 + end) - 1}; + + false -> + {ok, case Divisor@1 of + 0 -> 0; + Gleam@denominator@2 -> Dividend div Gleam@denominator@2 + end} + end + end. + +-spec add(integer(), integer()) -> integer(). +add(A, B) -> + A + B. + +-spec multiply(integer(), integer()) -> integer(). +multiply(A, B) -> + A * B. + +-spec subtract(integer(), integer()) -> integer(). +subtract(A, B) -> + A - B. + +-spec bitwise_and(integer(), integer()) -> integer(). +bitwise_and(X, Y) -> + erlang:'band'(X, Y). + +-spec bitwise_not(integer()) -> integer(). +bitwise_not(X) -> + erlang:'bnot'(X). + +-spec bitwise_or(integer(), integer()) -> integer(). +bitwise_or(X, Y) -> + erlang:'bor'(X, Y). + +-spec bitwise_exclusive_or(integer(), integer()) -> integer(). +bitwise_exclusive_or(X, Y) -> + erlang:'bxor'(X, Y). + +-spec bitwise_shift_left(integer(), integer()) -> integer(). +bitwise_shift_left(X, Y) -> + erlang:'bsl'(X, Y). + +-spec bitwise_shift_right(integer(), integer()) -> integer(). +bitwise_shift_right(X, Y) -> + erlang:'bsr'(X, Y). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@io.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@io.erl new file mode 100644 index 0000000..a46eae3 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@io.erl @@ -0,0 +1,27 @@ +-module(gleam@io). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([print/1, print_error/1, println/1, println_error/1, debug/1]). + +-spec print(binary()) -> nil. +print(String) -> + gleam_stdlib:print(String). + +-spec print_error(binary()) -> nil. +print_error(String) -> + gleam_stdlib:print_error(String). + +-spec println(binary()) -> nil. +println(String) -> + gleam_stdlib:println(String). + +-spec println_error(binary()) -> nil. +println_error(String) -> + gleam_stdlib:println_error(String). + +-spec debug(CZT) -> CZT. +debug(Term) -> + _pipe = Term, + _pipe@1 = gleam@string:inspect(_pipe), + gleam_stdlib:println_error(_pipe@1), + Term. diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@iterator.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@iterator.erl new file mode 100644 index 0000000..aa84139 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@iterator.erl @@ -0,0 +1,744 @@ +-module(gleam@iterator). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([unfold/2, repeatedly/1, repeat/1, from_list/1, transform/3, fold/3, run/1, to_list/1, step/1, take/2, drop/2, map/2, map2/3, append/2, flatten/1, concat/1, flat_map/2, filter/2, cycle/1, find/2, index/1, iterate/2, take_while/2, drop_while/2, scan/3, zip/2, chunk/2, sized_chunk/2, intersperse/2, any/2, all/2, group/2, reduce/2, last/1, empty/0, once/1, range/2, single/1, interleave/2, fold_until/3, try_fold/3, first/1, at/2, length/1, each/2, yield/2]). +-export_type([action/1, iterator/1, step/2, chunk/2, sized_chunk/1]). + +-type action(BPF) :: stop | {continue, BPF, fun(() -> action(BPF))}. + +-opaque iterator(BPG) :: {iterator, fun(() -> action(BPG))}. + +-type step(BPH, BPI) :: {next, BPH, BPI} | done. + +-type chunk(BPJ, BPK) :: {another_by, + list(BPJ), + BPK, + BPJ, + fun(() -> action(BPJ))} | + {last_by, list(BPJ)}. + +-type sized_chunk(BPL) :: {another, list(BPL), fun(() -> action(BPL))} | + {last, list(BPL)} | + no_more. + +-spec stop() -> action(any()). +stop() -> + stop. + +-spec do_unfold(BPO, fun((BPO) -> step(BPP, BPO))) -> fun(() -> action(BPP)). +do_unfold(Initial, F) -> + fun() -> case F(Initial) of + {next, X, Acc} -> + {continue, X, do_unfold(Acc, F)}; + + done -> + stop + end end. + +-spec unfold(BPT, fun((BPT) -> step(BPU, BPT))) -> iterator(BPU). +unfold(Initial, F) -> + _pipe = Initial, + _pipe@1 = do_unfold(_pipe, F), + {iterator, _pipe@1}. + +-spec repeatedly(fun(() -> BPY)) -> iterator(BPY). +repeatedly(F) -> + unfold(nil, fun(_) -> {next, F(), nil} end). + +-spec repeat(BQA) -> iterator(BQA). +repeat(X) -> + repeatedly(fun() -> X end). + +-spec from_list(list(BQC)) -> iterator(BQC). +from_list(List) -> + Yield = fun(Acc) -> case Acc of + [] -> + done; + + [Head | Tail] -> + {next, Head, Tail} + end end, + unfold(List, Yield). + +-spec do_transform( + fun(() -> action(BQF)), + BQH, + fun((BQH, BQF) -> step(BQI, BQH)) +) -> fun(() -> action(BQI)). +do_transform(Continuation, State, F) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, El, Next} -> + case F(State, El) of + done -> + stop; + + {next, Yield, Next_state} -> + {continue, Yield, do_transform(Next, Next_state, F)} + end + end end. + +-spec transform(iterator(BQM), BQO, fun((BQO, BQM) -> step(BQP, BQO))) -> iterator(BQP). +transform(Iterator, Initial, F) -> + _pipe = do_transform(erlang:element(2, Iterator), Initial, F), + {iterator, _pipe}. + +-spec do_fold(fun(() -> action(BQT)), fun((BQV, BQT) -> BQV), BQV) -> BQV. +do_fold(Continuation, F, Accumulator) -> + case Continuation() of + {continue, Elem, Next} -> + do_fold(Next, F, F(Accumulator, Elem)); + + stop -> + Accumulator + end. + +-spec fold(iterator(BQW), BQY, fun((BQY, BQW) -> BQY)) -> BQY. +fold(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + do_fold(_pipe, F, Initial). + +-spec run(iterator(any())) -> nil. +run(Iterator) -> + fold(Iterator, nil, fun(_, _) -> nil end). + +-spec to_list(iterator(BRB)) -> list(BRB). +to_list(Iterator) -> + _pipe = Iterator, + _pipe@1 = fold(_pipe, [], fun(Acc, E) -> [E | Acc] end), + gleam@list:reverse(_pipe@1). + +-spec step(iterator(BRE)) -> step(BRE, iterator(BRE)). +step(Iterator) -> + case (erlang:element(2, Iterator))() of + stop -> + done; + + {continue, E, A} -> + {next, E, {iterator, A}} + end. + +-spec do_take(fun(() -> action(BRJ)), integer()) -> fun(() -> action(BRJ)). +do_take(Continuation, Desired) -> + fun() -> case Desired > 0 of + false -> + stop; + + true -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + {continue, E, do_take(Next, Desired - 1)} + end + end end. + +-spec take(iterator(BRM), integer()) -> iterator(BRM). +take(Iterator, Desired) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_take(_pipe, Desired), + {iterator, _pipe@1}. + +-spec do_drop(fun(() -> action(BRP)), integer()) -> action(BRP). +do_drop(Continuation, Desired) -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + case Desired > 0 of + true -> + do_drop(Next, Desired - 1); + + false -> + {continue, E, Next} + end + end. + +-spec drop(iterator(BRS), integer()) -> iterator(BRS). +drop(Iterator, Desired) -> + _pipe = fun() -> do_drop(erlang:element(2, Iterator), Desired) end, + {iterator, _pipe}. + +-spec do_map(fun(() -> action(BRV)), fun((BRV) -> BRX)) -> fun(() -> action(BRX)). +do_map(Continuation, F) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, E, Continuation@1} -> + {continue, F(E), do_map(Continuation@1, F)} + end end. + +-spec map(iterator(BRZ), fun((BRZ) -> BSB)) -> iterator(BSB). +map(Iterator, F) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_map(_pipe, F), + {iterator, _pipe@1}. + +-spec do_map2( + fun(() -> action(BSD)), + fun(() -> action(BSF)), + fun((BSD, BSF) -> BSH) +) -> fun(() -> action(BSH)). +do_map2(Continuation1, Continuation2, Fun) -> + fun() -> case Continuation1() of + stop -> + stop; + + {continue, A, Next_a} -> + case Continuation2() of + stop -> + stop; + + {continue, B, Next_b} -> + {continue, Fun(A, B), do_map2(Next_a, Next_b, Fun)} + end + end end. + +-spec map2(iterator(BSJ), iterator(BSL), fun((BSJ, BSL) -> BSN)) -> iterator(BSN). +map2(Iterator1, Iterator2, Fun) -> + _pipe = do_map2( + erlang:element(2, Iterator1), + erlang:element(2, Iterator2), + Fun + ), + {iterator, _pipe}. + +-spec do_append(fun(() -> action(BSP)), fun(() -> action(BSP))) -> action(BSP). +do_append(First, Second) -> + case First() of + {continue, E, First@1} -> + {continue, E, fun() -> do_append(First@1, Second) end}; + + stop -> + Second() + end. + +-spec append(iterator(BST), iterator(BST)) -> iterator(BST). +append(First, Second) -> + _pipe = fun() -> + do_append(erlang:element(2, First), erlang:element(2, Second)) + end, + {iterator, _pipe}. + +-spec do_flatten(fun(() -> action(iterator(BSX)))) -> action(BSX). +do_flatten(Flattened) -> + case Flattened() of + stop -> + stop; + + {continue, It, Next_iterator} -> + do_append( + erlang:element(2, It), + fun() -> do_flatten(Next_iterator) end + ) + end. + +-spec flatten(iterator(iterator(BTB))) -> iterator(BTB). +flatten(Iterator) -> + _pipe = fun() -> do_flatten(erlang:element(2, Iterator)) end, + {iterator, _pipe}. + +-spec concat(list(iterator(BTF))) -> iterator(BTF). +concat(Iterators) -> + flatten(from_list(Iterators)). + +-spec flat_map(iterator(BTJ), fun((BTJ) -> iterator(BTL))) -> iterator(BTL). +flat_map(Iterator, F) -> + _pipe = Iterator, + _pipe@1 = map(_pipe, F), + flatten(_pipe@1). + +-spec do_filter(fun(() -> action(BTO)), fun((BTO) -> boolean())) -> action(BTO). +do_filter(Continuation, Predicate) -> + case Continuation() of + stop -> + stop; + + {continue, E, Iterator} -> + case Predicate(E) of + true -> + {continue, E, fun() -> do_filter(Iterator, Predicate) end}; + + false -> + do_filter(Iterator, Predicate) + end + end. + +-spec filter(iterator(BTR), fun((BTR) -> boolean())) -> iterator(BTR). +filter(Iterator, Predicate) -> + _pipe = fun() -> do_filter(erlang:element(2, Iterator), Predicate) end, + {iterator, _pipe}. + +-spec cycle(iterator(BTU)) -> iterator(BTU). +cycle(Iterator) -> + _pipe = repeat(Iterator), + flatten(_pipe). + +-spec do_find(fun(() -> action(BTY)), fun((BTY) -> boolean())) -> {ok, BTY} | + {error, nil}. +do_find(Continuation, F) -> + case Continuation() of + stop -> + {error, nil}; + + {continue, E, Next} -> + case F(E) of + true -> + {ok, E}; + + false -> + do_find(Next, F) + end + end. + +-spec find(iterator(BUC), fun((BUC) -> boolean())) -> {ok, BUC} | {error, nil}. +find(Haystack, Is_desired) -> + _pipe = erlang:element(2, Haystack), + do_find(_pipe, Is_desired). + +-spec do_index(fun(() -> action(BUG)), integer()) -> fun(() -> action({integer(), + BUG})). +do_index(Continuation, Next) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, E, Continuation@1} -> + {continue, {Next, E}, do_index(Continuation@1, Next + 1)} + end end. + +-spec index(iterator(BUJ)) -> iterator({integer(), BUJ}). +index(Iterator) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_index(_pipe, 0), + {iterator, _pipe@1}. + +-spec iterate(BUM, fun((BUM) -> BUM)) -> iterator(BUM). +iterate(Initial, F) -> + unfold(Initial, fun(Element) -> {next, Element, F(Element)} end). + +-spec do_take_while(fun(() -> action(BUO)), fun((BUO) -> boolean())) -> fun(() -> action(BUO)). +do_take_while(Continuation, Predicate) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + case Predicate(E) of + false -> + stop; + + true -> + {continue, E, do_take_while(Next, Predicate)} + end + end end. + +-spec take_while(iterator(BUR), fun((BUR) -> boolean())) -> iterator(BUR). +take_while(Iterator, Predicate) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_take_while(_pipe, Predicate), + {iterator, _pipe@1}. + +-spec do_drop_while(fun(() -> action(BUU)), fun((BUU) -> boolean())) -> action(BUU). +do_drop_while(Continuation, Predicate) -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + case Predicate(E) of + false -> + {continue, E, Next}; + + true -> + do_drop_while(Next, Predicate) + end + end. + +-spec drop_while(iterator(BUX), fun((BUX) -> boolean())) -> iterator(BUX). +drop_while(Iterator, Predicate) -> + _pipe = fun() -> do_drop_while(erlang:element(2, Iterator), Predicate) end, + {iterator, _pipe}. + +-spec do_scan(fun(() -> action(BVA)), fun((BVC, BVA) -> BVC), BVC) -> fun(() -> action(BVC)). +do_scan(Continuation, F, Accumulator) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, El, Next} -> + Accumulated = F(Accumulator, El), + {continue, Accumulated, do_scan(Next, F, Accumulated)} + end end. + +-spec scan(iterator(BVE), BVG, fun((BVG, BVE) -> BVG)) -> iterator(BVG). +scan(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_scan(_pipe, F, Initial), + {iterator, _pipe@1}. + +-spec do_zip(fun(() -> action(BVI)), fun(() -> action(BVK))) -> fun(() -> action({BVI, + BVK})). +do_zip(Left, Right) -> + fun() -> case Left() of + stop -> + stop; + + {continue, El_left, Next_left} -> + case Right() of + stop -> + stop; + + {continue, El_right, Next_right} -> + {continue, + {El_left, El_right}, + do_zip(Next_left, Next_right)} + end + end end. + +-spec zip(iterator(BVN), iterator(BVP)) -> iterator({BVN, BVP}). +zip(Left, Right) -> + _pipe = do_zip(erlang:element(2, Left), erlang:element(2, Right)), + {iterator, _pipe}. + +-spec next_chunk(fun(() -> action(BVS)), fun((BVS) -> BVU), BVU, list(BVS)) -> chunk(BVS, BVU). +next_chunk(Continuation, F, Previous_key, Current_chunk) -> + case Continuation() of + stop -> + {last_by, gleam@list:reverse(Current_chunk)}; + + {continue, E, Next} -> + Key = F(E), + case Key =:= Previous_key of + true -> + next_chunk(Next, F, Key, [E | Current_chunk]); + + false -> + {another_by, + gleam@list:reverse(Current_chunk), + Key, + E, + Next} + end + end. + +-spec do_chunk(fun(() -> action(BVY)), fun((BVY) -> BWA), BWA, BVY) -> action(list(BVY)). +do_chunk(Continuation, F, Previous_key, Previous_element) -> + case next_chunk(Continuation, F, Previous_key, [Previous_element]) of + {last_by, Chunk} -> + {continue, Chunk, fun stop/0}; + + {another_by, Chunk@1, Key, El, Next} -> + {continue, Chunk@1, fun() -> do_chunk(Next, F, Key, El) end} + end. + +-spec chunk(iterator(BWD), fun((BWD) -> any())) -> iterator(list(BWD)). +chunk(Iterator, F) -> + _pipe = fun() -> case (erlang:element(2, Iterator))() of + stop -> + stop; + + {continue, E, Next} -> + do_chunk(Next, F, F(E), E) + end end, + {iterator, _pipe}. + +-spec next_sized_chunk(fun(() -> action(BWI)), integer(), list(BWI)) -> sized_chunk(BWI). +next_sized_chunk(Continuation, Left, Current_chunk) -> + case Continuation() of + stop -> + case Current_chunk of + [] -> + no_more; + + Remaining -> + {last, gleam@list:reverse(Remaining)} + end; + + {continue, E, Next} -> + Chunk = [E | Current_chunk], + case Left > 1 of + false -> + {another, gleam@list:reverse(Chunk), Next}; + + true -> + next_sized_chunk(Next, Left - 1, Chunk) + end + end. + +-spec do_sized_chunk(fun(() -> action(BWM)), integer()) -> fun(() -> action(list(BWM))). +do_sized_chunk(Continuation, Count) -> + fun() -> case next_sized_chunk(Continuation, Count, []) of + no_more -> + stop; + + {last, Chunk} -> + {continue, Chunk, fun stop/0}; + + {another, Chunk@1, Next_element} -> + {continue, Chunk@1, do_sized_chunk(Next_element, Count)} + end end. + +-spec sized_chunk(iterator(BWQ), integer()) -> iterator(list(BWQ)). +sized_chunk(Iterator, Count) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_sized_chunk(_pipe, Count), + {iterator, _pipe@1}. + +-spec do_intersperse(fun(() -> action(BWU)), BWU) -> action(BWU). +do_intersperse(Continuation, Separator) -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + Next_interspersed = fun() -> do_intersperse(Next, Separator) end, + {continue, Separator, fun() -> {continue, E, Next_interspersed} end} + end. + +-spec intersperse(iterator(BWX), BWX) -> iterator(BWX). +intersperse(Iterator, Elem) -> + _pipe = fun() -> case (erlang:element(2, Iterator))() of + stop -> + stop; + + {continue, E, Next} -> + {continue, E, fun() -> do_intersperse(Next, Elem) end} + end end, + {iterator, _pipe}. + +-spec do_any(fun(() -> action(BXA)), fun((BXA) -> boolean())) -> boolean(). +do_any(Continuation, Predicate) -> + case Continuation() of + stop -> + false; + + {continue, E, Next} -> + case Predicate(E) of + true -> + true; + + false -> + do_any(Next, Predicate) + end + end. + +-spec any(iterator(BXC), fun((BXC) -> boolean())) -> boolean(). +any(Iterator, Predicate) -> + _pipe = erlang:element(2, Iterator), + do_any(_pipe, Predicate). + +-spec do_all(fun(() -> action(BXE)), fun((BXE) -> boolean())) -> boolean(). +do_all(Continuation, Predicate) -> + case Continuation() of + stop -> + true; + + {continue, E, Next} -> + case Predicate(E) of + true -> + do_all(Next, Predicate); + + false -> + false + end + end. + +-spec all(iterator(BXG), fun((BXG) -> boolean())) -> boolean(). +all(Iterator, Predicate) -> + _pipe = erlang:element(2, Iterator), + do_all(_pipe, Predicate). + +-spec update_group_with(BXI) -> fun((gleam@option:option(list(BXI))) -> list(BXI)). +update_group_with(El) -> + fun(Maybe_group) -> case Maybe_group of + {some, Group} -> + [El | Group]; + + none -> + [El] + end end. + +-spec group_updater(fun((BXM) -> BXN)) -> fun((gleam@dict:dict(BXN, list(BXM)), BXM) -> gleam@dict:dict(BXN, list(BXM))). +group_updater(F) -> + fun(Groups, Elem) -> _pipe = Groups, + gleam@dict:update(_pipe, F(Elem), update_group_with(Elem)) end. + +-spec group(iterator(BXU), fun((BXU) -> BXW)) -> gleam@dict:dict(BXW, list(BXU)). +group(Iterator, Key) -> + _pipe = Iterator, + _pipe@1 = fold(_pipe, gleam@dict:new(), group_updater(Key)), + gleam@dict:map_values( + _pipe@1, + fun(_, Group) -> gleam@list:reverse(Group) end + ). + +-spec reduce(iterator(BYA), fun((BYA, BYA) -> BYA)) -> {ok, BYA} | {error, nil}. +reduce(Iterator, F) -> + case (erlang:element(2, Iterator))() of + stop -> + {error, nil}; + + {continue, E, Next} -> + _pipe = do_fold(Next, F, E), + {ok, _pipe} + end. + +-spec last(iterator(BYE)) -> {ok, BYE} | {error, nil}. +last(Iterator) -> + _pipe = Iterator, + reduce(_pipe, fun(_, Elem) -> Elem end). + +-spec empty() -> iterator(any()). +empty() -> + {iterator, fun stop/0}. + +-spec once(fun(() -> BYK)) -> iterator(BYK). +once(F) -> + _pipe = fun() -> {continue, F(), fun stop/0} end, + {iterator, _pipe}. + +-spec range(integer(), integer()) -> iterator(integer()). +range(Start, Stop) -> + case gleam@int:compare(Start, Stop) of + eq -> + once(fun() -> Start end); + + gt -> + unfold(Start, fun(Current) -> case Current < Stop of + false -> + {next, Current, Current - 1}; + + true -> + done + end end); + + lt -> + unfold(Start, fun(Current@1) -> case Current@1 > Stop of + false -> + {next, Current@1, Current@1 + 1}; + + true -> + done + end end) + end. + +-spec single(BYM) -> iterator(BYM). +single(Elem) -> + once(fun() -> Elem end). + +-spec do_interleave(fun(() -> action(BYO)), fun(() -> action(BYO))) -> action(BYO). +do_interleave(Current, Next) -> + case Current() of + stop -> + Next(); + + {continue, E, Next_other} -> + {continue, E, fun() -> do_interleave(Next, Next_other) end} + end. + +-spec interleave(iterator(BYS), iterator(BYS)) -> iterator(BYS). +interleave(Left, Right) -> + _pipe = fun() -> + do_interleave(erlang:element(2, Left), erlang:element(2, Right)) + end, + {iterator, _pipe}. + +-spec do_fold_until( + fun(() -> action(BYW)), + fun((BYY, BYW) -> gleam@list:continue_or_stop(BYY)), + BYY +) -> BYY. +do_fold_until(Continuation, F, Accumulator) -> + case Continuation() of + stop -> + Accumulator; + + {continue, Elem, Next} -> + case F(Accumulator, Elem) of + {continue, Accumulator@1} -> + do_fold_until(Next, F, Accumulator@1); + + {stop, Accumulator@2} -> + Accumulator@2 + end + end. + +-spec fold_until( + iterator(BZA), + BZC, + fun((BZC, BZA) -> gleam@list:continue_or_stop(BZC)) +) -> BZC. +fold_until(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + do_fold_until(_pipe, F, Initial). + +-spec do_try_fold( + fun(() -> action(BZE)), + fun((BZG, BZE) -> {ok, BZG} | {error, BZH}), + BZG +) -> {ok, BZG} | {error, BZH}. +do_try_fold(Continuation, F, Accumulator) -> + case Continuation() of + stop -> + {ok, Accumulator}; + + {continue, Elem, Next} -> + gleam@result:'try'( + F(Accumulator, Elem), + fun(Accumulator@1) -> do_try_fold(Next, F, Accumulator@1) end + ) + end. + +-spec try_fold(iterator(BZM), BZO, fun((BZO, BZM) -> {ok, BZO} | {error, BZP})) -> {ok, + BZO} | + {error, BZP}. +try_fold(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + do_try_fold(_pipe, F, Initial). + +-spec first(iterator(BZU)) -> {ok, BZU} | {error, nil}. +first(Iterator) -> + case (erlang:element(2, Iterator))() of + stop -> + {error, nil}; + + {continue, E, _} -> + {ok, E} + end. + +-spec at(iterator(BZY), integer()) -> {ok, BZY} | {error, nil}. +at(Iterator, Index) -> + _pipe = Iterator, + _pipe@1 = drop(_pipe, Index), + first(_pipe@1). + +-spec do_length(fun(() -> action(any())), integer()) -> integer(). +do_length(Continuation, Length) -> + case Continuation() of + stop -> + Length; + + {continue, _, Next} -> + do_length(Next, Length + 1) + end. + +-spec length(iterator(any())) -> integer(). +length(Iterator) -> + _pipe = erlang:element(2, Iterator), + do_length(_pipe, 0). + +-spec each(iterator(CAG), fun((CAG) -> any())) -> nil. +each(Iterator, F) -> + _pipe = Iterator, + _pipe@1 = map(_pipe, F), + run(_pipe@1). + +-spec yield(CAJ, fun(() -> iterator(CAJ))) -> iterator(CAJ). +yield(Element, Next) -> + {iterator, fun() -> {continue, Element, erlang:element(2, Next())} end}. diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@list.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@list.erl new file mode 100644 index 0000000..6c2e684 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@list.erl @@ -0,0 +1,1129 @@ +-module(gleam@list). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([length/1, reverse/1, is_empty/1, contains/2, first/1, rest/1, filter/2, filter_map/2, map/2, map2/3, index_map/2, try_map/2, drop/2, take/2, new/0, append/2, prepend/2, concat/1, flatten/1, flat_map/2, fold/3, group/2, map_fold/3, fold_right/3, index_fold/3, try_fold/3, fold_until/3, find/2, find_map/2, all/2, any/2, zip/2, strict_zip/2, unzip/1, intersperse/2, at/2, unique/1, sort/2, range/2, repeat/2, split/2, split_while/2, key_find/2, key_filter/2, pop/2, pop_map/2, key_pop/2, key_set/3, each/2, try_each/2, partition/2, permutations/1, window/2, window_by_2/1, drop_while/2, take_while/2, chunk/2, sized_chunk/2, reduce/2, scan/3, last/1, combinations/2, combination_pairs/1, transpose/1, interleave/1, shuffle/1]). +-export_type([length_mismatch/0, continue_or_stop/1]). + +-type length_mismatch() :: length_mismatch. + +-type continue_or_stop(UD) :: {continue, UD} | {stop, UD}. + +-spec length(list(any())) -> integer(). +length(List) -> + erlang:length(List). + +-spec reverse(list(UI)) -> list(UI). +reverse(Xs) -> + lists:reverse(Xs). + +-spec is_empty(list(any())) -> boolean(). +is_empty(List) -> + List =:= []. + +-spec contains(list(UQ), UQ) -> boolean(). +contains(List, Elem) -> + case List of + [] -> + false; + + [First | _] when First =:= Elem -> + true; + + [_ | Rest] -> + contains(Rest, Elem) + end. + +-spec first(list(US)) -> {ok, US} | {error, nil}. +first(List) -> + case List of + [] -> + {error, nil}; + + [X | _] -> + {ok, X} + end. + +-spec rest(list(UW)) -> {ok, list(UW)} | {error, nil}. +rest(List) -> + case List of + [] -> + {error, nil}; + + [_ | Xs] -> + {ok, Xs} + end. + +-spec update_group(fun((VB) -> VC)) -> fun((gleam@dict:dict(VC, list(VB)), VB) -> gleam@dict:dict(VC, list(VB))). +update_group(F) -> + fun(Groups, Elem) -> case gleam@dict:get(Groups, F(Elem)) of + {ok, Existing} -> + gleam@dict:insert(Groups, F(Elem), [Elem | Existing]); + + {error, _} -> + gleam@dict:insert(Groups, F(Elem), [Elem]) + end end. + +-spec do_filter(list(VP), fun((VP) -> boolean()), list(VP)) -> list(VP). +do_filter(List, Fun, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + New_acc = case Fun(X) of + true -> + [X | Acc]; + + false -> + Acc + end, + do_filter(Xs, Fun, New_acc) + end. + +-spec filter(list(VT), fun((VT) -> boolean())) -> list(VT). +filter(List, Predicate) -> + do_filter(List, Predicate, []). + +-spec do_filter_map(list(VW), fun((VW) -> {ok, VY} | {error, any()}), list(VY)) -> list(VY). +do_filter_map(List, Fun, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + New_acc = case Fun(X) of + {ok, X@1} -> + [X@1 | Acc]; + + {error, _} -> + Acc + end, + do_filter_map(Xs, Fun, New_acc) + end. + +-spec filter_map(list(WE), fun((WE) -> {ok, WG} | {error, any()})) -> list(WG). +filter_map(List, Fun) -> + do_filter_map(List, Fun, []). + +-spec do_map(list(WL), fun((WL) -> WN), list(WN)) -> list(WN). +do_map(List, Fun, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + do_map(Xs, Fun, [Fun(X) | Acc]) + end. + +-spec map(list(WQ), fun((WQ) -> WS)) -> list(WS). +map(List, Fun) -> + do_map(List, Fun, []). + +-spec do_map2(list(XA), list(XC), fun((XA, XC) -> XE), list(XE)) -> list(XE). +do_map2(List1, List2, Fun, Acc) -> + case {List1, List2} of + {[], _} -> + reverse(Acc); + + {_, []} -> + reverse(Acc); + + {[A | As_], [B | Bs]} -> + do_map2(As_, Bs, Fun, [Fun(A, B) | Acc]) + end. + +-spec map2(list(WU), list(WW), fun((WU, WW) -> WY)) -> list(WY). +map2(List1, List2, Fun) -> + do_map2(List1, List2, Fun, []). + +-spec do_index_map(list(XM), fun((integer(), XM) -> XO), integer(), list(XO)) -> list(XO). +do_index_map(List, Fun, Index, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + Acc@1 = [Fun(Index, X) | Acc], + do_index_map(Xs, Fun, Index + 1, Acc@1) + end. + +-spec index_map(list(XR), fun((integer(), XR) -> XT)) -> list(XT). +index_map(List, Fun) -> + do_index_map(List, Fun, 0, []). + +-spec do_try_map(list(XV), fun((XV) -> {ok, XX} | {error, XY}), list(XX)) -> {ok, + list(XX)} | + {error, XY}. +do_try_map(List, Fun, Acc) -> + case List of + [] -> + {ok, reverse(Acc)}; + + [X | Xs] -> + case Fun(X) of + {ok, Y} -> + do_try_map(Xs, Fun, [Y | Acc]); + + {error, Error} -> + {error, Error} + end + end. + +-spec try_map(list(YF), fun((YF) -> {ok, YH} | {error, YI})) -> {ok, list(YH)} | + {error, YI}. +try_map(List, Fun) -> + do_try_map(List, Fun, []). + +-spec drop(list(YO), integer()) -> list(YO). +drop(List, N) -> + case N =< 0 of + true -> + List; + + false -> + case List of + [] -> + []; + + [_ | Xs] -> + drop(Xs, N - 1) + end + end. + +-spec do_take(list(YR), integer(), list(YR)) -> list(YR). +do_take(List, N, Acc) -> + case N =< 0 of + true -> + reverse(Acc); + + false -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + do_take(Xs, N - 1, [X | Acc]) + end + end. + +-spec take(list(YV), integer()) -> list(YV). +take(List, N) -> + do_take(List, N, []). + +-spec new() -> list(any()). +new() -> + []. + +-spec append(list(AAA), list(AAA)) -> list(AAA). +append(First, Second) -> + lists:append(First, Second). + +-spec prepend(list(AAI), AAI) -> list(AAI). +prepend(List, Item) -> + [Item | List]. + +-spec reverse_and_prepend(list(AAL), list(AAL)) -> list(AAL). +reverse_and_prepend(Prefix, Suffix) -> + case Prefix of + [] -> + Suffix; + + [First | Rest] -> + reverse_and_prepend(Rest, [First | Suffix]) + end. + +-spec do_concat(list(list(AAP)), list(AAP)) -> list(AAP). +do_concat(Lists, Acc) -> + case Lists of + [] -> + reverse(Acc); + + [List | Further_lists] -> + do_concat(Further_lists, reverse_and_prepend(List, Acc)) + end. + +-spec concat(list(list(AAU))) -> list(AAU). +concat(Lists) -> + do_concat(Lists, []). + +-spec flatten(list(list(AAY))) -> list(AAY). +flatten(Lists) -> + do_concat(Lists, []). + +-spec flat_map(list(ABC), fun((ABC) -> list(ABE))) -> list(ABE). +flat_map(List, Fun) -> + _pipe = map(List, Fun), + concat(_pipe). + +-spec fold(list(ABH), ABJ, fun((ABJ, ABH) -> ABJ)) -> ABJ. +fold(List, Initial, Fun) -> + case List of + [] -> + Initial; + + [X | Rest] -> + fold(Rest, Fun(Initial, X), Fun) + end. + +-spec group(list(VJ), fun((VJ) -> VL)) -> gleam@dict:dict(VL, list(VJ)). +group(List, Key) -> + fold(List, gleam@dict:new(), update_group(Key)). + +-spec map_fold(list(XH), XJ, fun((XJ, XH) -> {XJ, XK})) -> {XJ, list(XK)}. +map_fold(List, Acc, Fun) -> + _pipe = fold( + List, + {Acc, []}, + fun(Acc@1, Item) -> + {Current_acc, Items} = Acc@1, + {Next_acc, Next_item} = Fun(Current_acc, Item), + {Next_acc, [Next_item | Items]} + end + ), + gleam@pair:map_second(_pipe, fun reverse/1). + +-spec fold_right(list(ABK), ABM, fun((ABM, ABK) -> ABM)) -> ABM. +fold_right(List, Initial, Fun) -> + case List of + [] -> + Initial; + + [X | Rest] -> + Fun(fold_right(Rest, Initial, Fun), X) + end. + +-spec do_index_fold( + list(ABN), + ABP, + fun((ABP, ABN, integer()) -> ABP), + integer() +) -> ABP. +do_index_fold(Over, Acc, With, Index) -> + case Over of + [] -> + Acc; + + [First | Rest] -> + do_index_fold(Rest, With(Acc, First, Index), With, Index + 1) + end. + +-spec index_fold(list(ABQ), ABS, fun((ABS, ABQ, integer()) -> ABS)) -> ABS. +index_fold(Over, Initial, Fun) -> + do_index_fold(Over, Initial, Fun, 0). + +-spec try_fold(list(ABT), ABV, fun((ABV, ABT) -> {ok, ABV} | {error, ABW})) -> {ok, + ABV} | + {error, ABW}. +try_fold(Collection, Accumulator, Fun) -> + case Collection of + [] -> + {ok, Accumulator}; + + [First | Rest] -> + case Fun(Accumulator, First) of + {ok, Result} -> + try_fold(Rest, Result, Fun); + + {error, _} = Error -> + Error + end + end. + +-spec fold_until(list(ACB), ACD, fun((ACD, ACB) -> continue_or_stop(ACD))) -> ACD. +fold_until(Collection, Accumulator, Fun) -> + case Collection of + [] -> + Accumulator; + + [First | Rest] -> + case Fun(Accumulator, First) of + {continue, Next_accumulator} -> + fold_until(Rest, Next_accumulator, Fun); + + {stop, B} -> + B + end + end. + +-spec find(list(ACF), fun((ACF) -> boolean())) -> {ok, ACF} | {error, nil}. +find(Haystack, Is_desired) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Is_desired(X) of + true -> + {ok, X}; + + _ -> + find(Rest, Is_desired) + end + end. + +-spec find_map(list(ACJ), fun((ACJ) -> {ok, ACL} | {error, any()})) -> {ok, ACL} | + {error, nil}. +find_map(Haystack, Fun) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Fun(X) of + {ok, X@1} -> + {ok, X@1}; + + _ -> + find_map(Rest, Fun) + end + end. + +-spec all(list(ACR), fun((ACR) -> boolean())) -> boolean(). +all(List, Predicate) -> + case List of + [] -> + true; + + [First | Rest] -> + case Predicate(First) of + true -> + all(Rest, Predicate); + + false -> + false + end + end. + +-spec any(list(ACT), fun((ACT) -> boolean())) -> boolean(). +any(List, Predicate) -> + case List of + [] -> + false; + + [First | Rest] -> + case Predicate(First) of + true -> + true; + + false -> + any(Rest, Predicate) + end + end. + +-spec do_zip(list(ACV), list(ACX), list({ACV, ACX})) -> list({ACV, ACX}). +do_zip(Xs, Ys, Acc) -> + case {Xs, Ys} of + {[X | Xs@1], [Y | Ys@1]} -> + do_zip(Xs@1, Ys@1, [{X, Y} | Acc]); + + {_, _} -> + reverse(Acc) + end. + +-spec zip(list(ADB), list(ADD)) -> list({ADB, ADD}). +zip(List, Other) -> + do_zip(List, Other, []). + +-spec strict_zip(list(ADG), list(ADI)) -> {ok, list({ADG, ADI})} | + {error, length_mismatch()}. +strict_zip(List, Other) -> + case length(List) =:= length(Other) of + true -> + {ok, zip(List, Other)}; + + false -> + {error, length_mismatch} + end. + +-spec do_unzip(list({ATA, ATB}), list(ATA), list(ATB)) -> {list(ATA), list(ATB)}. +do_unzip(Input, Xs, Ys) -> + case Input of + [] -> + {reverse(Xs), reverse(Ys)}; + + [{X, Y} | Rest] -> + do_unzip(Rest, [X | Xs], [Y | Ys]) + end. + +-spec unzip(list({ADR, ADS})) -> {list(ADR), list(ADS)}. +unzip(Input) -> + do_unzip(Input, [], []). + +-spec do_intersperse(list(ADW), ADW, list(ADW)) -> list(ADW). +do_intersperse(List, Separator, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Rest] -> + do_intersperse(Rest, Separator, [X, Separator | Acc]) + end. + +-spec intersperse(list(AEA), AEA) -> list(AEA). +intersperse(List, Elem) -> + case List of + [] -> + List; + + [_] -> + List; + + [X | Rest] -> + do_intersperse(Rest, Elem, [X]) + end. + +-spec at(list(AED), integer()) -> {ok, AED} | {error, nil}. +at(List, Index) -> + case Index >= 0 of + true -> + _pipe = List, + _pipe@1 = drop(_pipe, Index), + first(_pipe@1); + + false -> + {error, nil} + end. + +-spec unique(list(AEH)) -> list(AEH). +unique(List) -> + case List of + [] -> + []; + + [X | Rest] -> + [X | unique(filter(Rest, fun(Y) -> Y /= X end))] + end. + +-spec merge_up( + integer(), + integer(), + list(AEK), + list(AEK), + list(AEK), + fun((AEK, AEK) -> gleam@order:order()) +) -> list(AEK). +merge_up(Na, Nb, A, B, Acc, Compare) -> + case {Na, Nb, A, B} of + {0, 0, _, _} -> + Acc; + + {_, 0, [Ax | Ar], _} -> + merge_up(Na - 1, Nb, Ar, B, [Ax | Acc], Compare); + + {0, _, _, [Bx | Br]} -> + merge_up(Na, Nb - 1, A, Br, [Bx | Acc], Compare); + + {_, _, [Ax@1 | Ar@1], [Bx@1 | Br@1]} -> + case Compare(Ax@1, Bx@1) of + gt -> + merge_up(Na, Nb - 1, A, Br@1, [Bx@1 | Acc], Compare); + + _ -> + merge_up(Na - 1, Nb, Ar@1, B, [Ax@1 | Acc], Compare) + end; + + {_, _, _, _} -> + Acc + end. + +-spec merge_down( + integer(), + integer(), + list(AEP), + list(AEP), + list(AEP), + fun((AEP, AEP) -> gleam@order:order()) +) -> list(AEP). +merge_down(Na, Nb, A, B, Acc, Compare) -> + case {Na, Nb, A, B} of + {0, 0, _, _} -> + Acc; + + {_, 0, [Ax | Ar], _} -> + merge_down(Na - 1, Nb, Ar, B, [Ax | Acc], Compare); + + {0, _, _, [Bx | Br]} -> + merge_down(Na, Nb - 1, A, Br, [Bx | Acc], Compare); + + {_, _, [Ax@1 | Ar@1], [Bx@1 | Br@1]} -> + case Compare(Bx@1, Ax@1) of + lt -> + merge_down(Na - 1, Nb, Ar@1, B, [Ax@1 | Acc], Compare); + + _ -> + merge_down(Na, Nb - 1, A, Br@1, [Bx@1 | Acc], Compare) + end; + + {_, _, _, _} -> + Acc + end. + +-spec merge_sort( + list(AEU), + integer(), + fun((AEU, AEU) -> gleam@order:order()), + boolean() +) -> list(AEU). +merge_sort(L, Ln, Compare, Down) -> + N = Ln div 2, + A = L, + B = drop(L, N), + case Ln < 3 of + true -> + case Down of + true -> + merge_down(N, Ln - N, A, B, [], Compare); + + false -> + merge_up(N, Ln - N, A, B, [], Compare) + end; + + false -> + case Down of + true -> + merge_down( + N, + Ln - N, + merge_sort(A, N, Compare, false), + merge_sort(B, Ln - N, Compare, false), + [], + Compare + ); + + false -> + merge_up( + N, + Ln - N, + merge_sort(A, N, Compare, true), + merge_sort(B, Ln - N, Compare, true), + [], + Compare + ) + end + end. + +-spec sort(list(AEX), fun((AEX, AEX) -> gleam@order:order())) -> list(AEX). +sort(List, Compare) -> + merge_sort(List, length(List), Compare, true). + +-spec tail_recursive_range(integer(), integer(), list(integer())) -> list(integer()). +tail_recursive_range(Start, Stop, Acc) -> + case gleam@int:compare(Start, Stop) of + eq -> + [Stop | Acc]; + + gt -> + tail_recursive_range(Start, Stop + 1, [Stop | Acc]); + + lt -> + tail_recursive_range(Start, Stop - 1, [Stop | Acc]) + end. + +-spec range(integer(), integer()) -> list(integer()). +range(Start, Stop) -> + tail_recursive_range(Start, Stop, []). + +-spec do_repeat(AFD, integer(), list(AFD)) -> list(AFD). +do_repeat(A, Times, Acc) -> + case Times =< 0 of + true -> + Acc; + + false -> + do_repeat(A, Times - 1, [A | Acc]) + end. + +-spec repeat(AFG, integer()) -> list(AFG). +repeat(A, Times) -> + do_repeat(A, Times, []). + +-spec do_split(list(AFI), integer(), list(AFI)) -> {list(AFI), list(AFI)}. +do_split(List, N, Taken) -> + case N =< 0 of + true -> + {reverse(Taken), List}; + + false -> + case List of + [] -> + {reverse(Taken), []}; + + [X | Xs] -> + do_split(Xs, N - 1, [X | Taken]) + end + end. + +-spec split(list(AFN), integer()) -> {list(AFN), list(AFN)}. +split(List, Index) -> + do_split(List, Index, []). + +-spec do_split_while(list(AFR), fun((AFR) -> boolean()), list(AFR)) -> {list(AFR), + list(AFR)}. +do_split_while(List, F, Acc) -> + case List of + [] -> + {reverse(Acc), []}; + + [X | Xs] -> + case F(X) of + false -> + {reverse(Acc), List}; + + _ -> + do_split_while(Xs, F, [X | Acc]) + end + end. + +-spec split_while(list(AFW), fun((AFW) -> boolean())) -> {list(AFW), list(AFW)}. +split_while(List, Predicate) -> + do_split_while(List, Predicate, []). + +-spec key_find(list({AGA, AGB}), AGA) -> {ok, AGB} | {error, nil}. +key_find(Keyword_list, Desired_key) -> + find_map( + Keyword_list, + fun(Keyword) -> + {Key, Value} = Keyword, + case Key =:= Desired_key of + true -> + {ok, Value}; + + false -> + {error, nil} + end + end + ). + +-spec key_filter(list({AGF, AGG}), AGF) -> list(AGG). +key_filter(Keyword_list, Desired_key) -> + filter_map( + Keyword_list, + fun(Keyword) -> + {Key, Value} = Keyword, + case Key =:= Desired_key of + true -> + {ok, Value}; + + false -> + {error, nil} + end + end + ). + +-spec do_pop(list(AWT), fun((AWT) -> boolean()), list(AWT)) -> {ok, + {AWT, list(AWT)}} | + {error, nil}. +do_pop(Haystack, Predicate, Checked) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Predicate(X) of + true -> + {ok, {X, append(reverse(Checked), Rest)}}; + + false -> + do_pop(Rest, Predicate, [X | Checked]) + end + end. + +-spec pop(list(AGN), fun((AGN) -> boolean())) -> {ok, {AGN, list(AGN)}} | + {error, nil}. +pop(Haystack, Is_desired) -> + do_pop(Haystack, Is_desired, []). + +-spec do_pop_map(list(AXH), fun((AXH) -> {ok, AXU} | {error, any()}), list(AXH)) -> {ok, + {AXU, list(AXH)}} | + {error, nil}. +do_pop_map(Haystack, Mapper, Checked) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Mapper(X) of + {ok, Y} -> + {ok, {Y, append(reverse(Checked), Rest)}}; + + {error, _} -> + do_pop_map(Rest, Mapper, [X | Checked]) + end + end. + +-spec pop_map(list(AGW), fun((AGW) -> {ok, AGY} | {error, any()})) -> {ok, + {AGY, list(AGW)}} | + {error, nil}. +pop_map(Haystack, Is_desired) -> + do_pop_map(Haystack, Is_desired, []). + +-spec key_pop(list({AHF, AHG}), AHF) -> {ok, {AHG, list({AHF, AHG})}} | + {error, nil}. +key_pop(Haystack, Key) -> + pop_map( + Haystack, + fun(Entry) -> + {K, V} = Entry, + case K of + K@1 when K@1 =:= Key -> + {ok, V}; + + _ -> + {error, nil} + end + end + ). + +-spec key_set(list({AHL, AHM}), AHL, AHM) -> list({AHL, AHM}). +key_set(List, Key, Value) -> + case List of + [] -> + [{Key, Value}]; + + [{K, _} | Rest] when K =:= Key -> + [{Key, Value} | Rest]; + + [First | Rest@1] -> + [First | key_set(Rest@1, Key, Value)] + end. + +-spec each(list(AHP), fun((AHP) -> any())) -> nil. +each(List, F) -> + case List of + [] -> + nil; + + [X | Xs] -> + F(X), + each(Xs, F) + end. + +-spec try_each(list(AHS), fun((AHS) -> {ok, any()} | {error, AHV})) -> {ok, nil} | + {error, AHV}. +try_each(List, Fun) -> + case List of + [] -> + {ok, nil}; + + [X | Xs] -> + case Fun(X) of + {ok, _} -> + try_each(Xs, Fun); + + {error, E} -> + {error, E} + end + end. + +-spec do_partition(list(AZB), fun((AZB) -> boolean()), list(AZB), list(AZB)) -> {list(AZB), + list(AZB)}. +do_partition(List, Categorise, Trues, Falses) -> + case List of + [] -> + {reverse(Trues), reverse(Falses)}; + + [X | Xs] -> + case Categorise(X) of + true -> + do_partition(Xs, Categorise, [X | Trues], Falses); + + false -> + do_partition(Xs, Categorise, Trues, [X | Falses]) + end + end. + +-spec partition(list(AIF), fun((AIF) -> boolean())) -> {list(AIF), list(AIF)}. +partition(List, Categorise) -> + do_partition(List, Categorise, [], []). + +-spec permutations(list(AIJ)) -> list(list(AIJ)). +permutations(L) -> + case L of + [] -> + [[]]; + + _ -> + _pipe = L, + _pipe@5 = index_map(_pipe, fun(I_idx, I) -> _pipe@1 = L, + _pipe@2 = index_fold( + _pipe@1, + [], + fun(Acc, J, J_idx) -> case I_idx =:= J_idx of + true -> + Acc; + + false -> + [J | Acc] + end end + ), + _pipe@3 = reverse(_pipe@2), + _pipe@4 = permutations(_pipe@3), + map(_pipe@4, fun(Permutation) -> [I | Permutation] end) end), + concat(_pipe@5) + end. + +-spec do_window(list(list(AIN)), list(AIN), integer()) -> list(list(AIN)). +do_window(Acc, L, N) -> + Window = take(L, N), + case length(Window) =:= N of + true -> + do_window([Window | Acc], drop(L, 1), N); + + false -> + Acc + end. + +-spec window(list(AIT), integer()) -> list(list(AIT)). +window(L, N) -> + _pipe = do_window([], L, N), + reverse(_pipe). + +-spec window_by_2(list(AIX)) -> list({AIX, AIX}). +window_by_2(L) -> + zip(L, drop(L, 1)). + +-spec drop_while(list(AJA), fun((AJA) -> boolean())) -> list(AJA). +drop_while(List, Predicate) -> + case List of + [] -> + []; + + [X | Xs] -> + case Predicate(X) of + true -> + drop_while(Xs, Predicate); + + false -> + [X | Xs] + end + end. + +-spec do_take_while(list(AJD), fun((AJD) -> boolean()), list(AJD)) -> list(AJD). +do_take_while(List, Predicate, Acc) -> + case List of + [] -> + reverse(Acc); + + [First | Rest] -> + case Predicate(First) of + true -> + do_take_while(Rest, Predicate, [First | Acc]); + + false -> + reverse(Acc) + end + end. + +-spec take_while(list(AJH), fun((AJH) -> boolean())) -> list(AJH). +take_while(List, Predicate) -> + do_take_while(List, Predicate, []). + +-spec do_chunk(list(AJK), fun((AJK) -> AJM), AJM, list(AJK), list(list(AJK))) -> list(list(AJK)). +do_chunk(List, F, Previous_key, Current_chunk, Acc) -> + case List of + [First | Rest] -> + Key = F(First), + case Key =:= Previous_key of + false -> + New_acc = [reverse(Current_chunk) | Acc], + do_chunk(Rest, F, Key, [First], New_acc); + + _ -> + do_chunk(Rest, F, Key, [First | Current_chunk], Acc) + end; + + _ -> + reverse([reverse(Current_chunk) | Acc]) + end. + +-spec chunk(list(AJS), fun((AJS) -> any())) -> list(list(AJS)). +chunk(List, F) -> + case List of + [] -> + []; + + [First | Rest] -> + do_chunk(Rest, F, F(First), [First], []) + end. + +-spec do_sized_chunk( + list(AJX), + integer(), + integer(), + list(AJX), + list(list(AJX)) +) -> list(list(AJX)). +do_sized_chunk(List, Count, Left, Current_chunk, Acc) -> + case List of + [] -> + case Current_chunk of + [] -> + reverse(Acc); + + Remaining -> + reverse([reverse(Remaining) | Acc]) + end; + + [First | Rest] -> + Chunk = [First | Current_chunk], + case Left > 1 of + false -> + do_sized_chunk( + Rest, + Count, + Count, + [], + [reverse(Chunk) | Acc] + ); + + true -> + do_sized_chunk(Rest, Count, Left - 1, Chunk, Acc) + end + end. + +-spec sized_chunk(list(AKE), integer()) -> list(list(AKE)). +sized_chunk(List, Count) -> + do_sized_chunk(List, Count, Count, [], []). + +-spec reduce(list(AKI), fun((AKI, AKI) -> AKI)) -> {ok, AKI} | {error, nil}. +reduce(List, Fun) -> + case List of + [] -> + {error, nil}; + + [First | Rest] -> + {ok, fold(Rest, First, Fun)} + end. + +-spec do_scan(list(AKM), AKO, list(AKO), fun((AKO, AKM) -> AKO)) -> list(AKO). +do_scan(List, Accumulator, Accumulated, Fun) -> + case List of + [] -> + reverse(Accumulated); + + [X | Xs] -> + Next = Fun(Accumulator, X), + do_scan(Xs, Next, [Next | Accumulated], Fun) + end. + +-spec scan(list(AKR), AKT, fun((AKT, AKR) -> AKT)) -> list(AKT). +scan(List, Initial, Fun) -> + do_scan(List, Initial, [], Fun). + +-spec last(list(AKV)) -> {ok, AKV} | {error, nil}. +last(List) -> + _pipe = List, + reduce(_pipe, fun(_, Elem) -> Elem end). + +-spec combinations(list(AKZ), integer()) -> list(list(AKZ)). +combinations(Items, N) -> + case N of + 0 -> + [[]]; + + _ -> + case Items of + [] -> + []; + + [X | Xs] -> + First_combinations = begin + _pipe = map( + combinations(Xs, N - 1), + fun(Com) -> [X | Com] end + ), + reverse(_pipe) + end, + fold( + First_combinations, + combinations(Xs, N), + fun(Acc, C) -> [C | Acc] end + ) + end + end. + +-spec do_combination_pairs(list(ALD)) -> list(list({ALD, ALD})). +do_combination_pairs(Items) -> + case Items of + [] -> + []; + + [X | Xs] -> + First_combinations = map(Xs, fun(Other) -> {X, Other} end), + [First_combinations | do_combination_pairs(Xs)] + end. + +-spec combination_pairs(list(ALH)) -> list({ALH, ALH}). +combination_pairs(Items) -> + _pipe = do_combination_pairs(Items), + concat(_pipe). + +-spec transpose(list(list(ALO))) -> list(list(ALO)). +transpose(List_of_list) -> + Take_first = fun(List) -> case List of + [] -> + []; + + [F] -> + [F]; + + [F@1 | _] -> + [F@1] + end end, + case List_of_list of + [] -> + []; + + [[] | Xss] -> + transpose(Xss); + + Rows -> + Firsts = begin + _pipe = Rows, + _pipe@1 = map(_pipe, Take_first), + concat(_pipe@1) + end, + Rest = transpose(map(Rows, fun(_capture) -> drop(_capture, 1) end)), + [Firsts | Rest] + end. + +-spec interleave(list(list(ALK))) -> list(ALK). +interleave(List) -> + _pipe = transpose(List), + concat(_pipe). + +-spec do_shuffle_pair_unwrap(list({float(), ALT}), list(ALT)) -> list(ALT). +do_shuffle_pair_unwrap(List, Acc) -> + case List of + [] -> + Acc; + + [Elem_pair | Enumerable] -> + do_shuffle_pair_unwrap( + Enumerable, + [erlang:element(2, Elem_pair) | Acc] + ) + end. + +-spec do_shuffle_by_pair_indexes(list({float(), ALX})) -> list({float(), ALX}). +do_shuffle_by_pair_indexes(List_of_pairs) -> + sort( + List_of_pairs, + fun(A_pair, B_pair) -> + gleam@float:compare( + erlang:element(1, A_pair), + erlang:element(1, B_pair) + ) + end + ). + +-spec shuffle(list(AMA)) -> list(AMA). +shuffle(List) -> + _pipe = List, + _pipe@1 = fold( + _pipe, + [], + fun(Acc, A) -> [{gleam@float:random(+0.0, 1.0), A} | Acc] end + ), + _pipe@2 = do_shuffle_by_pair_indexes(_pipe@1), + do_shuffle_pair_unwrap(_pipe@2, []). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@map.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@map.erl new file mode 100644 index 0000000..33e89a9 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@map.erl @@ -0,0 +1,76 @@ +-module(gleam@map). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([size/1, to_list/1, from_list/1, has_key/2, new/0, get/2, insert/3, map_values/2, keys/1, values/1, filter/2, take/2, merge/2, delete/2, drop/2, update/3, fold/3]). + +-spec size(gleam@dict:dict(any(), any())) -> integer(). +size(Map) -> + gleam@dict:size(Map). + +-spec to_list(gleam@dict:dict(DAJ, DAK)) -> list({DAJ, DAK}). +to_list(Map) -> + gleam@dict:to_list(Map). + +-spec from_list(list({DAM, DAN})) -> gleam@dict:dict(DAM, DAN). +from_list(List) -> + gleam@dict:from_list(List). + +-spec has_key(gleam@dict:dict(DAR, any()), DAR) -> boolean(). +has_key(Map, Key) -> + gleam@dict:has_key(Map, Key). + +-spec new() -> gleam@dict:dict(any(), any()). +new() -> + gleam@dict:new(). + +-spec get(gleam@dict:dict(DAU, DAV), DAU) -> {ok, DAV} | {error, nil}. +get(From, Get) -> + gleam@dict:get(From, Get). + +-spec insert(gleam@dict:dict(DAZ, DBA), DAZ, DBA) -> gleam@dict:dict(DAZ, DBA). +insert(Map, Key, Value) -> + gleam@dict:insert(Map, Key, Value). + +-spec map_values(gleam@dict:dict(DBD, DBE), fun((DBD, DBE) -> DBF)) -> gleam@dict:dict(DBD, DBF). +map_values(Map, Fun) -> + gleam@dict:map_values(Map, Fun). + +-spec keys(gleam@dict:dict(DBI, any())) -> list(DBI). +keys(Map) -> + gleam@dict:keys(Map). + +-spec values(gleam@dict:dict(any(), DBL)) -> list(DBL). +values(Map) -> + gleam@dict:values(Map). + +-spec filter(gleam@dict:dict(DBO, DBP), fun((DBO, DBP) -> boolean())) -> gleam@dict:dict(DBO, DBP). +filter(Map, Predicate) -> + gleam@dict:filter(Map, Predicate). + +-spec take(gleam@dict:dict(DBS, DDM), list(DBS)) -> gleam@dict:dict(DBS, DDM). +take(Map, Desired_keys) -> + gleam@dict:take(Map, Desired_keys). + +-spec merge(gleam@dict:dict(DDN, DDO), gleam@dict:dict(DDN, DDO)) -> gleam@dict:dict(DDN, DDO). +merge(Map, New_entries) -> + gleam@dict:merge(Map, New_entries). + +-spec delete(gleam@dict:dict(DBZ, DDQ), DBZ) -> gleam@dict:dict(DBZ, DDQ). +delete(Map, Key) -> + gleam@dict:delete(Map, Key). + +-spec drop(gleam@dict:dict(DCC, DDS), list(DCC)) -> gleam@dict:dict(DCC, DDS). +drop(Map, Disallowed_keys) -> + gleam@dict:drop(Map, Disallowed_keys). + +-spec update( + gleam@dict:dict(DCG, DCH), + DCG, + fun((gleam@option:option(DCH)) -> DCH) +) -> gleam@dict:dict(DCG, DCH). +update(Map, Key, Fun) -> + gleam@dict:update(Map, Key, Fun). + +-spec fold(gleam@dict:dict(DCM, DCN), DCL, fun((DCL, DCM, DCN) -> DCL)) -> DCL. +fold(Map, Initial, Fun) -> + gleam@dict:fold(Map, Initial, Fun). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@option.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@option.erl new file mode 100644 index 0000000..5c20713 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@option.erl @@ -0,0 +1,147 @@ +-module(gleam@option). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([all/1, is_some/1, is_none/1, to_result/2, from_result/1, unwrap/2, lazy_unwrap/2, map/2, flatten/1, then/2, 'or'/2, lazy_or/2, values/1]). +-export_type([option/1]). + +-type option(GB) :: {some, GB} | none. + +-spec do_all(list(option(GC)), list(GC)) -> option(list(GC)). +do_all(List, Acc) -> + case List of + [] -> + {some, Acc}; + + [X | Rest] -> + Accumulate = fun(Acc@1, Item) -> case {Acc@1, Item} of + {{some, Values}, {some, Value}} -> + {some, [Value | Values]}; + + {_, _} -> + none + end end, + Accumulate(do_all(Rest, Acc), X) + end. + +-spec all(list(option(GI))) -> option(list(GI)). +all(List) -> + do_all(List, []). + +-spec is_some(option(any())) -> boolean(). +is_some(Option) -> + Option /= none. + +-spec is_none(option(any())) -> boolean(). +is_none(Option) -> + Option =:= none. + +-spec to_result(option(GR), GU) -> {ok, GR} | {error, GU}. +to_result(Option, E) -> + case Option of + {some, A} -> + {ok, A}; + + _ -> + {error, E} + end. + +-spec from_result({ok, GX} | {error, any()}) -> option(GX). +from_result(Result) -> + case Result of + {ok, A} -> + {some, A}; + + _ -> + none + end. + +-spec unwrap(option(HC), HC) -> HC. +unwrap(Option, Default) -> + case Option of + {some, X} -> + X; + + none -> + Default + end. + +-spec lazy_unwrap(option(HE), fun(() -> HE)) -> HE. +lazy_unwrap(Option, Default) -> + case Option of + {some, X} -> + X; + + none -> + Default() + end. + +-spec map(option(HG), fun((HG) -> HI)) -> option(HI). +map(Option, Fun) -> + case Option of + {some, X} -> + {some, Fun(X)}; + + none -> + none + end. + +-spec flatten(option(option(HK))) -> option(HK). +flatten(Option) -> + case Option of + {some, X} -> + X; + + none -> + none + end. + +-spec then(option(HO), fun((HO) -> option(HQ))) -> option(HQ). +then(Option, Fun) -> + case Option of + {some, X} -> + Fun(X); + + none -> + none + end. + +-spec 'or'(option(HT), option(HT)) -> option(HT). +'or'(First, Second) -> + case First of + {some, _} -> + First; + + none -> + Second + end. + +-spec lazy_or(option(HX), fun(() -> option(HX))) -> option(HX). +lazy_or(First, Second) -> + case First of + {some, _} -> + First; + + none -> + Second() + end. + +-spec do_values(list(option(IB)), list(IB)) -> list(IB). +do_values(List, Acc) -> + case List of + [] -> + Acc; + + [X | Xs] -> + Accumulate = fun(Acc@1, Item) -> case Item of + {some, Value} -> + [Value | Acc@1]; + + none -> + Acc@1 + end end, + Accumulate(do_values(Xs, Acc), X) + end. + +-spec values(list(option(IG))) -> list(IG). +values(Options) -> + do_values(Options, []). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@order.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@order.erl new file mode 100644 index 0000000..61649b9 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@order.erl @@ -0,0 +1,79 @@ +-module(gleam@order). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([negate/1, to_int/1, compare/2, max/2, min/2, reverse/1]). +-export_type([order/0]). + +-type order() :: lt | eq | gt. + +-spec negate(order()) -> order(). +negate(Order) -> + case Order of + lt -> + gt; + + eq -> + eq; + + gt -> + lt + end. + +-spec to_int(order()) -> integer(). +to_int(Order) -> + case Order of + lt -> + -1; + + eq -> + 0; + + gt -> + 1 + end. + +-spec compare(order(), order()) -> order(). +compare(A, B) -> + case {A, B} of + {X, Y} when X =:= Y -> + eq; + + {lt, _} -> + lt; + + {eq, gt} -> + lt; + + {_, _} -> + gt + end. + +-spec max(order(), order()) -> order(). +max(A, B) -> + case {A, B} of + {gt, _} -> + gt; + + {eq, lt} -> + eq; + + {_, _} -> + B + end. + +-spec min(order(), order()) -> order(). +min(A, B) -> + case {A, B} of + {lt, _} -> + lt; + + {eq, gt} -> + eq; + + {_, _} -> + B + end. + +-spec reverse(fun((I, I) -> order())) -> fun((I, I) -> order()). +reverse(Orderer) -> + fun(A, B) -> Orderer(B, A) end. diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@pair.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@pair.erl new file mode 100644 index 0000000..f4eff52 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@pair.erl @@ -0,0 +1,33 @@ +-module(gleam@pair). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([first/1, second/1, swap/1, map_first/2, map_second/2, new/2]). + +-spec first({FM, any()}) -> FM. +first(Pair) -> + {A, _} = Pair, + A. + +-spec second({any(), FP}) -> FP. +second(Pair) -> + {_, A} = Pair, + A. + +-spec swap({FQ, FR}) -> {FR, FQ}. +swap(Pair) -> + {A, B} = Pair, + {B, A}. + +-spec map_first({FS, FT}, fun((FS) -> FU)) -> {FU, FT}. +map_first(Pair, Fun) -> + {A, B} = Pair, + {Fun(A), B}. + +-spec map_second({FV, FW}, fun((FW) -> FX)) -> {FV, FX}. +map_second(Pair, Fun) -> + {A, B} = Pair, + {A, Fun(B)}. + +-spec new(FY, FZ) -> {FY, FZ}. +new(First, Second) -> + {First, Second}. diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@queue.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@queue.erl new file mode 100644 index 0000000..6b587e7 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@queue.erl @@ -0,0 +1,121 @@ +-module(gleam@queue). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-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]). +-export_type([queue/1]). + +-opaque queue(DRL) :: {queue, list(DRL), list(DRL)}. + +-spec new() -> queue(any()). +new() -> + {queue, [], []}. + +-spec from_list(list(DRO)) -> queue(DRO). +from_list(List) -> + {queue, [], List}. + +-spec to_list(queue(DRR)) -> list(DRR). +to_list(Queue) -> + _pipe = erlang:element(3, Queue), + gleam@list:append(_pipe, gleam@list:reverse(erlang:element(2, Queue))). + +-spec is_empty(queue(any())) -> boolean(). +is_empty(Queue) -> + (erlang:element(2, Queue) =:= []) andalso (erlang:element(3, Queue) =:= []). + +-spec length(queue(any())) -> integer(). +length(Queue) -> + gleam@list:length(erlang:element(2, Queue)) + gleam@list:length( + erlang:element(3, Queue) + ). + +-spec push_back(queue(DRY), DRY) -> queue(DRY). +push_back(Queue, Item) -> + {queue, [Item | erlang:element(2, Queue)], erlang:element(3, Queue)}. + +-spec push_front(queue(DSB), DSB) -> queue(DSB). +push_front(Queue, Item) -> + {queue, erlang:element(2, Queue), [Item | erlang:element(3, Queue)]}. + +-spec pop_back(queue(DSE)) -> {ok, {DSE, queue(DSE)}} | {error, nil}. +pop_back(Queue) -> + case Queue of + {queue, [], []} -> + {error, nil}; + + {queue, [], Out} -> + pop_back({queue, gleam@list:reverse(Out), []}); + + {queue, [First | Rest], Out@1} -> + Queue@1 = {queue, Rest, Out@1}, + {ok, {First, Queue@1}} + end. + +-spec pop_front(queue(DSJ)) -> {ok, {DSJ, queue(DSJ)}} | {error, nil}. +pop_front(Queue) -> + case Queue of + {queue, [], []} -> + {error, nil}; + + {queue, In, []} -> + pop_front({queue, [], gleam@list:reverse(In)}); + + {queue, In@1, [First | Rest]} -> + Queue@1 = {queue, In@1, Rest}, + {ok, {First, Queue@1}} + end. + +-spec reverse(queue(DSO)) -> queue(DSO). +reverse(Queue) -> + {queue, erlang:element(3, Queue), erlang:element(2, Queue)}. + +-spec check_equal( + list(DSR), + list(DSR), + list(DSR), + list(DSR), + fun((DSR, DSR) -> boolean()) +) -> boolean(). +check_equal(Xs, X_tail, Ys, Y_tail, Eq) -> + case {Xs, X_tail, Ys, Y_tail} of + {[], [], [], []} -> + true; + + {[X | Xs@1], _, [Y | Ys@1], _} -> + case Eq(X, Y) of + false -> + false; + + true -> + check_equal(Xs@1, X_tail, Ys@1, Y_tail, Eq) + end; + + {[], [_ | _], _, _} -> + check_equal(gleam@list:reverse(X_tail), [], Ys, Y_tail, Eq); + + {_, _, [], [_ | _]} -> + check_equal(Xs, X_tail, gleam@list:reverse(Y_tail), [], Eq); + + {_, _, _, _} -> + false + end. + +-spec is_logically_equal(queue(DSW), queue(DSW), fun((DSW, DSW) -> boolean())) -> boolean(). +is_logically_equal(A, B, Element_is_equal) -> + check_equal( + erlang:element(3, A), + erlang:element(2, A), + erlang:element(3, B), + erlang:element(2, B), + Element_is_equal + ). + +-spec is_equal(queue(DSZ), queue(DSZ)) -> boolean(). +is_equal(A, B) -> + check_equal( + erlang:element(3, A), + erlang:element(2, A), + erlang:element(3, B), + erlang:element(2, B), + fun(A@1, B@1) -> A@1 =:= B@1 end + ). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@regex.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@regex.erl new file mode 100644 index 0000000..2d1c5fc --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@regex.erl @@ -0,0 +1,33 @@ +-module(gleam@regex). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([compile/2, from_string/1, check/2, split/2, scan/2]). +-export_type([regex/0, match/0, compile_error/0, options/0]). + +-type regex() :: any(). + +-type match() :: {match, binary(), list(gleam@option:option(binary()))}. + +-type compile_error() :: {compile_error, binary(), integer()}. + +-type options() :: {options, boolean(), boolean()}. + +-spec compile(binary(), options()) -> {ok, regex()} | {error, compile_error()}. +compile(Pattern, Options) -> + gleam_stdlib:compile_regex(Pattern, Options). + +-spec from_string(binary()) -> {ok, regex()} | {error, compile_error()}. +from_string(Pattern) -> + compile(Pattern, {options, false, false}). + +-spec check(regex(), binary()) -> boolean(). +check(Regex, Content) -> + gleam_stdlib:regex_check(Regex, Content). + +-spec split(regex(), binary()) -> list(binary()). +split(Regex, String) -> + gleam_stdlib:regex_split(Regex, String). + +-spec scan(regex(), binary()) -> list(match()). +scan(Regex, String) -> + gleam_stdlib:regex_scan(Regex, String). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@result.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@result.erl new file mode 100644 index 0000000..7324e45 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@result.erl @@ -0,0 +1,201 @@ +-module(gleam@result). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([is_ok/1, is_error/1, map/2, map_error/2, flatten/1, 'try'/2, then/2, unwrap/2, lazy_unwrap/2, unwrap_error/2, unwrap_both/1, nil_error/1, 'or'/2, lazy_or/2, all/1, partition/1, replace/2, replace_error/2, values/1, try_recover/2]). + +-spec is_ok({ok, any()} | {error, any()}) -> boolean(). +is_ok(Result) -> + case Result of + {error, _} -> + false; + + {ok, _} -> + true + end. + +-spec is_error({ok, any()} | {error, any()}) -> boolean(). +is_error(Result) -> + case Result of + {ok, _} -> + false; + + {error, _} -> + true + end. + +-spec map({ok, BFM} | {error, BFN}, fun((BFM) -> BFQ)) -> {ok, BFQ} | + {error, BFN}. +map(Result, Fun) -> + case Result of + {ok, X} -> + {ok, Fun(X)}; + + {error, E} -> + {error, E} + end. + +-spec map_error({ok, BFT} | {error, BFU}, fun((BFU) -> BFX)) -> {ok, BFT} | + {error, BFX}. +map_error(Result, Fun) -> + case Result of + {ok, X} -> + {ok, X}; + + {error, Error} -> + {error, Fun(Error)} + end. + +-spec flatten({ok, {ok, BGA} | {error, BGB}} | {error, BGB}) -> {ok, BGA} | + {error, BGB}. +flatten(Result) -> + case Result of + {ok, X} -> + X; + + {error, Error} -> + {error, Error} + end. + +-spec 'try'({ok, BGI} | {error, BGJ}, fun((BGI) -> {ok, BGM} | {error, BGJ})) -> {ok, + BGM} | + {error, BGJ}. +'try'(Result, Fun) -> + case Result of + {ok, X} -> + Fun(X); + + {error, E} -> + {error, E} + end. + +-spec then({ok, BGR} | {error, BGS}, fun((BGR) -> {ok, BGV} | {error, BGS})) -> {ok, + BGV} | + {error, BGS}. +then(Result, Fun) -> + 'try'(Result, Fun). + +-spec unwrap({ok, BHA} | {error, any()}, BHA) -> BHA. +unwrap(Result, Default) -> + case Result of + {ok, V} -> + V; + + {error, _} -> + Default + end. + +-spec lazy_unwrap({ok, BHE} | {error, any()}, fun(() -> BHE)) -> BHE. +lazy_unwrap(Result, Default) -> + case Result of + {ok, V} -> + V; + + {error, _} -> + Default() + end. + +-spec unwrap_error({ok, any()} | {error, BHJ}, BHJ) -> BHJ. +unwrap_error(Result, Default) -> + case Result of + {ok, _} -> + Default; + + {error, E} -> + E + end. + +-spec unwrap_both({ok, BHM} | {error, BHM}) -> BHM. +unwrap_both(Result) -> + case Result of + {ok, A} -> + A; + + {error, A@1} -> + A@1 + end. + +-spec nil_error({ok, BHP} | {error, any()}) -> {ok, BHP} | {error, nil}. +nil_error(Result) -> + map_error(Result, fun(_) -> nil end). + +-spec 'or'({ok, BHV} | {error, BHW}, {ok, BHV} | {error, BHW}) -> {ok, BHV} | + {error, BHW}. +'or'(First, Second) -> + case First of + {ok, _} -> + First; + + {error, _} -> + Second + end. + +-spec lazy_or({ok, BID} | {error, BIE}, fun(() -> {ok, BID} | {error, BIE})) -> {ok, + BID} | + {error, BIE}. +lazy_or(First, Second) -> + case First of + {ok, _} -> + First; + + {error, _} -> + Second() + end. + +-spec all(list({ok, BIL} | {error, BIM})) -> {ok, list(BIL)} | {error, BIM}. +all(Results) -> + gleam@list:try_map(Results, fun(X) -> X end). + +-spec do_partition(list({ok, BJA} | {error, BJB}), list(BJA), list(BJB)) -> {list(BJA), + list(BJB)}. +do_partition(Results, Oks, Errors) -> + case Results of + [] -> + {Oks, Errors}; + + [{ok, A} | Rest] -> + do_partition(Rest, [A | Oks], Errors); + + [{error, E} | Rest@1] -> + do_partition(Rest@1, Oks, [E | Errors]) + end. + +-spec partition(list({ok, BIT} | {error, BIU})) -> {list(BIT), list(BIU)}. +partition(Results) -> + do_partition(Results, [], []). + +-spec replace({ok, any()} | {error, BJJ}, BJM) -> {ok, BJM} | {error, BJJ}. +replace(Result, Value) -> + case Result of + {ok, _} -> + {ok, Value}; + + {error, Error} -> + {error, Error} + end. + +-spec replace_error({ok, BJP} | {error, any()}, BJT) -> {ok, BJP} | {error, BJT}. +replace_error(Result, Error) -> + case Result of + {ok, X} -> + {ok, X}; + + {error, _} -> + {error, Error} + end. + +-spec values(list({ok, BJW} | {error, any()})) -> list(BJW). +values(Results) -> + gleam@list:filter_map(Results, fun(R) -> R end). + +-spec try_recover( + {ok, BKC} | {error, BKD}, + fun((BKD) -> {ok, BKC} | {error, BKG}) +) -> {ok, BKC} | {error, BKG}. +try_recover(Result, Fun) -> + case Result of + {ok, Value} -> + {ok, Value}; + + {error, Error} -> + Fun(Error) + end. diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@set.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@set.erl new file mode 100644 index 0000000..df87b13 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@set.erl @@ -0,0 +1,85 @@ +-module(gleam@set). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([new/0, size/1, insert/2, contains/2, delete/2, to_list/1, from_list/1, fold/3, filter/2, drop/2, take/2, union/2, intersection/2]). +-export_type([set/1]). + +-opaque set(DJZ) :: {set, gleam@dict:dict(DJZ, list(nil))}. + +-spec new() -> set(any()). +new() -> + {set, gleam@dict:new()}. + +-spec size(set(any())) -> integer(). +size(Set) -> + gleam@dict:size(erlang:element(2, Set)). + +-spec insert(set(DKF), DKF) -> set(DKF). +insert(Set, Member) -> + {set, gleam@dict:insert(erlang:element(2, Set), Member, [])}. + +-spec contains(set(DKI), DKI) -> boolean(). +contains(Set, Member) -> + _pipe = erlang:element(2, Set), + _pipe@1 = gleam@dict:get(_pipe, Member), + gleam@result:is_ok(_pipe@1). + +-spec delete(set(DKK), DKK) -> set(DKK). +delete(Set, Member) -> + {set, gleam@dict:delete(erlang:element(2, Set), Member)}. + +-spec to_list(set(DKN)) -> list(DKN). +to_list(Set) -> + gleam@dict:keys(erlang:element(2, Set)). + +-spec from_list(list(DKQ)) -> set(DKQ). +from_list(Members) -> + Map = gleam@list:fold( + Members, + gleam@dict:new(), + fun(M, K) -> gleam@dict:insert(M, K, []) end + ), + {set, Map}. + +-spec fold(set(DKT), DKV, fun((DKV, DKT) -> DKV)) -> DKV. +fold(Set, Initial, Reducer) -> + gleam@dict:fold( + erlang:element(2, Set), + Initial, + fun(A, K, _) -> Reducer(A, K) end + ). + +-spec filter(set(DKW), fun((DKW) -> boolean())) -> set(DKW). +filter(Set, Predicate) -> + {set, + gleam@dict:filter(erlang:element(2, Set), fun(M, _) -> Predicate(M) end)}. + +-spec drop(set(DKZ), list(DKZ)) -> set(DKZ). +drop(Set, Disallowed) -> + gleam@list:fold(Disallowed, Set, fun delete/2). + +-spec take(set(DLD), list(DLD)) -> set(DLD). +take(Set, Desired) -> + {set, gleam@dict:take(erlang:element(2, Set), Desired)}. + +-spec order(set(DLH), set(DLH)) -> {set(DLH), set(DLH)}. +order(First, Second) -> + case gleam@dict:size(erlang:element(2, First)) > gleam@dict:size( + erlang:element(2, Second) + ) of + true -> + {First, Second}; + + false -> + {Second, First} + end. + +-spec union(set(DLM), set(DLM)) -> set(DLM). +union(First, Second) -> + {Larger, Smaller} = order(First, Second), + fold(Smaller, Larger, fun insert/2). + +-spec intersection(set(DLQ), set(DLQ)) -> set(DLQ). +intersection(First, Second) -> + {Larger, Smaller} = order(First, Second), + take(Larger, to_list(Smaller)). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@string.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@string.erl new file mode 100644 index 0000000..6cba31d --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@string.erl @@ -0,0 +1,352 @@ +-module(gleam@string). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([is_empty/1, length/1, reverse/1, replace/3, lowercase/1, uppercase/1, compare/2, slice/3, crop/2, drop_left/2, drop_right/2, contains/2, starts_with/2, ends_with/2, split_once/2, append/2, concat/1, repeat/2, join/2, pad_left/3, pad_right/3, trim/1, trim_left/1, trim_right/1, pop_grapheme/1, to_graphemes/1, split/2, to_utf_codepoints/1, from_utf_codepoints/1, utf_codepoint/1, utf_codepoint_to_int/1, to_option/1, first/1, last/1, capitalise/1, inspect/1, byte_size/1]). +-export_type([direction/0]). + +-type direction() :: leading | trailing | both. + +-spec is_empty(binary()) -> boolean(). +is_empty(Str) -> + Str =:= <<""/utf8>>. + +-spec length(binary()) -> integer(). +length(String) -> + string:length(String). + +-spec do_reverse(binary()) -> binary(). +do_reverse(String) -> + _pipe = String, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:reverse(_pipe@1), + gleam@string_builder:to_string(_pipe@2). + +-spec reverse(binary()) -> binary(). +reverse(String) -> + do_reverse(String). + +-spec replace(binary(), binary(), binary()) -> binary(). +replace(String, Pattern, Substitute) -> + _pipe = String, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:replace(_pipe@1, Pattern, Substitute), + gleam@string_builder:to_string(_pipe@2). + +-spec lowercase(binary()) -> binary(). +lowercase(String) -> + string:lowercase(String). + +-spec uppercase(binary()) -> binary(). +uppercase(String) -> + string:uppercase(String). + +-spec compare(binary(), binary()) -> gleam@order:order(). +compare(A, B) -> + case A =:= B of + true -> + eq; + + _ -> + case gleam_stdlib:less_than(A, B) of + true -> + lt; + + _ -> + gt + end + end. + +-spec slice(binary(), integer(), integer()) -> binary(). +slice(String, Idx, Len) -> + case Len < 0 of + true -> + <<""/utf8>>; + + false -> + case Idx < 0 of + true -> + Translated_idx = length(String) + Idx, + case Translated_idx < 0 of + true -> + <<""/utf8>>; + + false -> + string:slice(String, Translated_idx, Len) + end; + + false -> + string:slice(String, Idx, Len) + end + end. + +-spec crop(binary(), binary()) -> binary(). +crop(String, Substring) -> + gleam_stdlib:crop_string(String, Substring). + +-spec drop_left(binary(), integer()) -> binary(). +drop_left(String, Num_graphemes) -> + case Num_graphemes < 0 of + true -> + String; + + false -> + slice(String, Num_graphemes, length(String) - Num_graphemes) + end. + +-spec drop_right(binary(), integer()) -> binary(). +drop_right(String, Num_graphemes) -> + case Num_graphemes < 0 of + true -> + String; + + false -> + slice(String, 0, length(String) - Num_graphemes) + end. + +-spec contains(binary(), binary()) -> boolean(). +contains(Haystack, Needle) -> + gleam_stdlib:contains_string(Haystack, Needle). + +-spec starts_with(binary(), binary()) -> boolean(). +starts_with(String, Prefix) -> + gleam_stdlib:string_starts_with(String, Prefix). + +-spec ends_with(binary(), binary()) -> boolean(). +ends_with(String, Suffix) -> + gleam_stdlib:string_ends_with(String, Suffix). + +-spec do_split_once(binary(), binary()) -> {ok, {binary(), binary()}} | + {error, nil}. +do_split_once(X, Substring) -> + case string:split(X, Substring) of + [First, Rest] -> + {ok, {First, Rest}}; + + _ -> + {error, nil} + end. + +-spec split_once(binary(), binary()) -> {ok, {binary(), binary()}} | + {error, nil}. +split_once(X, Substring) -> + do_split_once(X, Substring). + +-spec append(binary(), binary()) -> binary(). +append(First, Second) -> + _pipe = First, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:append(_pipe@1, Second), + gleam@string_builder:to_string(_pipe@2). + +-spec concat(list(binary())) -> binary(). +concat(Strings) -> + _pipe = Strings, + _pipe@1 = gleam@string_builder:from_strings(_pipe), + gleam@string_builder:to_string(_pipe@1). + +-spec repeat(binary(), integer()) -> binary(). +repeat(String, Times) -> + _pipe = gleam@iterator:repeat(String), + _pipe@1 = gleam@iterator:take(_pipe, Times), + _pipe@2 = gleam@iterator:to_list(_pipe@1), + concat(_pipe@2). + +-spec do_join(list(binary()), binary()) -> binary(). +do_join(Strings, Separator) -> + _pipe = Strings, + _pipe@1 = gleam@list:intersperse(_pipe, Separator), + concat(_pipe@1). + +-spec join(list(binary()), binary()) -> binary(). +join(Strings, Separator) -> + do_join(Strings, Separator). + +-spec padding(integer(), binary()) -> gleam@iterator:iterator(binary()). +padding(Size, Pad_string) -> + Pad_length = length(Pad_string), + Num_pads = case Pad_length of + 0 -> 0; + Gleam@denominator -> Size div Gleam@denominator + end, + Extra = case Pad_length of + 0 -> 0; + Gleam@denominator@1 -> Size rem Gleam@denominator@1 + end, + _pipe = gleam@iterator:repeat(Pad_string), + _pipe@1 = gleam@iterator:take(_pipe, Num_pads), + gleam@iterator:append( + _pipe@1, + gleam@iterator:single(slice(Pad_string, 0, Extra)) + ). + +-spec pad_left(binary(), integer(), binary()) -> binary(). +pad_left(String, Desired_length, Pad_string) -> + Current_length = length(String), + To_pad_length = Desired_length - Current_length, + _pipe = padding(To_pad_length, Pad_string), + _pipe@1 = gleam@iterator:append(_pipe, gleam@iterator:single(String)), + _pipe@2 = gleam@iterator:to_list(_pipe@1), + concat(_pipe@2). + +-spec pad_right(binary(), integer(), binary()) -> binary(). +pad_right(String, Desired_length, Pad_string) -> + Current_length = length(String), + To_pad_length = Desired_length - Current_length, + _pipe = gleam@iterator:single(String), + _pipe@1 = gleam@iterator:append(_pipe, padding(To_pad_length, Pad_string)), + _pipe@2 = gleam@iterator:to_list(_pipe@1), + concat(_pipe@2). + +-spec do_trim(binary()) -> binary(). +do_trim(String) -> + string:trim(String, both). + +-spec trim(binary()) -> binary(). +trim(String) -> + do_trim(String). + +-spec do_trim_left(binary()) -> binary(). +do_trim_left(String) -> + string:trim(String, leading). + +-spec trim_left(binary()) -> binary(). +trim_left(String) -> + do_trim_left(String). + +-spec do_trim_right(binary()) -> binary(). +do_trim_right(String) -> + string:trim(String, trailing). + +-spec trim_right(binary()) -> binary(). +trim_right(String) -> + do_trim_right(String). + +-spec pop_grapheme(binary()) -> {ok, {binary(), binary()}} | {error, nil}. +pop_grapheme(String) -> + gleam_stdlib:string_pop_grapheme(String). + +-spec do_to_graphemes(binary(), list(binary())) -> list(binary()). +do_to_graphemes(String, Acc) -> + case pop_grapheme(String) of + {ok, {Grapheme, Rest}} -> + do_to_graphemes(Rest, [Grapheme | Acc]); + + _ -> + Acc + end. + +-spec to_graphemes(binary()) -> list(binary()). +to_graphemes(String) -> + _pipe = do_to_graphemes(String, []), + gleam@list:reverse(_pipe). + +-spec split(binary(), binary()) -> list(binary()). +split(X, Substring) -> + case Substring of + <<""/utf8>> -> + to_graphemes(X); + + _ -> + _pipe = X, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:split(_pipe@1, Substring), + gleam@list:map(_pipe@2, fun gleam@string_builder:to_string/1) + end. + +-spec do_to_utf_codepoints_impl(bitstring(), list(integer())) -> list(integer()). +do_to_utf_codepoints_impl(Bit_array, Acc) -> + case Bit_array of + <<First/utf8, Rest/binary>> -> + do_to_utf_codepoints_impl(Rest, [First | Acc]); + + _ -> + Acc + end. + +-spec do_to_utf_codepoints(binary()) -> list(integer()). +do_to_utf_codepoints(String) -> + _pipe = do_to_utf_codepoints_impl(<<String/binary>>, []), + gleam@list:reverse(_pipe). + +-spec to_utf_codepoints(binary()) -> list(integer()). +to_utf_codepoints(String) -> + do_to_utf_codepoints(String). + +-spec from_utf_codepoints(list(integer())) -> binary(). +from_utf_codepoints(Utf_codepoints) -> + gleam_stdlib:utf_codepoint_list_to_string(Utf_codepoints). + +-spec utf_codepoint(integer()) -> {ok, integer()} | {error, nil}. +utf_codepoint(Value) -> + case Value of + I when I > 1114111 -> + {error, nil}; + + 65534 -> + {error, nil}; + + 65535 -> + {error, nil}; + + I@1 when (I@1 >= 55296) andalso (I@1 =< 57343) -> + {error, nil}; + + I@2 -> + {ok, gleam_stdlib:identity(I@2)} + end. + +-spec utf_codepoint_to_int(integer()) -> integer(). +utf_codepoint_to_int(Cp) -> + gleam_stdlib:identity(Cp). + +-spec to_option(binary()) -> gleam@option:option(binary()). +to_option(S) -> + case S of + <<""/utf8>> -> + none; + + _ -> + {some, S} + end. + +-spec first(binary()) -> {ok, binary()} | {error, nil}. +first(S) -> + case pop_grapheme(S) of + {ok, {First, _}} -> + {ok, First}; + + {error, E} -> + {error, E} + end. + +-spec last(binary()) -> {ok, binary()} | {error, nil}. +last(S) -> + case pop_grapheme(S) of + {ok, {First, <<""/utf8>>}} -> + {ok, First}; + + {ok, {_, Rest}} -> + {ok, slice(Rest, -1, 1)}; + + {error, E} -> + {error, E} + end. + +-spec capitalise(binary()) -> binary(). +capitalise(S) -> + case pop_grapheme(S) of + {ok, {First, Rest}} -> + append(uppercase(First), lowercase(Rest)); + + _ -> + <<""/utf8>> + end. + +-spec inspect(any()) -> binary(). +inspect(Term) -> + _pipe = gleam_stdlib:inspect(Term), + gleam@string_builder:to_string(_pipe). + +-spec byte_size(binary()) -> integer(). +byte_size(String) -> + erlang:byte_size(String). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@string_builder.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@string_builder.erl new file mode 100644 index 0000000..693e840 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@string_builder.erl @@ -0,0 +1,91 @@ +-module(gleam@string_builder). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([prepend_builder/2, append_builder/2, new/0, from_strings/1, concat/1, from_string/1, prepend/2, append/2, to_string/1, byte_size/1, join/2, lowercase/1, uppercase/1, reverse/1, split/2, replace/3, is_equal/2, is_empty/1]). +-export_type([string_builder/0, direction/0]). + +-type string_builder() :: any(). + +-type direction() :: all. + +-spec prepend_builder(string_builder(), string_builder()) -> string_builder(). +prepend_builder(Builder, Prefix) -> + gleam_stdlib:iodata_append(Prefix, Builder). + +-spec append_builder(string_builder(), string_builder()) -> string_builder(). +append_builder(Builder, Suffix) -> + gleam_stdlib:iodata_append(Builder, Suffix). + +-spec new() -> string_builder(). +new() -> + gleam_stdlib:identity([]). + +-spec from_strings(list(binary())) -> string_builder(). +from_strings(Strings) -> + gleam_stdlib:identity(Strings). + +-spec concat(list(string_builder())) -> string_builder(). +concat(Builders) -> + gleam_stdlib:identity(Builders). + +-spec from_string(binary()) -> string_builder(). +from_string(String) -> + gleam_stdlib:identity(String). + +-spec prepend(string_builder(), binary()) -> string_builder(). +prepend(Builder, Prefix) -> + append_builder(from_string(Prefix), Builder). + +-spec append(string_builder(), binary()) -> string_builder(). +append(Builder, Second) -> + append_builder(Builder, from_string(Second)). + +-spec to_string(string_builder()) -> binary(). +to_string(Builder) -> + unicode:characters_to_binary(Builder). + +-spec byte_size(string_builder()) -> integer(). +byte_size(Builder) -> + erlang:iolist_size(Builder). + +-spec join(list(string_builder()), binary()) -> string_builder(). +join(Builders, Sep) -> + _pipe = Builders, + _pipe@1 = gleam@list:intersperse(_pipe, from_string(Sep)), + concat(_pipe@1). + +-spec lowercase(string_builder()) -> string_builder(). +lowercase(Builder) -> + string:lowercase(Builder). + +-spec uppercase(string_builder()) -> string_builder(). +uppercase(Builder) -> + string:uppercase(Builder). + +-spec reverse(string_builder()) -> string_builder(). +reverse(Builder) -> + string:reverse(Builder). + +-spec do_split(string_builder(), binary()) -> list(string_builder()). +do_split(Iodata, Pattern) -> + string:split(Iodata, Pattern, all). + +-spec split(string_builder(), binary()) -> list(string_builder()). +split(Iodata, Pattern) -> + do_split(Iodata, Pattern). + +-spec do_replace(string_builder(), binary(), binary()) -> string_builder(). +do_replace(Iodata, Pattern, Substitute) -> + string:replace(Iodata, Pattern, Substitute, all). + +-spec replace(string_builder(), binary(), binary()) -> string_builder(). +replace(Builder, Pattern, Substitute) -> + do_replace(Builder, Pattern, Substitute). + +-spec is_equal(string_builder(), string_builder()) -> boolean(). +is_equal(A, B) -> + string:equal(A, B). + +-spec is_empty(string_builder()) -> boolean(). +is_empty(Builder) -> + string:is_empty(Builder). diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam@uri.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam@uri.erl new file mode 100644 index 0000000..7ec4fe7 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam@uri.erl @@ -0,0 +1,252 @@ +-module(gleam@uri). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([parse/1, parse_query/1, percent_encode/1, query_to_string/1, percent_decode/1, path_segments/1, to_string/1, origin/1, merge/2]). +-export_type([uri/0]). + +-type uri() :: {uri, + gleam@option:option(binary()), + gleam@option:option(binary()), + gleam@option:option(binary()), + gleam@option:option(integer()), + binary(), + gleam@option:option(binary()), + gleam@option:option(binary())}. + +-spec parse(binary()) -> {ok, uri()} | {error, nil}. +parse(Uri_string) -> + gleam_stdlib:uri_parse(Uri_string). + +-spec parse_query(binary()) -> {ok, list({binary(), binary()})} | {error, nil}. +parse_query(Query) -> + gleam_stdlib:parse_query(Query). + +-spec percent_encode(binary()) -> binary(). +percent_encode(Value) -> + gleam_stdlib:percent_encode(Value). + +-spec query_pair({binary(), binary()}) -> gleam@string_builder:string_builder(). +query_pair(Pair) -> + gleam@string_builder:from_strings( + [percent_encode(erlang:element(1, Pair)), + <<"="/utf8>>, + percent_encode(erlang:element(2, Pair))] + ). + +-spec query_to_string(list({binary(), binary()})) -> binary(). +query_to_string(Query) -> + _pipe = Query, + _pipe@1 = gleam@list:map(_pipe, fun query_pair/1), + _pipe@2 = gleam@list:intersperse( + _pipe@1, + gleam@string_builder:from_string(<<"&"/utf8>>) + ), + _pipe@3 = gleam@string_builder:concat(_pipe@2), + gleam@string_builder:to_string(_pipe@3). + +-spec percent_decode(binary()) -> {ok, binary()} | {error, nil}. +percent_decode(Value) -> + gleam_stdlib:percent_decode(Value). + +-spec do_remove_dot_segments(list(binary()), list(binary())) -> list(binary()). +do_remove_dot_segments(Input, Accumulator) -> + case Input of + [] -> + gleam@list:reverse(Accumulator); + + [Segment | Rest] -> + Accumulator@5 = case {Segment, Accumulator} of + {<<""/utf8>>, Accumulator@1} -> + Accumulator@1; + + {<<"."/utf8>>, Accumulator@2} -> + Accumulator@2; + + {<<".."/utf8>>, []} -> + []; + + {<<".."/utf8>>, [_ | Accumulator@3]} -> + Accumulator@3; + + {Segment@1, Accumulator@4} -> + [Segment@1 | Accumulator@4] + end, + do_remove_dot_segments(Rest, Accumulator@5) + end. + +-spec remove_dot_segments(list(binary())) -> list(binary()). +remove_dot_segments(Input) -> + do_remove_dot_segments(Input, []). + +-spec path_segments(binary()) -> list(binary()). +path_segments(Path) -> + remove_dot_segments(gleam@string:split(Path, <<"/"/utf8>>)). + +-spec to_string(uri()) -> binary(). +to_string(Uri) -> + Parts = case erlang:element(8, Uri) of + {some, Fragment} -> + [<<"#"/utf8>>, Fragment]; + + _ -> + [] + end, + Parts@1 = case erlang:element(7, Uri) of + {some, Query} -> + [<<"?"/utf8>>, Query | Parts]; + + _ -> + Parts + end, + Parts@2 = [erlang:element(6, Uri) | Parts@1], + Parts@3 = case {erlang:element(4, Uri), + gleam@string:starts_with(erlang:element(6, Uri), <<"/"/utf8>>)} of + {{some, Host}, false} when Host =/= <<""/utf8>> -> + [<<"/"/utf8>> | Parts@2]; + + {_, _} -> + Parts@2 + end, + Parts@4 = case {erlang:element(4, Uri), erlang:element(5, Uri)} of + {{some, _}, {some, Port}} -> + [<<":"/utf8>>, gleam@int:to_string(Port) | Parts@3]; + + {_, _} -> + Parts@3 + end, + Parts@5 = case {erlang:element(2, Uri), + erlang:element(3, Uri), + erlang:element(4, Uri)} of + {{some, S}, {some, U}, {some, H}} -> + [S, <<"://"/utf8>>, U, <<"@"/utf8>>, H | Parts@4]; + + {{some, S@1}, none, {some, H@1}} -> + [S@1, <<"://"/utf8>>, H@1 | Parts@4]; + + {{some, S@2}, {some, _}, none} -> + [S@2, <<":"/utf8>> | Parts@4]; + + {{some, S@2}, none, none} -> + [S@2, <<":"/utf8>> | Parts@4]; + + {none, none, {some, H@2}} -> + [<<"//"/utf8>>, H@2 | Parts@4]; + + {_, _, _} -> + Parts@4 + end, + gleam@string:concat(Parts@5). + +-spec origin(uri()) -> {ok, binary()} | {error, nil}. +origin(Uri) -> + {uri, Scheme, _, Host, Port, _, _, _} = Uri, + case Scheme of + {some, <<"https"/utf8>>} when Port =:= {some, 443} -> + Origin = {uri, Scheme, none, Host, none, <<""/utf8>>, none, none}, + {ok, to_string(Origin)}; + + {some, <<"http"/utf8>>} when Port =:= {some, 80} -> + Origin@1 = {uri, Scheme, none, Host, none, <<""/utf8>>, none, none}, + {ok, to_string(Origin@1)}; + + {some, S} when (S =:= <<"http"/utf8>>) orelse (S =:= <<"https"/utf8>>) -> + Origin@2 = {uri, Scheme, none, Host, Port, <<""/utf8>>, none, none}, + {ok, to_string(Origin@2)}; + + _ -> + {error, nil} + end. + +-spec drop_last(list(DFL)) -> list(DFL). +drop_last(Elements) -> + gleam@list:take(Elements, gleam@list:length(Elements) - 1). + +-spec join_segments(list(binary())) -> binary(). +join_segments(Segments) -> + gleam@string:join([<<""/utf8>> | Segments], <<"/"/utf8>>). + +-spec merge(uri(), uri()) -> {ok, uri()} | {error, nil}. +merge(Base, Relative) -> + case Base of + {uri, {some, _}, _, {some, _}, _, _, _, _} -> + case Relative of + {uri, _, _, {some, _}, _, _, _, _} -> + Path = begin + _pipe = gleam@string:split( + erlang:element(6, Relative), + <<"/"/utf8>> + ), + _pipe@1 = remove_dot_segments(_pipe), + join_segments(_pipe@1) + end, + Resolved = {uri, + gleam@option:'or'( + erlang:element(2, Relative), + erlang:element(2, Base) + ), + none, + erlang:element(4, Relative), + gleam@option:'or'( + erlang:element(5, Relative), + erlang:element(5, Base) + ), + Path, + erlang:element(7, Relative), + erlang:element(8, Relative)}, + {ok, Resolved}; + + _ -> + {New_path, New_query} = case erlang:element(6, Relative) of + <<""/utf8>> -> + {erlang:element(6, Base), + gleam@option:'or'( + erlang:element(7, Relative), + erlang:element(7, Base) + )}; + + _ -> + Path_segments = case gleam@string:starts_with( + erlang:element(6, Relative), + <<"/"/utf8>> + ) of + true -> + gleam@string:split( + erlang:element(6, Relative), + <<"/"/utf8>> + ); + + false -> + _pipe@2 = gleam@string:split( + erlang:element(6, Base), + <<"/"/utf8>> + ), + _pipe@3 = drop_last(_pipe@2), + gleam@list:append( + _pipe@3, + gleam@string:split( + erlang:element(6, Relative), + <<"/"/utf8>> + ) + ) + end, + Path@1 = begin + _pipe@4 = Path_segments, + _pipe@5 = remove_dot_segments(_pipe@4), + join_segments(_pipe@5) + end, + {Path@1, erlang:element(7, Relative)} + end, + Resolved@1 = {uri, + erlang:element(2, Base), + none, + erlang:element(4, Base), + erlang:element(5, Base), + New_path, + New_query, + erlang:element(8, Relative)}, + {ok, Resolved@1} + end; + + _ -> + {error, nil} + end. diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.app.src b/aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.app.src new file mode 100644 index 0000000..bcf08e2 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.app.src @@ -0,0 +1,31 @@ +{application, gleam_stdlib, [ + {vsn, "0.33.0"}, + {applications, []}, + {description, "A standard library for the Gleam programming language"}, + {modules, [gleam@base, + gleam@bit_array, + gleam@bit_builder, + gleam@bit_string, + gleam@bool, + gleam@bytes_builder, + gleam@dict, + gleam@dynamic, + gleam@float, + gleam@function, + gleam@int, + gleam@io, + gleam@iterator, + gleam@list, + gleam@map, + gleam@option, + gleam@order, + gleam@pair, + gleam@queue, + gleam@regex, + gleam@result, + gleam@set, + gleam@string, + gleam@string_builder, + gleam@uri]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.erl b/aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.erl new file mode 100644 index 0000000..c6ea125 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.erl @@ -0,0 +1,529 @@ +-module(gleam_stdlib). + +-export([ + map_get/2, iodata_append/2, identity/1, decode_int/1, decode_bool/1, + decode_float/1, decode_list/1, decode_option/2, decode_field/2, parse_int/1, + parse_float/1, less_than/2, string_pop_grapheme/1, string_starts_with/2, + wrap_list/1, string_ends_with/2, string_pad/4, decode_map/1, uri_parse/1, + bit_array_int_to_u32/1, bit_array_int_from_u32/1, decode_result/1, + bit_array_slice/3, decode_bit_array/1, compile_regex/2, regex_scan/2, + percent_encode/1, percent_decode/1, regex_check/2, regex_split/2, + base_decode64/1, parse_query/1, bit_array_concat/1, size_of_tuple/1, + decode_tuple/1, decode_tuple2/1, decode_tuple3/1, decode_tuple4/1, + decode_tuple5/1, decode_tuple6/1, tuple_get/2, classify_dynamic/1, print/1, + println/1, print_error/1, println_error/1, inspect/1, float_to_string/1, + int_from_base_string/2, utf_codepoint_list_to_string/1, contains_string/2, + crop_string/2, base16_decode/1 +]). + +%% Taken from OTP's uri_string module +-define(DEC2HEX(X), + if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0; + ((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10 + end). + +%% Taken from OTP's uri_string module +-define(HEX2DEC(X), + if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0; + ((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10; + ((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10 + end). + +-define(is_lowercase_char(X), (X > 96 andalso X < 123)). +-define(is_underscore_char(X), (X == 95)). +-define(is_digit_char(X), (X > 47 andalso X < 58)). + +uppercase(X) -> X - 32. + +map_get(Map, Key) -> + case maps:find(Key, Map) of + error -> {error, nil}; + OkFound -> OkFound + end. + +iodata_append(Iodata, String) -> [Iodata, String]. + +identity(X) -> X. + +decode_error_msg(Expected, Data) when is_binary(Expected) -> + decode_error(Expected, classify_dynamic(Data)). +decode_error(Expected, Got) when is_binary(Expected) andalso is_binary(Got) -> + {error, [{decode_error, Expected, Got, []}]}. + +classify_dynamic(nil) -> <<"Nil">>; +classify_dynamic(X) when is_atom(X) -> <<"Atom">>; +classify_dynamic(X) when is_binary(X) -> <<"String">>; +classify_dynamic(X) when is_bitstring(X) -> <<"BitArray">>; +classify_dynamic(X) when is_integer(X) -> <<"Int">>; +classify_dynamic(X) when is_float(X) -> <<"Float">>; +classify_dynamic(X) when is_list(X) -> <<"List">>; +classify_dynamic(X) when is_boolean(X) -> <<"Bool">>; +classify_dynamic(X) when is_map(X) -> <<"Map">>; +classify_dynamic(X) when is_tuple(X) -> + iolist_to_binary(["Tuple of ", integer_to_list(tuple_size(X)), " elements"]); +classify_dynamic(X) when + is_function(X, 0) orelse is_function(X, 1) orelse is_function(X, 2) orelse + is_function(X, 3) orelse is_function(X, 4) orelse is_function(X, 5) orelse + is_function(X, 6) orelse is_function(X, 7) orelse is_function(X, 8) orelse + is_function(X, 9) orelse is_function(X, 10) orelse is_function(X, 11) orelse + is_function(X, 12) -> <<"Function">>; +classify_dynamic(_) -> <<"Some other type">>. + +decode_map(Data) when is_map(Data) -> {ok, Data}; +decode_map(Data) -> decode_error_msg(<<"Map">>, Data). + +decode_bit_array(Data) when is_bitstring(Data) -> {ok, Data}; +decode_bit_array(Data) -> decode_error_msg(<<"BitArray">>, Data). + +decode_int(Data) when is_integer(Data) -> {ok, Data}; +decode_int(Data) -> decode_error_msg(<<"Int">>, Data). + +decode_float(Data) when is_float(Data) -> {ok, Data}; +decode_float(Data) -> decode_error_msg(<<"Float">>, Data). + +decode_bool(Data) when is_boolean(Data) -> {ok, Data}; +decode_bool(Data) -> decode_error_msg(<<"Bool">>, Data). + +decode_list(Data) when is_list(Data) -> {ok, Data}; +decode_list(Data) -> decode_error_msg(<<"List">>, Data). + +decode_field(Data, Key) when is_map(Data) -> + case Data of + #{Key := Value} -> {ok, {some, Value}}; + _ -> + {ok, none} + end; +decode_field(Data, _) -> + decode_error_msg(<<"Map">>, Data). + +size_of_tuple(Data) -> tuple_size(Data). + +tuple_get(_tup, Index) when Index < 0 -> {error, nil}; +tuple_get(Data, Index) when Index >= tuple_size(Data) -> {error, nil}; +tuple_get(Data, Index) -> {ok, element(Index + 1, Data)}. + +decode_tuple(Data) when is_tuple(Data) -> {ok, Data}; +decode_tuple(Data) -> decode_error_msg(<<"Tuple">>, Data). + +decode_tuple2({_,_} = A) -> {ok, A}; +decode_tuple2([A,B]) -> {ok, {A,B}}; +decode_tuple2(Data) -> decode_error_msg(<<"Tuple of 2 elements">>, Data). + +decode_tuple3({_,_,_} = A) -> {ok, A}; +decode_tuple3([A,B,C]) -> {ok, {A,B,C}}; +decode_tuple3(Data) -> decode_error_msg(<<"Tuple of 3 elements">>, Data). + +decode_tuple4({_,_,_,_} = A) -> {ok, A}; +decode_tuple4([A,B,C,D]) -> {ok, {A,B,C,D}}; +decode_tuple4(Data) -> decode_error_msg(<<"Tuple of 4 elements">>, Data). + +decode_tuple5({_,_,_,_,_} = A) -> {ok, A}; +decode_tuple5([A,B,C,D,E]) -> {ok, {A,B,C,D,E}}; +decode_tuple5(Data) -> decode_error_msg(<<"Tuple of 5 elements">>, Data). + +decode_tuple6({_,_,_,_,_,_} = A) -> {ok, A}; +decode_tuple6([A,B,C,D,E,F]) -> {ok, {A,B,C,D,E,F}}; +decode_tuple6(Data) -> decode_error_msg(<<"Tuple of 6 elements">>, Data). + +decode_option(Term, F) -> + Decode = fun(Inner) -> + case F(Inner) of + {ok, Decoded} -> {ok, {some, Decoded}}; + Error -> Error + end + end, + case Term of + undefined -> {ok, none}; + error -> {ok, none}; + null -> {ok, none}; + none -> {ok, none}; + nil -> {ok, none}; + {some, Inner} -> Decode(Inner); + _ -> Decode(Term) + end. + +decode_result(Term) -> + case Term of + {ok, Inner} -> {ok, {ok, Inner}}; + ok -> {ok, {ok, nil}}; + {error, Inner} -> {ok, {error, Inner}}; + error -> {ok, {error, nil}}; + _ -> decode_error_msg(<<"Result">>, Term) + end. + +int_from_base_string(String, Base) -> + case catch binary_to_integer(String, Base) of + Int when is_integer(Int) -> {ok, Int}; + _ -> {error, nil} + end. + +parse_int(String) -> + case catch binary_to_integer(String) of + Int when is_integer(Int) -> {ok, Int}; + _ -> {error, nil} + end. + +parse_float(String) -> + case catch binary_to_float(String) of + Float when is_float(Float) -> {ok, Float}; + _ -> {error, nil} + end. + +less_than(Lhs, Rhs) -> + Lhs < Rhs. + +string_starts_with(_, <<>>) -> true; +string_starts_with(String, Prefix) when byte_size(Prefix) > byte_size(String) -> false; +string_starts_with(String, Prefix) -> + PrefixSize = byte_size(Prefix), + Prefix == binary_part(String, 0, PrefixSize). + +string_ends_with(_, <<>>) -> true; +string_ends_with(String, Suffix) when byte_size(Suffix) > byte_size(String) -> false; +string_ends_with(String, Suffix) -> + SuffixSize = byte_size(Suffix), + Suffix == binary_part(String, byte_size(String) - SuffixSize, SuffixSize). + +string_pad(String, Length, Dir, PadString) -> + Chars = string:pad(String, Length, Dir, binary_to_list(PadString)), + case unicode:characters_to_binary(Chars) of + Bin when is_binary(Bin) -> Bin; + Error -> erlang:error({gleam_error, {string_invalid_utf8, Error}}) + end. + +string_pop_grapheme(String) -> + case string:next_grapheme(String) of + [ Next | Rest ] -> + {ok, {unicode:characters_to_binary([Next]), unicode:characters_to_binary(Rest)}}; + _ -> {error, nil} + end. + +bit_array_concat(BitArrays) -> + list_to_bitstring(BitArrays). + +bit_array_slice(Bin, Pos, Len) -> + try {ok, binary:part(Bin, Pos, Len)} + catch error:badarg -> {error, nil} + end. + +bit_array_int_to_u32(I) when 0 =< I, I < 4294967296 -> + {ok, <<I:32>>}; +bit_array_int_to_u32(_) -> + {error, nil}. + +bit_array_int_from_u32(<<I:32>>) -> + {ok, I}; +bit_array_int_from_u32(_) -> + {error, nil}. + +compile_regex(String, Options) -> + {options, Caseless, Multiline} = Options, + OptionsList = [ + unicode, + ucp, + Caseless andalso caseless, + Multiline andalso multiline + ], + FilteredOptions = [Option || Option <- OptionsList, Option /= false], + case re:compile(String, FilteredOptions) of + {ok, MP} -> {ok, MP}; + {error, {Str, Pos}} -> + {error, {compile_error, unicode:characters_to_binary(Str), Pos}} + end. + +regex_check(Regex, String) -> + re:run(String, Regex) /= nomatch. + +regex_split(Regex, String) -> + re:split(String, Regex). + +regex_submatches(_, {-1, 0}) -> none; +regex_submatches(String, {Start, Length}) -> + BinarySlice = binary:part(String, {Start, Length}), + case string:is_empty(binary_to_list(BinarySlice)) of + true -> none; + false -> {some, BinarySlice} + end. + +regex_matches(String, [{Start, Length} | Submatches]) -> + Submatches1 = lists:map(fun(X) -> regex_submatches(String, X) end, Submatches), + {match, binary:part(String, Start, Length), Submatches1}. + +regex_scan(Regex, String) -> + case re:run(String, Regex, [global]) of + {match, Captured} -> lists:map(fun(X) -> regex_matches(String, X) end, Captured); + nomatch -> [] + end. + +base_decode64(S) -> + try {ok, base64:decode(S)} + catch error:_ -> {error, nil} + end. + +wrap_list(X) when is_list(X) -> X; +wrap_list(X) -> [X]. + +parse_query(Query) -> + case uri_string:dissect_query(Query) of + {error, _, _} -> {error, nil}; + Pairs -> + Pairs1 = lists:map(fun + ({K, true}) -> {K, <<"">>}; + (Pair) -> Pair + end, Pairs), + {ok, Pairs1} + end. + +percent_encode(B) -> percent_encode(B, <<>>). +percent_encode(<<>>, Acc) -> + Acc; +percent_encode(<<H,T/binary>>, Acc) -> + case percent_ok(H) of + true -> + percent_encode(T, <<Acc/binary,H>>); + false -> + <<A:4,B:4>> = <<H>>, + percent_encode(T, <<Acc/binary,$%,(?DEC2HEX(A)),(?DEC2HEX(B))>>) + end. + +percent_decode(Cs) -> percent_decode(Cs, <<>>). +percent_decode(<<$%, C0, C1, Cs/binary>>, Acc) -> + case is_hex_digit(C0) andalso is_hex_digit(C1) of + true -> + B = ?HEX2DEC(C0)*16+?HEX2DEC(C1), + percent_decode(Cs, <<Acc/binary, B>>); + false -> + {error, nil} + end; +percent_decode(<<C,Cs/binary>>, Acc) -> + percent_decode(Cs, <<Acc/binary, C>>); +percent_decode(<<>>, Acc) -> + check_utf8(Acc). + +percent_ok($!) -> true; +percent_ok($$) -> true; +percent_ok($') -> true; +percent_ok($() -> true; +percent_ok($)) -> true; +percent_ok($*) -> true; +percent_ok($+) -> true; +percent_ok($-) -> true; +percent_ok($.) -> true; +percent_ok($_) -> true; +percent_ok($~) -> true; +percent_ok(C) when $0 =< C, C =< $9 -> true; +percent_ok(C) when $A =< C, C =< $Z -> true; +percent_ok(C) when $a =< C, C =< $z -> true; +percent_ok(_) -> false. + +is_hex_digit(C) -> + ($0 =< C andalso C =< $9) orelse ($a =< C andalso C =< $f) orelse ($A =< C andalso C =< $F). + +check_utf8(Cs) -> + case unicode:characters_to_list(Cs) of + {incomplete, _, _} -> {error, nil}; + {error, _, _} -> {error, nil}; + _ -> {ok, Cs} + end. + +uri_parse(String) -> + case uri_string:parse(String) of + {error, _, _} -> {error, nil}; + Uri -> + {ok, {uri, + maps_get_optional(Uri, scheme), + maps_get_optional(Uri, userinfo), + maps_get_optional(Uri, host), + maps_get_optional(Uri, port), + maps_get_or(Uri, path, <<>>), + maps_get_optional(Uri, query), + maps_get_optional(Uri, fragment) + }} + end. + +maps_get_optional(Map, Key) -> + try {some, maps:get(Key, Map)} + catch _:_ -> none + end. + +maps_get_or(Map, Key, Default) -> + try maps:get(Key, Map) + catch _:_ -> Default + end. + +print(String) -> + io:put_chars(String), + nil. + +println(String) -> + io:put_chars([String, $\n]), + nil. + +print_error(String) -> + io:put_chars(standard_error, String), + nil. + +println_error(String) -> + io:put_chars(standard_error, [String, $\n]), + nil. + +inspect(true) -> + "True"; +inspect(false) -> + "False"; +inspect(nil) -> + "Nil"; +inspect(Data) when is_map(Data) -> + Fields = [ + [<<"#(">>, inspect(Key), <<", ">>, inspect(Value), <<")">>] + || {Key, Value} <- maps:to_list(Data) + ], + ["dict.from_list([", lists:join(", ", Fields), "])"]; +inspect(Atom) when is_atom(Atom) -> + Binary = erlang:atom_to_binary(Atom), + case inspect_maybe_gleam_atom(Binary, none, <<>>) of + {ok, Inspected} -> Inspected; + {error, _} -> ["atom.create_from_string(\"", Binary, "\")"] + end; +inspect(Any) when is_integer(Any) -> + erlang:integer_to_list(Any); +inspect(Any) when is_float(Any) -> + io_lib_format:fwrite_g(Any); +inspect(Binary) when is_binary(Binary) -> + case inspect_maybe_utf8_string(Binary, <<>>) of + {ok, InspectedUtf8String} -> InspectedUtf8String; + {error, not_a_utf8_string} -> + Segments = [erlang:integer_to_list(X) || <<X>> <= Binary], + ["<<", lists:join(", ", Segments), ">>"] + end; +inspect(Bits) when is_bitstring(Bits) -> + inspect_bit_array(Bits); +inspect(List) when is_list(List) -> + case inspect_list(List) of + {proper, Elements} -> ["[", Elements, "]"]; + {improper, Elements} -> ["//erl([", Elements, "])"] + end; +inspect(Any) when is_tuple(Any) % Record constructors + andalso is_atom(element(1, Any)) + andalso element(1, Any) =/= false + andalso element(1, Any) =/= true + andalso element(1, Any) =/= nil +-> + [Atom | ArgsList] = erlang:tuple_to_list(Any), + Args = lists:join(<<", ">>, + lists:map(fun inspect/1, ArgsList) + ), + [inspect(Atom), "(", Args, ")"]; +inspect(Tuple) when is_tuple(Tuple) -> + Elements = lists:map(fun inspect/1, erlang:tuple_to_list(Tuple)), + ["#(", lists:join(", ", Elements), ")"]; +inspect(Any) when is_function(Any) -> + {arity, Arity} = erlang:fun_info(Any, arity), + ArgsAsciiCodes = lists:seq($a, $a + Arity - 1), + Args = lists:join(<<", ">>, + lists:map(fun(Arg) -> <<Arg>> end, ArgsAsciiCodes) + ), + ["//fn(", Args, ") { ... }"]; +inspect(Any) -> + ["//erl(", io_lib:format("~p", [Any]), ")"]. + + +inspect_maybe_gleam_atom(<<>>, none, _) -> + {error, nil}; +inspect_maybe_gleam_atom(<<First, _Rest/binary>>, none, _) when ?is_digit_char(First) -> + {error, nil}; +inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, none, _) -> + {error, nil}; +inspect_maybe_gleam_atom(<<"_">>, _PrevChar, _Acc) -> + {error, nil}; +inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, $_, _Acc) -> + {error, nil}; +inspect_maybe_gleam_atom(<<First, _Rest/binary>>, _PrevChar, _Acc) + when not (?is_lowercase_char(First) orelse ?is_underscore_char(First) orelse ?is_digit_char(First)) -> + {error, nil}; +inspect_maybe_gleam_atom(<<First, Rest/binary>>, none, Acc) -> + inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, (uppercase(First))>>); +inspect_maybe_gleam_atom(<<"_", Rest/binary>>, _PrevChar, Acc) -> + inspect_maybe_gleam_atom(Rest, $_, Acc); +inspect_maybe_gleam_atom(<<First, Rest/binary>>, $_, Acc) -> + inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, (uppercase(First))>>); +inspect_maybe_gleam_atom(<<First, Rest/binary>>, _PrevChar, Acc) -> + inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, First>>); +inspect_maybe_gleam_atom(<<>>, _PrevChar, Acc) -> + {ok, Acc}; +inspect_maybe_gleam_atom(A, B, C) -> + erlang:display({A, B, C}), + throw({gleam_error, A, B, C}). + +inspect_list([]) -> + {proper, []}; +inspect_list([First]) -> + {proper, [inspect(First)]}; +inspect_list([First | Rest]) when is_list(Rest) -> + {Kind, Inspected} = inspect_list(Rest), + {Kind, [inspect(First), <<", ">> | Inspected]}; +inspect_list([First | ImproperTail]) -> + {improper, [inspect(First), <<" | ">>, inspect(ImproperTail)]}. + +inspect_bit_array(Bits) -> + Text = inspect_bit_array(Bits, <<"<<">>), + <<Text/binary, ">>">>. + +inspect_bit_array(<<>>, Acc) -> + Acc; +inspect_bit_array(<<X, Rest/bitstring>>, Acc) -> + inspect_bit_array(Rest, append_segment(Acc, erlang:integer_to_binary(X))); +inspect_bit_array(Rest, Acc) -> + Size = bit_size(Rest), + <<X:Size>> = Rest, + X1 = erlang:integer_to_binary(X), + Size1 = erlang:integer_to_binary(Size), + Segment = <<X1/binary, ":size(", Size1/binary, ")">>, + inspect_bit_array(<<>>, append_segment(Acc, Segment)). + +append_segment(<<"<<">>, Segment) -> + <<"<<", Segment/binary>>; +append_segment(Acc, Segment) -> + <<Acc/binary, ", ", Segment/binary>>. + + +inspect_maybe_utf8_string(Binary, Acc) -> + case Binary of + <<>> -> {ok, <<$", Acc/binary, $">>}; + <<First/utf8, Rest/binary>> -> + Escaped = case First of + $" -> <<$\\, $">>; + $\\ -> <<$\\, $\\>>; + $\r -> <<$\\, $r>>; + $\n -> <<$\\, $n>>; + $\t -> <<$\\, $t>>; + Other -> <<Other/utf8>> + end, + inspect_maybe_utf8_string(Rest, <<Acc/binary, Escaped/binary>>); + _ -> {error, not_a_utf8_string} + end. + +float_to_string(Float) when is_float(Float) -> + erlang:iolist_to_binary(io_lib_format:fwrite_g(Float)). + +utf_codepoint_list_to_string(List) -> + case unicode:characters_to_binary(List) of + {error, _} -> erlang:error({gleam_error, {string_invalid_utf8, List}}); + Binary -> Binary + end. + +crop_string(String, Prefix) -> + case string:find(String, Prefix) of + nomatch -> String; + New -> New + end. + +contains_string(String, Substring) -> + is_bitstring(string:find(String, Substring)). + +base16_decode(String) -> + try + {ok, binary:decode_hex(String)} + catch + _:_ -> {error, nil} + end. diff --git a/aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.mjs b/aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.mjs new file mode 100644 index 0000000..a908b23 --- /dev/null +++ b/aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.mjs @@ -0,0 +1,875 @@ +import { + BitArray, + Error, + List, + Ok, + Result, + UtfCodepoint, + stringBits, + toBitArray, + NonEmpty, + CustomType, +} from "./gleam.mjs"; +import { + CompileError as RegexCompileError, + Match as RegexMatch, +} from "./gleam/regex.mjs"; +import { DecodeError } from "./gleam/dynamic.mjs"; +import { Some, None } from "./gleam/option.mjs"; +import Dict from "./dict.mjs"; + +const Nil = undefined; +const NOT_FOUND = {}; + +export function identity(x) { + return x; +} + +export function parse_int(value) { + if (/^[-+]?(\d+)$/.test(value)) { + return new Ok(parseInt(value)); + } else { + return new Error(Nil); + } +} + +export function parse_float(value) { + if (/^[-+]?(\d+)\.(\d+)$/.test(value)) { + return new Ok(parseFloat(value)); + } else { + return new Error(Nil); + } +} + +export function to_string(term) { + return term.toString(); +} + +export function float_to_string(float) { + const string = float.toString(); + if (string.indexOf(".") >= 0) { + return string; + } else { + return string + ".0"; + } +} + +export function int_to_base_string(int, base) { + return int.toString(base).toUpperCase(); +} + +const int_base_patterns = { + 2: /[^0-1]/, + 3: /[^0-2]/, + 4: /[^0-3]/, + 5: /[^0-4]/, + 6: /[^0-5]/, + 7: /[^0-6]/, + 8: /[^0-7]/, + 9: /[^0-8]/, + 10: /[^0-9]/, + 11: /[^0-9a]/, + 12: /[^0-9a-b]/, + 13: /[^0-9a-c]/, + 14: /[^0-9a-d]/, + 15: /[^0-9a-e]/, + 16: /[^0-9a-f]/, + 17: /[^0-9a-g]/, + 18: /[^0-9a-h]/, + 19: /[^0-9a-i]/, + 20: /[^0-9a-j]/, + 21: /[^0-9a-k]/, + 22: /[^0-9a-l]/, + 23: /[^0-9a-m]/, + 24: /[^0-9a-n]/, + 25: /[^0-9a-o]/, + 26: /[^0-9a-p]/, + 27: /[^0-9a-q]/, + 28: /[^0-9a-r]/, + 29: /[^0-9a-s]/, + 30: /[^0-9a-t]/, + 31: /[^0-9a-u]/, + 32: /[^0-9a-v]/, + 33: /[^0-9a-w]/, + 34: /[^0-9a-x]/, + 35: /[^0-9a-y]/, + 36: /[^0-9a-z]/, +}; + +export function int_from_base_string(string, base) { + if (int_base_patterns[base].test(string.replace(/^-/, "").toLowerCase())) { + return new Error(Nil); + } + + const result = parseInt(string, base); + + if (isNaN(result)) { + return new Error(Nil); + } + + return new Ok(result); +} + +export function string_replace(string, target, substitute) { + if (typeof string.replaceAll !== "undefined") { + return string.replaceAll(target, substitute); + } + // Fallback for older Node.js versions: + // 1. <https://stackoverflow.com/a/1144788> + // 2. <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping> + // TODO: This fallback could be remove once Node.js 14 is EOL + // aka <https://nodejs.org/en/about/releases/> on or after 2024-04-30 + return string.replace( + // $& means the whole matched string + new RegExp(target.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), + substitute + ); +} + +export function string_reverse(string) { + return [...string].reverse().join(""); +} + +export function string_length(string) { + if (string === "") { + return 0; + } + const iterator = graphemes_iterator(string); + if (iterator) { + let i = 0; + for (const _ of iterator) { + i++; + } + return i; + } else { + return string.match(/./gsu).length; + } +} + +export function graphemes(string) { + return List.fromArray( + Array.from(graphemes_iterator(string)).map((item) => item.segment) + ); +} + +function graphemes_iterator(string) { + if (Intl && Intl.Segmenter) { + return new Intl.Segmenter().segment(string)[Symbol.iterator](); + } +} + +export function pop_grapheme(string) { + let first; + const iterator = graphemes_iterator(string); + if (iterator) { + first = iterator.next().value?.segment; + } else { + first = string.match(/./su)?.[0]; + } + if (first) { + return new Ok([first, string.slice(first.length)]); + } else { + return new Error(Nil); + } +} + +export function lowercase(string) { + return string.toLowerCase(); +} + +export function uppercase(string) { + return string.toUpperCase(); +} + +export function less_than(a, b) { + return a < b; +} + +export function add(a, b) { + return a + b; +} + +export function equal(a, b) { + return a === b; +} + +export function split(xs, pattern) { + return List.fromArray(xs.split(pattern)); +} + +export function join(xs, separator) { + const iterator = xs[Symbol.iterator](); + let result = iterator.next().value || ""; + let current = iterator.next(); + while (!current.done) { + result = result + separator + current.value; + current = iterator.next(); + } + return result; +} + +export function concat(xs) { + let result = ""; + for (const x of xs) { + result = result + x; + } + return result; +} + +export function length(data) { + return data.length; +} + +export function crop_string(string, substring) { + return string.substring(string.indexOf(substring)); +} + +export function contains_string(haystack, needle) { + return haystack.indexOf(needle) >= 0; +} + +export function starts_with(haystack, needle) { + return haystack.startsWith(needle); +} + +export function ends_with(haystack, needle) { + return haystack.endsWith(needle); +} + +export function split_once(haystack, needle) { + const index = haystack.indexOf(needle); + if (index >= 0) { + const before = haystack.slice(0, index); + const after = haystack.slice(index + needle.length); + return new Ok([before, after]); + } else { + return new Error(Nil); + } +} + +export function trim(string) { + return string.trim(); +} + +export function trim_left(string) { + return string.trimLeft(); +} + +export function trim_right(string) { + return string.trimRight(); +} + +export function bit_array_from_string(string) { + return toBitArray([stringBits(string)]); +} + +export function bit_array_concat(bit_arrays) { + return toBitArray(bit_arrays.toArray().map((b) => b.buffer)); +} + +export function console_log(term) { + console.log(term); +} + +export function console_error(term) { + console.error(term); +} + +export function crash(message) { + throw new globalThis.Error(message); +} + +export function bit_array_to_string(bit_array) { + try { + const decoder = new TextDecoder("utf-8", { fatal: true }); + return new Ok(decoder.decode(bit_array.buffer)); + } catch (_error) { + return new Error(Nil); + } +} + +export function print(string) { + if (typeof process === "object") { + process.stdout.write(string); // We can write without a trailing newline + } else if (typeof Deno === "object") { + Deno.stdout.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline + } else { + console.log(string); // We're in a browser. Newlines are mandated + } +} + +export function print_error(string) { + if (typeof process === "object" && process.stderr?.write) { + process.stderr.write(string); // We can write without a trailing newline + } else if (typeof Deno === "object") { + Deno.stderr.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline + } else { + console.error(string); // We're in a browser. Newlines are mandated + } +} + +export function print_debug(string) { + if (typeof process === "object" && process.stderr?.write) { + process.stderr.write(string + "\n"); // If we're in Node.js, use `stderr` + } else if (typeof Deno === "object") { + Deno.stderr.writeSync(new TextEncoder().encode(string + "\n")); // If we're in Deno, use `stderr` + } else { + console.log(string); // Otherwise, use `console.log` (so that it doesn't look like an error) + } +} + +export function ceiling(float) { + return Math.ceil(float); +} + +export function floor(float) { + return Math.floor(float); +} + +export function round(float) { + return Math.round(float); +} + +export function truncate(float) { + return Math.trunc(float); +} + +export function power(base, exponent) { + // It is checked in Gleam that: + // - The base is non-negative and that the exponent is not fractional. + // - The base is non-zero and the exponent is non-negative (otherwise + // the result will essentially be division by zero). + // It can thus be assumed that valid input is passed to the Math.pow + // function and a NaN or Infinity value will not be produced. + return Math.pow(base, exponent); +} + +export function random_uniform() { + const random_uniform_result = Math.random(); + // With round-to-nearest-even behavior, the ranges claimed for the functions below + // (excluding the one for Math.random() itself) aren't exact. + // If extremely large bounds are chosen (2^53 or higher), + // it's possible in extremely rare cases to calculate the usually-excluded upper bound. + // Note that as numbers in JavaScript are IEEE 754 floating point numbers + // See: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random> + // Because of this, we just loop 'until' we get a valid result where 0.0 <= x < 1.0: + if (random_uniform_result === 1.0) { + return random_uniform(); + } + return random_uniform_result; +} + +export function bit_array_slice(bits, position, length) { + const start = Math.min(position, position + length); + const end = Math.max(position, position + length); + if (start < 0 || end > bits.length) return new Error(Nil); + const buffer = new Uint8Array(bits.buffer.buffer, start, Math.abs(length)); + return new Ok(new BitArray(buffer)); +} + +export function codepoint(int) { + return new UtfCodepoint(int); +} + +export function string_to_codepoint_integer_list(string) { + return List.fromArray(Array.from(string).map((item) => item.codePointAt(0))); +} + +export function utf_codepoint_list_to_string(utf_codepoint_integer_list) { + return utf_codepoint_integer_list + .toArray() + .map((x) => String.fromCodePoint(x.value)) + .join(""); +} + +export function utf_codepoint_to_int(utf_codepoint) { + return utf_codepoint.value; +} + +export function regex_check(regex, string) { + regex.lastIndex = 0; + return regex.test(string); +} + +export function compile_regex(pattern, options) { + try { + let flags = "gu"; + if (options.case_insensitive) flags += "i"; + if (options.multi_line) flags += "m"; + return new Ok(new RegExp(pattern, flags)); + } catch (error) { + const number = (error.columnNumber || 0) | 0; + return new Error(new RegexCompileError(error.message, number)); + } +} + +export function regex_scan(regex, string) { + const matches = Array.from(string.matchAll(regex)).map((match) => { + const content = match[0]; + const submatches = []; + for (let n = match.length - 1; n > 0; n--) { + if (match[n]) { + submatches[n - 1] = new Some(match[n]); + continue; + } + if (submatches.length > 0) { + submatches[n - 1] = new None(); + } + } + return new RegexMatch(content, List.fromArray(submatches)); + }); + return List.fromArray(matches); +} + +export function new_map() { + return Dict.new(); +} + +export function map_size(map) { + return map.size; +} + +export function map_to_list(map) { + return List.fromArray(map.entries()); +} + +export function map_remove(key, map) { + return map.delete(key); +} + +export function map_get(map, key) { + const value = map.get(key, NOT_FOUND); + if (value === NOT_FOUND) { + return new Error(Nil); + } + return new Ok(value); +} + +export function map_insert(key, value, map) { + return map.set(key, value); +} + +function unsafe_percent_decode(string) { + return decodeURIComponent((string || "").replace("+", " ")); +} + +export function percent_decode(string) { + try { + return new Ok(unsafe_percent_decode(string)); + } catch (_error) { + return new Error(Nil); + } +} + +export function percent_encode(string) { + return encodeURIComponent(string); +} + +export function parse_query(query) { + try { + const pairs = []; + for (const section of query.split("&")) { + const [key, value] = section.split("="); + if (!key) continue; + pairs.push([unsafe_percent_decode(key), unsafe_percent_decode(value)]); + } + return new Ok(List.fromArray(pairs)); + } catch (_error) { + return new Error(Nil); + } +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +export function encode64(bit_array) { + const aBytes = bit_array.buffer; + let nMod3 = 2; + let sB64Enc = ""; + + for (let nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) { + nMod3 = nIdx % 3; + if (nIdx > 0 && ((nIdx * 4) / 3) % 76 === 0) { + sB64Enc += "\r\n"; + } + nUint24 |= aBytes[nIdx] << ((16 >>> nMod3) & 24); + if (nMod3 === 2 || aBytes.length - nIdx === 1) { + sB64Enc += String.fromCharCode( + uint6ToB64((nUint24 >>> 18) & 63), + uint6ToB64((nUint24 >>> 12) & 63), + uint6ToB64((nUint24 >>> 6) & 63), + uint6ToB64(nUint24 & 63) + ); + nUint24 = 0; + } + } + + return ( + sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + + (nMod3 === 2 ? "" : nMod3 === 1 ? "=" : "==") + ); +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function uint6ToB64(nUint6) { + return nUint6 < 26 + ? nUint6 + 65 + : nUint6 < 52 + ? nUint6 + 71 + : nUint6 < 62 + ? nUint6 - 4 + : nUint6 === 62 + ? 43 + : nUint6 === 63 + ? 47 + : 65; +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function b64ToUint6(nChr) { + return nChr > 64 && nChr < 91 + ? nChr - 65 + : nChr > 96 && nChr < 123 + ? nChr - 71 + : nChr > 47 && nChr < 58 + ? nChr + 4 + : nChr === 43 + ? 62 + : nChr === 47 + ? 63 + : 0; +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +export function decode64(sBase64) { + if (sBase64.match(/[^A-Za-z0-9\+\/=]/g)) return new Error(Nil); + const sB64Enc = sBase64.replace(/=/g, ""); + const nInLen = sB64Enc.length; + const nOutLen = (nInLen * 3 + 1) >> 2; + const taBytes = new Uint8Array(nOutLen); + + for ( + let nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; + nInIdx < nInLen; + nInIdx++ + ) { + nMod4 = nInIdx & 3; + nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << (6 * (3 - nMod4)); + if (nMod4 === 3 || nInLen - nInIdx === 1) { + for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) { + taBytes[nOutIdx] = (nUint24 >>> ((16 >>> nMod3) & 24)) & 255; + } + nUint24 = 0; + } + } + + return new Ok(new BitArray(taBytes)); +} + +export function classify_dynamic(data) { + if (typeof data === "string") { + return "String"; + } else if (data instanceof Result) { + return "Result"; + } else if (data instanceof List) { + return "List"; + } else if (data instanceof BitArray) { + return "BitArray"; + } else if (data instanceof Dict) { + return "Map"; + } else if (Number.isInteger(data)) { + return "Int"; + } else if (Array.isArray(data)) { + return `Tuple of ${data.length} elements`; + } else if (typeof data === "number") { + return "Float"; + } else if (data === null) { + return "Null"; + } else if (data === undefined) { + return "Nil"; + } else { + const type = typeof data; + return type.charAt(0).toUpperCase() + type.slice(1); + } +} + +function decoder_error(expected, got) { + return decoder_error_no_classify(expected, classify_dynamic(got)); +} + +function decoder_error_no_classify(expected, got) { + return new Error( + List.fromArray([new DecodeError(expected, got, List.fromArray([]))]) + ); +} + +export function decode_string(data) { + return typeof data === "string" + ? new Ok(data) + : decoder_error("String", data); +} + +export function decode_int(data) { + return Number.isInteger(data) ? new Ok(data) : decoder_error("Int", data); +} + +export function decode_float(data) { + return typeof data === "number" ? new Ok(data) : decoder_error("Float", data); +} + +export function decode_bool(data) { + return typeof data === "boolean" ? new Ok(data) : decoder_error("Bool", data); +} + +export function decode_bit_array(data) { + if (data instanceof BitArray) { + return new Ok(data); + } + if (data instanceof Uint8Array) { + return new Ok(new BitArray(data)); + } + return decoder_error("BitArray", data); +} + +export function decode_tuple(data) { + return Array.isArray(data) ? new Ok(data) : decoder_error("Tuple", data); +} + +export function decode_tuple2(data) { + return decode_tupleN(data, 2); +} + +export function decode_tuple3(data) { + return decode_tupleN(data, 3); +} + +export function decode_tuple4(data) { + return decode_tupleN(data, 4); +} + +export function decode_tuple5(data) { + return decode_tupleN(data, 5); +} + +export function decode_tuple6(data) { + return decode_tupleN(data, 6); +} + +function decode_tupleN(data, n) { + if (Array.isArray(data) && data.length == n) { + return new Ok(data); + } + + const list = decode_exact_length_list(data, n); + if (list) return new Ok(list); + + return decoder_error(`Tuple of ${n} elements`, data); +} + +function decode_exact_length_list(data, n) { + if (!(data instanceof List)) return; + + const elements = []; + let current = data; + + for (let i = 0; i < n; i++) { + if (!(current instanceof NonEmpty)) break; + elements.push(current.head); + current = current.tail; + } + + if (elements.length === n && !(current instanceof NonEmpty)) return elements; +} + +export function tuple_get(data, index) { + return index >= 0 && data.length > index + ? new Ok(data[index]) + : new Error(Nil); +} + +export function decode_list(data) { + if (Array.isArray(data)) { + return new Ok(List.fromArray(data)); + } + return data instanceof List ? new Ok(data) : decoder_error("List", data); +} + +export function decode_result(data) { + return data instanceof Result ? new Ok(data) : decoder_error("Result", data); +} + +export function decode_map(data) { + if (data instanceof Dict) { + return new Ok(Dict.fromMap(data)); + } + if (data == null) { + return decoder_error("Map", data); + } + if (typeof data !== "object") { + return decoder_error("Map", data); + } + const proto = Object.getPrototypeOf(data); + if (proto === Object.prototype || proto === null) { + return new Ok(Dict.fromObject(data)); + } + return decoder_error("Map", data); +} + +export function decode_option(data, decoder) { + if (data === null || data === undefined || data instanceof None) + return new Ok(new None()); + if (data instanceof Some) data = data[0]; + const result = decoder(data); + if (result.isOk()) { + return new Ok(new Some(result[0])); + } else { + return result; + } +} + +export function decode_field(value, name) { + const not_a_map_error = () => decoder_error("Map", value); + + if ( + value instanceof Dict || + value instanceof WeakMap || + value instanceof Map + ) { + const entry = map_get(value, name); + return new Ok(entry.isOk() ? new Some(entry[0]) : new None()); + } else if (Object.getPrototypeOf(value) == Object.prototype) { + return try_get_field(value, name, () => new Ok(new None())); + } else { + return try_get_field(value, name, not_a_map_error); + } +} + +function try_get_field(value, field, or_else) { + try { + return field in value ? new Ok(new Some(value[field])) : or_else(); + } catch { + return or_else(); + } +} + +export function byte_size(string) { + return new TextEncoder().encode(string).length; +} + +// In Javascript bitwise operations convert numbers to a sequence of 32 bits +// while Erlang uses arbitrary precision. +// To get around this problem and get consistent results use BigInt and then +// downcast the value back to a Number value. + +export function bitwise_and(x, y) { + return Number(BigInt(x) & BigInt(y)); +} + +export function bitwise_not(x) { + return Number(~BigInt(x)); +} + +export function bitwise_or(x, y) { + return Number(BigInt(x) | BigInt(y)); +} + +export function bitwise_exclusive_or(x, y) { + return Number(BigInt(x) ^ BigInt(y)); +} + +export function bitwise_shift_left(x, y) { + return Number(BigInt(x) << BigInt(y)); +} + +export function bitwise_shift_right(x, y) { + return Number(BigInt(x) >> BigInt(y)); +} + +export function inspect(v) { + const t = typeof v; + if (v === true) return "True"; + if (v === false) return "False"; + if (v === null) return "//js(null)"; + if (v === undefined) return "Nil"; + if (t === "string") return JSON.stringify(v); + if (t === "bigint" || t === "number") return v.toString(); + if (Array.isArray(v)) return `#(${v.map(inspect).join(", ")})`; + if (v instanceof List) return inspectList(v); + if (v instanceof UtfCodepoint) return inspectUtfCodepoint(v); + if (v instanceof BitArray) return inspectBitArray(v); + if (v instanceof CustomType) return inspectCustomType(v); + if (v instanceof Dict) return inspectDict(v); + if (v instanceof Set) return `//js(Set(${[...v].map(inspect).join(", ")}))`; + if (v instanceof RegExp) return `//js(${v})`; + if (v instanceof Date) return `//js(Date("${v.toISOString()}"))`; + if (v instanceof Function) { + const args = []; + for (const i of Array(v.length).keys()) + args.push(String.fromCharCode(i + 97)); + return `//fn(${args.join(", ")}) { ... }`; + } + return inspectObject(v); +} + +function inspectDict(map) { + let body = "dict.from_list(["; + let first = true; + map.forEach((value, key) => { + if (!first) body = body + ", "; + body = body + "#(" + inspect(key) + ", " + inspect(value) + ")"; + first = false; + }); + return body + "])"; +} + +function inspectObject(v) { + const name = Object.getPrototypeOf(v)?.constructor?.name || "Object"; + const props = []; + for (const k of Object.keys(v)) { + props.push(`${inspect(k)}: ${inspect(v[k])}`); + } + const body = props.length ? " " + props.join(", ") + " " : ""; + const head = name === "Object" ? "" : name + " "; + return `//js(${head}{${body}})`; +} + +function inspectCustomType(record) { + const props = Object.keys(record) + .map((label) => { + const value = inspect(record[label]); + return isNaN(parseInt(label)) ? `${label}: ${value}` : value; + }) + .join(", "); + return props + ? `${record.constructor.name}(${props})` + : record.constructor.name; +} + +export function inspectList(list) { + return `[${list.toArray().map(inspect).join(", ")}]`; +} + +export function inspectBitArray(bits) { + return `<<${Array.from(bits.buffer).join(", ")}>>`; +} + +export function inspectUtfCodepoint(codepoint) { + return `//utfcodepoint(${String.fromCodePoint(codepoint.value)})`; +} + +export function base16_encode(bit_array) { + let result = ""; + for (const byte of bit_array.buffer) { + result += byte.toString(16).padStart(2, "0").toUpperCase(); + } + return result; +} + +export function base16_decode(string) { + const bytes = new Uint8Array(string.length / 2); + for (let i = 0; i < string.length; i += 2) { + const a = parseInt(string[i], 16); + const b = parseInt(string[i + 1], 16); + if (isNaN(a) || isNaN(b)) return new Error(Nil); + bytes[i / 2] = a * 16 + b; + } + return new Ok(new BitArray(bytes)); +} diff --git a/aoc2023/build/packages/glint/LICENSE b/aoc2023/build/packages/glint/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/aoc2023/build/packages/glint/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/aoc2023/build/packages/glint/README.md b/aoc2023/build/packages/glint/README.md new file mode 100644 index 0000000..d6d5821 --- /dev/null +++ b/aoc2023/build/packages/glint/README.md @@ -0,0 +1,104 @@ +# glint + +[](https://hex.pm/packages/glint) +[](https://hex.pm/packages/glint) +[](https://hexdocs.pm/glint/) +[](https://github.com/tanklesxl/glint/actions) + +Gleam command line argument parsing with basic flag support. + +## Installation + +To install from hex: + +```sh +gleam add glint +``` + +## Usage + +### Glint's Core + +`glint` is conceptually quite small, your general flow will be: + +1. create a new glint instance with `glint.new` +1. configure it with `glint.with_pretty_help` and other configuration functions +1. add commands with `glint.add` + 1. create a new command with `glint.cmd` + 1. assign that command any flags required + 1. assign the command a custom description +1. run your cli with `glnt.run`, run with a function to handle command output with `glint.run_and_handle` + +### Mini Example + +You can import `glint` as a dependency and use it to build simple command-line applications like the following simplified version of the [the hello world example](https://github.com/TanklesXL/glint/tree/main/examples/hello/README.md) + +```gleam +// stdlib imports +import gleam/io +import gleam/list +import gleam/result +import gleam/string.{uppercase} +// external dep imports +import snag +// glint imports +import glint +import glint/flag +// erlang-specific imports + +@target(erlang) +import gleam/erlang.{start_arguments} + +/// the key for the caps flag +const caps = "caps" + +/// a boolean flag with default False to control message capitalization. +/// +fn caps_flag() -> flag.FlagBuilder(Bool) { + flag.bool() + |> flag.default(False) + |> flag.description("Capitalize the provided name") +} + +/// the command function that will be executed +/// +fn hello(input: glint.CommandInput) -> Nil { + let assert Ok(caps) = flag.get_bool(from: input.flags, for: caps) + + let name = + case input.args { + [] -> "Joe" + [name,..] -> name + } + + let msg = "Hello, " <> name <> "!" + + + case caps { + True -> uppercase(msg) + False -> msg + } + |> io.println +} + +pub fn main() { + // create a new glint instance + glint.new() + // with an app name of "hello", this is used when printing help text + |> glint.with_name("hello") + // with pretty help enabled, using the built-in colours + |> glint.with_pretty_help(glint.default_pretty_help()) + // with a root command that executes the `hello` function + |> glint.add( + // add the command to the root + at: [], + // create the command, add any flags + do: glint.command(hello) + // with flag `caps` + |> glint.flag(caps, caps_flag()) + // with a short description + |> glint.description("Prints Hello, <NAME>!"), + ) + |> glint.run(start_arguments()) +} +``` diff --git a/aoc2023/build/packages/glint/gleam.toml b/aoc2023/build/packages/glint/gleam.toml new file mode 100644 index 0000000..e8ac4ae --- /dev/null +++ b/aoc2023/build/packages/glint/gleam.toml @@ -0,0 +1,23 @@ +name = "glint" +version = "0.13.0" + +# Fill out these fields if you intend to generate HTML documentation or publishname = "glint" +# your project to the Hex package manager. +# +licences = ["Apache-2.0"] +description = "Gleam command line argument parsing with basic flag support." +repository = { type = "github", user = "TanklesXL", repo = "glint" } +links = [ + { title = "Hex", href = "https://hex.pm/packages/glint" }, + { title = "Docs", href = "https://hexdocs.pm/glint/" }, +] +gleam = ">= 0.32.0" + +[dependencies] +gleam_stdlib = "~> 0.19" +snag = "~> 0.2" +gleam_community_ansi = "~> 1.0" +gleam_community_colour = "~> 1.0" + +[dev-dependencies] +gleeunit = "~> 0.5" diff --git a/aoc2023/build/packages/glint/include/glint@flag_Flag.hrl b/aoc2023/build/packages/glint/include/glint@flag_Flag.hrl new file mode 100644 index 0000000..645cb12 --- /dev/null +++ b/aoc2023/build/packages/glint/include/glint@flag_Flag.hrl @@ -0,0 +1 @@ +-record(flag, {value :: glint@flag:value(), description :: binary()}). diff --git a/aoc2023/build/packages/glint/include/glint@flag_FlagBuilder.hrl b/aoc2023/build/packages/glint/include/glint@flag_FlagBuilder.hrl new file mode 100644 index 0000000..b5e21a2 --- /dev/null +++ b/aoc2023/build/packages/glint/include/glint@flag_FlagBuilder.hrl @@ -0,0 +1,6 @@ +-record(flag_builder, { + desc :: binary(), + parser :: fun((binary()) -> {ok, any()} | {error, snag:snag()}), + value :: fun((glint@flag:internal(any())) -> glint@flag:value()), + default :: gleam@option:option(any()) +}). diff --git a/aoc2023/build/packages/glint/include/glint@flag_Internal.hrl b/aoc2023/build/packages/glint/include/glint@flag_Internal.hrl new file mode 100644 index 0000000..281bbd0 --- /dev/null +++ b/aoc2023/build/packages/glint/include/glint@flag_Internal.hrl @@ -0,0 +1,4 @@ +-record(internal, { + value :: gleam@option:option(any()), + parser :: fun((binary()) -> {ok, any()} | {error, snag:snag()}) +}). diff --git a/aoc2023/build/packages/glint/include/glint_Command.hrl b/aoc2023/build/packages/glint/include/glint_Command.hrl new file mode 100644 index 0000000..00a03e3 --- /dev/null +++ b/aoc2023/build/packages/glint/include/glint_Command.hrl @@ -0,0 +1,5 @@ +-record(command, { + do :: fun((glint:command_input()) -> any()), + flags :: gleam@map:map_(binary(), glint@flag:flag()), + description :: binary() +}). diff --git a/aoc2023/build/packages/glint/include/glint_CommandInput.hrl b/aoc2023/build/packages/glint/include/glint_CommandInput.hrl new file mode 100644 index 0000000..72c9641 --- /dev/null +++ b/aoc2023/build/packages/glint/include/glint_CommandInput.hrl @@ -0,0 +1,4 @@ +-record(command_input, { + args :: list(binary()), + flags :: gleam@map:map_(binary(), glint@flag:flag()) +}). diff --git a/aoc2023/build/packages/glint/include/glint_Config.hrl b/aoc2023/build/packages/glint/include/glint_Config.hrl new file mode 100644 index 0000000..70cf645 --- /dev/null +++ b/aoc2023/build/packages/glint/include/glint_Config.hrl @@ -0,0 +1,4 @@ +-record(config, { + pretty_help :: gleam@option:option(glint:pretty_help()), + name :: gleam@option:option(binary()) +}). diff --git a/aoc2023/build/packages/glint/include/glint_Glint.hrl b/aoc2023/build/packages/glint/include/glint_Glint.hrl new file mode 100644 index 0000000..7ece11d --- /dev/null +++ b/aoc2023/build/packages/glint/include/glint_Glint.hrl @@ -0,0 +1,5 @@ +-record(glint, { + config :: glint:config(), + cmd :: glint:command_node(any()), + global_flags :: gleam@map:map_(binary(), glint@flag:flag()) +}). diff --git a/aoc2023/build/packages/glint/include/glint_PrettyHelp.hrl b/aoc2023/build/packages/glint/include/glint_PrettyHelp.hrl new file mode 100644 index 0000000..79bd887 --- /dev/null +++ b/aoc2023/build/packages/glint/include/glint_PrettyHelp.hrl @@ -0,0 +1,5 @@ +-record(pretty_help, { + usage :: gleam_community@colour:colour(), + flags :: gleam_community@colour:colour(), + subcommands :: gleam_community@colour:colour() +}). diff --git a/aoc2023/build/packages/glint/include/glint_Stub.hrl b/aoc2023/build/packages/glint/include/glint_Stub.hrl new file mode 100644 index 0000000..5aa5d83 --- /dev/null +++ b/aoc2023/build/packages/glint/include/glint_Stub.hrl @@ -0,0 +1,6 @@ +-record(stub, { + path :: list(binary()), + run :: fun((glint:command_input()) -> any()), + flags :: list({binary(), glint@flag:flag()}), + description :: binary() +}). diff --git a/aoc2023/build/packages/glint/src/glint.app.src b/aoc2023/build/packages/glint/src/glint.app.src new file mode 100644 index 0000000..7eb7649 --- /dev/null +++ b/aoc2023/build/packages/glint/src/glint.app.src @@ -0,0 +1,13 @@ +{application, glint, [ + {vsn, "0.13.0"}, + {applications, [gleam_community_ansi, + gleam_community_colour, + gleam_stdlib, + gleeunit, + snag]}, + {description, "Gleam command line argument parsing with basic flag support."}, + {modules, [glint, + glint@flag, + glint@flag@constraint]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/glint/src/glint.erl b/aoc2023/build/packages/glint/src/glint.erl new file mode 100644 index 0000000..0501cc6 --- /dev/null +++ b/aoc2023/build/packages/glint/src/glint.erl @@ -0,0 +1,513 @@ +-module(glint). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([with_config/2, with_pretty_help/2, without_pretty_help/1, with_name/2, new/0, command/1, description/2, flag/3, flag_tuple/2, flags/2, global_flag/3, global_flag_tuple/2, global_flags/2, default_pretty_help/0, add/3, help_flag/0, execute/2, run_and_handle/3, run/2, add_command_from_stub/2]). +-export_type([config/0, pretty_help/0, glint/1, command/1, command_input/0, command_node/1, out/1, stub/1]). + +-type config() :: {config, + gleam@option:option(pretty_help()), + gleam@option:option(binary())}. + +-type pretty_help() :: {pretty_help, + gleam_community@colour:colour(), + gleam_community@colour:colour(), + gleam_community@colour:colour()}. + +-opaque glint(GHR) :: {glint, + config(), + command_node(GHR), + gleam@map:map_(binary(), glint@flag:flag())}. + +-opaque command(GHS) :: {command, + fun((command_input()) -> GHS), + gleam@map:map_(binary(), glint@flag:flag()), + binary()}. + +-type command_input() :: {command_input, + list(binary()), + gleam@map:map_(binary(), glint@flag:flag())}. + +-type command_node(GHT) :: {command_node, + gleam@option:option(command(GHT)), + gleam@map:map_(binary(), command_node(GHT))}. + +-type out(GHU) :: {out, GHU} | {help, binary()}. + +-type stub(GHV) :: {stub, + list(binary()), + fun((command_input()) -> GHV), + list({binary(), glint@flag:flag()}), + binary()}. + +-spec with_config(glint(GIA), config()) -> glint(GIA). +with_config(Glint, Config) -> + erlang:setelement(2, Glint, Config). + +-spec with_pretty_help(glint(GID), pretty_help()) -> glint(GID). +with_pretty_help(Glint, Pretty) -> + _pipe = erlang:setelement(2, erlang:element(2, Glint), {some, Pretty}), + with_config(Glint, _pipe). + +-spec without_pretty_help(glint(GIG)) -> glint(GIG). +without_pretty_help(Glint) -> + _pipe = erlang:setelement(2, erlang:element(2, Glint), none), + with_config(Glint, _pipe). + +-spec with_name(glint(GIJ), binary()) -> glint(GIJ). +with_name(Glint, Name) -> + _pipe = erlang:setelement(3, erlang:element(2, Glint), {some, Name}), + with_config(Glint, _pipe). + +-spec empty_command() -> command_node(any()). +empty_command() -> + {command_node, none, gleam@map:new()}. + +-spec new() -> glint(any()). +new() -> + {glint, {config, none, none}, empty_command(), gleam@map:new()}. + +-spec do_add(command_node(GIT), list(binary()), command(GIT)) -> command_node(GIT). +do_add(Root, Path, Contents) -> + case Path of + [] -> + erlang:setelement(2, Root, {some, Contents}); + + [X | Xs] -> + erlang:setelement( + 3, + Root, + (gleam@map:update( + erlang:element(3, Root), + X, + fun(Node) -> _pipe = Node, + _pipe@1 = gleam@option:lazy_unwrap( + _pipe, + fun empty_command/0 + ), + do_add(_pipe@1, Xs, Contents) end + )) + ) + end. + +-spec command(fun((command_input()) -> GJC)) -> command(GJC). +command(Runner) -> + {command, Runner, gleam@map:new(), <<""/utf8>>}. + +-spec description(command(GJF), binary()) -> command(GJF). +description(Cmd, Description) -> + erlang:setelement(4, Cmd, Description). + +-spec flag(command(GJI), binary(), glint@flag:flag_builder(any())) -> command(GJI). +flag(Cmd, Key, Flag) -> + erlang:setelement( + 3, + Cmd, + gleam@map:insert(erlang:element(3, Cmd), Key, glint@flag:build(Flag)) + ). + +-spec flag_tuple(command(GJN), {binary(), glint@flag:flag_builder(any())}) -> command(GJN). +flag_tuple(Cmd, Tup) -> + flag(Cmd, erlang:element(1, Tup), erlang:element(2, Tup)). + +-spec flags(command(GJS), list({binary(), glint@flag:flag()})) -> command(GJS). +flags(Cmd, Flags) -> + gleam@list:fold( + Flags, + Cmd, + fun(Cmd@1, _use1) -> + {Key, Flag} = _use1, + erlang:setelement( + 3, + Cmd@1, + gleam@map:insert(erlang:element(3, Cmd@1), Key, Flag) + ) + end + ). + +-spec global_flag(glint(GJW), binary(), glint@flag:flag_builder(any())) -> glint(GJW). +global_flag(Glint, Key, Flag) -> + erlang:setelement( + 4, + Glint, + gleam@map:insert(erlang:element(4, Glint), Key, glint@flag:build(Flag)) + ). + +-spec global_flag_tuple(glint(GKB), {binary(), glint@flag:flag_builder(any())}) -> glint(GKB). +global_flag_tuple(Glint, Tup) -> + global_flag(Glint, erlang:element(1, Tup), erlang:element(2, Tup)). + +-spec global_flags(glint(GKG), list({binary(), glint@flag:flag()})) -> glint(GKG). +global_flags(Glint, Flags) -> + erlang:setelement( + 4, + Glint, + (gleam@list:fold( + Flags, + erlang:element(4, Glint), + fun(Acc, Tup) -> + gleam@map:insert( + Acc, + erlang:element(1, Tup), + erlang:element(2, Tup) + ) + end + )) + ). + +-spec execute_root( + command_node(GKU), + gleam@map:map_(binary(), glint@flag:flag()), + list(binary()), + list(binary()) +) -> {ok, out(GKU)} | {error, snag:snag()}. +execute_root(Cmd, Global_flags, Args, Flag_inputs) -> + _pipe@3 = case erlang:element(2, Cmd) of + {some, Contents} -> + gleam@result:'try'( + gleam@list:try_fold( + Flag_inputs, + gleam@map:merge(Global_flags, erlang:element(3, Contents)), + fun glint@flag:update_flags/2 + ), + fun(New_flags) -> _pipe = {command_input, Args, New_flags}, + _pipe@1 = (erlang:element(2, Contents))(_pipe), + _pipe@2 = {out, _pipe@1}, + {ok, _pipe@2} end + ); + + none -> + snag:error(<<"command not found"/utf8>>) + end, + snag:context(_pipe@3, <<"failed to run command"/utf8>>). + +-spec default_pretty_help() -> pretty_help(). +default_pretty_help() -> + _assert_subject = gleam_community@colour:from_rgb255(182, 255, 234), + {ok, Usage_colour} = case _assert_subject of + {ok, _} -> _assert_subject; + _assert_fail -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail, + module => <<"glint"/utf8>>, + function => <<"default_pretty_help"/utf8>>, + line => 404}) + end, + _assert_subject@1 = gleam_community@colour:from_rgb255(255, 175, 243), + {ok, Flags_colour} = case _assert_subject@1 of + {ok, _} -> _assert_subject@1; + _assert_fail@1 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@1, + module => <<"glint"/utf8>>, + function => <<"default_pretty_help"/utf8>>, + line => 405}) + end, + _assert_subject@2 = gleam_community@colour:from_rgb255(252, 226, 174), + {ok, Subcommands_colour} = case _assert_subject@2 of + {ok, _} -> _assert_subject@2; + _assert_fail@2 -> + erlang:error(#{gleam_error => let_assert, + message => <<"Assertion pattern match failed"/utf8>>, + value => _assert_fail@2, + module => <<"glint"/utf8>>, + function => <<"default_pretty_help"/utf8>>, + line => 406}) + end, + {pretty_help, Usage_colour, Flags_colour, Subcommands_colour}. + +-spec is_not_empty(binary()) -> boolean(). +is_not_empty(S) -> + S /= <<""/utf8>>. + +-spec sanitize_path(list(binary())) -> list(binary()). +sanitize_path(Path) -> + _pipe = Path, + _pipe@1 = gleam@list:map(_pipe, fun gleam@string:trim/1), + gleam@list:filter(_pipe@1, fun is_not_empty/1). + +-spec add(glint(GIO), list(binary()), command(GIO)) -> glint(GIO). +add(Glint, Path, Contents) -> + erlang:setelement( + 3, + Glint, + begin + _pipe = Path, + _pipe@1 = sanitize_path(_pipe), + do_add(erlang:element(3, Glint), _pipe@1, Contents) + end + ). + +-spec help_flag() -> binary(). +help_flag() -> + <<(<<"--"/utf8>>)/binary, "help"/utf8>>. + +-spec wrap_with_space(binary()) -> binary(). +wrap_with_space(S) -> + case S of + <<""/utf8>> -> + <<" "/utf8>>; + + _ -> + <<<<" "/utf8, S/binary>>/binary, " "/utf8>> + end. + +-spec subcommand_help(binary(), command_node(any())) -> binary(). +subcommand_help(Name, Cmd) -> + case erlang:element(2, Cmd) of + none -> + Name; + + {some, Contents} -> + <<<<Name/binary, "\t\t"/utf8>>/binary, + (erlang:element(4, Contents))/binary>> + end. + +-spec subcommands_help(gleam@map:map_(binary(), command_node(any()))) -> binary(). +subcommands_help(Cmds) -> + _pipe = Cmds, + _pipe@1 = gleam@map:map_values(_pipe, fun subcommand_help/2), + _pipe@2 = gleam@map:values(_pipe@1), + _pipe@3 = gleam@list:sort(_pipe@2, fun gleam@string:compare/2), + gleam@string:join(_pipe@3, <<"\n\t"/utf8>>). + +-spec heading_style(binary(), gleam_community@colour:colour()) -> binary(). +heading_style(Heading, Colour) -> + _pipe = Heading, + _pipe@1 = gleam_community@ansi:bold(_pipe), + _pipe@2 = gleam_community@ansi:underline(_pipe@1), + _pipe@3 = gleam_community@ansi:italic(_pipe@2), + _pipe@4 = gleam_community@ansi:hex( + _pipe@3, + gleam_community@colour:to_rgb_hex(Colour) + ), + gleam_community@ansi:reset(_pipe@4). + +-spec usage_help( + binary(), + gleam@map:map_(binary(), glint@flag:flag()), + config() +) -> binary(). +usage_help(Cmd_name, Flags, Config) -> + App_name = gleam@option:unwrap( + erlang:element(3, Config), + <<"gleam run"/utf8>> + ), + Flags@1 = begin + _pipe = Flags, + _pipe@1 = gleam@map:to_list(_pipe), + _pipe@2 = gleam@list:map(_pipe@1, fun glint@flag:flag_type_help/1), + gleam@list:sort(_pipe@2, fun gleam@string:compare/2) + end, + Flag_sb = case Flags@1 of + [] -> + gleam@string_builder:new(); + + _ -> + _pipe@3 = Flags@1, + _pipe@4 = gleam@list:intersperse(_pipe@3, <<" "/utf8>>), + _pipe@5 = gleam@string_builder:from_strings(_pipe@4), + _pipe@6 = gleam@string_builder:prepend(_pipe@5, <<" [ "/utf8>>), + gleam@string_builder:append(_pipe@6, <<" ]"/utf8>>) + end, + _pipe@7 = [App_name, wrap_with_space(Cmd_name), <<"[ ARGS ]"/utf8>>], + _pipe@8 = gleam@string_builder:from_strings(_pipe@7), + _pipe@9 = gleam@string_builder:append_builder(_pipe@8, Flag_sb), + _pipe@12 = gleam@string_builder:prepend( + _pipe@9, + <<(begin + _pipe@10 = erlang:element(2, Config), + _pipe@11 = gleam@option:map( + _pipe@10, + fun(Styling) -> + heading_style( + <<"USAGE:"/utf8>>, + erlang:element(2, Styling) + ) + end + ), + gleam@option:unwrap(_pipe@11, <<"USAGE:"/utf8>>) + end)/binary, + "\n\t"/utf8>> + ), + gleam@string_builder:to_string(_pipe@12). + +-spec cmd_help( + list(binary()), + command_node(any()), + config(), + gleam@map:map_(binary(), glint@flag:flag()) +) -> binary(). +cmd_help(Path, Cmd, Config, Global_flags) -> + Name = begin + _pipe = Path, + _pipe@1 = gleam@list:reverse(_pipe), + gleam@string:join(_pipe@1, <<" "/utf8>>) + end, + Flags = begin + _pipe@2 = gleam@option:map( + erlang:element(2, Cmd), + fun(Contents) -> erlang:element(3, Contents) end + ), + _pipe@3 = gleam@option:lazy_unwrap(_pipe@2, fun gleam@map:new/0), + gleam@map:merge(Global_flags, _pipe@3) + end, + Flags_help_body = <<<<(begin + _pipe@4 = erlang:element(2, Config), + _pipe@5 = gleam@option:map( + _pipe@4, + fun(P) -> + heading_style(<<"FLAGS:"/utf8>>, erlang:element(3, P)) + end + ), + gleam@option:unwrap(_pipe@5, <<"FLAGS:"/utf8>>) + end)/binary, + "\n\t"/utf8>>/binary, + (gleam@string:join( + gleam@list:sort( + [<<"--help\t\t\tPrint help information"/utf8>> | + glint@flag:flags_help(Flags)], + fun gleam@string:compare/2 + ), + <<"\n\t"/utf8>> + ))/binary>>, + Usage = usage_help(Name, Flags, Config), + Description = begin + _pipe@6 = erlang:element(2, Cmd), + _pipe@7 = gleam@option:map( + _pipe@6, + fun(Contents@1) -> erlang:element(4, Contents@1) end + ), + gleam@option:unwrap(_pipe@7, <<""/utf8>>) + end, + Header_items = begin + _pipe@8 = [Name, Description], + _pipe@9 = gleam@list:filter(_pipe@8, fun is_not_empty/1), + gleam@string:join(_pipe@9, <<"\n"/utf8>>) + end, + Subcommands = case subcommands_help(erlang:element(3, Cmd)) of + <<""/utf8>> -> + <<""/utf8>>; + + Subcommands_help_body -> + <<<<(begin + _pipe@10 = erlang:element(2, Config), + _pipe@11 = gleam@option:map( + _pipe@10, + fun(P@1) -> + heading_style( + <<"SUBCOMMANDS:"/utf8>>, + erlang:element(4, P@1) + ) + end + ), + gleam@option:unwrap(_pipe@11, <<"SUBCOMMANDS:"/utf8>>) + end)/binary, + "\n\t"/utf8>>/binary, + Subcommands_help_body/binary>> + end, + _pipe@12 = [Header_items, Usage, Flags_help_body, Subcommands], + _pipe@13 = gleam@list:filter(_pipe@12, fun is_not_empty/1), + gleam@string:join(_pipe@13, <<"\n\n"/utf8>>). + +-spec do_execute( + command_node(GKO), + config(), + gleam@map:map_(binary(), glint@flag:flag()), + list(binary()), + list(binary()), + boolean(), + list(binary()) +) -> {ok, out(GKO)} | {error, snag:snag()}. +do_execute(Cmd, Config, Global_flags, Args, Flags, Help, Command_path) -> + case Args of + [] when Help -> + _pipe = Command_path, + _pipe@1 = cmd_help(_pipe, Cmd, Config, Global_flags), + _pipe@2 = {help, _pipe@1}, + {ok, _pipe@2}; + + [] -> + execute_root(Cmd, Global_flags, [], Flags); + + [Arg | Rest] -> + case gleam@map:get(erlang:element(3, Cmd), Arg) of + {ok, Cmd@1} -> + do_execute( + Cmd@1, + Config, + Global_flags, + Rest, + Flags, + Help, + [Arg | Command_path] + ); + + _ when Help -> + _pipe@3 = Command_path, + _pipe@4 = cmd_help(_pipe@3, Cmd, Config, Global_flags), + _pipe@5 = {help, _pipe@4}, + {ok, _pipe@5}; + + _ -> + execute_root(Cmd, Global_flags, Args, Flags) + end + end. + +-spec execute(glint(GKK), list(binary())) -> {ok, out(GKK)} | + {error, snag:snag()}. +execute(Glint, Args) -> + Help_flag = help_flag(), + {Help, Args@2} = case gleam@list:pop(Args, fun(S) -> S =:= Help_flag end) of + {ok, {_, Args@1}} -> + {true, Args@1}; + + _ -> + {false, Args} + end, + {Flags, Args@3} = gleam@list:partition( + Args@2, + fun(_capture) -> gleam@string:starts_with(_capture, <<"--"/utf8>>) end + ), + do_execute( + erlang:element(3, Glint), + erlang:element(2, Glint), + erlang:element(4, Glint), + Args@3, + Flags, + Help, + [] + ). + +-spec run_and_handle(glint(GLC), list(binary()), fun((GLC) -> any())) -> nil. +run_and_handle(Glint, Args, Handle) -> + case execute(Glint, Args) of + {error, Err} -> + _pipe = Err, + _pipe@1 = snag:pretty_print(_pipe), + gleam@io:println(_pipe@1); + + {ok, {help, Help}} -> + gleam@io:println(Help); + + {ok, {out, Out}} -> + Handle(Out), + nil + end. + +-spec run(glint(any()), list(binary())) -> nil. +run(Glint, Args) -> + run_and_handle(Glint, Args, gleam@function:constant(nil)). + +-spec add_command_from_stub(glint(GLP), stub(GLP)) -> glint(GLP). +add_command_from_stub(Glint, Stub) -> + add( + Glint, + erlang:element(2, Stub), + begin + _pipe = command(erlang:element(3, Stub)), + _pipe@1 = flags(_pipe, erlang:element(4, Stub)), + description(_pipe@1, erlang:element(5, Stub)) + end + ). diff --git a/aoc2023/build/packages/glint/src/glint.gleam b/aoc2023/build/packages/glint/src/glint.gleam new file mode 100644 index 0000000..b159016 --- /dev/null +++ b/aoc2023/build/packages/glint/src/glint.gleam @@ -0,0 +1,588 @@ +import gleam/map.{type Map} +import gleam/option.{type Option, None, Some} +import gleam/list +import gleam/io +import gleam/string +import snag.{type Result} +import glint/flag.{type Flag, type Map as FlagMap} +import gleam/string_builder as sb +import gleam_community/ansi +import gleam_community/colour.{type Colour} +import gleam/result +import gleam/function + +// --- CONFIGURATION --- + +// -- CONFIGURATION: TYPES -- + +/// Config for glint +/// +pub type Config { + Config(pretty_help: Option(PrettyHelp), name: Option(String)) +} + +/// PrettyHelp defines the header colours to be used when styling help text +/// +pub type PrettyHelp { + PrettyHelp(usage: Colour, flags: Colour, subcommands: Colour) +} + +// -- CONFIGURATION: CONSTANTS -- + +/// Default config +/// +pub const default_config = Config(pretty_help: None, name: None) + +// -- CONFIGURATION: FUNCTIONS -- + +/// Add the provided config to the existing command tree +/// +pub fn with_config(glint: Glint(a), config: Config) -> Glint(a) { + Glint(..glint, config: config) +} + +/// Enable custom colours for help text headers +/// For a pre-made colouring use `default_pretty_help()` +/// +pub fn with_pretty_help(glint: Glint(a), pretty: PrettyHelp) -> Glint(a) { + Config(..glint.config, pretty_help: Some(pretty)) + |> with_config(glint, _) +} + +/// Disable custom colours for help text headers +/// +pub fn without_pretty_help(glint: Glint(a)) -> Glint(a) { + Config(..glint.config, pretty_help: None) + |> with_config(glint, _) +} + +pub fn with_name(glint: Glint(a), name: String) -> Glint(a) { + Config(..glint.config, name: Some(name)) + |> with_config(glint, _) +} + +// --- CORE --- + +// -- CORE: TYPES -- + +/// Glint container type for config and commands +/// +pub opaque type Glint(a) { + Glint(config: Config, cmd: CommandNode(a), global_flags: FlagMap) +} + +/// CommandNode contents +/// +pub opaque type Command(a) { + Command(do: Runner(a), flags: FlagMap, description: String) +} + +/// Input type for `Runner`. +/// +pub type CommandInput { + CommandInput(args: List(String), flags: FlagMap) +} + +/// Function type to be run by `glint`. +/// +pub type Runner(a) = + fn(CommandInput) -> a + +/// CommandNode tree representation. +/// +type CommandNode(a) { + CommandNode( + contents: Option(Command(a)), + subcommands: Map(String, CommandNode(a)), + ) +} + +/// Ok type for command execution +/// +pub type Out(a) { + /// Container for the command return value + Out(a) + /// Container for the generated help string + Help(String) +} + +/// Result type for command execution +/// +pub type CmdResult(a) = + Result(Out(a)) + +// -- CORE: BUILDER FUNCTIONS -- + +/// Creates a new command tree. +/// +pub fn new() -> Glint(a) { + Glint(config: default_config, cmd: empty_command(), global_flags: map.new()) +} + +/// Adds a new command to be run at the specified path. +/// +/// If the path is `[]`, the root command is set with the provided function and +/// flags. +/// +/// Note: all command paths are sanitized by stripping whitespace and removing any empty string elements. +/// +pub fn add( + to glint: Glint(a), + at path: List(String), + do contents: Command(a), +) -> Glint(a) { + Glint( + ..glint, + cmd: path + |> sanitize_path + |> do_add(to: glint.cmd, put: contents), + ) +} + +/// Recursive traversal of the command tree to find where to puth the provided command +/// +fn do_add( + to root: CommandNode(a), + at path: List(String), + put contents: Command(a), +) -> CommandNode(a) { + case path { + // update current command with provided contents + [] -> CommandNode(..root, contents: Some(contents)) + // continue down the path, creating empty command nodes along the way + [x, ..xs] -> + CommandNode( + ..root, + subcommands: { + use node <- map.update(root.subcommands, x) + node + |> option.lazy_unwrap(empty_command) + |> do_add(xs, contents) + }, + ) + } +} + +/// Helper for initializing empty commands +/// +fn empty_command() -> CommandNode(a) { + CommandNode(contents: None, subcommands: map.new()) +} + +/// Trim each path element and remove any resulting empty strings. +/// +fn sanitize_path(path: List(String)) -> List(String) { + path + |> list.map(string.trim) + |> list.filter(is_not_empty) +} + +/// Create a Command(a) from a Runner(a) +/// +pub fn command(do runner: Runner(a)) -> Command(a) { + Command(do: runner, flags: map.new(), description: "") +} + +/// Attach a description to a Command(a) +/// +pub fn description(cmd: Command(a), description: String) -> Command(a) { + Command(..cmd, description: description) +} + +/// add a `flag.Flag` to a `Command` +/// +pub fn flag( + cmd: Command(a), + at key: String, + of flag: flag.FlagBuilder(_), +) -> Command(a) { + Command(..cmd, flags: map.insert(cmd.flags, key, flag.build(flag))) +} + +/// Add a `flag.Flag to a `Command` when the flag name and builder are bundled as a #(String, flag.FlagBuilder(a)). +/// +/// This is merely a convenience function and calls `glint.flag` under the hood. +/// +pub fn flag_tuple( + cmd: Command(a), + with tup: #(String, flag.FlagBuilder(_)), +) -> Command(a) { + flag(cmd, tup.0, tup.1) +} + +/// Add multiple `Flag`s to a `Command`, note that this function uses `Flag` and not `FlagBuilder(_)`, so the user will need to call `flag.build` before providing the flags here. +/// +/// It is recommended to call `glint.flag` instead. +/// +pub fn flags(cmd: Command(a), with flags: List(#(String, Flag))) -> Command(a) { + use cmd, #(key, flag) <- list.fold(flags, cmd) + Command(..cmd, flags: map.insert(cmd.flags, key, flag)) +} + +/// Add global flags to the existing command tree +/// +pub fn global_flag( + glint: Glint(a), + at key: String, + of flag: flag.FlagBuilder(_), +) -> Glint(a) { + Glint( + ..glint, + global_flags: map.insert(glint.global_flags, key, flag.build(flag)), + ) +} + +/// Add global flags to the existing command tree. +/// +pub fn global_flag_tuple( + glint: Glint(a), + with tup: #(String, flag.FlagBuilder(_)), +) -> Glint(a) { + global_flag(glint, tup.0, tup.1) +} + +/// Add global flags to the existing command tree. +/// +/// Like `glint.flags`, this function requires `Flag`s insead of `FlagBuilder(_)`. +/// +/// It is recommended to use `glint.global_flag` instead. +/// +pub fn global_flags(glint: Glint(a), flags: List(#(String, Flag))) -> Glint(a) { + Glint( + ..glint, + global_flags: { + list.fold( + flags, + glint.global_flags, + fn(acc, tup) { map.insert(acc, tup.0, tup.1) }, + ) + }, + ) +} + +// -- CORE: EXECUTION FUNCTIONS -- + +/// Determines which command to run and executes it. +/// +/// Sets any provided flags if necessary. +/// +/// Each value prefixed with `--` is parsed as a flag. +/// +/// This function does not print its output and is mainly intended for use within `glint` itself. +/// If you would like to print or handle the output of a command please see the `run_and_handle` function. +/// +pub fn execute(glint: Glint(a), args: List(String)) -> CmdResult(a) { + // create help flag to check for + let help_flag = help_flag() + + // check if help flag is present + let #(help, args) = case list.pop(args, fn(s) { s == help_flag }) { + Ok(#(_, args)) -> #(True, args) + _ -> #(False, args) + } + + // split flags out from the args list + let #(flags, args) = list.partition(args, string.starts_with(_, flag.prefix)) + + // search for command and execute + do_execute(glint.cmd, glint.config, glint.global_flags, args, flags, help, []) +} + +/// Find which command to execute and run it with computed flags and args +/// +fn do_execute( + cmd: CommandNode(a), + config: Config, + global_flags: FlagMap, + args: List(String), + flags: List(String), + help: Bool, + command_path: List(String), +) -> CmdResult(a) { + case args { + // when there are no more available arguments + // and help flag has been passed, generate help message + [] if help -> + command_path + |> cmd_help(cmd, config, global_flags) + |> Help + |> Ok + + // when there are no more available arguments + // run the current command + [] -> execute_root(cmd, global_flags, [], flags) + + // when there are arguments remaining + // check if the next one is a subcommand of the current command + [arg, ..rest] -> + case map.get(cmd.subcommands, arg) { + // subcommand found, continue + Ok(cmd) -> + do_execute( + cmd, + config, + global_flags, + rest, + flags, + help, + [arg, ..command_path], + ) + // subcommand not found, but help flag has been passed + // generate and return help message + _ if help -> + command_path + |> cmd_help(cmd, config, global_flags) + |> Help + |> Ok + // subcommand not found, but help flag has not been passed + // execute the current command + _ -> execute_root(cmd, global_flags, args, flags) + } + } +} + +/// Executes the current root command. +/// +fn execute_root( + cmd: CommandNode(a), + global_flags: FlagMap, + args: List(String), + flag_inputs: List(String), +) -> CmdResult(a) { + case cmd.contents { + Some(contents) -> { + use new_flags <- result.try(list.try_fold( + over: flag_inputs, + from: map.merge(global_flags, contents.flags), + with: flag.update_flags, + )) + CommandInput(args, new_flags) + |> contents.do + |> Out + |> Ok + } + None -> snag.error("command not found") + } + |> snag.context("failed to run command") +} + +/// A wrapper for `execute` that prints any errors enountered or the help text if requested. +/// This function ignores any value returned by the command that was run. +/// If you would like to do something with the command output please see the run_and_handle function. +/// +pub fn run(from glint: Glint(a), for args: List(String)) -> Nil { + run_and_handle(from: glint, for: args, with: function.constant(Nil)) +} + +/// A wrapper for `execute` that prints any errors enountered or the help text if requested. +/// This function calls the provided handler with the value returned by the command that was run. +/// +pub fn run_and_handle( + from glint: Glint(a), + for args: List(String), + with handle: fn(a) -> _, +) -> Nil { + case execute(glint, args) { + Error(err) -> + err + |> snag.pretty_print + |> io.println + Ok(Help(help)) -> io.println(help) + Ok(Out(out)) -> { + handle(out) + Nil + } + } +} + +/// Default pretty help heading colouring +/// mint (r: 182, g: 255, b: 234) colour for usage +/// pink (r: 255, g: 175, b: 243) colour for flags +/// buttercup (r: 252, g: 226, b: 174) colour for subcommands +/// +pub fn default_pretty_help() -> PrettyHelp { + let assert Ok(usage_colour) = colour.from_rgb255(182, 255, 234) + let assert Ok(flags_colour) = colour.from_rgb255(255, 175, 243) + let assert Ok(subcommands_colour) = colour.from_rgb255(252, 226, 174) + + PrettyHelp( + usage: usage_colour, + flags: flags_colour, + subcommands: subcommands_colour, + ) +} + +// constants for setting up sections of the help message +const flags_heading = "FLAGS:" + +const subcommands_heading = "SUBCOMMANDS:" + +const usage_heading = "USAGE:" + +/// Helper for filtering out empty strings +/// +fn is_not_empty(s: String) -> Bool { + s != "" +} + +const help_flag_name = "help" + +const help_flag_message = "--help\t\t\tPrint help information" + +/// Function to create the help flag string +/// Exported for testing purposes only +/// +pub fn help_flag() -> String { + flag.prefix <> help_flag_name +} + +// -- HELP: FUNCTIONS -- + +fn wrap_with_space(s: String) -> String { + case s { + "" -> " " + _ -> " " <> s <> " " + } +} + +/// generate the usage help string for a command +fn usage_help(cmd_name: String, flags: FlagMap, config: Config) -> String { + let app_name = option.unwrap(config.name, "gleam run") + let flags = + flags + |> map.to_list + |> list.map(flag.flag_type_help) + |> list.sort(string.compare) + + let flag_sb = case flags { + [] -> sb.new() + _ -> + flags + |> list.intersperse(" ") + |> sb.from_strings() + |> sb.prepend(prefix: " [ ") + |> sb.append(suffix: " ]") + } + + [app_name, wrap_with_space(cmd_name), "[ ARGS ]"] + |> sb.from_strings + |> sb.append_builder(flag_sb) + |> sb.prepend( + config.pretty_help + |> option.map(fn(styling) { heading_style(usage_heading, styling.usage) }) + |> option.unwrap(usage_heading) <> "\n\t", + ) + |> sb.to_string +} + +/// generate the help text for a command +fn cmd_help( + path: List(String), + cmd: CommandNode(a), + config: Config, + global_flags: FlagMap, +) -> String { + // recreate the path of the current command + // reverse the path because it is created by prepending each section as do_execute walks down the tree + let name = + path + |> list.reverse + |> string.join(" ") + + let flags = + option.map(cmd.contents, fn(contents) { contents.flags }) + |> option.lazy_unwrap(map.new) + |> map.merge(global_flags, _) + + let flags_help_body = + config.pretty_help + |> option.map(fn(p) { heading_style(flags_heading, p.flags) }) + |> option.unwrap(flags_heading) <> "\n\t" <> string.join( + list.sort([help_flag_message, ..flag.flags_help(flags)], string.compare), + "\n\t", + ) + + let usage = usage_help(name, flags, config) + + let description = + cmd.contents + |> option.map(fn(contents) { contents.description }) + |> option.unwrap("") + + // create the header block from the name and description + let header_items = + [name, description] + |> list.filter(is_not_empty) + |> string.join("\n") + + // create the subcommands help block + let subcommands = case subcommands_help(cmd.subcommands) { + "" -> "" + subcommands_help_body -> + config.pretty_help + |> option.map(fn(p) { heading_style(subcommands_heading, p.subcommands) }) + |> option.unwrap(subcommands_heading) <> "\n\t" <> subcommands_help_body + } + + // join the resulting help blocks into the final help message + [header_items, usage, flags_help_body, subcommands] + |> list.filter(is_not_empty) + |> string.join("\n\n") +} + +// create the help text for subcommands +fn subcommands_help(cmds: Map(String, CommandNode(a))) -> String { + cmds + |> map.map_values(subcommand_help) + |> map.values + |> list.sort(string.compare) + |> string.join("\n\t") +} + +// generate the help text for a subcommand +fn subcommand_help(name: String, cmd: CommandNode(_)) -> String { + case cmd.contents { + None -> name + Some(contents) -> name <> "\t\t" <> contents.description + } +} + +/// Style heading text with the provided rgb colouring +/// this is only intended for use within glint itself. +/// +fn heading_style(heading: String, colour: Colour) -> String { + heading + |> ansi.bold + |> ansi.underline + |> ansi.italic + |> ansi.hex(colour.to_rgb_hex(colour)) + |> ansi.reset +} + +// -- DEPRECATED: STUBS -- + +/// DEPRECATED: use `glint.cmd` and related new functions instead to create a Command +/// +/// Create command stubs to be used in `add_command_from_stub` +/// +pub type Stub(a) { + Stub( + path: List(String), + run: Runner(a), + flags: List(#(String, Flag)), + description: String, + ) +} + +/// Add a command to the root given a stub +/// +@deprecated("use `glint.cmd` and related new functions instead to create a Command") +pub fn add_command_from_stub(to glint: Glint(a), with stub: Stub(a)) -> Glint(a) { + add( + to: glint, + at: stub.path, + do: command(stub.run) + |> flags(stub.flags) + |> description(stub.description), + ) +} diff --git a/aoc2023/build/packages/glint/src/glint/flag.gleam b/aoc2023/build/packages/glint/src/glint/flag.gleam new file mode 100644 index 0000000..0a6cae1 --- /dev/null +++ b/aoc2023/build/packages/glint/src/glint/flag.gleam @@ -0,0 +1,478 @@ +import gleam/map +import gleam/string +import gleam/result +import gleam/int +import gleam/list +import gleam/float +import snag.{type Result, type Snag} +import gleam/option.{type Option, None, Some} +import glint/flag/constraint.{type Constraint} +import gleam + +/// Flag inputs must start with this prefix +/// +pub const prefix = "--" + +/// The separation character for flag names and their values +const delimiter = "=" + +/// Supported flag types. +/// +pub type Value { + /// Boolean flags, to be passed in as `--flag=true` or `--flag=false`. + /// Can be toggled by omitting the desired value like `--flag`. + /// Toggling will negate the existing value. + /// + B(Internal(Bool)) + + /// Int flags, to be passed in as `--flag=1` + /// + I(Internal(Int)) + + /// List(Int) flags, to be passed in as `--flag=1,2,3` + /// + LI(Internal(List(Int))) + + /// Float flags, to be passed in as `--flag=1.0` + /// + F(Internal(Float)) + + /// List(Float) flags, to be passed in as `--flag=1.0,2.0` + /// + LF(Internal(List(Float))) + + /// String flags, to be passed in as `--flag=hello` + /// + S(Internal(String)) + + /// List(String) flags, to be passed in as `--flag=hello,world` + /// + LS(Internal(List(String))) +} + +/// A type that facilitates the creation of `Flag`s +/// +pub opaque type FlagBuilder(a) { + FlagBuilder( + desc: Description, + parser: Parser(a, Snag), + value: fn(Internal(a)) -> Value, + default: Option(a), + ) +} + +/// An internal representation of flag contents +/// +pub opaque type Internal(a) { + Internal(value: Option(a), parser: Parser(a, Snag)) +} + +// Builder initializers + +type Parser(a, b) = + fn(String) -> gleam.Result(a, b) + +/// initialise an int flag builder +/// +pub fn int() -> FlagBuilder(Int) { + use input <- new(I) + input + |> int.parse + |> result.replace_error(cannot_parse(input, "int")) +} + +/// initialise an int list flag builder +/// +pub fn int_list() -> FlagBuilder(List(Int)) { + use input <- new(LI) + input + |> string.split(",") + |> list.try_map(int.parse) + |> result.replace_error(cannot_parse(input, "int list")) +} + +/// initialise a float flag builder +/// +pub fn float() -> FlagBuilder(Float) { + use input <- new(F) + input + |> float.parse + |> result.replace_error(cannot_parse(input, "float")) +} + +/// initialise a float list flag builder +/// +pub fn float_list() -> FlagBuilder(List(Float)) { + use input <- new(LF) + input + |> string.split(",") + |> list.try_map(float.parse) + |> result.replace_error(cannot_parse(input, "float list")) +} + +/// initialise a string flag builder +/// +pub fn string() -> FlagBuilder(String) { + new(S, fn(s) { Ok(s) }) +} + +/// intitialise a string list flag builder +/// +pub fn string_list() -> FlagBuilder(List(String)) { + use input <- new(LS) + input + |> string.split(",") + |> Ok +} + +/// initialise a bool flag builder +/// +pub fn bool() -> FlagBuilder(Bool) { + use input <- new(B) + case string.lowercase(input) { + "true" | "t" -> Ok(True) + "false" | "f" -> Ok(False) + _ -> Error(cannot_parse(input, "bool")) + } +} + +/// initialize custom builders using a Value constructor and a parsing function +/// +fn new(valuer: fn(Internal(a)) -> Value, p: Parser(a, Snag)) -> FlagBuilder(a) { + FlagBuilder(desc: "", parser: p, value: valuer, default: None) +} + +/// convert a FlagBuilder(a) into its corresponding Flag representation +/// +pub fn build(fb: FlagBuilder(a)) -> Flag { + Flag( + value: fb.value(Internal(value: fb.default, parser: fb.parser)), + description: fb.desc, + ) +} + +/// attach a constraint to a `Flag` +/// +pub fn constraint( + builder: FlagBuilder(a), + constraint: Constraint(a), +) -> FlagBuilder(a) { + FlagBuilder( + ..builder, + parser: wrap_with_constraint(builder.parser, constraint), + ) +} + +/// attach a Constraint(a) to a Parser(a,Snag) +/// this function should not be used directly unless +fn wrap_with_constraint( + p: Parser(a, Snag), + constraint: Constraint(a), +) -> Parser(a, Snag) { + fn(input: String) -> Result(a) { attempt(p(input), constraint) } +} + +fn attempt( + val: gleam.Result(a, e), + f: fn(a) -> gleam.Result(_, e), +) -> gleam.Result(a, e) { + use a <- result.try(val) + result.replace(f(a), a) +} + +/// Flag descriptions +/// +pub type Description = + String + +/// Flag data and descriptions +/// +pub type Flag { + Flag(value: Value, description: Description) +} + +/// attach a description to a `Flag` +/// +pub fn description( + for builder: FlagBuilder(a), + of description: Description, +) -> FlagBuilder(a) { + FlagBuilder(..builder, desc: description) +} + +/// Set the default value for a flag `Value` +/// +pub fn default(for builder: FlagBuilder(a), of default: a) -> FlagBuilder(a) { + FlagBuilder(..builder, default: Some(default)) +} + +/// Associate flag names to their current values. +/// +pub type Map = + map.Map(String, Flag) + +/// Convert a list of flags to a Map. +/// +pub fn build_map(flags: List(#(String, Flag))) -> Map { + map.from_list(flags) +} + +/// Updates a flag value, ensuring that the new value can satisfy the required type. +/// Assumes that all flag inputs passed in start with -- +/// This function is only intended to be used from glint.execute_root +/// +pub fn update_flags(in flags: Map, with flag_input: String) -> Result(Map) { + let flag_input = string.drop_left(flag_input, string.length(prefix)) + + case string.split_once(flag_input, delimiter) { + Ok(data) -> update_flag_value(flags, data) + Error(_) -> attempt_toggle_flag(flags, flag_input) + } +} + +fn update_flag_value(in flags: Map, with data: #(String, String)) -> Result(Map) { + let #(key, input) = data + use contents <- result.try(access(flags, key)) + use value <- result.map( + compute_flag(with: input, given: contents.value) + |> result.map_error(layer_invalid_flag(_, key)), + ) + map.insert(flags, key, Flag(..contents, value: value)) +} + +fn attempt_toggle_flag(in flags: Map, at key: String) -> Result(Map) { + use contents <- result.try(access(flags, key)) + case contents.value { + B(Internal(None, ..) as internal) -> + Internal(..internal, value: Some(True)) + |> B + |> fn(val) { Flag(..contents, value: val) } + |> map.insert(into: flags, for: key) + |> Ok() + B(Internal(Some(val), ..) as internal) -> + Internal(..internal, value: Some(!val)) + |> B + |> fn(val) { Flag(..contents, value: val) } + |> map.insert(into: flags, for: key) + |> Ok() + _ -> Error(no_value_flag_err(key)) + } +} + +fn access_type_error(flag_type) { + snag.error("cannot access flag as " <> flag_type) +} + +fn flag_not_provided_error() { + snag.error("no value provided") +} + +fn construct_value( + input: String, + internal: Internal(a), + constructor: fn(Internal(a)) -> Value, +) -> Result(Value) { + use val <- result.map(internal.parser(input)) + constructor(Internal(..internal, value: Some(val))) +} + +/// Computes the new flag value given the input and the expected flag type +/// +fn compute_flag(with input: String, given current: Value) -> Result(Value) { + input + |> case current { + I(internal) -> construct_value(_, internal, I) + LI(internal) -> construct_value(_, internal, LI) + F(internal) -> construct_value(_, internal, F) + LF(internal) -> construct_value(_, internal, LF) + S(internal) -> construct_value(_, internal, S) + LS(internal) -> construct_value(_, internal, LS) + B(internal) -> construct_value(_, internal, B) + } + |> snag.context("failed to compute value for flag") +} + +// Error creation and manipulation functions +fn layer_invalid_flag(err: Snag, flag: String) -> Snag { + snag.layer(err, "invalid flag '" <> flag <> "'") +} + +fn no_value_flag_err(flag_input: String) -> Snag { + { "flag '" <> flag_input <> "' has no assigned value" } + |> snag.new() + |> layer_invalid_flag(flag_input) +} + +fn undefined_flag_err(key: String) -> Snag { + "flag provided but not defined" + |> snag.new() + |> layer_invalid_flag(key) +} + +fn cannot_parse(with value: String, is kind: String) -> Snag { + { "cannot parse value '" <> value <> "' as " <> kind } + |> snag.new() +} + +// Help Message Functions +/// Generate the help message contents for a single flag +/// +pub fn flag_type_help(flag: #(String, Flag)) { + let #(name, contents) = flag + let kind = case contents.value { + I(_) -> "INT" + B(_) -> "BOOL" + F(_) -> "FLOAT" + LF(_) -> "FLOAT_LIST" + LI(_) -> "INT_LIST" + LS(_) -> "STRING_LIST" + S(_) -> "STRING" + } + + prefix <> name <> delimiter <> "<" <> kind <> ">" +} + +/// Generate help message line for a single flag +/// +fn flag_help(flag: #(String, Flag)) -> String { + flag_type_help(flag) <> "\t\t" <> { flag.1 }.description +} + +/// Generate help messages for all flags +/// +pub fn flags_help(flags: Map) -> List(String) { + flags + |> map.to_list + |> list.map(flag_help) +} + +// -- FLAG ACCESS FUNCTIONS -- + +/// Access the contents for the associated flag +/// +fn access(flags: Map, name: String) -> Result(Flag) { + map.get(flags, name) + |> result.replace_error(undefined_flag_err(name)) +} + +fn get_value( + from flags: Map, + at key: String, + expecting kind: fn(Flag) -> Result(a), +) -> Result(a) { + access(flags, key) + |> result.try(kind) + |> snag.context("failed to retrieve value for flag '" <> key <> "'") +} + +/// Gets the current value for the provided int flag +/// +pub fn get_int_value(from flag: Flag) -> Result(Int) { + case flag.value { + I(Internal(value: Some(val), ..)) -> Ok(val) + I(Internal(value: None, ..)) -> flag_not_provided_error() + _ -> access_type_error("int") + } +} + +/// Gets the current value for the associated int flag +/// +pub fn get_int(from flags: Map, for name: String) -> Result(Int) { + get_value(flags, name, get_int_value) +} + +/// Gets the current value for the provided ints flag +/// +pub fn get_ints_value(from flag: Flag) -> Result(List(Int)) { + case flag.value { + LI(Internal(value: Some(val), ..)) -> Ok(val) + LI(Internal(value: None, ..)) -> flag_not_provided_error() + _ -> access_type_error("int list") + } +} + +/// Gets the current value for the associated ints flag +/// +pub fn get_ints(from flags: Map, for name: String) -> Result(List(Int)) { + get_value(flags, name, get_ints_value) +} + +/// Gets the current value for the provided bool flag +/// +pub fn get_bool_value(from flag: Flag) -> Result(Bool) { + case flag.value { + B(Internal(Some(val), ..)) -> Ok(val) + B(Internal(None, ..)) -> flag_not_provided_error() + _ -> access_type_error("bool") + } +} + +/// Gets the current value for the associated bool flag +/// +pub fn get_bool(from flags: Map, for name: String) -> Result(Bool) { + get_value(flags, name, get_bool_value) +} + +/// Gets the current value for the provided string flag +/// +pub fn get_string_value(from flag: Flag) -> Result(String) { + case flag.value { + S(Internal(value: Some(val), ..)) -> Ok(val) + S(Internal(value: None, ..)) -> flag_not_provided_error() + _ -> access_type_error("string") + } +} + +/// Gets the current value for the associated string flag +/// +pub fn get_string(from flags: Map, for name: String) -> Result(String) { + get_value(flags, name, get_string_value) +} + +/// Gets the current value for the provided strings flag +/// +pub fn get_strings_value(from flag: Flag) -> Result(List(String)) { + case flag.value { + LS(Internal(value: Some(val), ..)) -> Ok(val) + LS(Internal(value: None, ..)) -> flag_not_provided_error() + _ -> access_type_error("string list") + } +} + +/// Gets the current value for the associated strings flag +/// +pub fn get_strings(from flags: Map, for name: String) -> Result(List(String)) { + get_value(flags, name, get_strings_value) +} + +/// Gets the current value for the provided float flag +/// +pub fn get_float_value(from flag: Flag) -> Result(Float) { + case flag.value { + F(Internal(value: Some(val), ..)) -> Ok(val) + F(Internal(value: None, ..)) -> flag_not_provided_error() + _ -> access_type_error("float") + } +} + +/// Gets the current value for the associated float flag +/// +pub fn get_float(from flags: Map, for name: String) -> Result(Float) { + get_value(flags, name, get_float_value) +} + +/// Gets the current value for the provided floats flag +/// +pub fn get_floats_value(from flag: Flag) -> Result(List(Float)) { + case flag.value { + LF(Internal(value: Some(val), ..)) -> Ok(val) + LF(Internal(value: None, ..)) -> flag_not_provided_error() + _ -> access_type_error("float list") + } +} + +/// Gets the current value for the associated floats flag +/// +pub fn get_floats(from flags: Map, for name: String) -> Result(List(Float)) { + get_value(flags, name, get_floats_value) +} diff --git a/aoc2023/build/packages/glint/src/glint/flag/constraint.gleam b/aoc2023/build/packages/glint/src/glint/flag/constraint.gleam new file mode 100644 index 0000000..e474bc2 --- /dev/null +++ b/aoc2023/build/packages/glint/src/glint/flag/constraint.gleam @@ -0,0 +1,66 @@ +import gleam/list +import gleam/result +import gleam/string +import gleam/set +import snag.{type Result} + +/// Constraint type for verifying flag values +/// +pub type Constraint(a) = + fn(a) -> Result(Nil) + +/// one_of returns a Constraint that ensures the parsed flag value is +/// one of the allowed values. +/// +pub fn one_of(allowed: List(a)) -> Constraint(a) { + let allowed_set = set.from_list(allowed) + fn(val: a) -> Result(Nil) { + case set.contains(allowed_set, val) { + True -> Ok(Nil) + False -> + snag.error( + "invalid value '" <> string.inspect(val) <> "', must be one of: [" <> { + allowed + |> list.map(fn(a) { "'" <> string.inspect(a) <> "'" }) + |> string.join(", ") <> "]" + }, + ) + } + } +} + +/// none_of returns a Constraint that ensures the parsed flag value is not one of the disallowed values. +/// +pub fn none_of(disallowed: List(a)) -> Constraint(a) { + let disallowed_set = set.from_list(disallowed) + fn(val: a) -> Result(Nil) { + case set.contains(disallowed_set, val) { + False -> Ok(Nil) + True -> + snag.error( + "invalid value '" <> string.inspect(val) <> "', must not be one of: [" <> { + { + disallowed + |> list.map(fn(a) { "'" <> string.inspect(a) <> "'" }) + |> string.join(", ") <> "]" + } + }, + ) + } + } +} + +/// each is a convenience function for applying a Constraint(a) to a List(a). +/// This is useful because the default behaviour for constraints on lists is that they will apply to the list as a whole. +/// +/// For example, to apply one_of to all items in a `List(Int)`: +/// ```gleam +/// [1, 2, 3, 4] |> one_of |> each +/// ``` +pub fn each(constraint: Constraint(a)) -> Constraint(List(a)) { + fn(l: List(a)) -> Result(Nil) { + l + |> list.try_map(constraint) + |> result.replace(Nil) + } +} diff --git a/aoc2023/build/packages/glint/src/glint@flag.erl b/aoc2023/build/packages/glint/src/glint@flag.erl new file mode 100644 index 0000000..bcce6db --- /dev/null +++ b/aoc2023/build/packages/glint/src/glint@flag.erl @@ -0,0 +1,523 @@ +-module(glint@flag). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([string/0, string_list/0, build/1, constraint/2, description/2, default/2, build_map/1, int/0, int_list/0, float/0, float_list/0, bool/0, flag_type_help/1, flags_help/1, update_flags/2, get_int_value/1, get_int/2, get_ints_value/1, get_ints/2, get_bool_value/1, get_bool/2, get_string_value/1, get_string/2, get_strings_value/1, get_strings/2, get_float_value/1, get_float/2, get_floats_value/1, get_floats/2]). +-export_type([value/0, flag_builder/1, internal/1, flag/0]). + +-type value() :: {b, internal(boolean())} | + {i, internal(integer())} | + {li, internal(list(integer()))} | + {f, internal(float())} | + {lf, internal(list(float()))} | + {s, internal(binary())} | + {ls, internal(list(binary()))}. + +-opaque flag_builder(FTZ) :: {flag_builder, + binary(), + fun((binary()) -> {ok, FTZ} | {error, snag:snag()}), + fun((internal(FTZ)) -> value()), + gleam@option:option(FTZ)}. + +-opaque internal(FUA) :: {internal, + gleam@option:option(FUA), + fun((binary()) -> {ok, FUA} | {error, snag:snag()})}. + +-type flag() :: {flag, value(), binary()}. + +-spec new( + fun((internal(FUR)) -> value()), + fun((binary()) -> {ok, FUR} | {error, snag:snag()}) +) -> flag_builder(FUR). +new(Valuer, P) -> + {flag_builder, <<""/utf8>>, P, Valuer, none}. + +-spec string() -> flag_builder(binary()). +string() -> + new(fun(Field@0) -> {s, Field@0} end, fun(S) -> {ok, S} end). + +-spec string_list() -> flag_builder(list(binary())). +string_list() -> + new(fun(Field@0) -> {ls, Field@0} end, fun(Input) -> _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<","/utf8>>), + {ok, _pipe@1} end). + +-spec build(flag_builder(any())) -> flag(). +build(Fb) -> + {flag, + (erlang:element(4, Fb))( + {internal, erlang:element(5, Fb), erlang:element(3, Fb)} + ), + erlang:element(2, Fb)}. + +-spec attempt( + {ok, FVI} | {error, FVJ}, + fun((FVI) -> {ok, any()} | {error, FVJ}) +) -> {ok, FVI} | {error, FVJ}. +attempt(Val, F) -> + gleam@result:'try'(Val, fun(A) -> gleam@result:replace(F(A), A) end). + +-spec wrap_with_constraint( + fun((binary()) -> {ok, FVC} | {error, snag:snag()}), + fun((FVC) -> {ok, nil} | {error, snag:snag()}) +) -> fun((binary()) -> {ok, FVC} | {error, snag:snag()}). +wrap_with_constraint(P, Constraint) -> + fun(Input) -> attempt(P(Input), Constraint) end. + +-spec constraint( + flag_builder(FUY), + fun((FUY) -> {ok, nil} | {error, snag:snag()}) +) -> flag_builder(FUY). +constraint(Builder, Constraint) -> + erlang:setelement( + 3, + Builder, + wrap_with_constraint(erlang:element(3, Builder), Constraint) + ). + +-spec description(flag_builder(FVR), binary()) -> flag_builder(FVR). +description(Builder, Description) -> + erlang:setelement(2, Builder, Description). + +-spec default(flag_builder(FVU), FVU) -> flag_builder(FVU). +default(Builder, Default) -> + erlang:setelement(5, Builder, {some, Default}). + +-spec build_map(list({binary(), flag()})) -> gleam@map:map_(binary(), flag()). +build_map(Flags) -> + gleam@map:from_list(Flags). + +-spec access_type_error(binary()) -> {ok, any()} | {error, snag:snag()}. +access_type_error(Flag_type) -> + snag:error(<<"cannot access flag as "/utf8, Flag_type/binary>>). + +-spec flag_not_provided_error() -> {ok, any()} | {error, snag:snag()}. +flag_not_provided_error() -> + snag:error(<<"no value provided"/utf8>>). + +-spec construct_value(binary(), internal(FWE), fun((internal(FWE)) -> value())) -> {ok, + value()} | + {error, snag:snag()}. +construct_value(Input, Internal, Constructor) -> + gleam@result:map( + (erlang:element(3, Internal))(Input), + fun(Val) -> Constructor(erlang:setelement(2, Internal, {some, Val})) end + ). + +-spec compute_flag(binary(), value()) -> {ok, value()} | {error, snag:snag()}. +compute_flag(Input, Current) -> + _pipe = Input, + _pipe@1 = case Current of + {i, Internal} -> + fun(_capture) -> + construct_value( + _capture, + Internal, + fun(Field@0) -> {i, Field@0} end + ) + end; + + {li, Internal@1} -> + fun(_capture@1) -> + construct_value( + _capture@1, + Internal@1, + fun(Field@0) -> {li, Field@0} end + ) + end; + + {f, Internal@2} -> + fun(_capture@2) -> + construct_value( + _capture@2, + Internal@2, + fun(Field@0) -> {f, Field@0} end + ) + end; + + {lf, Internal@3} -> + fun(_capture@3) -> + construct_value( + _capture@3, + Internal@3, + fun(Field@0) -> {lf, Field@0} end + ) + end; + + {s, Internal@4} -> + fun(_capture@4) -> + construct_value( + _capture@4, + Internal@4, + fun(Field@0) -> {s, Field@0} end + ) + end; + + {ls, Internal@5} -> + fun(_capture@5) -> + construct_value( + _capture@5, + Internal@5, + fun(Field@0) -> {ls, Field@0} end + ) + end; + + {b, Internal@6} -> + fun(_capture@6) -> + construct_value( + _capture@6, + Internal@6, + fun(Field@0) -> {b, Field@0} end + ) + end + end(_pipe), + snag:context(_pipe@1, <<"failed to compute value for flag"/utf8>>). + +-spec layer_invalid_flag(snag:snag(), binary()) -> snag:snag(). +layer_invalid_flag(Err, Flag) -> + snag:layer(Err, <<<<"invalid flag '"/utf8, Flag/binary>>/binary, "'"/utf8>>). + +-spec no_value_flag_err(binary()) -> snag:snag(). +no_value_flag_err(Flag_input) -> + _pipe = (<<<<"flag '"/utf8, Flag_input/binary>>/binary, + "' has no assigned value"/utf8>>), + _pipe@1 = snag:new(_pipe), + layer_invalid_flag(_pipe@1, Flag_input). + +-spec undefined_flag_err(binary()) -> snag:snag(). +undefined_flag_err(Key) -> + _pipe = <<"flag provided but not defined"/utf8>>, + _pipe@1 = snag:new(_pipe), + layer_invalid_flag(_pipe@1, Key). + +-spec cannot_parse(binary(), binary()) -> snag:snag(). +cannot_parse(Value, Kind) -> + _pipe = (<<<<<<"cannot parse value '"/utf8, Value/binary>>/binary, + "' as "/utf8>>/binary, + Kind/binary>>), + snag:new(_pipe). + +-spec int() -> flag_builder(integer()). +int() -> + new(fun(Field@0) -> {i, Field@0} end, fun(Input) -> _pipe = Input, + _pipe@1 = gleam@int:parse(_pipe), + gleam@result:replace_error( + _pipe@1, + cannot_parse(Input, <<"int"/utf8>>) + ) end). + +-spec int_list() -> flag_builder(list(integer())). +int_list() -> + new(fun(Field@0) -> {li, Field@0} end, fun(Input) -> _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<","/utf8>>), + _pipe@2 = gleam@list:try_map(_pipe@1, fun gleam@int:parse/1), + gleam@result:replace_error( + _pipe@2, + cannot_parse(Input, <<"int list"/utf8>>) + ) end). + +-spec float() -> flag_builder(float()). +float() -> + new(fun(Field@0) -> {f, Field@0} end, fun(Input) -> _pipe = Input, + _pipe@1 = gleam@float:parse(_pipe), + gleam@result:replace_error( + _pipe@1, + cannot_parse(Input, <<"float"/utf8>>) + ) end). + +-spec float_list() -> flag_builder(list(float())). +float_list() -> + new(fun(Field@0) -> {lf, Field@0} end, fun(Input) -> _pipe = Input, + _pipe@1 = gleam@string:split(_pipe, <<","/utf8>>), + _pipe@2 = gleam@list:try_map(_pipe@1, fun gleam@float:parse/1), + gleam@result:replace_error( + _pipe@2, + cannot_parse(Input, <<"float list"/utf8>>) + ) end). + +-spec bool() -> flag_builder(boolean()). +bool() -> + new( + fun(Field@0) -> {b, Field@0} end, + fun(Input) -> case gleam@string:lowercase(Input) of + <<"true"/utf8>> -> + {ok, true}; + + <<"t"/utf8>> -> + {ok, true}; + + <<"false"/utf8>> -> + {ok, false}; + + <<"f"/utf8>> -> + {ok, false}; + + _ -> + {error, cannot_parse(Input, <<"bool"/utf8>>)} + end end + ). + +-spec flag_type_help({binary(), flag()}) -> binary(). +flag_type_help(Flag) -> + {Name, Contents} = Flag, + Kind = case erlang:element(2, Contents) of + {i, _} -> + <<"INT"/utf8>>; + + {b, _} -> + <<"BOOL"/utf8>>; + + {f, _} -> + <<"FLOAT"/utf8>>; + + {lf, _} -> + <<"FLOAT_LIST"/utf8>>; + + {li, _} -> + <<"INT_LIST"/utf8>>; + + {ls, _} -> + <<"STRING_LIST"/utf8>>; + + {s, _} -> + <<"STRING"/utf8>> + end, + <<<<<<<<<<"--"/utf8, Name/binary>>/binary, "="/utf8>>/binary, "<"/utf8>>/binary, + Kind/binary>>/binary, + ">"/utf8>>. + +-spec flag_help({binary(), flag()}) -> binary(). +flag_help(Flag) -> + <<<<(flag_type_help(Flag))/binary, "\t\t"/utf8>>/binary, + (erlang:element(3, (erlang:element(2, Flag))))/binary>>. + +-spec flags_help(gleam@map:map_(binary(), flag())) -> list(binary()). +flags_help(Flags) -> + _pipe = Flags, + _pipe@1 = gleam@map:to_list(_pipe), + gleam@list:map(_pipe@1, fun flag_help/1). + +-spec access(gleam@map:map_(binary(), flag()), binary()) -> {ok, flag()} | + {error, snag:snag()}. +access(Flags, Name) -> + _pipe = gleam@map:get(Flags, Name), + gleam@result:replace_error(_pipe, undefined_flag_err(Name)). + +-spec update_flag_value(gleam@map:map_(binary(), flag()), {binary(), binary()}) -> {ok, + gleam@map:map_(binary(), flag())} | + {error, snag:snag()}. +update_flag_value(Flags, Data) -> + {Key, Input} = Data, + gleam@result:'try'( + access(Flags, Key), + fun(Contents) -> + gleam@result:map( + begin + _pipe = compute_flag(Input, erlang:element(2, Contents)), + gleam@result:map_error( + _pipe, + fun(_capture) -> layer_invalid_flag(_capture, Key) end + ) + end, + fun(Value) -> + gleam@map:insert( + Flags, + Key, + erlang:setelement(2, Contents, Value) + ) + end + ) + end + ). + +-spec attempt_toggle_flag(gleam@map:map_(binary(), flag()), binary()) -> {ok, + gleam@map:map_(binary(), flag())} | + {error, snag:snag()}. +attempt_toggle_flag(Flags, Key) -> + gleam@result:'try'( + access(Flags, Key), + fun(Contents) -> case erlang:element(2, Contents) of + {b, {internal, none, _} = Internal} -> + _pipe = erlang:setelement(2, Internal, {some, true}), + _pipe@1 = {b, _pipe}, + _pipe@2 = (fun(Val) -> + erlang:setelement(2, Contents, Val) + end)(_pipe@1), + _pipe@3 = gleam@map:insert(Flags, Key, _pipe@2), + {ok, _pipe@3}; + + {b, {internal, {some, Val@1}, _} = Internal@1} -> + _pipe@4 = erlang:setelement( + 2, + Internal@1, + {some, not Val@1} + ), + _pipe@5 = {b, _pipe@4}, + _pipe@6 = (fun(Val@2) -> + erlang:setelement(2, Contents, Val@2) + end)(_pipe@5), + _pipe@7 = gleam@map:insert(Flags, Key, _pipe@6), + {ok, _pipe@7}; + + _ -> + {error, no_value_flag_err(Key)} + end end + ). + +-spec update_flags(gleam@map:map_(binary(), flag()), binary()) -> {ok, + gleam@map:map_(binary(), flag())} | + {error, snag:snag()}. +update_flags(Flags, Flag_input) -> + Flag_input@1 = gleam@string:drop_left( + Flag_input, + gleam@string:length(<<"--"/utf8>>) + ), + case gleam@string:split_once(Flag_input@1, <<"="/utf8>>) of + {ok, Data} -> + update_flag_value(Flags, Data); + + {error, _} -> + attempt_toggle_flag(Flags, Flag_input@1) + end. + +-spec get_value( + gleam@map:map_(binary(), flag()), + binary(), + fun((flag()) -> {ok, FWM} | {error, snag:snag()}) +) -> {ok, FWM} | {error, snag:snag()}. +get_value(Flags, Key, Kind) -> + _pipe = access(Flags, Key), + _pipe@1 = gleam@result:'try'(_pipe, Kind), + snag:context( + _pipe@1, + <<<<"failed to retrieve value for flag '"/utf8, Key/binary>>/binary, + "'"/utf8>> + ). + +-spec get_int_value(flag()) -> {ok, integer()} | {error, snag:snag()}. +get_int_value(Flag) -> + case erlang:element(2, Flag) of + {i, {internal, {some, Val}, _}} -> + {ok, Val}; + + {i, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"int"/utf8>>) + end. + +-spec get_int(gleam@map:map_(binary(), flag()), binary()) -> {ok, integer()} | + {error, snag:snag()}. +get_int(Flags, Name) -> + get_value(Flags, Name, fun get_int_value/1). + +-spec get_ints_value(flag()) -> {ok, list(integer())} | {error, snag:snag()}. +get_ints_value(Flag) -> + case erlang:element(2, Flag) of + {li, {internal, {some, Val}, _}} -> + {ok, Val}; + + {li, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"int list"/utf8>>) + end. + +-spec get_ints(gleam@map:map_(binary(), flag()), binary()) -> {ok, + list(integer())} | + {error, snag:snag()}. +get_ints(Flags, Name) -> + get_value(Flags, Name, fun get_ints_value/1). + +-spec get_bool_value(flag()) -> {ok, boolean()} | {error, snag:snag()}. +get_bool_value(Flag) -> + case erlang:element(2, Flag) of + {b, {internal, {some, Val}, _}} -> + {ok, Val}; + + {b, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"bool"/utf8>>) + end. + +-spec get_bool(gleam@map:map_(binary(), flag()), binary()) -> {ok, boolean()} | + {error, snag:snag()}. +get_bool(Flags, Name) -> + get_value(Flags, Name, fun get_bool_value/1). + +-spec get_string_value(flag()) -> {ok, binary()} | {error, snag:snag()}. +get_string_value(Flag) -> + case erlang:element(2, Flag) of + {s, {internal, {some, Val}, _}} -> + {ok, Val}; + + {s, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"string"/utf8>>) + end. + +-spec get_string(gleam@map:map_(binary(), flag()), binary()) -> {ok, binary()} | + {error, snag:snag()}. +get_string(Flags, Name) -> + get_value(Flags, Name, fun get_string_value/1). + +-spec get_strings_value(flag()) -> {ok, list(binary())} | {error, snag:snag()}. +get_strings_value(Flag) -> + case erlang:element(2, Flag) of + {ls, {internal, {some, Val}, _}} -> + {ok, Val}; + + {ls, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"string list"/utf8>>) + end. + +-spec get_strings(gleam@map:map_(binary(), flag()), binary()) -> {ok, + list(binary())} | + {error, snag:snag()}. +get_strings(Flags, Name) -> + get_value(Flags, Name, fun get_strings_value/1). + +-spec get_float_value(flag()) -> {ok, float()} | {error, snag:snag()}. +get_float_value(Flag) -> + case erlang:element(2, Flag) of + {f, {internal, {some, Val}, _}} -> + {ok, Val}; + + {f, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"float"/utf8>>) + end. + +-spec get_float(gleam@map:map_(binary(), flag()), binary()) -> {ok, float()} | + {error, snag:snag()}. +get_float(Flags, Name) -> + get_value(Flags, Name, fun get_float_value/1). + +-spec get_floats_value(flag()) -> {ok, list(float())} | {error, snag:snag()}. +get_floats_value(Flag) -> + case erlang:element(2, Flag) of + {lf, {internal, {some, Val}, _}} -> + {ok, Val}; + + {lf, {internal, none, _}} -> + flag_not_provided_error(); + + _ -> + access_type_error(<<"float list"/utf8>>) + end. + +-spec get_floats(gleam@map:map_(binary(), flag()), binary()) -> {ok, + list(float())} | + {error, snag:snag()}. +get_floats(Flags, Name) -> + get_value(Flags, Name, fun get_floats_value/1). diff --git a/aoc2023/build/packages/glint/src/glint@flag@constraint.erl b/aoc2023/build/packages/glint/src/glint@flag@constraint.erl new file mode 100644 index 0000000..2978be0 --- /dev/null +++ b/aoc2023/build/packages/glint/src/glint@flag@constraint.erl @@ -0,0 +1,68 @@ +-module(glint@flag@constraint). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([one_of/1, none_of/1, each/1]). + +-spec one_of(list(FSI)) -> fun((FSI) -> {ok, nil} | {error, snag:snag()}). +one_of(Allowed) -> + Allowed_set = gleam@set:from_list(Allowed), + fun(Val) -> case gleam@set:contains(Allowed_set, Val) of + true -> + {ok, nil}; + + false -> + snag:error( + <<<<<<"invalid value '"/utf8, + (gleam@string:inspect(Val))/binary>>/binary, + "', must be one of: ["/utf8>>/binary, + ((<<(begin + _pipe = Allowed, + _pipe@1 = gleam@list:map( + _pipe, + fun(A) -> + <<<<"'"/utf8, + (gleam@string:inspect(A))/binary>>/binary, + "'"/utf8>> + end + ), + gleam@string:join(_pipe@1, <<", "/utf8>>) + end)/binary, + "]"/utf8>>))/binary>> + ) + end end. + +-spec none_of(list(FSL)) -> fun((FSL) -> {ok, nil} | {error, snag:snag()}). +none_of(Disallowed) -> + Disallowed_set = gleam@set:from_list(Disallowed), + fun(Val) -> case gleam@set:contains(Disallowed_set, Val) of + false -> + {ok, nil}; + + true -> + snag:error( + <<<<<<"invalid value '"/utf8, + (gleam@string:inspect(Val))/binary>>/binary, + "', must not be one of: ["/utf8>>/binary, + (((<<(begin + _pipe = Disallowed, + _pipe@1 = gleam@list:map( + _pipe, + fun(A) -> + <<<<"'"/utf8, + (gleam@string:inspect(A))/binary>>/binary, + "'"/utf8>> + end + ), + gleam@string:join(_pipe@1, <<", "/utf8>>) + end)/binary, + "]"/utf8>>)))/binary>> + ) + end end. + +-spec each(fun((FSO) -> {ok, nil} | {error, snag:snag()})) -> fun((list(FSO)) -> {ok, + nil} | + {error, snag:snag()}). +each(Constraint) -> + fun(L) -> _pipe = L, + _pipe@1 = gleam@list:try_map(_pipe, Constraint), + gleam@result:replace(_pipe@1, nil) end. diff --git a/aoc2023/build/packages/packages.toml b/aoc2023/build/packages/packages.toml new file mode 100644 index 0000000..132c3a4 --- /dev/null +++ b/aoc2023/build/packages/packages.toml @@ -0,0 +1,16 @@ +[packages] +gleam_community_colour = "1.2.0" +gleam_stdlib = "0.33.0" +pqueue = "2.0.7" +snag = "0.2.1" +gleam_http = "3.5.2" +gleam_otp = "0.8.0" +simplifile = "1.0.0" +gleam_community_maths = "1.0.1" +gleam_httpc = "2.1.1" +glint = "0.13.0" +adglent = "1.2.0" +gleam_community_ansi = "1.2.0" +gleam_erlang = "0.23.1" +gap = "1.0.1" +tom = "0.2.1" diff --git a/aoc2023/build/packages/pqueue/LICENSE b/aoc2023/build/packages/pqueue/LICENSE new file mode 100644 index 0000000..5697803 --- /dev/null +++ b/aoc2023/build/packages/pqueue/LICENSE @@ -0,0 +1,21 @@ +MIT License
+
+Copyright (c) 2011-2023 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.
diff --git a/aoc2023/build/packages/pqueue/README.markdown b/aoc2023/build/packages/pqueue/README.markdown new file mode 100644 index 0000000..77aaf1c --- /dev/null +++ b/aoc2023/build/packages/pqueue/README.markdown @@ -0,0 +1,31 @@ +Erlang Priority Queue Implementation +==================================== + +The priority queue implementations implement a subset of the stdlib Erlang queue interface as seen in the implementation used by both [Riak and RabbitMQ](https://github.com/basho/riak_core/blob/master/src/riak_core_priority_queue.erl). + +The implementations: + +* `priority_queue` (fastest for any priorities when only using a single priority at a time) +* `pqueue` (fastest for 41 priorities, -20 (high) to 20 (low), when using 2 or more priorities at the same time) +* `pqueue2` (slower heap implementation) +* `pqueue3` (faster than `pqueue2` and `priority_queue` when using 64 or more priorities at the same time) +* `pqueue4` (slightly slower than `pqueue` but fastest for allowing 257 priorities, -128 (high) to 128 (low), i.e., fastest when using 42 or more priorities at the same time) + +[The latest results are here](http://okeuday.livejournal.com/19539.html), with [the benchmark here](http://github.com/okeuday/erlbench). + +Author +------ + +Michael Truog (mjtruog at protonmail dot com) + +Thanks +------ + +* Jesper Louis andersen (PropEr integration and testing) +* Ulf Wiger (suggestions and insight) + +License +------- + +MIT License + diff --git a/aoc2023/build/packages/pqueue/doc/edoc-info b/aoc2023/build/packages/pqueue/doc/edoc-info new file mode 100644 index 0000000..5e5a8d3 --- /dev/null +++ b/aoc2023/build/packages/pqueue/doc/edoc-info @@ -0,0 +1,3 @@ +%% encoding: UTF-8 +{application,pqueue}. +{modules,[pqueue,pqueue2,pqueue3,pqueue4]}. diff --git a/aoc2023/build/packages/pqueue/doc/erlang.png b/aoc2023/build/packages/pqueue/doc/erlang.png Binary files differnew file mode 100644 index 0000000..987a618 --- /dev/null +++ b/aoc2023/build/packages/pqueue/doc/erlang.png diff --git a/aoc2023/build/packages/pqueue/doc/index.html b/aoc2023/build/packages/pqueue/doc/index.html new file mode 100644 index 0000000..d55b5e6 --- /dev/null +++ b/aoc2023/build/packages/pqueue/doc/index.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<title>The pqueue application</title> +</head> +<frameset cols="20%,80%"> +<frame src="modules-frame.html" name="modulesFrame" title=""> + +<frame src="overview-summary.html" name="overviewFrame" title=""> +<noframes> +<h2>This page uses frames</h2> +<p>Your browser does not accept frames. +<br>You should go to the <a href="overview-summary.html">non-frame version</a> instead. +</p> +</noframes> +</frameset> +</html>
\ No newline at end of file diff --git a/aoc2023/build/packages/pqueue/doc/modules-frame.html b/aoc2023/build/packages/pqueue/doc/modules-frame.html new file mode 100644 index 0000000..5a87cc4 --- /dev/null +++ b/aoc2023/build/packages/pqueue/doc/modules-frame.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<title>The pqueue application</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<h2 class="indextitle">Modules</h2> +<table width="100%" border="0" summary="list of modules"> +<tr><td><a href="pqueue.html" target="overviewFrame" class="module">pqueue</a></td></tr> +<tr><td><a href="pqueue2.html" target="overviewFrame" class="module">pqueue2</a></td></tr> +<tr><td><a href="pqueue3.html" target="overviewFrame" class="module">pqueue3</a></td></tr> +<tr><td><a href="pqueue4.html" target="overviewFrame" class="module">pqueue4</a></td></tr></table> +</body> +</html>
\ No newline at end of file diff --git a/aoc2023/build/packages/pqueue/doc/overview-summary.html b/aoc2023/build/packages/pqueue/doc/overview-summary.html new file mode 100644 index 0000000..e2f8906 --- /dev/null +++ b/aoc2023/build/packages/pqueue/doc/overview-summary.html @@ -0,0 +1,16 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>The pqueue application</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<h1>The pqueue application</h1> + +<hr> +<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<p><i>Generated by EDoc</i></p> +</body> +</html> diff --git a/aoc2023/build/packages/pqueue/doc/pqueue.html b/aoc2023/build/packages/pqueue/doc/pqueue.html new file mode 100644 index 0000000..40b05ac --- /dev/null +++ b/aoc2023/build/packages/pqueue/doc/pqueue.html @@ -0,0 +1,166 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Module pqueue</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<hr> + +<h1>Module pqueue</h1> +<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul> + <h3><a name="Static_Priority_Queue.">Static Priority Queue.</a></h3> + This priority queue implementation depends on a static number of priorities + (-20 (high) to 20 (low)) so that tuple access times can be exploited for + quick in/out priority queue operations. +<p>Copyright © 2011-2020 Michael Truog</p> + +<p><b>Version:</b> 2.0.1 Nov 26 2020 14:55:34 + ------------------------------------------------------------------------</p> +<p><b>Authors:</b> Michael Truog (<a href="mailto:mjtruog at protonmail dot com"><tt>mjtruog at protonmail dot com</tt></a>).</p> + +<h2><a name="description">Description</a></h2> + <h3><a name="Static_Priority_Queue.">Static Priority Queue.</a></h3> + This priority queue implementation depends on a static number of priorities + (-20 (high) to 20 (low)) so that tuple access times can be exploited for + quick in/out priority queue operations. This implementation was created to + avoid the slowness within the priority queue used by both RabbitMQ and Riak + (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +<h2><a name="types">Data Types</a></h2> + +<h3 class="typedecl"><a name="type-pqueue">pqueue()</a></h3> +<p><tt>pqueue() = {integer(), {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, <a href="queue.html#type-queue">queue:queue()</a>, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}} | {empty, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, <a href="queue.html#type-queue">queue:queue()</a>, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}, {<a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>, <a href="queue.html#type-queue">queue:queue()</a>}}</tt></p> + + +<h2><a name="index">Function Index</a></h2> +<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#in-2">in/2</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#in-3">in/3</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_empty-1">is_empty/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_queue-1">is_queue/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#join-2">join/2</a></td><td> + <h4><a name="Join_two_priority_queues.">Join two priority queues.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#len-1">len/1</a></td><td> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#new-0">new/0</a></td><td> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#out-1">out/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#out-2">out/2</a></td><td> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#pout-1">pout/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value.</td></tr> +<tr><td valign="top"><a href="#test-0">test/0</a></td><td> + <h4><a name="Regression_test.">Regression test.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#to_list-1">to_list/1</a></td><td> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N).</td></tr> +</table> + +<h2><a name="functions">Function Details</a></h2> + +<h3 class="function"><a name="in-2">in/2</a></h3> +<div class="spec"> +<p><tt>in(X::term(), Q::<a href="#type-pqueue">pqueue()</a>) -> <a href="#type-pqueue">pqueue()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="in-3">in/3</a></h3> +<div class="spec"> +<p><tt>in(X::term(), P::integer(), Q::<a href="#type-pqueue">pqueue()</a>) -> <a href="#type-pqueue">pqueue()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_empty-1">is_empty/1</a></h3> +<div class="spec"> +<p><tt>is_empty(X1::<a href="#type-pqueue">pqueue()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_queue-1">is_queue/1</a></h3> +<div class="spec"> +<p><tt>is_queue(X1::<a href="#type-pqueue">pqueue()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1)</p> + +<h3 class="function"><a name="join-2">join/2</a></h3> +<div class="spec"> +<p><tt>join(X1::<a href="#type-pqueue">pqueue()</a>, X2::<a href="#type-pqueue">pqueue()</a>) -> <a href="#type-pqueue">pqueue()</a></tt><br></p> +</div><p> + <h4><a name="Join_two_priority_queues.">Join two priority queues.</a></h4> + O(N)</p> + +<h3 class="function"><a name="len-1">len/1</a></h3> +<div class="spec"> +<p><tt>len(X1::<a href="#type-pqueue">pqueue()</a>) -> non_neg_integer()</tt><br></p> +</div><p> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(N)</p> + +<h3 class="function"><a name="new-0">new/0</a></h3> +<div class="spec"> +<p><tt>new() -> <a href="#type-pqueue">pqueue()</a></tt><br></p> +</div><p> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="out-1">out/1</a></h3> +<div class="spec"> +<p><tt>out(Q::<a href="#type-pqueue">pqueue()</a>) -> {{value, term()}, <a href="#type-pqueue">pqueue()</a>} | {empty, <a href="#type-pqueue">pqueue()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="out-2">out/2</a></h3> +<div class="spec"> +<p><tt>out(P::integer(), Q::<a href="#type-pqueue">pqueue()</a>) -> {{value, term()}, <a href="#type-pqueue">pqueue()</a>} | {empty, <a href="#type-pqueue">pqueue()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="pout-1">pout/1</a></h3> +<div class="spec"> +<p><tt>pout(Q::<a href="#type-pqueue">pqueue()</a>) -> {{value, term(), integer()}, <a href="#type-pqueue">pqueue()</a>} | {empty, <a href="#type-pqueue">pqueue()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value. + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="test-0">test/0</a></h3> +<div class="spec"> +<p><tt>test() -> any()</tt></p> +</div><p> + <h4><a name="Regression_test.">Regression test.</a></h4> +</p> + +<h3 class="function"><a name="to_list-1">to_list/1</a></h3> +<div class="spec"> +<p><tt>to_list(X1::<a href="#type-pqueue">pqueue()</a>) -> [term()]</tt><br></p> +</div><p> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N)</p> +<hr> + +<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<p><i>Generated by EDoc</i></p> +</body> +</html> diff --git a/aoc2023/build/packages/pqueue/doc/pqueue2.html b/aoc2023/build/packages/pqueue/doc/pqueue2.html new file mode 100644 index 0000000..2942b84 --- /dev/null +++ b/aoc2023/build/packages/pqueue/doc/pqueue2.html @@ -0,0 +1,143 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Module pqueue2</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<hr> + +<h1>Module pqueue2</h1> +<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul> + <h3><a name="Skew_Heap_Priority_Queue.">Skew Heap Priority Queue.</a></h3> + Ulf Wiger suggested pursuing a skew heap as an optimal Erlang priority + queue implementation. +<p>Copyright © 2011-2020 Michael Truog</p> + +<p><b>Version:</b> 2.0.1 Nov 26 2020 14:55:32 + ------------------------------------------------------------------------</p> +<p><b>Authors:</b> Michael Truog (<a href="mailto:mjtruog at protonmail dot com"><tt>mjtruog at protonmail dot com</tt></a>).</p> + +<h2><a name="description">Description</a></h2> + <h3><a name="Skew_Heap_Priority_Queue.">Skew Heap Priority Queue.</a></h3> + 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. +<h2><a name="types">Data Types</a></h2> + +<h3 class="typedecl"><a name="type-pqueue2">pqueue2()</a></h3> +<p><tt>pqueue2() = empty | {integer(), <a href="#type-pqueue2">pqueue2()</a>, <a href="#type-pqueue2">pqueue2()</a>, element, term()} | {integer(), <a href="#type-pqueue2">pqueue2()</a>, <a href="#type-pqueue2">pqueue2()</a>, queue, <a href="queue.html#type-queue">queue:queue()</a>}</tt></p> + + +<h2><a name="index">Function Index</a></h2> +<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#in-2">in/2</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#in-3">in/3</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#is_empty-1">is_empty/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#is_queue-1">is_queue/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#len-1">len/1</a></td><td> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#new-0">new/0</a></td><td> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#out-1">out/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#out-2">out/2</a></td><td> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#pout-1">pout/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value.</td></tr> +<tr><td valign="top"><a href="#test-0">test/0</a></td><td> + <h4><a name="Regression_test.">Regression test.</a></h4>.</td></tr> +<tr><td valign="top"><a href="#to_list-1">to_list/1</a></td><td> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4>.</td></tr> +</table> + +<h2><a name="functions">Function Details</a></h2> + +<h3 class="function"><a name="in-2">in/2</a></h3> +<div class="spec"> +<p><tt>in(Value::term(), H::<a href="#type-pqueue2">pqueue2()</a>) -> <a href="#type-pqueue2">pqueue2()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> +</p> + +<h3 class="function"><a name="in-3">in/3</a></h3> +<div class="spec"> +<p><tt>in(Value::term(), P::integer(), H::<a href="#type-pqueue2">pqueue2()</a>) -> <a href="#type-pqueue2">pqueue2()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> +</p> + +<h3 class="function"><a name="is_empty-1">is_empty/1</a></h3> +<div class="spec"> +<p><tt>is_empty(X1::<a href="#type-pqueue2">pqueue2()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> +</p> + +<h3 class="function"><a name="is_queue-1">is_queue/1</a></h3> +<div class="spec"> +<p><tt>is_queue(X1::<a href="#type-pqueue2">pqueue2()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> +</p> + +<h3 class="function"><a name="len-1">len/1</a></h3> +<div class="spec"> +<p><tt>len(H::<a href="#type-pqueue2">pqueue2()</a>) -> non_neg_integer()</tt><br></p> +</div><p> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> +</p> + +<h3 class="function"><a name="new-0">new/0</a></h3> +<div class="spec"> +<p><tt>new() -> <a href="#type-pqueue2">pqueue2()</a></tt><br></p> +</div><p> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> +</p> + +<h3 class="function"><a name="out-1">out/1</a></h3> +<div class="spec"> +<p><tt>out(X1::<a href="#type-pqueue2">pqueue2()</a>) -> {{value, term()}, <a href="#type-pqueue2">pqueue2()</a>} | {empty, <a href="#type-pqueue2">pqueue2()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> +</p> + +<h3 class="function"><a name="out-2">out/2</a></h3> +<div class="spec"> +<p><tt>out(P::integer(), H::<a href="#type-pqueue2">pqueue2()</a>) -> {{value, term()}, <a href="#type-pqueue2">pqueue2()</a>} | {empty, <a href="#type-pqueue2">pqueue2()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> +</p> + +<h3 class="function"><a name="pout-1">pout/1</a></h3> +<div class="spec"> +<p><tt>pout(X1::<a href="#type-pqueue2">pqueue2()</a>) -> {{value, term(), integer()}, <a href="#type-pqueue2">pqueue2()</a>} | {empty, <a href="#type-pqueue2">pqueue2()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value.</p> + +<h3 class="function"><a name="test-0">test/0</a></h3> +<div class="spec"> +<p><tt>test() -> any()</tt></p> +</div><p> + <h4><a name="Regression_test.">Regression test.</a></h4> +</p> + +<h3 class="function"><a name="to_list-1">to_list/1</a></h3> +<div class="spec"> +<p><tt>to_list(H::<a href="#type-pqueue2">pqueue2()</a>) -> [term()]</tt><br></p> +</div><p> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> +</p> +<hr> + +<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<p><i>Generated by EDoc</i></p> +</body> +</html> diff --git a/aoc2023/build/packages/pqueue/doc/pqueue3.html b/aoc2023/build/packages/pqueue/doc/pqueue3.html new file mode 100644 index 0000000..35f1a7b --- /dev/null +++ b/aoc2023/build/packages/pqueue/doc/pqueue3.html @@ -0,0 +1,162 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Module pqueue3</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<hr> + +<h1>Module pqueue3</h1> +<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul> + <h3><a name="A_Large_Priority_Queue.">A Large Priority Queue.</a></h3> + This priority queue implementation depends on layered tuples, so that tuple + access times can be exploited for quick in/out priority queue operations + when using 64 or more total priorities. +<p>Copyright © 2011-2020 Michael Truog</p> + +<p><b>Version:</b> 2.0.1 Nov 26 2020 14:55:32 + ------------------------------------------------------------------------</p> +<p><b>Authors:</b> Michael Truog (<a href="mailto:mjtruog at protonmail dot com"><tt>mjtruog at protonmail dot com</tt></a>).</p> + +<h2><a name="description">Description</a></h2> + <h3><a name="A_Large_Priority_Queue.">A Large Priority Queue.</a></h3> + This priority queue implementation depends on layered tuples, so that tuple + access times can be exploited for quick in/out priority queue operations + when using 64 or more total priorities. This implementation was created + to avoid the slowness within the priority queue used by + both RabbitMQ and Riak + (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +<h2><a name="types">Data Types</a></h2> + +<h3 class="typedecl"><a name="type-pqueue3">pqueue3()</a></h3> +<p><tt>pqueue3() = {integer(), integer(), empty | integer(), tuple()}</tt></p> + + +<h3 class="typedecl"><a name="type-pqueue3_empty">pqueue3_empty()</a></h3> +<p><tt>pqueue3_empty() = {integer(), integer(), empty, tuple()}</tt></p> + + +<h2><a name="index">Function Index</a></h2> +<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#in-2">in/2</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#in-3">in/3</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_empty-1">is_empty/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_queue-1">is_queue/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#len-1">len/1</a></td><td> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#new-0">new/0</a></td><td> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#new-1">new/1</a></td><td> + <h4><a name="Create_a_new_priority_queue_with_customization_options.">Create a new priority queue with customization options.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#out-1">out/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#out-2">out/2</a></td><td> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#pout-1">pout/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value.</td></tr> +<tr><td valign="top"><a href="#to_list-1">to_list/1</a></td><td> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N).</td></tr> +</table> + +<h2><a name="functions">Function Details</a></h2> + +<h3 class="function"><a name="in-2">in/2</a></h3> +<div class="spec"> +<p><tt>in(Value::term(), Q::<a href="#type-pqueue3">pqueue3()</a>) -> <a href="#type-pqueue3">pqueue3()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="in-3">in/3</a></h3> +<div class="spec"> +<p><tt>in(Value::term(), P::integer(), X3::<a href="#type-pqueue3">pqueue3()</a>) -> <a href="#type-pqueue3">pqueue3()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_empty-1">is_empty/1</a></h3> +<div class="spec"> +<p><tt>is_empty(Q::<a href="#type-pqueue3">pqueue3()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_queue-1">is_queue/1</a></h3> +<div class="spec"> +<p><tt>is_queue(X1::<a href="#type-pqueue3">pqueue3()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1)</p> + +<h3 class="function"><a name="len-1">len/1</a></h3> +<div class="spec"> +<p><tt>len(Q::<a href="#type-pqueue3">pqueue3()</a>) -> non_neg_integer()</tt><br></p> +</div><p> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(N)</p> + +<h3 class="function"><a name="new-0">new/0</a></h3> +<div class="spec"> +<p><tt>new() -> <a href="#type-pqueue3_empty">pqueue3_empty()</a></tt><br></p> +</div><p> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="new-1">new/1</a></h3> +<div class="spec"> +<p><tt>new(Options::[{atom(), term()}]) -> <a href="#type-pqueue3">pqueue3()</a></tt><br></p> +</div><p> + <h4><a name="Create_a_new_priority_queue_with_customization_options.">Create a new priority queue with customization options.</a></h4> + O(1)</p> + +<h3 class="function"><a name="out-1">out/1</a></h3> +<div class="spec"> +<p><tt>out(Q::<a href="#type-pqueue3">pqueue3()</a>) -> {{value, term()}, <a href="#type-pqueue3">pqueue3()</a>} | {empty, <a href="#type-pqueue3">pqueue3()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="out-2">out/2</a></h3> +<div class="spec"> +<p><tt>out(P::integer(), Q::<a href="#type-pqueue3">pqueue3()</a>) -> {{value, term()}, <a href="#type-pqueue3">pqueue3()</a>} | {empty, <a href="#type-pqueue3">pqueue3()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="pout-1">pout/1</a></h3> +<div class="spec"> +<p><tt>pout(Q::<a href="#type-pqueue3">pqueue3()</a>) -> {{value, term(), integer()}, <a href="#type-pqueue3">pqueue3()</a>} | {empty, <a href="#type-pqueue3">pqueue3()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value. + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="to_list-1">to_list/1</a></h3> +<div class="spec"> +<p><tt>to_list(Q::<a href="#type-pqueue3">pqueue3()</a>) -> [term()]</tt><br></p> +</div><p> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N)</p> +<hr> + +<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<p><i>Generated by EDoc</i></p> +</body> +</html> diff --git a/aoc2023/build/packages/pqueue/doc/pqueue4.html b/aoc2023/build/packages/pqueue/doc/pqueue4.html new file mode 100644 index 0000000..edcdb6e --- /dev/null +++ b/aoc2023/build/packages/pqueue/doc/pqueue4.html @@ -0,0 +1,205 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> +<title>Module pqueue4</title> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> +</head> +<body bgcolor="white"> +<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<hr> + +<h1>Module pqueue4</h1> +<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul> + <h3><a name="Static_Priority_Queue.">Static Priority Queue.</a></h3> + This priority queue implementation depends on a static number of priorities + (-128 (high) to 128 (low)) so that tuple access times can be exploited for + quick in/out priority queue operations. +<p>Copyright © 2011-2020 Michael Truog</p> + +<p><b>Version:</b> 2.0.1 Nov 26 2020 14:55:34 + ------------------------------------------------------------------------</p> +<p><b>Authors:</b> Michael Truog (<a href="mailto:mjtruog at protonmail dot com"><tt>mjtruog at protonmail dot com</tt></a>).</p> + +<h2><a name="description">Description</a></h2> + <h3><a name="Static_Priority_Queue.">Static Priority Queue.</a></h3> + This priority queue implementation depends on a static number of priorities + (-128 (high) to 128 (low)) so that tuple access times can be exploited for + quick in/out priority queue operations. This implementation was created to + avoid the slowness within the priority queue used by both RabbitMQ and Riak + (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +<h2><a name="types">Data Types</a></h2> + +<h3 class="typedecl"><a name="type-pqueue4">pqueue4()</a></h3> +<p><tt>pqueue4() = <a href="#type-pqueue4">pqueue4</a>(any())</tt></p> + + +<h3 class="typedecl"><a name="type-pqueue4">pqueue4()</a></h3> +<p><tt>pqueue4(T) = {<a href="#type-priority">priority()</a> | empty, non_neg_integer(), {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, <a href="queue.html#type-queue">queue:queue</a>(T), {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}, {<a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T), <a href="queue.html#type-queue">queue:queue</a>(T)}}</tt></p> + + +<h3 class="typedecl"><a name="type-priority">priority()</a></h3> +<p><tt>priority() = -128..128</tt></p> + + +<h2><a name="index">Function Index</a></h2> +<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#filter-2">filter/2</a></td><td> + <h4><a name="Filter_the_priority_queue.">Filter the priority queue.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#filter-3">filter/3</a></td><td> + <h4><a name="Filter_a_specific_priority_within_the_priority_queue.">Filter a specific priority within the priority queue.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#in-2">in/2</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#in-3">in/3</a></td><td> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_empty-1">is_empty/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#is_queue-1">is_queue/1</a></td><td> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#len-1">len/1</a></td><td> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#new-0">new/0</a></td><td> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1).</td></tr> +<tr><td valign="top"><a href="#out-1">out/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#out-2">out/2</a></td><td> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case.</td></tr> +<tr><td valign="top"><a href="#pout-1">pout/1</a></td><td> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value.</td></tr> +<tr><td valign="top"><a href="#remove_unique-2">remove_unique/2</a></td><td> + <h4><a name="Remove_a_unique_value_from_the_priority_queue_with_a_binary_predicate.">Remove a unique value from the priority queue with a binary predicate.</a></h4> + O(N) but smaller constant than filter/2.</td></tr> +<tr><td valign="top"><a href="#remove_unique-3">remove_unique/3</a></td><td> + <h4><a name="Remove_a_unique_value_in_a_specific_priority_within_the_priority_queue_with_a_binary_predicate.">Remove a unique value in a specific priority within the priority queue with a binary predicate.</a></h4> + O(N) but smaller constant than filter/3.</td></tr> +<tr><td valign="top"><a href="#to_list-1">to_list/1</a></td><td> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N).</td></tr> +<tr><td valign="top"><a href="#to_plist-1">to_plist/1</a></td><td> + <h4><a name="Convert_the_priority_queue_to_a_list_with_priorities.">Convert the priority queue to a list with priorities.</a></h4> + O(N).</td></tr> +</table> + +<h2><a name="functions">Function Details</a></h2> + +<h3 class="function"><a name="filter-2">filter/2</a></h3> +<div class="spec"> +<p><tt>filter(F::fun((any()) -> boolean()), Q::<a href="#type-pqueue4">pqueue4()</a>) -> <a href="#type-pqueue4">pqueue4()</a></tt><br></p> +</div><p> + <h4><a name="Filter_the_priority_queue.">Filter the priority queue.</a></h4> + O(N)</p> + +<h3 class="function"><a name="filter-3">filter/3</a></h3> +<div class="spec"> +<p><tt>filter(F::fun((any()) -> boolean()), P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -> <a href="#type-pqueue4">pqueue4()</a></tt><br></p> +</div><p> + <h4><a name="Filter_a_specific_priority_within_the_priority_queue.">Filter a specific priority within the priority queue.</a></h4> + O(N)</p> + +<h3 class="function"><a name="in-2">in/2</a></h3> +<div class="spec"> +<p><tt>in(X::any(), Q::<a href="#type-pqueue4">pqueue4()</a>) -> <a href="#type-pqueue4">pqueue4()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_the_0_priority_queue.">Append an item to the tail of the 0 priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="in-3">in/3</a></h3> +<div class="spec"> +<p><tt>in(X::any(), P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -> <a href="#type-pqueue4">pqueue4()</a></tt><br></p> +</div><p> + <h4><a name="Append_an_item_to_the_tail_of_a_specific_priority_queue.">Append an item to the tail of a specific priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_empty-1">is_empty/1</a></h3> +<div class="spec"> +<p><tt>is_empty(X1::<a href="#type-pqueue4">pqueue4()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_is_empty.">Check if the priority queue is empty.</a></h4> + O(1)</p> + +<h3 class="function"><a name="is_queue-1">is_queue/1</a></h3> +<div class="spec"> +<p><tt>is_queue(X1::<a href="#type-pqueue4">pqueue4()</a>) -> true | false</tt><br></p> +</div><p> + <h4><a name="Check_if_the_priority_queue_type_is_as_expected.">Check if the priority queue type is as expected.</a></h4> + O(1)</p> + +<h3 class="function"><a name="len-1">len/1</a></h3> +<div class="spec"> +<p><tt>len(X1::<a href="#type-pqueue4">pqueue4()</a>) -> non_neg_integer()</tt><br></p> +</div><p> + <h4><a name="Determine_the_length_of_a_priority_queue.">Determine the length of a priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="new-0">new/0</a></h3> +<div class="spec"> +<p><tt>new() -> <a href="#type-pqueue4">pqueue4()</a></tt><br></p> +</div><p> + <h4><a name="Create_a_new_priority_queue.">Create a new priority queue.</a></h4> + O(1)</p> + +<h3 class="function"><a name="out-1">out/1</a></h3> +<div class="spec"> +<p><tt>out(Q::<a href="#type-pqueue4">pqueue4()</a>) -> {{value, any()}, <a href="#type-pqueue4">pqueue4()</a>} | {empty, <a href="#type-pqueue4">pqueue4()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="out-2">out/2</a></h3> +<div class="spec"> +<p><tt>out(P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -> {{value, any()}, <a href="#type-pqueue4">pqueue4()</a>} | {empty, <a href="#type-pqueue4">pqueue4()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_of_a_specific_priority_from_the_head_of_the_queue.">Take an item of a specific priority from the head of the queue.</a></h4> + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="pout-1">pout/1</a></h3> +<div class="spec"> +<p><tt>pout(Q::<a href="#type-pqueue4">pqueue4()</a>) -> {{value, any(), integer()}, <a href="#type-pqueue4">pqueue4()</a>} | {empty, <a href="#type-pqueue4">pqueue4()</a>}</tt><br></p> +</div><p> + <h4><a name="Take_an_item_from_the_head_of_the_priority_queue.">Take an item from the head of the priority queue.</a></h4> + Includes the priority in the return value. + O(1) amortized, O(N) worst case</p> + +<h3 class="function"><a name="remove_unique-2">remove_unique/2</a></h3> +<div class="spec"> +<p><tt>remove_unique(F::fun((any()) -> boolean()), Q::<a href="#type-pqueue4">pqueue4()</a>) -> {boolean(), <a href="#type-pqueue4">pqueue4()</a>}</tt><br></p> +</div><p> + <h4><a name="Remove_a_unique_value_from_the_priority_queue_with_a_binary_predicate.">Remove a unique value from the priority queue with a binary predicate.</a></h4> + O(N) but smaller constant than filter/2</p> + +<h3 class="function"><a name="remove_unique-3">remove_unique/3</a></h3> +<div class="spec"> +<p><tt>remove_unique(F::fun((any()) -> boolean()), P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -> {boolean(), <a href="#type-pqueue4">pqueue4()</a>}</tt><br></p> +</div><p> + <h4><a name="Remove_a_unique_value_in_a_specific_priority_within_the_priority_queue_with_a_binary_predicate.">Remove a unique value in a specific priority within the priority queue with a binary predicate.</a></h4> + O(N) but smaller constant than filter/3</p> + +<h3 class="function"><a name="to_list-1">to_list/1</a></h3> +<div class="spec"> +<p><tt>to_list(Q::<a href="#type-pqueue4">pqueue4()</a>) -> list()</tt><br></p> +</div><p> + <h4><a name="Convert_the_priority_queue_to_a_list.">Convert the priority queue to a list.</a></h4> + O(N)</p> + +<h3 class="function"><a name="to_plist-1">to_plist/1</a></h3> +<div class="spec"> +<p><tt>to_plist(Q::<a href="#type-pqueue4">pqueue4()</a>) -> [{<a href="#type-priority">priority()</a>, list()}]</tt><br></p> +</div><p> + <h4><a name="Convert_the_priority_queue_to_a_list_with_priorities.">Convert the priority queue to a list with priorities.</a></h4> + O(N)</p> +<hr> + +<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<p><i>Generated by EDoc</i></p> +</body> +</html> diff --git a/aoc2023/build/packages/pqueue/doc/stylesheet.css b/aoc2023/build/packages/pqueue/doc/stylesheet.css new file mode 100644 index 0000000..ab170c0 --- /dev/null +++ b/aoc2023/build/packages/pqueue/doc/stylesheet.css @@ -0,0 +1,55 @@ +/* standard EDoc style sheet */ +body { + font-family: Verdana, Arial, Helvetica, sans-serif; + margin-left: .25in; + margin-right: .2in; + margin-top: 0.2in; + margin-bottom: 0.2in; + color: #000000; + background-color: #ffffff; +} +h1,h2 { + margin-left: -0.2in; +} +div.navbar { + background-color: #add8e6; + padding: 0.2em; +} +h2.indextitle { + padding: 0.4em; + background-color: #add8e6; +} +h3.function,h3.typedecl { + background-color: #add8e6; + padding-left: 1em; +} +div.spec { + margin-left: 2em; + background-color: #eeeeee; +} +a.module { + text-decoration:none +} +a.module:hover { + background-color: #eeeeee; +} +ul.definitions { + list-style-type: none; +} +ul.index { + list-style-type: none; + background-color: #eeeeee; +} + +/* + * Minor style tweaks + */ +ul { + list-style-type: square; +} +table { + border-collapse: collapse; +} +td { + padding: 3 +} diff --git a/aoc2023/build/packages/pqueue/rebar.config b/aoc2023/build/packages/pqueue/rebar.config new file mode 100644 index 0000000..f8022f0 --- /dev/null +++ b/aoc2023/build/packages/pqueue/rebar.config @@ -0,0 +1,14 @@ +%-*-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: + +{erl_opts, + [{platform_define, "^R16", 'ERLANG_OTP_VERSION_16'}, + {platform_define, "^17\.", 'ERLANG_OTP_VERSION_17'}, + {platform_define, "^18\.", 'ERLANG_OTP_VERSION_18'}, + {platform_define, "^19\.", 'ERLANG_OTP_VERSION_19'}, + {platform_define, "^20\.", 'ERLANG_OTP_VERSION_20'}, + warn_export_vars, + warn_unused_import, + %warn_missing_spec, + warnings_as_errors]}. +{edoc_opts, [{preprocess, true}]}. diff --git a/aoc2023/build/packages/pqueue/src/pqueue.app.src b/aoc2023/build/packages/pqueue/src/pqueue.app.src new file mode 100644 index 0000000..b153ad1 --- /dev/null +++ b/aoc2023/build/packages/pqueue/src/pqueue.app.src @@ -0,0 +1,10 @@ +%-*-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: + +{application, pqueue, + [{description, "Priority Queue Data Structures"}, + {vsn, "2.0.7"}, + {modules, [pqueue, pqueue2, pqueue3, pqueue4]}, + {registered, []}, + {applications, [stdlib, kernel]}]}. + diff --git a/aoc2023/build/packages/pqueue/src/pqueue.erl b/aoc2023/build/packages/pqueue/src/pqueue.erl new file mode 100644 index 0000000..2c57fa2 --- /dev/null +++ b/aoc2023/build/packages/pqueue/src/pqueue.erl @@ -0,0 +1,2246 @@ +%-*-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 +%%% ==Static Priority Queue.== +%%% This priority queue implementation depends on a static number of priorities +%%% (-20 (high) to 20 (low)) so that tuple access times can be exploited for +%%% quick in/out priority queue operations. This implementation was created to +%%% avoid the slowness within the priority queue used by both RabbitMQ and Riak +%%% (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +%%% @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(pqueue). +-author('mjtruog at protonmail dot com'). + +%% external interface +-export([in/2, % O(1) + in/3, % O(1) + is_empty/1, % O(1) + is_queue/1, % O(1) + join/2, % O(N) typically (?) + len/1, % O(N) + new/0, % O(1) + out/1, % O(1) amortized, O(N) worst case + out/2, % O(1) amortized, O(N) worst case + pout/1, % O(1) amortized, O(N) worst case + to_list/1, % O(N) + test/0]). + +%%%------------------------------------------------------------------------ +%%% External interface functions +%%%------------------------------------------------------------------------ + +-ifdef(ERLANG_OTP_VERSION_16). +-type pqueue() :: + {integer(), + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue()}, + queue(), + {queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}} | + {'empty', + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue()}, + queue(), + {queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue()}}. +-else. +-type pqueue() :: + {integer(), + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue()}, + queue:queue(), + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}} | + {'empty', + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue()}, + queue:queue(), + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}, + {queue:queue(), queue:queue(), queue:queue(), queue:queue(), + queue:queue(), queue:queue(), queue:queue()}}. +-endif. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of the 0 priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(term(), pqueue()) -> pqueue(). + +in(X, Q) -> + in(X, 0, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of a specific priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(term(), integer(), pqueue()) -> pqueue(). + +in(_, P, _) + when P < -20; P > 20 -> + erlang:exit(badarg); +in(X, P, {empty, _, _, _, _, _, _, _} = Q) -> + in_higher(P, Q, X); +in(X, P, {Pc, _, _, _, _, _, _, _} = Q) + when P < Pc -> + in_higher(P, Q, X); +in(X, P, Q) -> + in_lower(P, Q, X). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue is empty.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_empty(pqueue()) -> 'true' | 'false'. + +is_empty({empty, _, _, _, _, _, _, _}) -> + true; +is_empty({_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + queue:is_empty(Qn20) and queue:is_empty(Qn19) and queue:is_empty(Qn18) and + queue:is_empty(Qn17) and queue:is_empty(Qn16) and queue:is_empty(Qn15) and + queue:is_empty(Qn14) and + queue:is_empty(Qn13) and queue:is_empty(Qn12) and queue:is_empty(Qn11) and + queue:is_empty(Qn10) and queue:is_empty(Qn9) and queue:is_empty(Qn8) and + queue:is_empty(Qn7) and + queue:is_empty(Qn6) and queue:is_empty(Qn5) and queue:is_empty(Qn4) and + queue:is_empty(Qn3) and queue:is_empty(Qn2) and queue:is_empty(Qn1) and + queue:is_empty(Q0) and + queue:is_empty(Qp1) and queue:is_empty(Qp2) and queue:is_empty(Qp3) and + queue:is_empty(Qp4) and queue:is_empty(Qp5) and queue:is_empty(Qp6) and + queue:is_empty(Qp7) and queue:is_empty(Qp8) and queue:is_empty(Qp9) and + queue:is_empty(Qp10) and queue:is_empty(Qp11) and queue:is_empty(Qp12) and + queue:is_empty(Qp13) and + queue:is_empty(Qp14) and queue:is_empty(Qp15) and queue:is_empty(Qp16) and + queue:is_empty(Qp17) and queue:is_empty(Qp18) and queue:is_empty(Qp19) and + queue:is_empty(Qp20). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue type is as expected.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_queue(pqueue()) -> 'true' | 'false'. + +is_queue({Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) + when tuple_size(Qsn14) == 7, tuple_size(Qsn7) == 7, tuple_size(Qsn1) == 6, + tuple_size(Qsp14) == 7, tuple_size(Qsp7) == 7, tuple_size(Qsp1) == 6 -> + (((Pc =:= empty) or is_integer(Pc)) and queue:is_queue(Q0)); +is_queue(_) -> + false. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Join two priority queues.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec join(pqueue(), pqueue()) -> pqueue(). + +join({P1c, + {Q1_n20, Q1_n19, Q1_n18, Q1_n17, Q1_n16, Q1_n15, Q1_n14}, + {Q1_n13, Q1_n12, Q1_n11, Q1_n10, Q1_n9, Q1_n8, Q1_n7}, + {Q1_n6, Q1_n5, Q1_n4, Q1_n3, Q1_n2, Q1_n1}, + Q1_0, + {Q1_p1, Q1_p2, Q1_p3, Q1_p4, Q1_p5, Q1_p6}, + {Q1_p7, Q1_p8, Q1_p9, Q1_p10, Q1_p11, Q1_p12, Q1_p13}, + {Q1_p14, Q1_p15, Q1_p16, Q1_p17, Q1_p18, Q1_p19, Q1_p20}}, + {P2c, + {Q2_n20, Q2_n19, Q2_n18, Q2_n17, Q2_n16, Q2_n15, Q2_n14}, + {Q2_n13, Q2_n12, Q2_n11, Q2_n10, Q2_n9, Q2_n8, Q2_n7}, + {Q2_n6, Q2_n5, Q2_n4, Q2_n3, Q2_n2, Q2_n1}, + Q2_0, + {Q2_p1, Q2_p2, Q2_p3, Q2_p4, Q2_p5, Q2_p6}, + {Q2_p7, Q2_p8, Q2_p9, Q2_p10, Q2_p11, Q2_p12, Q2_p13}, + {Q2_p14, Q2_p15, Q2_p16, Q2_p17, Q2_p18, Q2_p19, Q2_p20}}) -> + {erlang:min(P1c, P2c), + {queue:join(Q1_n20, Q2_n20), queue:join(Q1_n19, Q2_n19), + queue:join(Q1_n18, Q2_n18), queue:join(Q1_n17, Q2_n17), + queue:join(Q1_n16, Q2_n16), queue:join(Q1_n15, Q2_n15), + queue:join(Q1_n14, Q2_n14)}, + {queue:join(Q1_n13, Q2_n13), queue:join(Q1_n12, Q2_n12), + queue:join(Q1_n11, Q2_n11), queue:join(Q1_n10, Q2_n10), + queue:join(Q1_n9, Q2_n9), queue:join(Q1_n8, Q2_n8), + queue:join(Q1_n7, Q2_n7)}, + {queue:join(Q1_n6, Q2_n6), queue:join(Q1_n5, Q2_n5), + queue:join(Q1_n4, Q2_n4), queue:join(Q1_n3, Q2_n3), + queue:join(Q1_n2, Q2_n2), queue:join(Q1_n1, Q2_n1)}, + queue:join(Q1_0, Q2_0), + {queue:join(Q1_p1, Q2_p1), queue:join(Q1_p2, Q2_p2), + queue:join(Q1_p3, Q2_p3), queue:join(Q1_p4, Q2_p4), + queue:join(Q1_p5, Q2_p5), queue:join(Q1_p6, Q2_p6)}, + {queue:join(Q1_p7, Q2_p7), queue:join(Q1_p8, Q2_p8), + queue:join(Q1_p9, Q2_p9), queue:join(Q1_p10, Q2_p10), + queue:join(Q1_p11, Q2_p11), queue:join(Q1_p12, Q2_p12), + queue:join(Q1_p13, Q2_p13)}, + {queue:join(Q1_p14, Q2_p14), queue:join(Q1_p15, Q2_p15), + queue:join(Q1_p16, Q2_p16), queue:join(Q1_p17, Q2_p17), + queue:join(Q1_p18, Q2_p18), queue:join(Q1_p19, Q2_p19), + queue:join(Q1_p20, Q2_p20)}}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Determine the length of a priority queue.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec len(pqueue()) -> non_neg_integer(). + +len({_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + queue:len(Qn20) + queue:len(Qn19) + queue:len(Qn18) + queue:len(Qn17) + + queue:len(Qn16) + queue:len(Qn15) + queue:len(Qn14) + + queue:len(Qn13) + queue:len(Qn12) + queue:len(Qn11) + queue:len(Qn10) + + queue:len(Qn9) + queue:len(Qn8) + queue:len(Qn7) + + queue:len(Qn6) + queue:len(Qn5) + queue:len(Qn4) + queue:len(Qn3) + + queue:len(Qn2) + queue:len(Qn1) + + queue:len(Q0) + + queue:len(Qp1) + queue:len(Qp2) + queue:len(Qp3) + queue:len(Qp4) + + queue:len(Qp5) + queue:len(Qp6) + + queue:len(Qp7) + queue:len(Qp8) + queue:len(Qp9) + queue:len(Qp10) + + queue:len(Qp11) + queue:len(Qp12) + queue:len(Qp13) + + queue:len(Qp14) + queue:len(Qp15) + queue:len(Qp16) + queue:len(Qp17) + + queue:len(Qp18) + queue:len(Qp19) + queue:len(Qp20). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Create a new priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec new() -> pqueue(). + +new() -> + {empty, % current priority + erlang:make_tuple(7, queue:new()), % priority [-20..-14] + erlang:make_tuple(7, queue:new()), % priority [-13.. -7] + erlang:make_tuple(6, queue:new()), % priority [ -6.. -1] + queue:new(), % priority 0 (default) + erlang:make_tuple(6, queue:new()), % priority [ 1.. 6] + erlang:make_tuple(7, queue:new()), % priority [ 7.. 13] + erlang:make_tuple(7, queue:new())}. % priority [ 14.. 20] + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(pqueue()) -> + {{'value', term()}, pqueue()} | {'empty', pqueue()}. + +out({empty, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +out({Pc, _, _, _, _, _, _, _} = Q) -> + out_current(Pc, Q, nopriority). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item of a specific priority from the head of the queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(integer(), pqueue()) -> + {{'value', term()}, pqueue()} | {'empty', pqueue()}. + +out(P, _) + when P < -20; P > 20 -> + erlang:exit(badarg); +out(_, {empty, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +out(P, Q) -> + out_specific(P, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% Includes the priority in the return value. +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec pout(pqueue()) -> + {{'value', term(), integer()}, pqueue()} | {'empty', pqueue()}. + +pout({empty, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +pout({Pc, _, _, _, _, _, _, _} = Q) -> + out_current(Pc, Q, priority). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Convert the priority queue to a list.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec to_list(pqueue()) -> list(term()). + +to_list({_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + queue:to_list(Qn20) ++ queue:to_list(Qn19) ++ queue:to_list(Qn18) ++ + queue:to_list(Qn17) ++ queue:to_list(Qn16) ++ queue:to_list(Qn15) ++ + queue:to_list(Qn14) ++ + queue:to_list(Qn13) ++ queue:to_list(Qn12) ++ queue:to_list(Qn11) ++ + queue:to_list(Qn10) ++ queue:to_list(Qn9) ++ queue:to_list(Qn8) ++ + queue:to_list(Qn7) ++ + queue:to_list(Qn6) ++ queue:to_list(Qn5) ++ queue:to_list(Qn4) ++ + queue:to_list(Qn3) ++ queue:to_list(Qn2) ++ queue:to_list(Qn1) ++ + queue:to_list(Q0) ++ + queue:to_list(Qp1) ++ queue:to_list(Qp2) ++ queue:to_list(Qp3) ++ + queue:to_list(Qp4) ++ queue:to_list(Qp5) ++ queue:to_list(Qp6) ++ + queue:to_list(Qp7) ++ queue:to_list(Qp8) ++ queue:to_list(Qp9) ++ + queue:to_list(Qp10) ++ queue:to_list(Qp11) ++ queue:to_list(Qp12) ++ + queue:to_list(Qp13) ++ + queue:to_list(Qp14) ++ queue:to_list(Qp15) ++ queue:to_list(Qp16) ++ + queue:to_list(Qp17) ++ queue:to_list(Qp18) ++ queue:to_list(Qp19) ++ + queue:to_list(Qp20). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Regression test.=== +%% @end +%%------------------------------------------------------------------------- + +test() -> + Q0 = pqueue:new(), + true = pqueue:is_queue(Q0), + Q1 = pqueue:in(20, 20, Q0), + Q2 = pqueue:in(19, 19, Q1), + Q3 = pqueue:in(18, 18, Q2), + Q4 = pqueue:in(17, 17, Q3), + Q5 = pqueue:in(16, 16, Q4), + Q6 = pqueue:in(15, 15, Q5), + Q7 = pqueue:in(14, 14, Q6), + Q8 = pqueue:in(13, 13, Q7), + Q9 = pqueue:in(12, 12, Q8), + Q10 = pqueue:in(11, 11, Q9), + Q11 = pqueue:in(10, 10, Q10), + Q12 = pqueue:in(9, 9, Q11), + Q13 = pqueue:in(8, 8, Q12), + Q14 = pqueue:in(7, 7, Q13), + Q15 = pqueue:in(6, 6, Q14), + Q16 = pqueue:in(5, 5, Q15), + Q17 = pqueue:in(4, 4, Q16), + Q18 = pqueue:in(3, 3, Q17), + Q19 = pqueue:in(2, 2, Q18), + Q20 = pqueue:in(1, 1, Q19), + Q21 = pqueue:in(0, 0, Q20), + Q22 = pqueue:in(-1, -1, Q21), + Q23 = pqueue:in(-2, -2, Q22), + Q24 = pqueue:in(-3, -3, Q23), + Q25 = pqueue:in(-4, -4, Q24), + Q26 = pqueue:in(-5, -5, Q25), + Q27 = pqueue:in(-6, -6, Q26), + Q28 = pqueue:in(-7, -7, Q27), + Q29 = pqueue:in(-8, -8, Q28), + Q30 = pqueue:in(-9, -9, Q29), + Q31 = pqueue:in(-10, -10, Q30), + Q32 = pqueue:in(-11, -11, Q31), + Q33 = pqueue:in(-12, -12, Q32), + Q34 = pqueue:in(-13, -13, Q33), + Q35 = pqueue:in(-14, -14, Q34), + Q36 = pqueue:in(-15, -15, Q35), + Q37 = pqueue:in(-16, -16, Q36), + Q38 = pqueue:in(-17, -17, Q37), + Q39 = pqueue:in(-18, -18, Q38), + Q40 = pqueue:in(-19, -19, Q39), + Q41 = pqueue:in(-20, -20, Q40), + Q42 = pqueue:in(-20, -20, Q41), + Q43 = pqueue:in(-19, -19, Q42), + Q44 = pqueue:in(-18, -18, Q43), + Q45 = pqueue:in(-17, -17, Q44), + Q46 = pqueue:in(-16, -16, Q45), + Q47 = pqueue:in(-15, -15, Q46), + Q48 = pqueue:in(-14, -14, Q47), + Q49 = pqueue:in(-13, -13, Q48), + Q50 = pqueue:in(-12, -12, Q49), + Q51 = pqueue:in(-11, -11, Q50), + Q52 = pqueue:in(-10, -10, Q51), + Q53 = pqueue:in(-9, -9, Q52), + Q54 = pqueue:in(-8, -8, Q53), + Q55 = pqueue:in(-7, -7, Q54), + Q56 = pqueue:in(-6, -6, Q55), + Q57 = pqueue:in(-5, -5, Q56), + Q58 = pqueue:in(-4, -4, Q57), + Q59 = pqueue:in(-3, -3, Q58), + Q60 = pqueue:in(-2, -2, Q59), + Q61 = pqueue:in(-1, -1, Q60), + Q62 = pqueue:in(0, 0, Q61), + Q63 = pqueue:in(1, 1, Q62), + Q64 = pqueue:in(2, 2, Q63), + Q65 = pqueue:in(3, 3, Q64), + Q66 = pqueue:in(4, 4, Q65), + Q67 = pqueue:in(5, 5, Q66), + Q68 = pqueue:in(6, 6, Q67), + Q69 = pqueue:in(7, 7, Q68), + Q70 = pqueue:in(8, 8, Q69), + Q71 = pqueue:in(9, 9, Q70), + Q72 = pqueue:in(10, 10, Q71), + Q73 = pqueue:in(11, 11, Q72), + Q74 = pqueue:in(12, 12, Q73), + Q75 = pqueue:in(13, 13, Q74), + Q76 = pqueue:in(14, 14, Q75), + Q77 = pqueue:in(15, 15, Q76), + Q78 = pqueue:in(16, 16, Q77), + Q79 = pqueue:in(17, 17, Q78), + Q80 = pqueue:in(18, 18, Q79), + Q81 = pqueue:in(19, 19, Q80), + Q82 = pqueue:in(20, 20, Q81), + true = pqueue:is_queue(Q82), + 82 = pqueue: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] = pqueue:to_list(Q82), + {{value, -20}, Q83} = pqueue:out(Q82), + {{value, -20}, Q84} = pqueue:out(Q83), + {{value, -19}, Q85} = pqueue:out(Q84), + {{value, -19}, Q86} = pqueue:out(Q85), + {{value, -18}, Q87} = pqueue:out(Q86), + {{value, -18}, Q88} = pqueue:out(Q87), + {{value, 0}, Q89} = pqueue:out(0, Q88), + {{value, 0}, Q90} = pqueue:out(0, Q89), + {empty, _} = pqueue:out(0, Q90), + {{value, -17, -17}, Q91} = pqueue:pout(Q90), + {{value, -17, -17}, Q92} = pqueue:pout(Q91), + {{value, -16, -16}, Q93} = pqueue:pout(Q92), + {{value, -16, -16}, Q94} = pqueue:pout(Q93), + {{value, -15, -15}, Q95} = pqueue:pout(Q94), + {{value, -15, -15}, Q96} = pqueue:pout(Q95), + {{value, -14, -14}, Q97} = pqueue:pout(Q96), + {{value, -14, -14}, Q98} = pqueue:pout(Q97), + {{value, -13, -13}, Q99} = pqueue:pout(Q98), + {{value, -13, -13}, Q100} = pqueue:pout(Q99), + {{value, -12, -12}, Q101} = pqueue:pout(Q100), + {{value, -12, -12}, Q102} = pqueue:pout(Q101), + {{value, -11, -11}, Q103} = pqueue:pout(Q102), + {{value, -11, -11}, Q104} = pqueue:pout(Q103), + {{value, -10, -10}, Q105} = pqueue:pout(Q104), + {{value, -10, -10}, Q106} = pqueue:pout(Q105), + {{value, -9, -9}, Q107} = pqueue:pout(Q106), + {{value, -9, -9}, Q108} = pqueue:pout(Q107), + {{value, -8, -8}, Q109} = pqueue:pout(Q108), + {{value, -8, -8}, Q110} = pqueue:pout(Q109), + {{value, -7, -7}, Q111} = pqueue:pout(Q110), + {{value, -7, -7}, Q112} = pqueue:pout(Q111), + {{value, -6, -6}, Q113} = pqueue:pout(Q112), + {{value, -6, -6}, Q114} = pqueue:pout(Q113), + {{value, -5, -5}, Q115} = pqueue:pout(Q114), + {{value, -5, -5}, Q116} = pqueue:pout(Q115), + {{value, -4, -4}, Q117} = pqueue:pout(Q116), + {{value, -4, -4}, Q118} = pqueue:pout(Q117), + {{value, -3, -3}, Q119} = pqueue:pout(Q118), + {{value, -3, -3}, Q120} = pqueue:pout(Q119), + {{value, -2, -2}, Q121} = pqueue:pout(Q120), + {{value, -2, -2}, Q122} = pqueue:pout(Q121), + {{value, -1, -1}, Q123} = pqueue:pout(Q122), + {{value, -1, -1}, Q124} = pqueue:pout(Q123), + {{value, 1, 1}, Q125} = pqueue:pout(Q124), + {{value, 1, 1}, Q126} = pqueue:pout(Q125), + {{value, 2, 2}, Q127} = pqueue:pout(Q126), + {{value, 2, 2}, Q128} = pqueue:pout(Q127), + {{value, 3, 3}, Q129} = pqueue:pout(Q128), + {{value, 3, 3}, Q130} = pqueue:pout(Q129), + {{value, 4, 4}, Q131} = pqueue:pout(Q130), + {{value, 4, 4}, Q132} = pqueue:pout(Q131), + {{value, 5, 5}, Q133} = pqueue:pout(Q132), + {{value, 5, 5}, Q134} = pqueue:pout(Q133), + {{value, 6, 6}, Q135} = pqueue:pout(Q134), + {{value, 6, 6}, Q136} = pqueue:pout(Q135), + {{value, 7, 7}, Q137} = pqueue:pout(Q136), + {{value, 7, 7}, Q138} = pqueue:pout(Q137), + {{value, 8, 8}, Q139} = pqueue:pout(Q138), + {{value, 8, 8}, Q140} = pqueue:pout(Q139), + {{value, 9, 9}, Q141} = pqueue:pout(Q140), + {{value, 9, 9}, Q142} = pqueue:pout(Q141), + {{value, 10, 10}, Q143} = pqueue:pout(Q142), + {{value, 10, 10}, Q144} = pqueue:pout(Q143), + {{value, 11, 11}, Q145} = pqueue:pout(Q144), + {{value, 11, 11}, Q146} = pqueue:pout(Q145), + {{value, 12, 12}, Q147} = pqueue:pout(Q146), + {{value, 12, 12}, Q148} = pqueue:pout(Q147), + {{value, 13, 13}, Q149} = pqueue:pout(Q148), + {{value, 13, 13}, Q150} = pqueue:pout(Q149), + {{value, 14, 14}, Q151} = pqueue:pout(Q150), + {{value, 14, 14}, Q152} = pqueue:pout(Q151), + {{value, 15, 15}, Q153} = pqueue:pout(Q152), + {{value, 15, 15}, Q154} = pqueue:pout(Q153), + {{value, 16, 16}, Q155} = pqueue:pout(Q154), + {{value, 16, 16}, Q156} = pqueue:pout(Q155), + {{value, 17, 17}, Q157} = pqueue:pout(Q156), + {{value, 17, 17}, Q158} = pqueue:pout(Q157), + {{value, 18, 18}, Q159} = pqueue:pout(Q158), + {{value, 18, 18}, Q160} = pqueue:pout(Q159), + {{value, 19, 19}, Q161} = pqueue:pout(Q160), + {{value, 19, 19}, Q162} = pqueue:pout(Q161), + {{value, 20, 20}, Q163} = pqueue:pout(Q162), + {{value, 20, 20}, Q164} = pqueue:pout(Q163), + true = pqueue:is_empty(Q164), + {empty, Q165} = pqueue:pout(Q164), + true = pqueue:is_empty(Q165), + ok. + +%%%------------------------------------------------------------------------ +%%% Private functions +%%%------------------------------------------------------------------------ + +in_higher(-20, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-20, + {queue:in(X, Qn20), Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-19, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-19, + {Qn20, queue:in(X, Qn19), Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-18, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-18, + {Qn20, Qn19, queue:in(X, Qn18), Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-17, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-17, + {Qn20, Qn19, Qn18, queue:in(X, Qn17), Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-16, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-16, + {Qn20, Qn19, Qn18, Qn17, queue:in(X, Qn16), Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-15, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-15, + {Qn20, Qn19, Qn18, Qn17, Qn16, queue:in(X, Qn15), Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-14, {_, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-14, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, queue:in(X, Qn14)}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-13, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-13, Qsn14, + {queue:in(X, Qn13), Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-12, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-12, Qsn14, + {Qn13, queue:in(X, Qn12), Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-11, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-11, Qsn14, + {Qn13, Qn12, queue:in(X, Qn11), Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-10, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-10, Qsn14, + {Qn13, Qn12, Qn11, queue:in(X, Qn10), Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-9, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-9, Qsn14, + {Qn13, Qn12, Qn11, Qn10, queue:in(X, Qn9), Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-8, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-8, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, queue:in(X, Qn8), Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-7, {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-7, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, queue:in(X, Qn7)}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-6, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-6, Qsn14, Qsn7, + {queue:in(X, Qn6), Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-5, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-5, Qsn14, Qsn7, + {Qn6, queue:in(X, Qn5), Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-4, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-4, Qsn14, Qsn7, + {Qn6, Qn5, queue:in(X, Qn4), Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-3, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-3, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, queue:in(X, Qn3), Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-2, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-2, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, queue:in(X, Qn2), Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(-1, {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {-1, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, queue:in(X, Qn1)}, + Q0, Qsp1, Qsp7, Qsp14}; +in_higher(0, {_, Qsn14, Qsn7, Qsn1, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {0, Qsn14, Qsn7, Qsn1, + queue:in(X, Q0), + Qsp1, Qsp7, Qsp14}; +in_higher(1, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {1, Qsn14, Qsn7, Qsn1, Q0, + {queue:in(X, Qp1), Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_higher(2, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {2, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, queue:in(X, Qp2), Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_higher(3, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {3, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, queue:in(X, Qp3), Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_higher(4, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {4, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, queue:in(X, Qp4), Qp5, Qp6}, + Qsp7, Qsp14}; +in_higher(5, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {5, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, queue:in(X, Qp5), Qp6}, + Qsp7, Qsp14}; +in_higher(6, {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {6, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, queue:in(X, Qp6)}, + Qsp7, Qsp14}; +in_higher(7, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {7, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {queue:in(X, Qp7), Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_higher(8, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {8, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, queue:in(X, Qp8), Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_higher(9, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {9, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, queue:in(X, Qp9), Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_higher(10, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {10, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, queue:in(X, Qp10), Qp11, Qp12, Qp13}, + Qsp14}; +in_higher(11, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {11, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, queue:in(X, Qp11), Qp12, Qp13}, + Qsp14}; +in_higher(12, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {12, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, queue:in(X, Qp12), Qp13}, + Qsp14}; +in_higher(13, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {13, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, queue:in(X, Qp13)}, + Qsp14}; +in_higher(14, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {14, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {queue:in(X, Qp14), Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}; +in_higher(15, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {15, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, queue:in(X, Qp15), Qp16, Qp17, Qp18, Qp19, Qp20}}; +in_higher(16, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {16, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, queue:in(X, Qp16), Qp17, Qp18, Qp19, Qp20}}; +in_higher(17, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {17, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, queue:in(X, Qp17), Qp18, Qp19, Qp20}}; +in_higher(18, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {18, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, queue:in(X, Qp18), Qp19, Qp20}}; +in_higher(19, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {19, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, queue:in(X, Qp19), Qp20}}; +in_higher(20, {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {20, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, queue:in(X, Qp20)}}. + +in_lower(-20, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {queue:in(X, Qn20), Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-19, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, queue:in(X, Qn19), Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-18, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, Qn19, queue:in(X, Qn18), Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-17, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, Qn19, Qn18, queue:in(X, Qn17), Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-16, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, Qn19, Qn18, Qn17, queue:in(X, Qn16), Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-15, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, queue:in(X, Qn15), Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-14, {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, queue:in(X, Qn14)}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-13, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {queue:in(X, Qn13), Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-12, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, queue:in(X, Qn12), Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-11, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, Qn12, queue:in(X, Qn11), Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-10, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, Qn12, Qn11, queue:in(X, Qn10), Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-9, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, queue:in(X, Qn9), Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-8, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, queue:in(X, Qn8), Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-7, {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, queue:in(X, Qn7)}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-6, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {queue:in(X, Qn6), Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-5, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {Qn6, queue:in(X, Qn5), Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-4, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, queue:in(X, Qn4), Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-3, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, queue:in(X, Qn3), Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-2, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, queue:in(X, Qn2), Qn1}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(-1, {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, queue:in(X, Qn1)}, + Q0, Qsp1, Qsp7, Qsp14}; +in_lower(0, {Pc, Qsn14, Qsn7, Qsn1, + Q0, Qsp1, Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, + queue:in(X, Q0), + Qsp1, Qsp7, Qsp14}; +in_lower(1, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {queue:in(X, Qp1), Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_lower(2, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, queue:in(X, Qp2), Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_lower(3, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, queue:in(X, Qp3), Qp4, Qp5, Qp6}, + Qsp7, Qsp14}; +in_lower(4, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, queue:in(X, Qp4), Qp5, Qp6}, + Qsp7, Qsp14}; +in_lower(5, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, queue:in(X, Qp5), Qp6}, + Qsp7, Qsp14}; +in_lower(6, {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, queue:in(X, Qp6)}, + Qsp7, Qsp14}; +in_lower(7, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {queue:in(X, Qp7), Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_lower(8, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, queue:in(X, Qp8), Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_lower(9, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, queue:in(X, Qp9), Qp10, Qp11, Qp12, Qp13}, + Qsp14}; +in_lower(10, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, queue:in(X, Qp10), Qp11, Qp12, Qp13}, + Qsp14}; +in_lower(11, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, queue:in(X, Qp11), Qp12, Qp13}, + Qsp14}; +in_lower(12, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, queue:in(X, Qp12), Qp13}, + Qsp14}; +in_lower(13, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, queue:in(X, Qp13)}, + Qsp14}; +in_lower(14, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {queue:in(X, Qp14), Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}; +in_lower(15, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, queue:in(X, Qp15), Qp16, Qp17, Qp18, Qp19, Qp20}}; +in_lower(16, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, queue:in(X, Qp16), Qp17, Qp18, Qp19, Qp20}}; +in_lower(17, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, queue:in(X, Qp17), Qp18, Qp19, Qp20}}; +in_lower(18, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, queue:in(X, Qp18), Qp19, Qp20}}; +in_lower(19, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, queue:in(X, Qp19), Qp20}}; +in_lower(20, {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}, X) -> + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, queue:in(X, Qp20)}}. + +out_current(-20, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn20} = queue:out(Qn20), + if + Value =:= empty -> + out_current(-19, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -20}; + true -> + Value + end, + {NewValue, + {-20, + {NewQn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-19, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn19} = queue:out(Qn19), + if + Value =:= empty -> + out_current(-18, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -19}; + true -> + Value + end, + {NewValue, + {-19, + {Qn20, NewQn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-18, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn18} = queue:out(Qn18), + if + Value =:= empty -> + out_current(-17, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -18}; + true -> + Value + end, + {NewValue, + {-18, + {Qn20, Qn19, NewQn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-17, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn17} = queue:out(Qn17), + if + Value =:= empty -> + out_current(-16, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -17}; + true -> + Value + end, + {NewValue, + {-17, + {Qn20, Qn19, Qn18, NewQn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-16, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn16} = queue:out(Qn16), + if + Value =:= empty -> + out_current(-15, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -16}; + true -> + Value + end, + {NewValue, + {-16, + {Qn20, Qn19, Qn18, Qn17, NewQn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-15, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn15} = queue:out(Qn15), + if + Value =:= empty -> + out_current(-14, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -15}; + true -> + Value + end, + {NewValue, + {-15, + {Qn20, Qn19, Qn18, Qn17, Qn16, NewQn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-14, + {_, {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn14} = queue:out(Qn14), + if + Value =:= empty -> + out_current(-13, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -14}; + true -> + Value + end, + {NewValue, + {-14, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, NewQn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-13, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn13} = queue:out(Qn13), + if + Value =:= empty -> + out_current(-12, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -13}; + true -> + Value + end, + {NewValue, + {-13, Qsn14, + {NewQn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-12, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn12} = queue:out(Qn12), + if + Value =:= empty -> + out_current(-11, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -12}; + true -> + Value + end, + {NewValue, + {-12, Qsn14, + {Qn13, NewQn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-11, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn11} = queue:out(Qn11), + if + Value =:= empty -> + out_current(-10, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -11}; + true -> + Value + end, + {NewValue, + {-11, Qsn14, + {Qn13, Qn12, NewQn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-10, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn10} = queue:out(Qn10), + if + Value =:= empty -> + out_current(-9, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -10}; + true -> + Value + end, + {NewValue, + {-10, Qsn14, + {Qn13, Qn12, Qn11, NewQn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-9, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn9} = queue:out(Qn9), + if + Value =:= empty -> + out_current(-8, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -9}; + true -> + Value + end, + {NewValue, + {-9, Qsn14, + {Qn13, Qn12, Qn11, Qn10, NewQn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-8, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn8} = queue:out(Qn8), + if + Value =:= empty -> + out_current(-7, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -8}; + true -> + Value + end, + {NewValue, + {-8, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, NewQn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-7, + {_, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn7} = queue:out(Qn7), + if + Value =:= empty -> + out_current(-6, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -7}; + true -> + Value + end, + {NewValue, + {-7, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, NewQn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-6, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn6} = queue:out(Qn6), + if + Value =:= empty -> + out_current(-5, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -6}; + true -> + Value + end, + {NewValue, + {-6, Qsn14, Qsn7, + {NewQn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-5, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn5} = queue:out(Qn5), + if + Value =:= empty -> + out_current(-4, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -5}; + true -> + Value + end, + {NewValue, + {-5, Qsn14, Qsn7, + {Qn6, NewQn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-4, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn4} = queue:out(Qn4), + if + Value =:= empty -> + out_current(-3, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -4}; + true -> + Value + end, + {NewValue, + {-4, Qsn14, Qsn7, + {Qn6, Qn5, NewQn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-3, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn3} = queue:out(Qn3), + if + Value =:= empty -> + out_current(-2, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -3}; + true -> + Value + end, + {NewValue, + {-3, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, NewQn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-2, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn2} = queue:out(Qn2), + if + Value =:= empty -> + out_current(-1, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -2}; + true -> + Value + end, + {NewValue, + {-2, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, NewQn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(-1, + {_, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQn1} = queue:out(Qn1), + if + Value =:= empty -> + out_current(0, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, -1}; + true -> + Value + end, + {NewValue, + {-1, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, NewQn1}, + Q0, Qsp1, Qsp7, Qsp14}} + end; +out_current(0, + {_, Qsn14, Qsn7, Qsn1, + Q0, Qsp1, Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQ0} = queue:out(Q0), + if + Value =:= empty -> + out_current(1, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 0}; + true -> + Value + end, + {NewValue, + {0, Qsn14, Qsn7, Qsn1, + NewQ0, + Qsp1, Qsp7, Qsp14}} + end; +out_current(1, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp1} = queue:out(Qp1), + if + Value =:= empty -> + out_current(2, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 1}; + true -> + Value + end, + {NewValue, + {1, Qsn14, Qsn7, Qsn1, Q0, + {NewQp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}} + end; +out_current(2, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp2} = queue:out(Qp2), + if + Value =:= empty -> + out_current(3, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 2}; + true -> + Value + end, + {NewValue, + {2, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, NewQp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}} + end; +out_current(3, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp3} = queue:out(Qp3), + if + Value =:= empty -> + out_current(4, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 3}; + true -> + Value + end, + {NewValue, + {3, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, NewQp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}} + end; +out_current(4, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp4} = queue:out(Qp4), + if + Value =:= empty -> + out_current(5, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 4}; + true -> + Value + end, + {NewValue, + {4, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, NewQp4, Qp5, Qp6}, + Qsp7, Qsp14}} + end; +out_current(5, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp5} = queue:out(Qp5), + if + Value =:= empty -> + out_current(6, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 5}; + true -> + Value + end, + {NewValue, + {5, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, NewQp5, Qp6}, + Qsp7, Qsp14}} + end; +out_current(6, + {_, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14} = Q, ReturnType) -> + {Value, NewQp6} = queue:out(Qp6), + if + Value =:= empty -> + out_current(7, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 6}; + true -> + Value + end, + {NewValue, + {6, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, NewQp6}, + Qsp7, Qsp14}} + end; +out_current(7, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp7} = queue:out(Qp7), + if + Value =:= empty -> + out_current(8, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 7}; + true -> + Value + end, + {NewValue, + {7, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {NewQp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}} + end; +out_current(8, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp8} = queue:out(Qp8), + if + Value =:= empty -> + out_current(9, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 8}; + true -> + Value + end, + {NewValue, + {8, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, NewQp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}} + end; +out_current(9, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp9} = queue:out(Qp9), + if + Value =:= empty -> + out_current(10, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 9}; + true -> + Value + end, + {NewValue, + {9, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, NewQp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}} + end; +out_current(10, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp10} = queue:out(Qp10), + if + Value =:= empty -> + out_current(11, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 10}; + true -> + Value + end, + {NewValue, + {10, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, NewQp10, Qp11, Qp12, Qp13}, + Qsp14}} + end; +out_current(11, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp11} = queue:out(Qp11), + if + Value =:= empty -> + out_current(12, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 11}; + true -> + Value + end, + {NewValue, + {11, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, NewQp11, Qp12, Qp13}, + Qsp14}} + end; +out_current(12, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp12} = queue:out(Qp12), + if + Value =:= empty -> + out_current(13, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 12}; + true -> + Value + end, + {NewValue, + {12, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, NewQp12, Qp13}, + Qsp14}} + end; +out_current(13, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14} = Q, ReturnType) -> + {Value, NewQp13} = queue:out(Qp13), + if + Value =:= empty -> + out_current(14, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 13}; + true -> + Value + end, + {NewValue, + {13, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, NewQp13}, + Qsp14}} + end; +out_current(14, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp14} = queue:out(Qp14), + if + Value =:= empty -> + out_current(15, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 14}; + true -> + Value + end, + {NewValue, + {14, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {NewQp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}} + end; +out_current(15, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp15} = queue:out(Qp15), + if + Value =:= empty -> + out_current(16, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 15}; + true -> + Value + end, + {NewValue, + {15, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, NewQp15, Qp16, Qp17, Qp18, Qp19, Qp20}}} + end; +out_current(16, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp16} = queue:out(Qp16), + if + Value =:= empty -> + out_current(17, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 16}; + true -> + Value + end, + {NewValue, + {16, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, NewQp16, Qp17, Qp18, Qp19, Qp20}}} + end; +out_current(17, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp17} = queue:out(Qp17), + if + Value =:= empty -> + out_current(18, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 17}; + true -> + Value + end, + {NewValue, + {17, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, NewQp17, Qp18, Qp19, Qp20}}} + end; +out_current(18, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp18} = queue:out(Qp18), + if + Value =:= empty -> + out_current(19, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 18}; + true -> + Value + end, + {NewValue, + {18, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, NewQp18, Qp19, Qp20}}} + end; +out_current(19, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}} = Q, ReturnType) -> + {Value, NewQp19} = queue:out(Qp19), + if + Value =:= empty -> + out_current(20, Q, ReturnType); + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 19}; + true -> + Value + end, + {NewValue, + {19, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, NewQp19, Qp20}}} + end; +out_current(20, + {_, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20} = Qsp14}, ReturnType) -> + {Value, NewQp20} = queue:out(Qp20), + if + Value =:= empty -> + {empty, {empty, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; + true -> + NewValue = if + ReturnType =:= priority -> + {value, Contents} = Value, + {value, Contents, 20}; + true -> + Value + end, + {NewValue, + {20, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, NewQp20}}} + end. + +out_specific(-20, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn20} = queue:out(Qn20), + {Value, + {Pc, + {NewQn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-19, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn19} = queue:out(Qn19), + {Value, + {Pc, + {Qn20, NewQn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-18, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn18} = queue:out(Qn18), + {Value, + {Pc, + {Qn20, Qn19, NewQn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-17, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn17} = queue:out(Qn17), + {Value, + {Pc, + {Qn20, Qn19, Qn18, NewQn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-16, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn16} = queue:out(Qn16), + {Value, + {Pc, + {Qn20, Qn19, Qn18, Qn17, NewQn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-15, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn15} = queue:out(Qn15), + {Value, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, NewQn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-14, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, Qn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn14} = queue:out(Qn14), + {Value, + {Pc, + {Qn20, Qn19, Qn18, Qn17, Qn16, Qn15, NewQn14}, + Qsn7, Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-13, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn13} = queue:out(Qn13), + {Value, + {Pc, Qsn14, + {NewQn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-12, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn12} = queue:out(Qn12), + {Value, + {Pc, Qsn14, + {Qn13, NewQn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-11, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn11} = queue:out(Qn11), + {Value, + {Pc, Qsn14, + {Qn13, Qn12, NewQn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-10, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn10} = queue:out(Qn10), + {Value, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, NewQn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-9, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn9} = queue:out(Qn9), + {Value, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, NewQn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-8, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn8} = queue:out(Qn8), + {Value, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, NewQn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-7, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, Qn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn7} = queue:out(Qn7), + {Value, + {Pc, Qsn14, + {Qn13, Qn12, Qn11, Qn10, Qn9, Qn8, NewQn7}, + Qsn1, Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-6, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn6} = queue:out(Qn6), + {Value, + {Pc, Qsn14, Qsn7, + {NewQn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-5, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn5} = queue:out(Qn5), + {Value, + {Pc, Qsn14, Qsn7, + {Qn6, NewQn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-4, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn4} = queue:out(Qn4), + {Value, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, NewQn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-3, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn3} = queue:out(Qn3), + {Value, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, NewQn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-2, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn2} = queue:out(Qn2), + {Value, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, NewQn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(-1, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQn1} = queue:out(Qn1), + {Value, + {Pc, Qsn14, Qsn7, + {Qn6, Qn5, Qn4, Qn3, Qn2, NewQn1}, + Q0, Qsp1, Qsp7, Qsp14}}; +out_specific(0, + {Pc, Qsn14, Qsn7, Qsn1, + Q0, Qsp1, Qsp7, Qsp14}) -> + {Value, NewQ0} = queue:out(Q0), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, + NewQ0, + Qsp1, Qsp7, Qsp14}}; +out_specific(1, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp1} = queue:out(Qp1), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {NewQp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}}; +out_specific(2, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp2} = queue:out(Qp2), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, NewQp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}}; +out_specific(3, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp3} = queue:out(Qp3), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, NewQp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}}; +out_specific(4, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp4} = queue:out(Qp4), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, NewQp4, Qp5, Qp6}, + Qsp7, Qsp14}}; +out_specific(5, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp5} = queue:out(Qp5), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, NewQp5, Qp6}, + Qsp7, Qsp14}}; +out_specific(6, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6}, + Qsp7, Qsp14}) -> + {Value, NewQp6} = queue:out(Qp6), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, NewQp6}, + Qsp7, Qsp14}}; +out_specific(7, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp7} = queue:out(Qp7), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {NewQp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}}; +out_specific(8, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp8} = queue:out(Qp8), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, NewQp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}}; +out_specific(9, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp9} = queue:out(Qp9), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, NewQp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}}; +out_specific(10, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp10} = queue:out(Qp10), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, NewQp10, Qp11, Qp12, Qp13}, + Qsp14}}; +out_specific(11, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp11} = queue:out(Qp11), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, NewQp11, Qp12, Qp13}, + Qsp14}}; +out_specific(12, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp12} = queue:out(Qp12), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, NewQp12, Qp13}, + Qsp14}}; +out_specific(13, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, Qp13}, + Qsp14}) -> + {Value, NewQp13} = queue:out(Qp13), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, + {Qp7, Qp8, Qp9, Qp10, Qp11, Qp12, NewQp13}, + Qsp14}}; +out_specific(14, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp14} = queue:out(Qp14), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {NewQp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}}; +out_specific(15, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp15} = queue:out(Qp15), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, NewQp15, Qp16, Qp17, Qp18, Qp19, Qp20}}}; +out_specific(16, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp16} = queue:out(Qp16), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, NewQp16, Qp17, Qp18, Qp19, Qp20}}}; +out_specific(17, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp17} = queue:out(Qp17), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, NewQp17, Qp18, Qp19, Qp20}}}; +out_specific(18, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp18} = queue:out(Qp18), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, NewQp18, Qp19, Qp20}}}; +out_specific(19, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp19} = queue:out(Qp19), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, NewQp19, Qp20}}}; +out_specific(20, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, Qp20}}) -> + {Value, NewQp20} = queue:out(Qp20), + {Value, + {Pc, Qsn14, Qsn7, Qsn1, Q0, Qsp1, Qsp7, + {Qp14, Qp15, Qp16, Qp17, Qp18, Qp19, NewQp20}}}. + +-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_pq())} + ], ?CLOUDI_LONG_TEST_TIMEOUT). + +-endif. + diff --git a/aoc2023/build/packages/pqueue/src/pqueue2.erl b/aoc2023/build/packages/pqueue/src/pqueue2.erl new file mode 100644 index 0000000..bbdeaaf --- /dev/null +++ b/aoc2023/build/packages/pqueue/src/pqueue2.erl @@ -0,0 +1,483 @@ +%-*-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. + diff --git a/aoc2023/build/packages/pqueue/src/pqueue3.erl b/aoc2023/build/packages/pqueue/src/pqueue3.erl new file mode 100644 index 0000000..03b370a --- /dev/null +++ b/aoc2023/build/packages/pqueue/src/pqueue3.erl @@ -0,0 +1,404 @@ +%-*-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 +%%% ==A Large Priority Queue.== +%%% This priority queue implementation depends on layered tuples, so that tuple +%%% access times can be exploited for quick in/out priority queue operations +%%% when using 64 or more total priorities. This implementation was created +%%% to avoid the slowness within the priority queue used by +%%% both RabbitMQ and Riak +%%% (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +%%% @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(pqueue3). +-author('mjtruog at protonmail dot com'). + +%% external interface +-export([in/2, % O(1) + in/3, % O(1) + is_empty/1, % O(1) + is_queue/1, % O(1) + len/1, % O(N) + new/0, % O(1) + new/1, % O(1) + out/1, % O(1) amortized, O(N) worst case + out/2, % O(1) amortized, O(N) worst case + pout/1, % O(1) amortized, O(N) worst case + to_list/1]). % O(N) + +%%%------------------------------------------------------------------------ +%%% External interface functions +%%%------------------------------------------------------------------------ + +-type pqueue3() :: {integer(), integer(), empty | integer(), tuple()}. +-type pqueue3_empty() :: {integer(), integer(), empty, tuple()}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of the 0 priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(term(), pqueue3()) -> pqueue3(). + +in(Value, Q) -> + in(Value, 0, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of a specific priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(term(), integer(), pqueue3()) -> pqueue3(). + +in(_, P, {Size, Offset, _, _}) + when (P + Offset) < 0; (P + Offset) > Size -> + erlang:exit(badarg); +in(Value, P, {Size, Offset, empty, Bins}) -> + PriorityIndex = P + Offset, + {Size, Offset, PriorityIndex, + in_queue(layer_indexes(Size, PriorityIndex), Value, Bins)}; +in(Value, P, {Size, Offset, I, Bins}) + when (P + Offset) < I -> + PriorityIndex = P + Offset, + {Size, Offset, PriorityIndex, + in_queue(layer_indexes(Size, PriorityIndex), Value, Bins)}; +in(Value, P, {Size, Offset, I, Bins}) -> + {Size, Offset, I, + in_queue(layer_indexes(Size, P + Offset), Value, Bins)}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue is empty.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_empty(pqueue3()) -> 'true' | 'false'. + +is_empty({_, _, empty, _}) -> + true; +is_empty({_, _, _, _} = Q) -> + case out(Q) of + {empty, _} -> + true; + {{value, _}, _} -> + false + end. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue type is as expected.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_queue(pqueue3()) -> 'true' | 'false'. + +is_queue({Size, Offset, I, Bins}) + when is_integer(Size), is_integer(Offset), is_tuple(Bins) -> + (I =:= empty) or is_integer(I); +is_queue(_) -> + false. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Determine the length of a priority queue.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec len(pqueue3()) -> non_neg_integer(). + +len(Q) -> + len(0, out(Q)). +len(I, {empty, _}) -> + I; +len(I, {{value, _}, Q}) -> + len(I + 1, out(Q)). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Create a new priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec new() -> pqueue3_empty(). + +new() -> + new([]). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Create a new priority queue with customization options.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec new(list({atom(), term()})) -> pqueue3(). + +new(Options) -> + Size = proplists:get_value(priorities, Options, 256), + MiddleZero = proplists:get_value(middle_priority_zero, Options, true), + Offset = if + MiddleZero =:= true -> + erlang:round((Size / 2) + 0.5) - 1; + true -> + 0 + end, + {Size, Offset, empty, create(layer_sizes(Size))}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(pqueue3()) -> + {{'value', term()}, pqueue3()} | {'empty', pqueue3()}. + +out({_, _, empty, _} = Q) -> + {empty, Q}; +out({Size, Offset, I, Bins}) -> + {Result, NewI, NewBins} = out_check( + I, Size, out_queue(layer_indexes(Size, I), Bins) + ), + {Result, {Size, Offset, NewI, NewBins}}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item of a specific priority from the head of the queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(integer(), pqueue3()) -> + {{'value', term()}, pqueue3()} | {'empty', pqueue3()}. + +out(P, {Size, Offset, _, _}) + when (P + Offset) < 0; (P + Offset) > Size -> + erlang:exit(badarg); +out(_, {_, _, empty, _} = Q) -> + {empty, Q}; +out(P, {Size, Offset, I, Bins}) -> + {Result, NewBins} = out_queue(layer_indexes(Size, P + Offset), Bins), + {Result, {Size, Offset, I, NewBins}}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% Includes the priority in the return value. +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec pout(pqueue3()) -> + {{'value', term(), integer()}, pqueue3()} | {'empty', pqueue3()}. + +pout({_, _, empty, _} = Q) -> + {empty, Q}; +pout({Size, Offset, I, Bins}) -> + {Result, NewI, NewBins} = pout_check( + I, Size, Offset, out_queue(layer_indexes(Size, I), Bins) + ), + {Result, {Size, Offset, NewI, NewBins}}. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Convert the priority queue to a list.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec to_list(pqueue3()) -> list(term()). + +to_list(Q) -> + to_list([], out(Q)). +to_list(L, {empty, _}) -> + lists:reverse(L); +to_list(L, {{value, Value}, Q}) -> + to_list([Value | L], out(Q)). + +%%%------------------------------------------------------------------------ +%%% Private functions +%%%------------------------------------------------------------------------ + +create([]) -> + queue:new(); + +create([I | Is]) -> + erlang:make_tuple(I + 1, create(Is)). + +in_queue({I1}, Value, Bins1) -> + erlang:setelement(I1, Bins1, queue:in(Value, erlang:element(I1, Bins1))); + +in_queue({I1, I2}, Value, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, queue:in(Value, erlang:element(I2, Bins2)))); + +in_queue({I1, I2, I3}, Value, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + Bins3 = erlang:element(I2, Bins2), + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, + erlang:setelement(I3, Bins3, queue:in(Value, erlang:element(I3, Bins3))))); + +in_queue({I1, I2, I3, I4}, Value, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + Bins3 = erlang:element(I2, Bins2), + Bins4 = erlang:element(I3, Bins3), + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, + erlang:setelement(I3, Bins3, + erlang:setelement(I4, Bins4, queue:in(Value, erlang:element(I4, Bins4)))))). + +pout_check(Size, Size, _, {empty, Bins}) -> + {empty, empty, Bins}; +pout_check(I, _, Offset, {{value, Value}, Bins}) -> + {{value, Value, I - Offset}, I, Bins}; +pout_check(I, Size, Offset, {empty, Bins}) -> + NewI = I + 1, + pout_check(NewI, Size, Offset, out_queue(layer_indexes(Size, NewI), Bins)). + +out_check(Size, Size, {empty, Bins}) -> + {empty, empty, Bins}; +out_check(I, _, {{value, _} = Result, Bins}) -> + {Result, I, Bins}; +out_check(I, Size, {empty, Bins}) -> + NewI = I + 1, + out_check(NewI, Size, out_queue(layer_indexes(Size, NewI), Bins)). + +out_queue({I1}, Bins1) -> + {Result, NewQueue} = queue:out(erlang:element(I1, Bins1)), + {Result, + erlang:setelement(I1, Bins1, NewQueue)}; + +out_queue({I1, I2}, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + {Result, NewQueue} = queue:out(erlang:element(I2, Bins2)), + {Result, + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, NewQueue))}; + +out_queue({I1, I2, I3}, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + Bins3 = erlang:element(I2, Bins2), + {Result, NewQueue} = queue:out(erlang:element(I3, Bins3)), + {Result, + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, + erlang:setelement(I3, Bins3, NewQueue)))}; + +out_queue({I1, I2, I3, I4}, Bins1) -> + Bins2 = erlang:element(I1, Bins1), + Bins3 = erlang:element(I2, Bins2), + Bins4 = erlang:element(I3, Bins3), + {Result, NewQueue} = queue:out(erlang:element(I4, Bins4)), + {Result, + erlang:setelement(I1, Bins1, + erlang:setelement(I2, Bins2, + erlang:setelement(I3, Bins3, + erlang:setelement(I4, Bins4, NewQueue))))}. + +layer_indexes(Size, PriorityIndex) -> + if + Size =< 127 -> + {PriorityIndex + 1}; + Size =< 255 -> + <<I1:4, I2:4>> = <<PriorityIndex:8>>, + {I1 + 1, I2 + 1}; + Size =< 511 -> + <<I1:4, I2:5>> = <<PriorityIndex:9>>, + {I1 + 1, I2 + 1}; + Size =< 1023 -> + <<I1:3, I2:3, I3:4>> = <<PriorityIndex:10>>, + {I1 + 1, I2 + 1, I3 + 1}; + Size =< 2047 -> + <<I1:3, I2:4, I3:4>> = <<PriorityIndex:11>>, + {I1 + 1, I2 + 1, I3 + 1}; + Size =< 4095 -> + <<I1:4, I2:4, I3:4>> = <<PriorityIndex:12>>, + {I1 + 1, I2 + 1, I3 + 1}; + Size =< 8191 -> + <<I1:4, I2:4, I3:5>> = <<PriorityIndex:13>>, + {I1 + 1, I2 + 1, I3 + 1}; + Size =< 16383 -> + <<I1:4, I2:5, I3:5>> = <<PriorityIndex:14>>, + {I1 + 1, I2 + 1, I3 + 1}; + Size =< 32767 -> + <<I1:3, I2:4, I3:4, I4:4>> = <<PriorityIndex:15>>, + {I1 + 1, I2 + 1, I3 + 1, I4 + 1}; + Size =< 65535 -> + <<I1:4, I2:4, I3:4, I4:4>> = <<PriorityIndex:16>>, + {I1 + 1, I2 + 1, I3 + 1, I4 + 1} + end. + +layer_sizes(Size) -> + if + Size =< 127 -> + <<I1:7>> = <<127:7>>, + [I1]; + Size =< 255 -> + <<I1:4, I2:4>> = <<255:8>>, + [I1, I2]; + Size =< 511 -> + <<I1:4, I2:5>> = <<511:9>>, + [I1, I2]; + Size =< 1023 -> + <<I1:3, I2:3, I3:4>> = <<1023:10>>, + [I1, I2, I3]; + Size =< 2047 -> + <<I1:3, I2:4, I3:4>> = <<2047:11>>, + [I1, I2, I3]; + Size =< 4095 -> + <<I1:4, I2:4, I3:4>> = <<4095:12>>, + [I1, I2, I3]; + Size =< 8191 -> + <<I1:4, I2:4, I3:5>> = <<8191:13>>, + [I1, I2, I3]; + Size =< 16383 -> + <<I1:4, I2:5, I3:5>> = <<16383:14>>, + [I1, I2, I3]; + Size =< 32767 -> + <<I1:3, I2:4, I3:4, I4:4>> = <<32767:15>>, + [I1, I2, I3, I4]; + Size =< 65535 -> + <<I1:4, I2:4, I3:4, I4:4>> = <<65535:16>>, + [I1, I2, I3, I4] + end. + diff --git a/aoc2023/build/packages/pqueue/src/pqueue4.erl b/aoc2023/build/packages/pqueue/src/pqueue4.erl new file mode 100644 index 0000000..30b188d --- /dev/null +++ b/aoc2023/build/packages/pqueue/src/pqueue4.erl @@ -0,0 +1,11662 @@ +%-*-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 +%%% ==Static Priority Queue.== +%%% This priority queue implementation depends on a static number of priorities +%%% (-128 (high) to 128 (low)) so that tuple access times can be exploited for +%%% quick in/out priority queue operations. This implementation was created to +%%% avoid the slowness within the priority queue used by both RabbitMQ and Riak +%%% (https://github.com/basho/riak_core/blob/master/src/priority_queue.erl). +%%% @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. +%%% +%%% +%%% queue_remove_unique/2 is based on queue:filter/2 +%%% which is under the Apache License 2.0: +%%% +%%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%%% +%%% Licensed under the Apache License, Version 2.0 (the "License"); +%%% you may not use this file except in compliance with the License. +%%% You may obtain a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, software +%%% distributed under the License is distributed on an "AS IS" BASIS, +%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%%% See the License for the specific language governing permissions and +%%% limitations under the License. +%%% +%%% @author Michael Truog <mjtruog at protonmail dot com> +%%% @copyright 2011-2020 Michael Truog +%%% @version 2.0.1 {@date} {@time} +%%%------------------------------------------------------------------------ + +-module(pqueue4). +-author('mjtruog at protonmail dot com'). + +%% external interface +-export([filter/2, % O(N) + filter/3, % O(N) + in/2, % O(1) + in/3, % O(1) + is_empty/1, % O(1) + is_queue/1, % O(1) + len/1, % O(1) + new/0, % O(1) + out/1, % O(1) amortized, O(N) worst case + out/2, % O(1) amortized, O(N) worst case + pout/1, % O(1) amortized, O(N) worst case + remove_unique/2, % O(N) but smaller constant than filter/2 + remove_unique/3, % O(N) but smaller constant than filter/3 + to_list/1, % O(N) + to_plist/1, % O(N) + test/0]). + +%%%------------------------------------------------------------------------ +%%% External interface functions +%%%------------------------------------------------------------------------ + +-type priority() :: -128..128. +-ifdef(ERLANG_OTP_VERSION_16). +-type pqueue4(_) :: + {priority() | 'empty', % current priority + non_neg_integer(), % total size + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + queue(), + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}, + {queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue(), + queue(), queue(), queue(), queue(), queue(), queue(), queue(), queue()}}. +-else. +-type pqueue4(T) :: + {priority() | 'empty', % current priority + non_neg_integer(), % total size + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + queue:queue(T), + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}, + {queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T), + queue:queue(T), queue:queue(T), queue:queue(T), queue:queue(T)}}. +-endif. +-type pqueue4() :: pqueue4(any()). +-export_type([pqueue4/0, pqueue4/1]). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Filter the priority queue.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec filter(fun((any()) -> boolean()), pqueue4()) -> pqueue4(). + +filter(F, {empty, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) + when is_function(F, 1) -> + Q; +filter(F, {Pc, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) + when is_function(F, 1) -> + filter_all(Pc, F, Q). + +filter_all(_, _, {_, 0, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _} = Q) -> + Q; +filter_all(128, F, Q) -> + filter_priority(128, F, Q); +filter_all(P, F, Q) when is_integer(P) -> + filter_all(P + 1, F, filter_priority(P, F, Q)). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Filter a specific priority within the priority queue.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec filter(fun((any()) -> boolean()), integer(), pqueue4()) -> pqueue4(). + +filter(_, P, _) + when P < -128; P > 128 -> + erlang:exit(badarg); +filter(F, P, Q) when is_function(F, 1) -> + filter_priority(P, F, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of the 0 priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(any(), pqueue4()) -> pqueue4(). + +in(X, Q) -> + in(X, 0, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Append an item to the tail of a specific priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec in(any(), integer(), pqueue4()) -> pqueue4(). + +in(_, P, _) + when P < -128; P > 128 -> + erlang:exit(badarg); +in(X, P, {empty, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + in_higher(P, Q, X); % (in a higher priority) +in(X, P, {Pc, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) + when P < Pc -> + in_higher(P, Q, X); % (in a higher priority) +in(X, P, Q) -> + in_lower(P, Q, X). % (in a lower priority) + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue is empty.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_empty(pqueue4()) -> 'true' | 'false'. + +is_empty({_, 0, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> + true; +is_empty({_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> + false. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Check if the priority queue type is as expected.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec is_queue(pqueue4()) -> 'true' | 'false'. + +is_queue({Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) + when is_integer(Size), + tuple_size(Qn128) == 16, tuple_size(Qn112) == 16, + tuple_size(Qn96) == 16, tuple_size(Qn80) == 16, + tuple_size(Qn64) == 16, tuple_size(Qn48) == 16, + tuple_size(Qn32) == 16, tuple_size(Qn16) == 16, + tuple_size(Qp16) == 16, tuple_size(Qp32) == 16, + tuple_size(Qp48) == 16, tuple_size(Qp64) == 16, + tuple_size(Qp80) == 16, tuple_size(Qp96) == 16, + tuple_size(Qp112) == 16, tuple_size(Qp128) == 16 -> + (((Pc =:= empty) or is_integer(Pc)) and queue:is_queue(Q0)); +is_queue(_) -> + false. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Determine the length of a priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec len(pqueue4()) -> non_neg_integer(). + +len({_, Size, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _}) -> + Size. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Create a new priority queue.=== +%% O(1) +%% @end +%%------------------------------------------------------------------------- + +-spec new() -> pqueue4(). + +new() -> + {empty, % current priority + 0, % current size + erlang:make_tuple(16, queue:new()), % priority [-128..-113] + erlang:make_tuple(16, queue:new()), % priority [-112.. -97] + erlang:make_tuple(16, queue:new()), % priority [ -96.. -81] + erlang:make_tuple(16, queue:new()), % priority [ -80.. -65] + erlang:make_tuple(16, queue:new()), % priority [ -64.. -49] + erlang:make_tuple(16, queue:new()), % priority [ -48.. -33] + erlang:make_tuple(16, queue:new()), % priority [ -32.. -17] + erlang:make_tuple(16, queue:new()), % priority [ -16.. -1] + queue:new(), % priority 0 (default) + erlang:make_tuple(16, queue:new()), % priority [ 1.. 16] + erlang:make_tuple(16, queue:new()), % priority [ 17.. 32] + erlang:make_tuple(16, queue:new()), % priority [ 33.. 48] + erlang:make_tuple(16, queue:new()), % priority [ 49.. 64] + erlang:make_tuple(16, queue:new()), % priority [ 65.. 80] + erlang:make_tuple(16, queue:new()), % priority [ 81.. 96] + erlang:make_tuple(16, queue:new()), % priority [ 97.. 112] + erlang:make_tuple(16, queue:new())}. % priority [ 113.. 128] + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(pqueue4()) -> + {{'value', any()}, pqueue4()} | {'empty', pqueue4()}. + +out({empty, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +out({Pc, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + out_current(Pc, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item of a specific priority from the head of the queue.=== +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec out(integer(), pqueue4()) -> + {{'value', any()}, pqueue4()} | {'empty', pqueue4()}. + +out(P, _) + when P < -128; P > 128 -> + erlang:exit(badarg); +out(_, {empty, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +out(P, Q) -> + out_specific(P, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Take an item from the head of the priority queue.=== +%% Includes the priority in the return value. +%% O(1) amortized, O(N) worst case +%% @end +%%------------------------------------------------------------------------- + +-spec pout(pqueue4()) -> + {{'value', any(), integer()}, pqueue4()} | {'empty', pqueue4()}. + +pout({empty, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + {empty, Q}; +pout({Pc, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _} = Q) -> + out_current_p(Pc, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Remove a unique value from the priority queue with a binary predicate.=== +%% O(N) but smaller constant than filter/2 +%% @end +%%------------------------------------------------------------------------- + +-spec remove_unique(fun((any()) -> boolean()), pqueue4()) -> + {boolean(), pqueue4()}. + +remove_unique(F, {_, 0, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _} = Q) + when is_function(F, 1) -> + {false, Q}; +remove_unique(F, {Pc, _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _} = Q) + when is_function(F, 1) -> + remove_unique_all(Pc, F, Q). + +remove_unique_all(128, F, Q) -> + remove_unique_p(128, F, Q); +remove_unique_all(P, F, Q) when is_integer(P) -> + case remove_unique_p(P, F, Q) of + {true, _} = Result -> + Result; + {false, Q} -> + remove_unique_all(P + 1, F, Q) + end. + +%%------------------------------------------------------------------------- +%% @doc +%% ===Remove a unique value in a specific priority within the priority queue with a binary predicate.=== +%% O(N) but smaller constant than filter/3 +%% @end +%%------------------------------------------------------------------------- + +-spec remove_unique(fun((any()) -> boolean()), integer(), pqueue4()) -> + {boolean(), pqueue4()}. + +remove_unique(_, P, _) + when P < -128; P > 128 -> + erlang:exit(badarg); +remove_unique(F, P, Q) when is_function(F, 1) -> + remove_unique_p(P, F, Q). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Convert the priority queue to a list.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec to_list(pqueue4()) -> list(). + +to_list(Q) -> + to_list([], out(Q)). +to_list(L, {empty, _}) -> + lists:reverse(L); +to_list(L, {{value, Value}, Q}) -> + to_list([Value | L], out(Q)). + +%%------------------------------------------------------------------------- +%% @doc +%% ===Convert the priority queue to a list with priorities.=== +%% O(N) +%% @end +%%------------------------------------------------------------------------- + +-spec to_plist(pqueue4()) -> list({priority(), list()}). + +to_plist(Q) -> + to_plist([], [], undefined, pout(Q)). +to_plist(L, [], _, {empty, _}) -> + lists:reverse(L); +to_plist(L, Lp, Pc, {empty, _}) -> + lists:reverse([{Pc, lists:reverse(Lp)} | L]); +to_plist(L, Lp, Pc, {{value, Value, Pc}, Q}) -> + to_plist(L, [Value | Lp], Pc, pout(Q)); +to_plist(L, [], _, {{value, Value, Pc}, Q}) -> + to_plist(L, [Value], Pc, pout(Q)); +to_plist(L, Lp, P, {{value, Value, Pc}, Q}) -> + to_plist([{P, lists:reverse(Lp)} | L], [Value], Pc, pout(Q)). + +%%------------------------------------------------------------------------- +%% @private +%% @doc +%% ===Regression test.=== +%% @end +%%------------------------------------------------------------------------- + +test() -> + Q0 = pqueue4:new(), + true = pqueue4:is_queue(Q0), + Q1 = pqueue4:in(20, 20, Q0), + Q2 = pqueue4:in(19, 19, Q1), + Q3 = pqueue4:in(18, 18, Q2), + Q4 = pqueue4:in(17, 17, Q3), + Q5 = pqueue4:in(16, 16, Q4), + Q6 = pqueue4:in(15, 15, Q5), + Q7 = pqueue4:in(14, 14, Q6), + Q8 = pqueue4:in(13, 13, Q7), + Q9 = pqueue4:in(12, 12, Q8), + Q10 = pqueue4:in(11, 11, Q9), + Q11 = pqueue4:in(10, 10, Q10), + Q12 = pqueue4:in(9, 9, Q11), + Q13 = pqueue4:in(8, 8, Q12), + Q14 = pqueue4:in(7, 7, Q13), + Q15 = pqueue4:in(6, 6, Q14), + Q16 = pqueue4:in(5, 5, Q15), + Q17 = pqueue4:in(4, 4, Q16), + Q18 = pqueue4:in(3, 3, Q17), + Q19 = pqueue4:in(2, 2, Q18), + Q20 = pqueue4:in(1, 1, Q19), + Q21 = pqueue4:in(0, 0, Q20), + Q22 = pqueue4:in(-1, -1, Q21), + Q23 = pqueue4:in(-2, -2, Q22), + Q24 = pqueue4:in(-3, -3, Q23), + Q25 = pqueue4:in(-4, -4, Q24), + Q26 = pqueue4:in(-5, -5, Q25), + Q27 = pqueue4:in(-6, -6, Q26), + Q28 = pqueue4:in(-7, -7, Q27), + Q29 = pqueue4:in(-8, -8, Q28), + Q30 = pqueue4:in(-9, -9, Q29), + Q31 = pqueue4:in(-10, -10, Q30), + Q32 = pqueue4:in(-11, -11, Q31), + Q33 = pqueue4:in(-12, -12, Q32), + Q34 = pqueue4:in(-13, -13, Q33), + Q35 = pqueue4:in(-14, -14, Q34), + Q36 = pqueue4:in(-15, -15, Q35), + Q37 = pqueue4:in(-16, -16, Q36), + Q38 = pqueue4:in(-17, -17, Q37), + Q39 = pqueue4:in(-18, -18, Q38), + Q40 = pqueue4:in(-19, -19, Q39), + Q41 = pqueue4:in(-20, -20, Q40), + Q42 = pqueue4:in(-20, -20, Q41), + Q43 = pqueue4:in(-19, -19, Q42), + Q44 = pqueue4:in(-18, -18, Q43), + Q45 = pqueue4:in(-17, -17, Q44), + Q46 = pqueue4:in(-16, -16, Q45), + Q47 = pqueue4:in(-15, -15, Q46), + Q48 = pqueue4:in(-14, -14, Q47), + Q49 = pqueue4:in(-13, -13, Q48), + Q50 = pqueue4:in(-12, -12, Q49), + Q51 = pqueue4:in(-11, -11, Q50), + Q52 = pqueue4:in(-10, -10, Q51), + Q53 = pqueue4:in(-9, -9, Q52), + Q54 = pqueue4:in(-8, -8, Q53), + Q55 = pqueue4:in(-7, -7, Q54), + Q56 = pqueue4:in(-6, -6, Q55), + Q57 = pqueue4:in(-5, -5, Q56), + Q58 = pqueue4:in(-4, -4, Q57), + Q59 = pqueue4:in(-3, -3, Q58), + Q60 = pqueue4:in(-2, -2, Q59), + Q61 = pqueue4:in(-1, -1, Q60), + Q62 = pqueue4:in(0, 0, Q61), + Q63 = pqueue4:in(1, 1, Q62), + Q64 = pqueue4:in(2, 2, Q63), + Q65 = pqueue4:in(3, 3, Q64), + Q66 = pqueue4:in(4, 4, Q65), + Q67 = pqueue4:in(5, 5, Q66), + Q68 = pqueue4:in(6, 6, Q67), + Q69 = pqueue4:in(7, 7, Q68), + Q70 = pqueue4:in(8, 8, Q69), + Q71 = pqueue4:in(9, 9, Q70), + Q72 = pqueue4:in(10, 10, Q71), + Q73 = pqueue4:in(11, 11, Q72), + Q74 = pqueue4:in(12, 12, Q73), + Q75 = pqueue4:in(13, 13, Q74), + Q76 = pqueue4:in(14, 14, Q75), + Q77 = pqueue4:in(15, 15, Q76), + Q78 = pqueue4:in(16, 16, Q77), + Q79 = pqueue4:in(17, 17, Q78), + Q80 = pqueue4:in(18, 18, Q79), + Q81 = pqueue4:in(19, 19, Q80), + Q82 = pqueue4:in(20, 20, Q81), + true = pqueue4:is_queue(Q82), + 82 = pqueue4: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] = pqueue4:to_list(Q82), + [{-20, [-20, -20]}, {-19, [-19, -19]}, {-18, [-18, -18]}, + {-17, [-17, -17]}, {-16, [-16, -16]}, {-15, [-15, -15]}, + {-14, [-14, -14]}, {-13, [-13, -13]}, {-12, [-12, -12]}, + {-11, [-11, -11]}, {-10, [-10, -10]}, {-9, [-9, -9]}, + {-8, [-8, -8]}, {-7, [-7, -7]}, {-6, [-6, -6]}, + {-5, [-5, -5]}, {-4, [-4, -4]}, {-3, [-3, -3]}, + {-2, [-2, -2]}, {-1, [-1, -1]}, {0, [0, 0]}, + {1, [1, 1]}, {2, [2, 2]}, {3, [3, 3]}, + {4, [4, 4]}, {5, [5, 5]}, {6, [6, 6]}, + {7, [7, 7]}, {8, [8, 8]}, {9, [9, 9]}, + {10, [10, 10]}, {11, [11, 11]}, {12, [12, 12]}, + {13, [13, 13]}, {14, [14, 14]}, {15, [15, 15]}, + {16, [16, 16]}, {17, [17, 17]}, {18, [18, 18]}, + {19, [19, 19]}, {20, [20, 20]}] = pqueue4:to_plist(Q82), + {{value, -20}, Q83} = pqueue4:out(Q82), + {{value, -20}, Q84} = pqueue4:out(Q83), + {{value, -19}, Q85} = pqueue4:out(Q84), + {{value, -19}, Q86} = pqueue4:out(Q85), + {{value, -18}, Q87} = pqueue4:out(Q86), + {{value, -18}, Q88} = pqueue4:out(Q87), + {{value, 0}, Q89} = pqueue4:out(0, Q88), + {{value, 0}, Q90} = pqueue4:out(0, Q89), + {empty, _} = pqueue4:out(0, Q90), + {{value, -17, -17}, Q91} = pqueue4:pout(Q90), + {{value, -17, -17}, Q92} = pqueue4:pout(Q91), + {{value, -16, -16}, Q93} = pqueue4:pout(Q92), + {{value, -16, -16}, Q94} = pqueue4:pout(Q93), + {{value, -15, -15}, Q95} = pqueue4:pout(Q94), + {{value, -15, -15}, Q96} = pqueue4:pout(Q95), + {{value, -14, -14}, Q97} = pqueue4:pout(Q96), + {{value, -14, -14}, Q98} = pqueue4:pout(Q97), + {{value, -13, -13}, Q99} = pqueue4:pout(Q98), + {{value, -13, -13}, Q100} = pqueue4:pout(Q99), + {{value, -12, -12}, Q101} = pqueue4:pout(Q100), + {{value, -12, -12}, Q102} = pqueue4:pout(Q101), + {{value, -11, -11}, Q103} = pqueue4:pout(Q102), + {{value, -11, -11}, Q104} = pqueue4:pout(Q103), + {{value, -10, -10}, Q105} = pqueue4:pout(Q104), + {{value, -10, -10}, Q106} = pqueue4:pout(Q105), + {{value, -9, -9}, Q107} = pqueue4:pout(Q106), + {{value, -9, -9}, Q108} = pqueue4:pout(Q107), + {{value, -8, -8}, Q109} = pqueue4:pout(Q108), + {{value, -8, -8}, Q110} = pqueue4:pout(Q109), + {{value, -7, -7}, Q111} = pqueue4:pout(Q110), + {{value, -7, -7}, Q112} = pqueue4:pout(Q111), + {{value, -6, -6}, Q113} = pqueue4:pout(Q112), + {{value, -6, -6}, Q114} = pqueue4:pout(Q113), + {{value, -5, -5}, Q115} = pqueue4:pout(Q114), + {{value, -5, -5}, Q116} = pqueue4:pout(Q115), + {{value, -4, -4}, Q117} = pqueue4:pout(Q116), + {{value, -4, -4}, Q118} = pqueue4:pout(Q117), + {{value, -3, -3}, Q119} = pqueue4:pout(Q118), + {{value, -3, -3}, Q120} = pqueue4:pout(Q119), + {{value, -2, -2}, Q121} = pqueue4:pout(Q120), + {{value, -2, -2}, Q122} = pqueue4:pout(Q121), + {{value, -1, -1}, Q123} = pqueue4:pout(Q122), + {{value, -1, -1}, Q124} = pqueue4:pout(Q123), + {{value, 1, 1}, Q125} = pqueue4:pout(Q124), + {{value, 1, 1}, Q126} = pqueue4:pout(Q125), + {{value, 2, 2}, Q127} = pqueue4:pout(Q126), + {{value, 2, 2}, Q128} = pqueue4:pout(Q127), + {{value, 3, 3}, Q129} = pqueue4:pout(Q128), + {{value, 3, 3}, Q130} = pqueue4:pout(Q129), + {{value, 4, 4}, Q131} = pqueue4:pout(Q130), + {{value, 4, 4}, Q132} = pqueue4:pout(Q131), + {{value, 5, 5}, Q133} = pqueue4:pout(Q132), + {{value, 5, 5}, Q134} = pqueue4:pout(Q133), + {{value, 6, 6}, Q135} = pqueue4:pout(Q134), + {{value, 6, 6}, Q136} = pqueue4:pout(Q135), + {{value, 7, 7}, Q137} = pqueue4:pout(Q136), + {{value, 7, 7}, Q138} = pqueue4:pout(Q137), + {{value, 8, 8}, Q139} = pqueue4:pout(Q138), + {{value, 8, 8}, Q140} = pqueue4:pout(Q139), + {{value, 9, 9}, Q141} = pqueue4:pout(Q140), + {{value, 9, 9}, Q142} = pqueue4:pout(Q141), + {{value, 10, 10}, Q143} = pqueue4:pout(Q142), + {{value, 10, 10}, Q144} = pqueue4:pout(Q143), + {{value, 11, 11}, Q145} = pqueue4:pout(Q144), + {{value, 11, 11}, Q146} = pqueue4:pout(Q145), + {{value, 12, 12}, Q147} = pqueue4:pout(Q146), + {{value, 12, 12}, Q148} = pqueue4:pout(Q147), + {{value, 13, 13}, Q149} = pqueue4:pout(Q148), + {{value, 13, 13}, Q150} = pqueue4:pout(Q149), + {{value, 14, 14}, Q151} = pqueue4:pout(Q150), + {{value, 14, 14}, Q152} = pqueue4:pout(Q151), + {{value, 15, 15}, Q153} = pqueue4:pout(Q152), + {{value, 15, 15}, Q154} = pqueue4:pout(Q153), + {{value, 16, 16}, Q155} = pqueue4:pout(Q154), + {{value, 16, 16}, Q156} = pqueue4:pout(Q155), + {{value, 17, 17}, Q157} = pqueue4:pout(Q156), + {{value, 17, 17}, Q158} = pqueue4:pout(Q157), + {{value, 18, 18}, Q159} = pqueue4:pout(Q158), + {{value, 18, 18}, Q160} = pqueue4:pout(Q159), + {{value, 19, 19}, Q161} = pqueue4:pout(Q160), + {{value, 19, 19}, Q162} = pqueue4:pout(Q161), + {{value, 20, 20}, Q163} = pqueue4:pout(Q162), + {{value, 20, 20}, Q164} = pqueue4:pout(Q163), + {{value, 20}, Q164} = pqueue4:out(Q163), + {{value, 20}, Q164} = pqueue4:out(20, Q163), + true = pqueue4:is_empty(Q164), + empty = erlang:element(1, Q164), % current priority + 0 = erlang:element(2, Q164), % size + {empty, Q164} = pqueue4:pout(Q164), + {empty, Q164} = pqueue4:out(Q164), + {empty, Q164} = pqueue4:out(20, Q164), + + Queue0 = queue:new(), + "{[],[]}" = lists:flatten(io_lib:format("~p", [Queue0])), + Queue1 = queue:in(1, Queue0), + Queue2 = queue:in(2, Queue1), + Queue3 = queue:in(3, Queue2), + {{value, 1}, _} = queue:out(Queue2), + "{[3,2],[1]}" = lists:flatten(io_lib:format("~p", [Queue3])), + {true, {[3],[1]}} = queue_remove_unique(fun(I) -> I == 2 end, {[3,2],[1]}), + Queue4 = queue:filter(fun(I) -> not (I == 2) end, Queue3), + "{[3],[1]}" = lists:flatten(io_lib:format("~p", [Queue4])), + 2 = queue:len(Queue4), + {{value, 1}, _} = queue:out(Queue4), + [1, 3] = queue:to_list(Queue4), + + Q166 = pqueue4:new(), + true = pqueue4:is_queue(Q166), + Q167 = pqueue4:in(6, 1, Q166), + Q168 = pqueue4:in(7, 1, Q167), + Q169 = pqueue4:in(8, 1, Q168), + Q170 = pqueue4:in(3, 0, Q169), + Q171 = pqueue4:in(4, 0, Q170), + Q172 = pqueue4:in(5, 0, Q171), + Q173 = pqueue4:in(0, -1, Q172), + Q174 = pqueue4:in(1, -1, Q173), + Q175 = pqueue4:in(2, -1, Q174), + [{-1, [0, 1, 2]}, {0, [3, 4, 5]}, {1, [6, 7, 8]}] = pqueue4:to_plist(Q175), + 3 = pqueue4:len(pqueue4:filter(fun(I) -> I > 5 end, Q175)), + 3 = pqueue4:len(pqueue4:filter(fun(I) -> I < 3 end, Q175)), + 3 = pqueue4:len(pqueue4:filter(fun(I) -> (I < 1) orelse (I > 6) end, Q175)), + {true, Q176} = pqueue4:remove_unique(fun(I) -> I == 4 end, Q175), + [{-1, [0, 1, 2]}, {0, [3, 5]}, {1, [6, 7, 8]}] = pqueue4:to_plist(Q176), + {true, Q177} = pqueue4:remove_unique(fun(I) -> I == 1 end, Q176), + [{-1, [0, 2]}, {0, [3, 5]}, {1, [6, 7, 8]}] = pqueue4:to_plist(Q177), + {true, Q178} = pqueue4:remove_unique(fun(I) -> I == 7 end, Q177), + [{-1, [0, 2]}, {0, [3, 5]}, {1, [6, 8]}] = pqueue4:to_plist(Q178), + 6 = pqueue4:len(Q178), + {{value, 0, -1}, Q179} = pqueue4:pout(Q178), + {{value, 2}, Q180} = pqueue4:out(Q179), + {{value, 6}, Q181} = pqueue4:out(1, Q180), + {false, Q181} = pqueue4:remove_unique(fun(I) -> I == 7 end, Q181), + [{0, [3, 5]}, {1, [8]}] = pqueue4:to_plist(Q181), + {true, Q182} = pqueue4:remove_unique(fun(I) -> I == 5 end, Q181), + {true, Q183} = pqueue4:remove_unique(fun(I) -> I == 8 end, 1, Q182), + {true, Q184} = pqueue4:remove_unique(fun(I) -> I == 3 end, Q183), + {empty, Q184} = pqueue4:pout(Q184), + {empty, Q184} = pqueue4:out(Q184), + {empty, Q184} = pqueue4:out(0, Q184), + ok. + +%%%------------------------------------------------------------------------ +%%% Private functions +%%%------------------------------------------------------------------------ + +%% @hidden +-define(FILTER_P_Qn128(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + V3, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn112(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, + V3, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn96(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, + V3, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn80(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, + V3, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn64(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, + V3, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn48(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, + V3, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn32(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V3, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qn16(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V3, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp16(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V3, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp32(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V3, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp48(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V3, + Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp64(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V3, + Qp80, Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp80(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V3, + Qp96, Qp112, Qp128}). +-define(FILTER_P_Qp96(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V3, + Qp112, Qp128}). +-define(FILTER_P_Qp112(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V3, + Qp128}). +-define(FILTER_P_Qp128(P, V1, V2, V3), +filter_priority(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}) -> + V2 = queue:filter(F, V1), + NewSize = Size - (queue:len(V1) - queue:len(V2)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V3}). + +?FILTER_P_Qn128(-128, + Qn128, NewQn128, + {NewQn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-127, + Qn127, NewQn127, + {Qn128, NewQn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-126, + Qn126, NewQn126, + {Qn128, Qn127, NewQn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-125, + Qn125, NewQn125, + {Qn128, Qn127, Qn126, NewQn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-124, + Qn124, NewQn124, + {Qn128, Qn127, Qn126, Qn125, NewQn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-123, + Qn123, NewQn123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + NewQn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-122, + Qn122, NewQn122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, NewQn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-121, + Qn121, NewQn121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, NewQn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-120, + Qn120, NewQn120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, NewQn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-119, + Qn119, NewQn119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, NewQn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-118, + Qn118, NewQn118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, NewQn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-117, + Qn117, NewQn117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + NewQn117, Qn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-116, + Qn116, NewQn116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, NewQn116, Qn115, Qn114, Qn113}); +?FILTER_P_Qn128(-115, + Qn115, NewQn115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, NewQn115, Qn114, Qn113}); +?FILTER_P_Qn128(-114, + Qn114, NewQn114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, NewQn114, Qn113}); +?FILTER_P_Qn128(-113, + Qn113, NewQn113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, NewQn113}); +?FILTER_P_Qn112(-112, + Qn112, NewQn112, + {NewQn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-111, + Qn111, NewQn111, + {Qn112, NewQn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-110, + Qn110, NewQn110, + {Qn112, Qn111, NewQn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-109, + Qn109, NewQn109, + {Qn112, Qn111, Qn110, NewQn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-108, + Qn108, NewQn108, + {Qn112, Qn111, Qn110, Qn109, NewQn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-107, + Qn107, NewQn107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + NewQn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-106, + Qn106, NewQn106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, NewQn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-105, + Qn105, NewQn105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, NewQn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-104, + Qn104, NewQn104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, NewQn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-103, + Qn103, NewQn103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, NewQn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-102, + Qn102, NewQn102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, NewQn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-101, + Qn101, NewQn101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + NewQn101, Qn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-100, + Qn100, NewQn100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, NewQn100, Qn99, Qn98, Qn97}); +?FILTER_P_Qn112(-99, + Qn99, NewQn99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, NewQn99, Qn98, Qn97}); +?FILTER_P_Qn112(-98, + Qn98, NewQn98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, NewQn98, Qn97}); +?FILTER_P_Qn112(-97, + Qn97, NewQn97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, NewQn97}); +?FILTER_P_Qn96(-96, + Qn96, NewQn96, + {NewQn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-95, + Qn95, NewQn95, + {Qn96, NewQn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-94, + Qn94, NewQn94, + {Qn96, Qn95, NewQn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-93, + Qn93, NewQn93, + {Qn96, Qn95, Qn94, NewQn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-92, + Qn92, NewQn92, + {Qn96, Qn95, Qn94, Qn93, NewQn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-91, + Qn91, NewQn91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + NewQn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-90, + Qn90, NewQn90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, NewQn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-89, + Qn89, NewQn89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, NewQn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-88, + Qn88, NewQn88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, NewQn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-87, + Qn87, NewQn87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, NewQn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-86, + Qn86, NewQn86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, NewQn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-85, + Qn85, NewQn85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + NewQn85, Qn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-84, + Qn84, NewQn84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, NewQn84, Qn83, Qn82, Qn81}); +?FILTER_P_Qn96(-83, + Qn83, NewQn83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, NewQn83, Qn82, Qn81}); +?FILTER_P_Qn96(-82, + Qn82, NewQn82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, NewQn82, Qn81}); +?FILTER_P_Qn96(-81, + Qn81, NewQn81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, NewQn81}); +?FILTER_P_Qn80(-80, + Qn80, NewQn80, + {NewQn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-79, + Qn79, NewQn79, + {Qn80, NewQn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-78, + Qn78, NewQn78, + {Qn80, Qn79, NewQn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-77, + Qn77, NewQn77, + {Qn80, Qn79, Qn78, NewQn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-76, + Qn76, NewQn76, + {Qn80, Qn79, Qn78, Qn77, NewQn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-75, + Qn75, NewQn75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + NewQn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-74, + Qn74, NewQn74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, NewQn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-73, + Qn73, NewQn73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, NewQn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-72, + Qn72, NewQn72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, NewQn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-71, + Qn71, NewQn71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, NewQn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-70, + Qn70, NewQn70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, NewQn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-69, + Qn69, NewQn69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + NewQn69, Qn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-68, + Qn68, NewQn68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, NewQn68, Qn67, Qn66, Qn65}); +?FILTER_P_Qn80(-67, + Qn67, NewQn67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, NewQn67, Qn66, Qn65}); +?FILTER_P_Qn80(-66, + Qn66, NewQn66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, NewQn66, Qn65}); +?FILTER_P_Qn80(-65, + Qn65, NewQn65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, NewQn65}); +?FILTER_P_Qn64(-64, + Qn64, NewQn64, + {NewQn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-63, + Qn63, NewQn63, + {Qn64, NewQn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-62, + Qn62, NewQn62, + {Qn64, Qn63, NewQn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-61, + Qn61, NewQn61, + {Qn64, Qn63, Qn62, NewQn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-60, + Qn60, NewQn60, + {Qn64, Qn63, Qn62, Qn61, NewQn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-59, + Qn59, NewQn59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + NewQn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-58, + Qn58, NewQn58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, NewQn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-57, + Qn57, NewQn57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, NewQn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-56, + Qn56, NewQn56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, NewQn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-55, + Qn55, NewQn55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, NewQn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-54, + Qn54, NewQn54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, NewQn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-53, + Qn53, NewQn53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + NewQn53, Qn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-52, + Qn52, NewQn52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, NewQn52, Qn51, Qn50, Qn49}); +?FILTER_P_Qn64(-51, + Qn51, NewQn51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, NewQn51, Qn50, Qn49}); +?FILTER_P_Qn64(-50, + Qn50, NewQn50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, NewQn50, Qn49}); +?FILTER_P_Qn64(-49, + Qn49, NewQn49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, NewQn49}); +?FILTER_P_Qn48(-48, + Qn48, NewQn48, + {NewQn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-47, + Qn47, NewQn47, + {Qn48, NewQn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-46, + Qn46, NewQn46, + {Qn48, Qn47, NewQn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-45, + Qn45, NewQn45, + {Qn48, Qn47, Qn46, NewQn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-44, + Qn44, NewQn44, + {Qn48, Qn47, Qn46, Qn45, NewQn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-43, + Qn43, NewQn43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + NewQn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-42, + Qn42, NewQn42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, NewQn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-41, + Qn41, NewQn41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, NewQn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-40, + Qn40, NewQn40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, NewQn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-39, + Qn39, NewQn39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, NewQn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-38, + Qn38, NewQn38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, NewQn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-37, + Qn37, NewQn37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + NewQn37, Qn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-36, + Qn36, NewQn36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, NewQn36, Qn35, Qn34, Qn33}); +?FILTER_P_Qn48(-35, + Qn35, NewQn35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, NewQn35, Qn34, Qn33}); +?FILTER_P_Qn48(-34, + Qn34, NewQn34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, NewQn34, Qn33}); +?FILTER_P_Qn48(-33, + Qn33, NewQn33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, NewQn33}); +?FILTER_P_Qn32(-32, + Qn32, NewQn32, + {NewQn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-31, + Qn31, NewQn31, + {Qn32, NewQn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-30, + Qn30, NewQn30, + {Qn32, Qn31, NewQn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-29, + Qn29, NewQn29, + {Qn32, Qn31, Qn30, NewQn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-28, + Qn28, NewQn28, + {Qn32, Qn31, Qn30, Qn29, NewQn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-27, + Qn27, NewQn27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + NewQn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-26, + Qn26, NewQn26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, NewQn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-25, + Qn25, NewQn25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, NewQn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-24, + Qn24, NewQn24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, NewQn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-23, + Qn23, NewQn23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, NewQn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-22, + Qn22, NewQn22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, NewQn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-21, + Qn21, NewQn21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + NewQn21, Qn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-20, + Qn20, NewQn20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, NewQn20, Qn19, Qn18, Qn17}); +?FILTER_P_Qn32(-19, + Qn19, NewQn19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, NewQn19, Qn18, Qn17}); +?FILTER_P_Qn32(-18, + Qn18, NewQn18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, NewQn18, Qn17}); +?FILTER_P_Qn32(-17, + Qn17, NewQn17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, NewQn17}); +?FILTER_P_Qn16(-16, + Qn16, NewQn16, + {NewQn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-15, + Qn15, NewQn15, + {Qn16, NewQn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-14, + Qn14, NewQn14, + {Qn16, Qn15, NewQn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-13, + Qn13, NewQn13, + {Qn16, Qn15, Qn14, NewQn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-12, + Qn12, NewQn12, + {Qn16, Qn15, Qn14, Qn13, NewQn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-11, + Qn11, NewQn11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + NewQn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-10, + Qn10, NewQn10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, NewQn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-9, + Qn9, NewQn9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, NewQn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-8, + Qn8, NewQn8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, NewQn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-7, + Qn7, NewQn7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, NewQn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-6, + Qn6, NewQn6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, NewQn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-5, + Qn5, NewQn5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + NewQn5, Qn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-4, + Qn4, NewQn4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, NewQn4, Qn3, Qn2, Qn1}); +?FILTER_P_Qn16(-3, + Qn3, NewQn3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, NewQn3, Qn2, Qn1}); +?FILTER_P_Qn16(-2, + Qn2, NewQn2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, NewQn2, Qn1}); +?FILTER_P_Qn16(-1, + Qn1, NewQn1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, NewQn1}); +filter_priority(0, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + NewQ0 = queue:filter(F, Q0), + NewSize = Size - (queue:len(Q0) - queue:len(NewQ0)), + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + NewQ0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}; +?FILTER_P_Qp16(1, + Qp1, NewQp1, + {NewQp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(2, + Qp2, NewQp2, + {Qp1, NewQp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(3, + Qp3, NewQp3, + {Qp1, Qp2, NewQp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(4, + Qp4, NewQp4, + {Qp1, Qp2, Qp3, NewQp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(5, + Qp5, NewQp5, + {Qp1, Qp2, Qp3, Qp4, NewQp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(6, + Qp6, NewQp6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + NewQp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(7, + Qp7, NewQp7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, NewQp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(8, + Qp8, NewQp8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, NewQp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(9, + Qp9, NewQp9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, NewQp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(10, + Qp10, NewQp10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, NewQp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(11, + Qp11, NewQp11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, NewQp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(12, + Qp12, NewQp12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + NewQp12, Qp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(13, + Qp13, NewQp13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, NewQp13, Qp14, Qp15, Qp16}); +?FILTER_P_Qp16(14, + Qp14, NewQp14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, NewQp14, Qp15, Qp16}); +?FILTER_P_Qp16(15, + Qp15, NewQp15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, NewQp15, Qp16}); +?FILTER_P_Qp16(16, + Qp16, NewQp16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, NewQp16}); +?FILTER_P_Qp32(17, + Qp17, NewQp17, + {NewQp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(18, + Qp18, NewQp18, + {Qp17, NewQp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(19, + Qp19, NewQp19, + {Qp17, Qp18, NewQp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(20, + Qp20, NewQp20, + {Qp17, Qp18, Qp19, NewQp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(21, + Qp21, NewQp21, + {Qp17, Qp18, Qp19, Qp20, NewQp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(22, + Qp22, NewQp22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + NewQp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(23, + Qp23, NewQp23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, NewQp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(24, + Qp24, NewQp24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, NewQp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(25, + Qp25, NewQp25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, NewQp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(26, + Qp26, NewQp26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, NewQp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(27, + Qp27, NewQp27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, NewQp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(28, + Qp28, NewQp28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + NewQp28, Qp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(29, + Qp29, NewQp29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, NewQp29, Qp30, Qp31, Qp32}); +?FILTER_P_Qp32(30, + Qp30, NewQp30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, NewQp30, Qp31, Qp32}); +?FILTER_P_Qp32(31, + Qp31, NewQp31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, NewQp31, Qp32}); +?FILTER_P_Qp32(32, + Qp32, NewQp32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, NewQp32}); +?FILTER_P_Qp48(33, + Qp33, NewQp33, + {NewQp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(34, + Qp34, NewQp34, + {Qp33, NewQp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(35, + Qp35, NewQp35, + {Qp33, Qp34, NewQp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(36, + Qp36, NewQp36, + {Qp33, Qp34, Qp35, NewQp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(37, + Qp37, NewQp37, + {Qp33, Qp34, Qp35, Qp36, NewQp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(38, + Qp38, NewQp38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + NewQp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(39, + Qp39, NewQp39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, NewQp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(40, + Qp40, NewQp40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, NewQp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(41, + Qp41, NewQp41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, NewQp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(42, + Qp42, NewQp42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, NewQp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(43, + Qp43, NewQp43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, NewQp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(44, + Qp44, NewQp44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + NewQp44, Qp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(45, + Qp45, NewQp45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, NewQp45, Qp46, Qp47, Qp48}); +?FILTER_P_Qp48(46, + Qp46, NewQp46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, NewQp46, Qp47, Qp48}); +?FILTER_P_Qp48(47, + Qp47, NewQp47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, NewQp47, Qp48}); +?FILTER_P_Qp48(48, + Qp48, NewQp48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, NewQp48}); +?FILTER_P_Qp64(49, + Qp49, NewQp49, + {NewQp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(50, + Qp50, NewQp50, + {Qp49, NewQp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(51, + Qp51, NewQp51, + {Qp49, Qp50, NewQp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(52, + Qp52, NewQp52, + {Qp49, Qp50, Qp51, NewQp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(53, + Qp53, NewQp53, + {Qp49, Qp50, Qp51, Qp52, NewQp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(54, + Qp54, NewQp54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + NewQp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(55, + Qp55, NewQp55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, NewQp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(56, + Qp56, NewQp56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, NewQp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(57, + Qp57, NewQp57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, NewQp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(58, + Qp58, NewQp58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, NewQp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(59, + Qp59, NewQp59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, NewQp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(60, + Qp60, NewQp60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + NewQp60, Qp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(61, + Qp61, NewQp61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, NewQp61, Qp62, Qp63, Qp64}); +?FILTER_P_Qp64(62, + Qp62, NewQp62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, NewQp62, Qp63, Qp64}); +?FILTER_P_Qp64(63, + Qp63, NewQp63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, NewQp63, Qp64}); +?FILTER_P_Qp64(64, + Qp64, NewQp64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, NewQp64}); +?FILTER_P_Qp80(65, + Qp65, NewQp65, + {NewQp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(66, + Qp66, NewQp66, + {Qp65, NewQp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(67, + Qp67, NewQp67, + {Qp65, Qp66, NewQp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(68, + Qp68, NewQp68, + {Qp65, Qp66, Qp67, NewQp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(69, + Qp69, NewQp69, + {Qp65, Qp66, Qp67, Qp68, NewQp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(70, + Qp70, NewQp70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + NewQp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(71, + Qp71, NewQp71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, NewQp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(72, + Qp72, NewQp72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, NewQp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(73, + Qp73, NewQp73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, NewQp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(74, + Qp74, NewQp74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, NewQp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(75, + Qp75, NewQp75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, NewQp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(76, + Qp76, NewQp76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + NewQp76, Qp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(77, + Qp77, NewQp77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, NewQp77, Qp78, Qp79, Qp80}); +?FILTER_P_Qp80(78, + Qp78, NewQp78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, NewQp78, Qp79, Qp80}); +?FILTER_P_Qp80(79, + Qp79, NewQp79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, NewQp79, Qp80}); +?FILTER_P_Qp80(80, + Qp80, NewQp80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, NewQp80}); +?FILTER_P_Qp96(81, + Qp81, NewQp81, + {NewQp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(82, + Qp82, NewQp82, + {Qp81, NewQp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(83, + Qp83, NewQp83, + {Qp81, Qp82, NewQp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(84, + Qp84, NewQp84, + {Qp81, Qp82, Qp83, NewQp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(85, + Qp85, NewQp85, + {Qp81, Qp82, Qp83, Qp84, NewQp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(86, + Qp86, NewQp86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + NewQp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(87, + Qp87, NewQp87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, NewQp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(88, + Qp88, NewQp88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, NewQp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(89, + Qp89, NewQp89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, NewQp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(90, + Qp90, NewQp90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, NewQp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(91, + Qp91, NewQp91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, NewQp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(92, + Qp92, NewQp92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + NewQp92, Qp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(93, + Qp93, NewQp93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, NewQp93, Qp94, Qp95, Qp96}); +?FILTER_P_Qp96(94, + Qp94, NewQp94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, NewQp94, Qp95, Qp96}); +?FILTER_P_Qp96(95, + Qp95, NewQp95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, NewQp95, Qp96}); +?FILTER_P_Qp96(96, + Qp96, NewQp96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, NewQp96}); +?FILTER_P_Qp112(97, + Qp97, NewQp97, + {NewQp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(98, + Qp98, NewQp98, + {Qp97, NewQp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(99, + Qp99, NewQp99, + {Qp97, Qp98, NewQp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(100, + Qp100, NewQp100, + {Qp97, Qp98, Qp99, NewQp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(101, + Qp101, NewQp101, + {Qp97, Qp98, Qp99, Qp100, NewQp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(102, + Qp102, NewQp102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + NewQp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(103, + Qp103, NewQp103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, NewQp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(104, + Qp104, NewQp104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, NewQp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(105, + Qp105, NewQp105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, NewQp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(106, + Qp106, NewQp106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, NewQp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(107, + Qp107, NewQp107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, NewQp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(108, + Qp108, NewQp108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + NewQp108, Qp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(109, + Qp109, NewQp109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, NewQp109, Qp110, Qp111, Qp112}); +?FILTER_P_Qp112(110, + Qp110, NewQp110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, NewQp110, Qp111, Qp112}); +?FILTER_P_Qp112(111, + Qp111, NewQp111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, NewQp111, Qp112}); +?FILTER_P_Qp112(112, + Qp112, NewQp112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, NewQp112}); +?FILTER_P_Qp128(113, + Qp113, NewQp113, + {NewQp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(114, + Qp114, NewQp114, + {Qp113, NewQp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(115, + Qp115, NewQp115, + {Qp113, Qp114, NewQp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(116, + Qp116, NewQp116, + {Qp113, Qp114, Qp115, NewQp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(117, + Qp117, NewQp117, + {Qp113, Qp114, Qp115, Qp116, NewQp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(118, + Qp118, NewQp118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + NewQp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(119, + Qp119, NewQp119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, NewQp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(120, + Qp120, NewQp120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, NewQp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(121, + Qp121, NewQp121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, NewQp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(122, + Qp122, NewQp122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, NewQp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(123, + Qp123, NewQp123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, NewQp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(124, + Qp124, NewQp124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + NewQp124, Qp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(125, + Qp125, NewQp125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, NewQp125, Qp126, Qp127, Qp128}); +?FILTER_P_Qp128(126, + Qp126, NewQp126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, NewQp126, Qp127, Qp128}); +?FILTER_P_Qp128(127, + Qp127, NewQp127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, NewQp127, Qp128}); +?FILTER_P_Qp128(128, + Qp128, NewQp128, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, NewQp128}). + +%% @hidden +-define(IN_HIGHER_Qn128(P, V), +in_higher(P, + {_, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + V, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn112(P, V), +in_higher(P, + {_, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, + V, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn96(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, + V, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn80(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, + V, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn64(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, + V, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn48(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, + V, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn32(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qn16(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp16(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp32(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp48(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V, + Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp64(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V, + Qp80, Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp80(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V, + Qp96, Qp112, Qp128}). +-define(IN_HIGHER_Qp96(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V, + Qp112, Qp128}). +-define(IN_HIGHER_Qp112(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V, + Qp128}). +-define(IN_HIGHER_Qp128(P, V), +in_higher(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}, X) -> + {P, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V}). + +?IN_HIGHER_Qn128(-128, + {queue:in(X, Qn128), Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-127, + {Qn128, queue:in(X, Qn127), Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-126, + {Qn128, Qn127, queue:in(X, Qn126), Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-125, + {Qn128, Qn127, Qn126, queue:in(X, Qn125), Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-124, + {Qn128, Qn127, Qn126, Qn125, queue:in(X, Qn124), + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + queue:in(X, Qn123), Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, queue:in(X, Qn122), Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, queue:in(X, Qn121), Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, queue:in(X, Qn120), Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, queue:in(X, Qn119), Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, queue:in(X, Qn118), + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + queue:in(X, Qn117), Qn116, Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, queue:in(X, Qn116), Qn115, Qn114, Qn113}); +?IN_HIGHER_Qn128(-115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, queue:in(X, Qn115), Qn114, Qn113}); +?IN_HIGHER_Qn128(-114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, queue:in(X, Qn114), Qn113}); +?IN_HIGHER_Qn128(-113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, queue:in(X, Qn113)}); +?IN_HIGHER_Qn112(-112, + {queue:in(X, Qn112), Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-111, + {Qn112, queue:in(X, Qn111), Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-110, + {Qn112, Qn111, queue:in(X, Qn110), Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-109, + {Qn112, Qn111, Qn110, queue:in(X, Qn109), Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-108, + {Qn112, Qn111, Qn110, Qn109, queue:in(X, Qn108), + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + queue:in(X, Qn107), Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, queue:in(X, Qn106), Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, queue:in(X, Qn105), Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, queue:in(X, Qn104), Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, queue:in(X, Qn103), Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, queue:in(X, Qn102), + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + queue:in(X, Qn101), Qn100, Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, queue:in(X, Qn100), Qn99, Qn98, Qn97}); +?IN_HIGHER_Qn112(-99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, queue:in(X, Qn99), Qn98, Qn97}); +?IN_HIGHER_Qn112(-98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, queue:in(X, Qn98), Qn97}); +?IN_HIGHER_Qn112(-97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, queue:in(X, Qn97)}); +?IN_HIGHER_Qn96(-96, + {queue:in(X, Qn96), Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-95, + {Qn96, queue:in(X, Qn95), Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-94, + {Qn96, Qn95, queue:in(X, Qn94), Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-93, + {Qn96, Qn95, Qn94, queue:in(X, Qn93), Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-92, + {Qn96, Qn95, Qn94, Qn93, queue:in(X, Qn92), + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + queue:in(X, Qn91), Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, queue:in(X, Qn90), Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, queue:in(X, Qn89), Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, queue:in(X, Qn88), Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, queue:in(X, Qn87), Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, queue:in(X, Qn86), + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + queue:in(X, Qn85), Qn84, Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, queue:in(X, Qn84), Qn83, Qn82, Qn81}); +?IN_HIGHER_Qn96(-83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, queue:in(X, Qn83), Qn82, Qn81}); +?IN_HIGHER_Qn96(-82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, queue:in(X, Qn82), Qn81}); +?IN_HIGHER_Qn96(-81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, queue:in(X, Qn81)}); +?IN_HIGHER_Qn80(-80, + {queue:in(X, Qn80), Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-79, + {Qn80, queue:in(X, Qn79), Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-78, + {Qn80, Qn79, queue:in(X, Qn78), Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-77, + {Qn80, Qn79, Qn78, queue:in(X, Qn77), Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-76, + {Qn80, Qn79, Qn78, Qn77, queue:in(X, Qn76), + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + queue:in(X, Qn75), Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, queue:in(X, Qn74), Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, queue:in(X, Qn73), Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, queue:in(X, Qn72), Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, queue:in(X, Qn71), Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, queue:in(X, Qn70), + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + queue:in(X, Qn69), Qn68, Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, queue:in(X, Qn68), Qn67, Qn66, Qn65}); +?IN_HIGHER_Qn80(-67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, queue:in(X, Qn67), Qn66, Qn65}); +?IN_HIGHER_Qn80(-66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, queue:in(X, Qn66), Qn65}); +?IN_HIGHER_Qn80(-65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, queue:in(X, Qn65)}); +?IN_HIGHER_Qn64(-64, + {queue:in(X, Qn64), Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-63, + {Qn64, queue:in(X, Qn63), Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-62, + {Qn64, Qn63, queue:in(X, Qn62), Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-61, + {Qn64, Qn63, Qn62, queue:in(X, Qn61), Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-60, + {Qn64, Qn63, Qn62, Qn61, queue:in(X, Qn60), + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + queue:in(X, Qn59), Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, queue:in(X, Qn58), Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, queue:in(X, Qn57), Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, queue:in(X, Qn56), Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, queue:in(X, Qn55), Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, queue:in(X, Qn54), + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + queue:in(X, Qn53), Qn52, Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, queue:in(X, Qn52), Qn51, Qn50, Qn49}); +?IN_HIGHER_Qn64(-51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, queue:in(X, Qn51), Qn50, Qn49}); +?IN_HIGHER_Qn64(-50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, queue:in(X, Qn50), Qn49}); +?IN_HIGHER_Qn64(-49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, queue:in(X, Qn49)}); +?IN_HIGHER_Qn48(-48, + {queue:in(X, Qn48), Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-47, + {Qn48, queue:in(X, Qn47), Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-46, + {Qn48, Qn47, queue:in(X, Qn46), Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-45, + {Qn48, Qn47, Qn46, queue:in(X, Qn45), Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-44, + {Qn48, Qn47, Qn46, Qn45, queue:in(X, Qn44), + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + queue:in(X, Qn43), Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, queue:in(X, Qn42), Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, queue:in(X, Qn41), Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, queue:in(X, Qn40), Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, queue:in(X, Qn39), Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, queue:in(X, Qn38), + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + queue:in(X, Qn37), Qn36, Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, queue:in(X, Qn36), Qn35, Qn34, Qn33}); +?IN_HIGHER_Qn48(-35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, queue:in(X, Qn35), Qn34, Qn33}); +?IN_HIGHER_Qn48(-34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, queue:in(X, Qn34), Qn33}); +?IN_HIGHER_Qn48(-33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, queue:in(X, Qn33)}); +?IN_HIGHER_Qn32(-32, + {queue:in(X, Qn32), Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-31, + {Qn32, queue:in(X, Qn31), Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-30, + {Qn32, Qn31, queue:in(X, Qn30), Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-29, + {Qn32, Qn31, Qn30, queue:in(X, Qn29), Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-28, + {Qn32, Qn31, Qn30, Qn29, queue:in(X, Qn28), + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + queue:in(X, Qn27), Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, queue:in(X, Qn26), Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, queue:in(X, Qn25), Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, queue:in(X, Qn24), Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, queue:in(X, Qn23), Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, queue:in(X, Qn22), + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + queue:in(X, Qn21), Qn20, Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, queue:in(X, Qn20), Qn19, Qn18, Qn17}); +?IN_HIGHER_Qn32(-19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, queue:in(X, Qn19), Qn18, Qn17}); +?IN_HIGHER_Qn32(-18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, queue:in(X, Qn18), Qn17}); +?IN_HIGHER_Qn32(-17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, queue:in(X, Qn17)}); +?IN_HIGHER_Qn16(-16, + {queue:in(X, Qn16), Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-15, + {Qn16, queue:in(X, Qn15), Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-14, + {Qn16, Qn15, queue:in(X, Qn14), Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-13, + {Qn16, Qn15, Qn14, queue:in(X, Qn13), Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-12, + {Qn16, Qn15, Qn14, Qn13, queue:in(X, Qn12), + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + queue:in(X, Qn11), Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, queue:in(X, Qn10), Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, queue:in(X, Qn9), Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, queue:in(X, Qn8), Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, queue:in(X, Qn7), Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, queue:in(X, Qn6), + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + queue:in(X, Qn5), Qn4, Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, queue:in(X, Qn4), Qn3, Qn2, Qn1}); +?IN_HIGHER_Qn16(-3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, queue:in(X, Qn3), Qn2, Qn1}); +?IN_HIGHER_Qn16(-2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, queue:in(X, Qn2), Qn1}); +?IN_HIGHER_Qn16(-1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, queue:in(X, Qn1)}); +in_higher(0, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {0, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + queue:in(X, Q0), + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}; +?IN_HIGHER_Qp16(1, + {queue:in(X, Qp1), Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(2, + {Qp1, queue:in(X, Qp2), Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(3, + {Qp1, Qp2, queue:in(X, Qp3), Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(4, + {Qp1, Qp2, Qp3, queue:in(X, Qp4), Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(5, + {Qp1, Qp2, Qp3, Qp4, queue:in(X, Qp5), + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + queue:in(X, Qp6), Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, queue:in(X, Qp7), Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, queue:in(X, Qp8), Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, queue:in(X, Qp9), Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, queue:in(X, Qp10), Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, queue:in(X, Qp11), + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + queue:in(X, Qp12), Qp13, Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, queue:in(X, Qp13), Qp14, Qp15, Qp16}); +?IN_HIGHER_Qp16(14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, queue:in(X, Qp14), Qp15, Qp16}); +?IN_HIGHER_Qp16(15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, queue:in(X, Qp15), Qp16}); +?IN_HIGHER_Qp16(16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, queue:in(X, Qp16)}); +?IN_HIGHER_Qp32(17, + {queue:in(X, Qp17), Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(18, + {Qp17, queue:in(X, Qp18), Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(19, + {Qp17, Qp18, queue:in(X, Qp19), Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(20, + {Qp17, Qp18, Qp19, queue:in(X, Qp20), Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(21, + {Qp17, Qp18, Qp19, Qp20, queue:in(X, Qp21), + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + queue:in(X, Qp22), Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, queue:in(X, Qp23), Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, queue:in(X, Qp24), Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, queue:in(X, Qp25), Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, queue:in(X, Qp26), Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, queue:in(X, Qp27), + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + queue:in(X, Qp28), Qp29, Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, queue:in(X, Qp29), Qp30, Qp31, Qp32}); +?IN_HIGHER_Qp32(30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, queue:in(X, Qp30), Qp31, Qp32}); +?IN_HIGHER_Qp32(31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, queue:in(X, Qp31), Qp32}); +?IN_HIGHER_Qp32(32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, queue:in(X, Qp32)}); +?IN_HIGHER_Qp48(33, + {queue:in(X, Qp33), Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(34, + {Qp33, queue:in(X, Qp34), Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(35, + {Qp33, Qp34, queue:in(X, Qp35), Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(36, + {Qp33, Qp34, Qp35, queue:in(X, Qp36), Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(37, + {Qp33, Qp34, Qp35, Qp36, queue:in(X, Qp37), + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + queue:in(X, Qp38), Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, queue:in(X, Qp39), Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, queue:in(X, Qp40), Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, queue:in(X, Qp41), Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, queue:in(X, Qp42), Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, queue:in(X, Qp43), + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + queue:in(X, Qp44), Qp45, Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, queue:in(X, Qp45), Qp46, Qp47, Qp48}); +?IN_HIGHER_Qp48(46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, queue:in(X, Qp46), Qp47, Qp48}); +?IN_HIGHER_Qp48(47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, queue:in(X, Qp47), Qp48}); +?IN_HIGHER_Qp48(48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, queue:in(X, Qp48)}); +?IN_HIGHER_Qp64(49, + {queue:in(X, Qp49), Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(50, + {Qp49, queue:in(X, Qp50), Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(51, + {Qp49, Qp50, queue:in(X, Qp51), Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(52, + {Qp49, Qp50, Qp51, queue:in(X, Qp52), Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(53, + {Qp49, Qp50, Qp51, Qp52, queue:in(X, Qp53), + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + queue:in(X, Qp54), Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, queue:in(X, Qp55), Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, queue:in(X, Qp56), Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, queue:in(X, Qp57), Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, queue:in(X, Qp58), Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, queue:in(X, Qp59), + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + queue:in(X, Qp60), Qp61, Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, queue:in(X, Qp61), Qp62, Qp63, Qp64}); +?IN_HIGHER_Qp64(62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, queue:in(X, Qp62), Qp63, Qp64}); +?IN_HIGHER_Qp64(63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, queue:in(X, Qp63), Qp64}); +?IN_HIGHER_Qp64(64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, queue:in(X, Qp64)}); +?IN_HIGHER_Qp80(65, + {queue:in(X, Qp65), Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(66, + {Qp65, queue:in(X, Qp66), Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(67, + {Qp65, Qp66, queue:in(X, Qp67), Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(68, + {Qp65, Qp66, Qp67, queue:in(X, Qp68), Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(69, + {Qp65, Qp66, Qp67, Qp68, queue:in(X, Qp69), + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + queue:in(X, Qp70), Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, queue:in(X, Qp71), Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, queue:in(X, Qp72), Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, queue:in(X, Qp73), Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, queue:in(X, Qp74), Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, queue:in(X, Qp75), + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + queue:in(X, Qp76), Qp77, Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, queue:in(X, Qp77), Qp78, Qp79, Qp80}); +?IN_HIGHER_Qp80(78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, queue:in(X, Qp78), Qp79, Qp80}); +?IN_HIGHER_Qp80(79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, queue:in(X, Qp79), Qp80}); +?IN_HIGHER_Qp80(80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, queue:in(X, Qp80)}); +?IN_HIGHER_Qp96(81, + {queue:in(X, Qp81), Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(82, + {Qp81, queue:in(X, Qp82), Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(83, + {Qp81, Qp82, queue:in(X, Qp83), Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(84, + {Qp81, Qp82, Qp83, queue:in(X, Qp84), Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(85, + {Qp81, Qp82, Qp83, Qp84, queue:in(X, Qp85), + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + queue:in(X, Qp86), Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, queue:in(X, Qp87), Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, queue:in(X, Qp88), Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, queue:in(X, Qp89), Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, queue:in(X, Qp90), Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, queue:in(X, Qp91), + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + queue:in(X, Qp92), Qp93, Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, queue:in(X, Qp93), Qp94, Qp95, Qp96}); +?IN_HIGHER_Qp96(94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, queue:in(X, Qp94), Qp95, Qp96}); +?IN_HIGHER_Qp96(95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, queue:in(X, Qp95), Qp96}); +?IN_HIGHER_Qp96(96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, queue:in(X, Qp96)}); +?IN_HIGHER_Qp112(97, + {queue:in(X, Qp97), Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(98, + {Qp97, queue:in(X, Qp98), Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(99, + {Qp97, Qp98, queue:in(X, Qp99), Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(100, + {Qp97, Qp98, Qp99, queue:in(X, Qp100), Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(101, + {Qp97, Qp98, Qp99, Qp100, queue:in(X, Qp101), + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + queue:in(X, Qp102), Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, queue:in(X, Qp103), Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, queue:in(X, Qp104), Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, queue:in(X, Qp105), Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, queue:in(X, Qp106), Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, queue:in(X, Qp107), + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + queue:in(X, Qp108), Qp109, Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, queue:in(X, Qp109), Qp110, Qp111, Qp112}); +?IN_HIGHER_Qp112(110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, queue:in(X, Qp110), Qp111, Qp112}); +?IN_HIGHER_Qp112(111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, queue:in(X, Qp111), Qp112}); +?IN_HIGHER_Qp112(112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, queue:in(X, Qp112)}); +?IN_HIGHER_Qp128(113, + {queue:in(X, Qp113), Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(114, + {Qp113, queue:in(X, Qp114), Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(115, + {Qp113, Qp114, queue:in(X, Qp115), Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(116, + {Qp113, Qp114, Qp115, queue:in(X, Qp116), Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(117, + {Qp113, Qp114, Qp115, Qp116, queue:in(X, Qp117), + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + queue:in(X, Qp118), Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, queue:in(X, Qp119), Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, queue:in(X, Qp120), Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, queue:in(X, Qp121), Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, queue:in(X, Qp122), Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, queue:in(X, Qp123), + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + queue:in(X, Qp124), Qp125, Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, queue:in(X, Qp125), Qp126, Qp127, Qp128}); +?IN_HIGHER_Qp128(126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, queue:in(X, Qp126), Qp127, Qp128}); +?IN_HIGHER_Qp128(127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, queue:in(X, Qp127), Qp128}); +?IN_HIGHER_Qp128(128, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, queue:in(X, Qp128)}). + +%% @hidden +-define(IN_LOWER_Qn128(P, V), +in_lower(P, + {Pc, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + V, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn112(P, V), +in_lower(P, + {Pc, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, + V, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn96(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, + V, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn80(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, + V, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn64(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, + V, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn48(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, + V, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn32(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qn16(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp16(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp32(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp48(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V, + Qp64, Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp64(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V, + Qp80, Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp80(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V, + Qp96, Qp112, Qp128}). +-define(IN_LOWER_Qp96(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V, + Qp112, Qp128}). +-define(IN_LOWER_Qp112(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V, + Qp128}). +-define(IN_LOWER_Qp128(P, V), +in_lower(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V}). + +?IN_LOWER_Qn128(-128, + {queue:in(X, Qn128), Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-127, + {Qn128, queue:in(X, Qn127), Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-126, + {Qn128, Qn127, queue:in(X, Qn126), Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-125, + {Qn128, Qn127, Qn126, queue:in(X, Qn125), Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-124, + {Qn128, Qn127, Qn126, Qn125, queue:in(X, Qn124), + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + queue:in(X, Qn123), Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, queue:in(X, Qn122), Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, queue:in(X, Qn121), Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, queue:in(X, Qn120), Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, queue:in(X, Qn119), Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, queue:in(X, Qn118), + Qn117, Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + queue:in(X, Qn117), Qn116, Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, queue:in(X, Qn116), Qn115, Qn114, Qn113}); +?IN_LOWER_Qn128(-115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, queue:in(X, Qn115), Qn114, Qn113}); +?IN_LOWER_Qn128(-114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, queue:in(X, Qn114), Qn113}); +?IN_LOWER_Qn128(-113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, queue:in(X, Qn113)}); +?IN_LOWER_Qn112(-112, + {queue:in(X, Qn112), Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-111, + {Qn112, queue:in(X, Qn111), Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-110, + {Qn112, Qn111, queue:in(X, Qn110), Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-109, + {Qn112, Qn111, Qn110, queue:in(X, Qn109), Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-108, + {Qn112, Qn111, Qn110, Qn109, queue:in(X, Qn108), + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + queue:in(X, Qn107), Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, queue:in(X, Qn106), Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, queue:in(X, Qn105), Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, queue:in(X, Qn104), Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, queue:in(X, Qn103), Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, queue:in(X, Qn102), + Qn101, Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + queue:in(X, Qn101), Qn100, Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, queue:in(X, Qn100), Qn99, Qn98, Qn97}); +?IN_LOWER_Qn112(-99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, queue:in(X, Qn99), Qn98, Qn97}); +?IN_LOWER_Qn112(-98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, queue:in(X, Qn98), Qn97}); +?IN_LOWER_Qn112(-97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, queue:in(X, Qn97)}); +?IN_LOWER_Qn96(-96, + {queue:in(X, Qn96), Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-95, + {Qn96, queue:in(X, Qn95), Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-94, + {Qn96, Qn95, queue:in(X, Qn94), Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-93, + {Qn96, Qn95, Qn94, queue:in(X, Qn93), Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-92, + {Qn96, Qn95, Qn94, Qn93, queue:in(X, Qn92), + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + queue:in(X, Qn91), Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, queue:in(X, Qn90), Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, queue:in(X, Qn89), Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, queue:in(X, Qn88), Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, queue:in(X, Qn87), Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, queue:in(X, Qn86), + Qn85, Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + queue:in(X, Qn85), Qn84, Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, queue:in(X, Qn84), Qn83, Qn82, Qn81}); +?IN_LOWER_Qn96(-83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, queue:in(X, Qn83), Qn82, Qn81}); +?IN_LOWER_Qn96(-82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, queue:in(X, Qn82), Qn81}); +?IN_LOWER_Qn96(-81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, queue:in(X, Qn81)}); +?IN_LOWER_Qn80(-80, + {queue:in(X, Qn80), Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-79, + {Qn80, queue:in(X, Qn79), Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-78, + {Qn80, Qn79, queue:in(X, Qn78), Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-77, + {Qn80, Qn79, Qn78, queue:in(X, Qn77), Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-76, + {Qn80, Qn79, Qn78, Qn77, queue:in(X, Qn76), + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + queue:in(X, Qn75), Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, queue:in(X, Qn74), Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, queue:in(X, Qn73), Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, queue:in(X, Qn72), Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, queue:in(X, Qn71), Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, queue:in(X, Qn70), + Qn69, Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + queue:in(X, Qn69), Qn68, Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, queue:in(X, Qn68), Qn67, Qn66, Qn65}); +?IN_LOWER_Qn80(-67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, queue:in(X, Qn67), Qn66, Qn65}); +?IN_LOWER_Qn80(-66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, queue:in(X, Qn66), Qn65}); +?IN_LOWER_Qn80(-65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, queue:in(X, Qn65)}); +?IN_LOWER_Qn64(-64, + {queue:in(X, Qn64), Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-63, + {Qn64, queue:in(X, Qn63), Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-62, + {Qn64, Qn63, queue:in(X, Qn62), Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-61, + {Qn64, Qn63, Qn62, queue:in(X, Qn61), Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-60, + {Qn64, Qn63, Qn62, Qn61, queue:in(X, Qn60), + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + queue:in(X, Qn59), Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, queue:in(X, Qn58), Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, queue:in(X, Qn57), Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, queue:in(X, Qn56), Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, queue:in(X, Qn55), Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, queue:in(X, Qn54), + Qn53, Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + queue:in(X, Qn53), Qn52, Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, queue:in(X, Qn52), Qn51, Qn50, Qn49}); +?IN_LOWER_Qn64(-51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, queue:in(X, Qn51), Qn50, Qn49}); +?IN_LOWER_Qn64(-50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, queue:in(X, Qn50), Qn49}); +?IN_LOWER_Qn64(-49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, queue:in(X, Qn49)}); +?IN_LOWER_Qn48(-48, + {queue:in(X, Qn48), Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-47, + {Qn48, queue:in(X, Qn47), Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-46, + {Qn48, Qn47, queue:in(X, Qn46), Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-45, + {Qn48, Qn47, Qn46, queue:in(X, Qn45), Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-44, + {Qn48, Qn47, Qn46, Qn45, queue:in(X, Qn44), + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + queue:in(X, Qn43), Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, queue:in(X, Qn42), Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, queue:in(X, Qn41), Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, queue:in(X, Qn40), Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, queue:in(X, Qn39), Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, queue:in(X, Qn38), + Qn37, Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + queue:in(X, Qn37), Qn36, Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, queue:in(X, Qn36), Qn35, Qn34, Qn33}); +?IN_LOWER_Qn48(-35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, queue:in(X, Qn35), Qn34, Qn33}); +?IN_LOWER_Qn48(-34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, queue:in(X, Qn34), Qn33}); +?IN_LOWER_Qn48(-33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, queue:in(X, Qn33)}); +?IN_LOWER_Qn32(-32, + {queue:in(X, Qn32), Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-31, + {Qn32, queue:in(X, Qn31), Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-30, + {Qn32, Qn31, queue:in(X, Qn30), Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-29, + {Qn32, Qn31, Qn30, queue:in(X, Qn29), Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-28, + {Qn32, Qn31, Qn30, Qn29, queue:in(X, Qn28), + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + queue:in(X, Qn27), Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, queue:in(X, Qn26), Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, queue:in(X, Qn25), Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, queue:in(X, Qn24), Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, queue:in(X, Qn23), Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, queue:in(X, Qn22), + Qn21, Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + queue:in(X, Qn21), Qn20, Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, queue:in(X, Qn20), Qn19, Qn18, Qn17}); +?IN_LOWER_Qn32(-19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, queue:in(X, Qn19), Qn18, Qn17}); +?IN_LOWER_Qn32(-18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, queue:in(X, Qn18), Qn17}); +?IN_LOWER_Qn32(-17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, queue:in(X, Qn17)}); +?IN_LOWER_Qn16(-16, + {queue:in(X, Qn16), Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-15, + {Qn16, queue:in(X, Qn15), Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-14, + {Qn16, Qn15, queue:in(X, Qn14), Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-13, + {Qn16, Qn15, Qn14, queue:in(X, Qn13), Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-12, + {Qn16, Qn15, Qn14, Qn13, queue:in(X, Qn12), + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + queue:in(X, Qn11), Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, queue:in(X, Qn10), Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, queue:in(X, Qn9), Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, queue:in(X, Qn8), Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, queue:in(X, Qn7), Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, queue:in(X, Qn6), + Qn5, Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + queue:in(X, Qn5), Qn4, Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, queue:in(X, Qn4), Qn3, Qn2, Qn1}); +?IN_LOWER_Qn16(-3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, queue:in(X, Qn3), Qn2, Qn1}); +?IN_LOWER_Qn16(-2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, queue:in(X, Qn2), Qn1}); +?IN_LOWER_Qn16(-1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, queue:in(X, Qn1)}); +in_lower(0, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}, X) -> + {Pc, + Size + 1, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + queue:in(X, Q0), + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}; +?IN_LOWER_Qp16(1, + {queue:in(X, Qp1), Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(2, + {Qp1, queue:in(X, Qp2), Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(3, + {Qp1, Qp2, queue:in(X, Qp3), Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(4, + {Qp1, Qp2, Qp3, queue:in(X, Qp4), Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(5, + {Qp1, Qp2, Qp3, Qp4, queue:in(X, Qp5), + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + queue:in(X, Qp6), Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, queue:in(X, Qp7), Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, queue:in(X, Qp8), Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, queue:in(X, Qp9), Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, queue:in(X, Qp10), Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, queue:in(X, Qp11), + Qp12, Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + queue:in(X, Qp12), Qp13, Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, queue:in(X, Qp13), Qp14, Qp15, Qp16}); +?IN_LOWER_Qp16(14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, queue:in(X, Qp14), Qp15, Qp16}); +?IN_LOWER_Qp16(15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, queue:in(X, Qp15), Qp16}); +?IN_LOWER_Qp16(16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, queue:in(X, Qp16)}); +?IN_LOWER_Qp32(17, + {queue:in(X, Qp17), Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(18, + {Qp17, queue:in(X, Qp18), Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(19, + {Qp17, Qp18, queue:in(X, Qp19), Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(20, + {Qp17, Qp18, Qp19, queue:in(X, Qp20), Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(21, + {Qp17, Qp18, Qp19, Qp20, queue:in(X, Qp21), + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + queue:in(X, Qp22), Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, queue:in(X, Qp23), Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, queue:in(X, Qp24), Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, queue:in(X, Qp25), Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, queue:in(X, Qp26), Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, queue:in(X, Qp27), + Qp28, Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + queue:in(X, Qp28), Qp29, Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, queue:in(X, Qp29), Qp30, Qp31, Qp32}); +?IN_LOWER_Qp32(30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, queue:in(X, Qp30), Qp31, Qp32}); +?IN_LOWER_Qp32(31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, queue:in(X, Qp31), Qp32}); +?IN_LOWER_Qp32(32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, queue:in(X, Qp32)}); +?IN_LOWER_Qp48(33, + {queue:in(X, Qp33), Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(34, + {Qp33, queue:in(X, Qp34), Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(35, + {Qp33, Qp34, queue:in(X, Qp35), Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(36, + {Qp33, Qp34, Qp35, queue:in(X, Qp36), Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(37, + {Qp33, Qp34, Qp35, Qp36, queue:in(X, Qp37), + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + queue:in(X, Qp38), Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, queue:in(X, Qp39), Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, queue:in(X, Qp40), Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, queue:in(X, Qp41), Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, queue:in(X, Qp42), Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, queue:in(X, Qp43), + Qp44, Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + queue:in(X, Qp44), Qp45, Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, queue:in(X, Qp45), Qp46, Qp47, Qp48}); +?IN_LOWER_Qp48(46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, queue:in(X, Qp46), Qp47, Qp48}); +?IN_LOWER_Qp48(47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, queue:in(X, Qp47), Qp48}); +?IN_LOWER_Qp48(48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, queue:in(X, Qp48)}); +?IN_LOWER_Qp64(49, + {queue:in(X, Qp49), Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(50, + {Qp49, queue:in(X, Qp50), Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(51, + {Qp49, Qp50, queue:in(X, Qp51), Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(52, + {Qp49, Qp50, Qp51, queue:in(X, Qp52), Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(53, + {Qp49, Qp50, Qp51, Qp52, queue:in(X, Qp53), + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + queue:in(X, Qp54), Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, queue:in(X, Qp55), Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, queue:in(X, Qp56), Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, queue:in(X, Qp57), Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, queue:in(X, Qp58), Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, queue:in(X, Qp59), + Qp60, Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + queue:in(X, Qp60), Qp61, Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, queue:in(X, Qp61), Qp62, Qp63, Qp64}); +?IN_LOWER_Qp64(62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, queue:in(X, Qp62), Qp63, Qp64}); +?IN_LOWER_Qp64(63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, queue:in(X, Qp63), Qp64}); +?IN_LOWER_Qp64(64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, queue:in(X, Qp64)}); +?IN_LOWER_Qp80(65, + {queue:in(X, Qp65), Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(66, + {Qp65, queue:in(X, Qp66), Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(67, + {Qp65, Qp66, queue:in(X, Qp67), Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(68, + {Qp65, Qp66, Qp67, queue:in(X, Qp68), Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(69, + {Qp65, Qp66, Qp67, Qp68, queue:in(X, Qp69), + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + queue:in(X, Qp70), Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, queue:in(X, Qp71), Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, queue:in(X, Qp72), Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, queue:in(X, Qp73), Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, queue:in(X, Qp74), Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, queue:in(X, Qp75), + Qp76, Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + queue:in(X, Qp76), Qp77, Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, queue:in(X, Qp77), Qp78, Qp79, Qp80}); +?IN_LOWER_Qp80(78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, queue:in(X, Qp78), Qp79, Qp80}); +?IN_LOWER_Qp80(79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, queue:in(X, Qp79), Qp80}); +?IN_LOWER_Qp80(80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, queue:in(X, Qp80)}); +?IN_LOWER_Qp96(81, + {queue:in(X, Qp81), Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(82, + {Qp81, queue:in(X, Qp82), Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(83, + {Qp81, Qp82, queue:in(X, Qp83), Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(84, + {Qp81, Qp82, Qp83, queue:in(X, Qp84), Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(85, + {Qp81, Qp82, Qp83, Qp84, queue:in(X, Qp85), + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + queue:in(X, Qp86), Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, queue:in(X, Qp87), Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, queue:in(X, Qp88), Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, queue:in(X, Qp89), Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, queue:in(X, Qp90), Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, queue:in(X, Qp91), + Qp92, Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + queue:in(X, Qp92), Qp93, Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, queue:in(X, Qp93), Qp94, Qp95, Qp96}); +?IN_LOWER_Qp96(94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, queue:in(X, Qp94), Qp95, Qp96}); +?IN_LOWER_Qp96(95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, queue:in(X, Qp95), Qp96}); +?IN_LOWER_Qp96(96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, queue:in(X, Qp96)}); +?IN_LOWER_Qp112(97, + {queue:in(X, Qp97), Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(98, + {Qp97, queue:in(X, Qp98), Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(99, + {Qp97, Qp98, queue:in(X, Qp99), Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(100, + {Qp97, Qp98, Qp99, queue:in(X, Qp100), Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(101, + {Qp97, Qp98, Qp99, Qp100, queue:in(X, Qp101), + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + queue:in(X, Qp102), Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, queue:in(X, Qp103), Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, queue:in(X, Qp104), Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, queue:in(X, Qp105), Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, queue:in(X, Qp106), Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, queue:in(X, Qp107), + Qp108, Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + queue:in(X, Qp108), Qp109, Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, queue:in(X, Qp109), Qp110, Qp111, Qp112}); +?IN_LOWER_Qp112(110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, queue:in(X, Qp110), Qp111, Qp112}); +?IN_LOWER_Qp112(111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, queue:in(X, Qp111), Qp112}); +?IN_LOWER_Qp112(112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, queue:in(X, Qp112)}); +?IN_LOWER_Qp128(113, + {queue:in(X, Qp113), Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(114, + {Qp113, queue:in(X, Qp114), Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(115, + {Qp113, Qp114, queue:in(X, Qp115), Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(116, + {Qp113, Qp114, Qp115, queue:in(X, Qp116), Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(117, + {Qp113, Qp114, Qp115, Qp116, queue:in(X, Qp117), + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + queue:in(X, Qp118), Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, queue:in(X, Qp119), Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, queue:in(X, Qp120), Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, queue:in(X, Qp121), Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, queue:in(X, Qp122), Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, queue:in(X, Qp123), + Qp124, Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + queue:in(X, Qp124), Qp125, Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, queue:in(X, Qp125), Qp126, Qp127, Qp128}); +?IN_LOWER_Qp128(126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, queue:in(X, Qp126), Qp127, Qp128}); +?IN_LOWER_Qp128(127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, queue:in(X, Qp127), Qp128}); +?IN_LOWER_Qp128(128, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, queue:in(X, Qp128)}). + +%% @hidden +-define(OUT_CURRENT_Qn128(P, V1, V2, V3), +out_current(P, + {_, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + V3, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn112(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, + V3, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn96(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, + V3, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn80(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, + V3, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn64(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, + V3, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn48(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, + V3, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn32(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V3, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qn16(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V3, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp16(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V3, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp32(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V3, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp48(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V3, + Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp64(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V3, + Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp80(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V3, + Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp96(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V3, + Qp112, Qp128}} + end). +-define(OUT_CURRENT_Qp112(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V3, + Qp128}} + end). +-define(OUT_CURRENT_Qp128(P, V1, V2, V3), +out_current(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}} = Q) -> + {Value, V2} = queue:out(V1), + if + Value =:= empty -> + out_current(P + 1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V3}} + end). + +?OUT_CURRENT_Qn128(-128, + Qn128, NewQn128, + {NewQn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-127, + Qn127, NewQn127, + {Qn128, NewQn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-126, + Qn126, NewQn126, + {Qn128, Qn127, NewQn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-125, + Qn125, NewQn125, + {Qn128, Qn127, Qn126, NewQn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-124, + Qn124, NewQn124, + {Qn128, Qn127, Qn126, Qn125, NewQn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-123, + Qn123, NewQn123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + NewQn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-122, + Qn122, NewQn122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, NewQn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-121, + Qn121, NewQn121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, NewQn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-120, + Qn120, NewQn120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, NewQn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-119, + Qn119, NewQn119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, NewQn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-118, + Qn118, NewQn118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, NewQn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-117, + Qn117, NewQn117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + NewQn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-116, + Qn116, NewQn116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, NewQn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-115, + Qn115, NewQn115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, NewQn115, Qn114, Qn113}); +?OUT_CURRENT_Qn128(-114, + Qn114, NewQn114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, NewQn114, Qn113}); +?OUT_CURRENT_Qn128(-113, + Qn113, NewQn113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, NewQn113}); +?OUT_CURRENT_Qn112(-112, + Qn112, NewQn112, + {NewQn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-111, + Qn111, NewQn111, + {Qn112, NewQn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-110, + Qn110, NewQn110, + {Qn112, Qn111, NewQn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-109, + Qn109, NewQn109, + {Qn112, Qn111, Qn110, NewQn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-108, + Qn108, NewQn108, + {Qn112, Qn111, Qn110, Qn109, NewQn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-107, + Qn107, NewQn107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + NewQn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-106, + Qn106, NewQn106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, NewQn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-105, + Qn105, NewQn105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, NewQn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-104, + Qn104, NewQn104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, NewQn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-103, + Qn103, NewQn103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, NewQn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-102, + Qn102, NewQn102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, NewQn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-101, + Qn101, NewQn101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + NewQn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-100, + Qn100, NewQn100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, NewQn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-99, + Qn99, NewQn99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, NewQn99, Qn98, Qn97}); +?OUT_CURRENT_Qn112(-98, + Qn98, NewQn98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, NewQn98, Qn97}); +?OUT_CURRENT_Qn112(-97, + Qn97, NewQn97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, NewQn97}); +?OUT_CURRENT_Qn96(-96, + Qn96, NewQn96, + {NewQn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-95, + Qn95, NewQn95, + {Qn96, NewQn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-94, + Qn94, NewQn94, + {Qn96, Qn95, NewQn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-93, + Qn93, NewQn93, + {Qn96, Qn95, Qn94, NewQn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-92, + Qn92, NewQn92, + {Qn96, Qn95, Qn94, Qn93, NewQn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-91, + Qn91, NewQn91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + NewQn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-90, + Qn90, NewQn90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, NewQn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-89, + Qn89, NewQn89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, NewQn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-88, + Qn88, NewQn88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, NewQn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-87, + Qn87, NewQn87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, NewQn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-86, + Qn86, NewQn86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, NewQn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-85, + Qn85, NewQn85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + NewQn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-84, + Qn84, NewQn84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, NewQn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-83, + Qn83, NewQn83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, NewQn83, Qn82, Qn81}); +?OUT_CURRENT_Qn96(-82, + Qn82, NewQn82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, NewQn82, Qn81}); +?OUT_CURRENT_Qn96(-81, + Qn81, NewQn81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, NewQn81}); +?OUT_CURRENT_Qn80(-80, + Qn80, NewQn80, + {NewQn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-79, + Qn79, NewQn79, + {Qn80, NewQn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-78, + Qn78, NewQn78, + {Qn80, Qn79, NewQn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-77, + Qn77, NewQn77, + {Qn80, Qn79, Qn78, NewQn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-76, + Qn76, NewQn76, + {Qn80, Qn79, Qn78, Qn77, NewQn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-75, + Qn75, NewQn75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + NewQn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-74, + Qn74, NewQn74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, NewQn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-73, + Qn73, NewQn73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, NewQn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-72, + Qn72, NewQn72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, NewQn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-71, + Qn71, NewQn71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, NewQn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-70, + Qn70, NewQn70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, NewQn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-69, + Qn69, NewQn69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + NewQn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-68, + Qn68, NewQn68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, NewQn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-67, + Qn67, NewQn67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, NewQn67, Qn66, Qn65}); +?OUT_CURRENT_Qn80(-66, + Qn66, NewQn66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, NewQn66, Qn65}); +?OUT_CURRENT_Qn80(-65, + Qn65, NewQn65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, NewQn65}); +?OUT_CURRENT_Qn64(-64, + Qn64, NewQn64, + {NewQn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-63, + Qn63, NewQn63, + {Qn64, NewQn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-62, + Qn62, NewQn62, + {Qn64, Qn63, NewQn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-61, + Qn61, NewQn61, + {Qn64, Qn63, Qn62, NewQn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-60, + Qn60, NewQn60, + {Qn64, Qn63, Qn62, Qn61, NewQn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-59, + Qn59, NewQn59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + NewQn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-58, + Qn58, NewQn58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, NewQn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-57, + Qn57, NewQn57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, NewQn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-56, + Qn56, NewQn56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, NewQn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-55, + Qn55, NewQn55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, NewQn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-54, + Qn54, NewQn54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, NewQn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-53, + Qn53, NewQn53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + NewQn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-52, + Qn52, NewQn52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, NewQn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-51, + Qn51, NewQn51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, NewQn51, Qn50, Qn49}); +?OUT_CURRENT_Qn64(-50, + Qn50, NewQn50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, NewQn50, Qn49}); +?OUT_CURRENT_Qn64(-49, + Qn49, NewQn49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, NewQn49}); +?OUT_CURRENT_Qn48(-48, + Qn48, NewQn48, + {NewQn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-47, + Qn47, NewQn47, + {Qn48, NewQn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-46, + Qn46, NewQn46, + {Qn48, Qn47, NewQn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-45, + Qn45, NewQn45, + {Qn48, Qn47, Qn46, NewQn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-44, + Qn44, NewQn44, + {Qn48, Qn47, Qn46, Qn45, NewQn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-43, + Qn43, NewQn43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + NewQn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-42, + Qn42, NewQn42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, NewQn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-41, + Qn41, NewQn41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, NewQn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-40, + Qn40, NewQn40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, NewQn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-39, + Qn39, NewQn39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, NewQn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-38, + Qn38, NewQn38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, NewQn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-37, + Qn37, NewQn37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + NewQn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-36, + Qn36, NewQn36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, NewQn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-35, + Qn35, NewQn35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, NewQn35, Qn34, Qn33}); +?OUT_CURRENT_Qn48(-34, + Qn34, NewQn34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, NewQn34, Qn33}); +?OUT_CURRENT_Qn48(-33, + Qn33, NewQn33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, NewQn33}); +?OUT_CURRENT_Qn32(-32, + Qn32, NewQn32, + {NewQn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-31, + Qn31, NewQn31, + {Qn32, NewQn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-30, + Qn30, NewQn30, + {Qn32, Qn31, NewQn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-29, + Qn29, NewQn29, + {Qn32, Qn31, Qn30, NewQn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-28, + Qn28, NewQn28, + {Qn32, Qn31, Qn30, Qn29, NewQn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-27, + Qn27, NewQn27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + NewQn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-26, + Qn26, NewQn26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, NewQn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-25, + Qn25, NewQn25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, NewQn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-24, + Qn24, NewQn24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, NewQn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-23, + Qn23, NewQn23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, NewQn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-22, + Qn22, NewQn22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, NewQn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-21, + Qn21, NewQn21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + NewQn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-20, + Qn20, NewQn20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, NewQn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-19, + Qn19, NewQn19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, NewQn19, Qn18, Qn17}); +?OUT_CURRENT_Qn32(-18, + Qn18, NewQn18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, NewQn18, Qn17}); +?OUT_CURRENT_Qn32(-17, + Qn17, NewQn17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, NewQn17}); +?OUT_CURRENT_Qn16(-16, + Qn16, NewQn16, + {NewQn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-15, + Qn15, NewQn15, + {Qn16, NewQn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-14, + Qn14, NewQn14, + {Qn16, Qn15, NewQn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-13, + Qn13, NewQn13, + {Qn16, Qn15, Qn14, NewQn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-12, + Qn12, NewQn12, + {Qn16, Qn15, Qn14, Qn13, NewQn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-11, + Qn11, NewQn11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + NewQn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-10, + Qn10, NewQn10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, NewQn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-9, + Qn9, NewQn9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, NewQn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-8, + Qn8, NewQn8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, NewQn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-7, + Qn7, NewQn7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, NewQn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-6, + Qn6, NewQn6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, NewQn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-5, + Qn5, NewQn5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + NewQn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-4, + Qn4, NewQn4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, NewQn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-3, + Qn3, NewQn3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, NewQn3, Qn2, Qn1}); +?OUT_CURRENT_Qn16(-2, + Qn2, NewQn2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, NewQn2, Qn1}); +?OUT_CURRENT_Qn16(-1, + Qn1, NewQn1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, NewQn1}); +out_current(0, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + {Value, NewQ0} = queue:out(Q0), + if + Value =:= empty -> + out_current(1, Q); + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> 0 end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + NewQ0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end; +?OUT_CURRENT_Qp16(1, + Qp1, NewQp1, + {NewQp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(2, + Qp2, NewQp2, + {Qp1, NewQp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(3, + Qp3, NewQp3, + {Qp1, Qp2, NewQp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(4, + Qp4, NewQp4, + {Qp1, Qp2, Qp3, NewQp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(5, + Qp5, NewQp5, + {Qp1, Qp2, Qp3, Qp4, NewQp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(6, + Qp6, NewQp6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + NewQp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(7, + Qp7, NewQp7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, NewQp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(8, + Qp8, NewQp8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, NewQp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(9, + Qp9, NewQp9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, NewQp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(10, + Qp10, NewQp10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, NewQp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(11, + Qp11, NewQp11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, NewQp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(12, + Qp12, NewQp12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + NewQp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(13, + Qp13, NewQp13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, NewQp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(14, + Qp14, NewQp14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, NewQp14, Qp15, Qp16}); +?OUT_CURRENT_Qp16(15, + Qp15, NewQp15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, NewQp15, Qp16}); +?OUT_CURRENT_Qp16(16, + Qp16, NewQp16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, NewQp16}); +?OUT_CURRENT_Qp32(17, + Qp17, NewQp17, + {NewQp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(18, + Qp18, NewQp18, + {Qp17, NewQp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(19, + Qp19, NewQp19, + {Qp17, Qp18, NewQp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(20, + Qp20, NewQp20, + {Qp17, Qp18, Qp19, NewQp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(21, + Qp21, NewQp21, + {Qp17, Qp18, Qp19, Qp20, NewQp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(22, + Qp22, NewQp22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + NewQp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(23, + Qp23, NewQp23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, NewQp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(24, + Qp24, NewQp24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, NewQp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(25, + Qp25, NewQp25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, NewQp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(26, + Qp26, NewQp26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, NewQp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(27, + Qp27, NewQp27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, NewQp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(28, + Qp28, NewQp28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + NewQp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(29, + Qp29, NewQp29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, NewQp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(30, + Qp30, NewQp30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, NewQp30, Qp31, Qp32}); +?OUT_CURRENT_Qp32(31, + Qp31, NewQp31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, NewQp31, Qp32}); +?OUT_CURRENT_Qp32(32, + Qp32, NewQp32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, NewQp32}); +?OUT_CURRENT_Qp48(33, + Qp33, NewQp33, + {NewQp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(34, + Qp34, NewQp34, + {Qp33, NewQp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(35, + Qp35, NewQp35, + {Qp33, Qp34, NewQp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(36, + Qp36, NewQp36, + {Qp33, Qp34, Qp35, NewQp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(37, + Qp37, NewQp37, + {Qp33, Qp34, Qp35, Qp36, NewQp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(38, + Qp38, NewQp38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + NewQp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(39, + Qp39, NewQp39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, NewQp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(40, + Qp40, NewQp40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, NewQp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(41, + Qp41, NewQp41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, NewQp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(42, + Qp42, NewQp42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, NewQp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(43, + Qp43, NewQp43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, NewQp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(44, + Qp44, NewQp44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + NewQp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(45, + Qp45, NewQp45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, NewQp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(46, + Qp46, NewQp46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, NewQp46, Qp47, Qp48}); +?OUT_CURRENT_Qp48(47, + Qp47, NewQp47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, NewQp47, Qp48}); +?OUT_CURRENT_Qp48(48, + Qp48, NewQp48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, NewQp48}); +?OUT_CURRENT_Qp64(49, + Qp49, NewQp49, + {NewQp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(50, + Qp50, NewQp50, + {Qp49, NewQp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(51, + Qp51, NewQp51, + {Qp49, Qp50, NewQp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(52, + Qp52, NewQp52, + {Qp49, Qp50, Qp51, NewQp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(53, + Qp53, NewQp53, + {Qp49, Qp50, Qp51, Qp52, NewQp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(54, + Qp54, NewQp54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + NewQp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(55, + Qp55, NewQp55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, NewQp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(56, + Qp56, NewQp56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, NewQp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(57, + Qp57, NewQp57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, NewQp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(58, + Qp58, NewQp58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, NewQp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(59, + Qp59, NewQp59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, NewQp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(60, + Qp60, NewQp60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + NewQp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(61, + Qp61, NewQp61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, NewQp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(62, + Qp62, NewQp62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, NewQp62, Qp63, Qp64}); +?OUT_CURRENT_Qp64(63, + Qp63, NewQp63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, NewQp63, Qp64}); +?OUT_CURRENT_Qp64(64, + Qp64, NewQp64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, NewQp64}); +?OUT_CURRENT_Qp80(65, + Qp65, NewQp65, + {NewQp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(66, + Qp66, NewQp66, + {Qp65, NewQp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(67, + Qp67, NewQp67, + {Qp65, Qp66, NewQp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(68, + Qp68, NewQp68, + {Qp65, Qp66, Qp67, NewQp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(69, + Qp69, NewQp69, + {Qp65, Qp66, Qp67, Qp68, NewQp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(70, + Qp70, NewQp70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + NewQp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(71, + Qp71, NewQp71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, NewQp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(72, + Qp72, NewQp72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, NewQp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(73, + Qp73, NewQp73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, NewQp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(74, + Qp74, NewQp74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, NewQp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(75, + Qp75, NewQp75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, NewQp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(76, + Qp76, NewQp76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + NewQp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(77, + Qp77, NewQp77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, NewQp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(78, + Qp78, NewQp78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, NewQp78, Qp79, Qp80}); +?OUT_CURRENT_Qp80(79, + Qp79, NewQp79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, NewQp79, Qp80}); +?OUT_CURRENT_Qp80(80, + Qp80, NewQp80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, NewQp80}); +?OUT_CURRENT_Qp96(81, + Qp81, NewQp81, + {NewQp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(82, + Qp82, NewQp82, + {Qp81, NewQp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(83, + Qp83, NewQp83, + {Qp81, Qp82, NewQp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(84, + Qp84, NewQp84, + {Qp81, Qp82, Qp83, NewQp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(85, + Qp85, NewQp85, + {Qp81, Qp82, Qp83, Qp84, NewQp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(86, + Qp86, NewQp86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + NewQp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(87, + Qp87, NewQp87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, NewQp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(88, + Qp88, NewQp88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, NewQp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(89, + Qp89, NewQp89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, NewQp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(90, + Qp90, NewQp90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, NewQp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(91, + Qp91, NewQp91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, NewQp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(92, + Qp92, NewQp92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + NewQp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(93, + Qp93, NewQp93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, NewQp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(94, + Qp94, NewQp94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, NewQp94, Qp95, Qp96}); +?OUT_CURRENT_Qp96(95, + Qp95, NewQp95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, NewQp95, Qp96}); +?OUT_CURRENT_Qp96(96, + Qp96, NewQp96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, NewQp96}); +?OUT_CURRENT_Qp112(97, + Qp97, NewQp97, + {NewQp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(98, + Qp98, NewQp98, + {Qp97, NewQp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(99, + Qp99, NewQp99, + {Qp97, Qp98, NewQp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(100, + Qp100, NewQp100, + {Qp97, Qp98, Qp99, NewQp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(101, + Qp101, NewQp101, + {Qp97, Qp98, Qp99, Qp100, NewQp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(102, + Qp102, NewQp102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + NewQp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(103, + Qp103, NewQp103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, NewQp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(104, + Qp104, NewQp104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, NewQp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(105, + Qp105, NewQp105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, NewQp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(106, + Qp106, NewQp106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, NewQp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(107, + Qp107, NewQp107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, NewQp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(108, + Qp108, NewQp108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + NewQp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(109, + Qp109, NewQp109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, NewQp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(110, + Qp110, NewQp110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, NewQp110, Qp111, Qp112}); +?OUT_CURRENT_Qp112(111, + Qp111, NewQp111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, NewQp111, Qp112}); +?OUT_CURRENT_Qp112(112, + Qp112, NewQp112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, NewQp112}); +?OUT_CURRENT_Qp128(113, + Qp113, NewQp113, + {NewQp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(114, + Qp114, NewQp114, + {Qp113, NewQp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(115, + Qp115, NewQp115, + {Qp113, Qp114, NewQp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(116, + Qp116, NewQp116, + {Qp113, Qp114, Qp115, NewQp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(117, + Qp117, NewQp117, + {Qp113, Qp114, Qp115, Qp116, NewQp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(118, + Qp118, NewQp118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + NewQp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(119, + Qp119, NewQp119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, NewQp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(120, + Qp120, NewQp120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, NewQp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(121, + Qp121, NewQp121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, NewQp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(122, + Qp122, NewQp122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, NewQp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(123, + Qp123, NewQp123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, NewQp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(124, + Qp124, NewQp124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + NewQp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(125, + Qp125, NewQp125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, NewQp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(126, + Qp126, NewQp126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, NewQp126, Qp127, Qp128}); +?OUT_CURRENT_Qp128(127, + Qp127, NewQp127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, NewQp127, Qp128}); +out_current(128, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}) -> + {Value, NewQp128} = queue:out(Qp128), + if + Value =:= empty -> + {empty, + {empty, + 0, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, NewQp128}}}; + true -> + NewSize = Size - 1, + {Value, + {if NewSize == 0 -> empty; true -> 128 end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, NewQp128}}} + end. + +%% @hidden +-define(OUT_CURRENT_P_Qn128(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + V3, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn112(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, + V3, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn96(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, + V3, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn80(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, + V3, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn64(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, + V3, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn48(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, + V3, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn32(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V3, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qn16(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V3, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp16(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V3, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp32(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V3, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp48(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V3, + Qp64, Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp64(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V3, + Qp80, Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp80(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V3, + Qp96, Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp96(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V3, + Qp112, Qp128}} + end). +-define(OUT_CURRENT_P_Qp112(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V3, + Qp128}} + end). +-define(OUT_CURRENT_P_Qp128(P, V1, V2, V3), +out_current_p(P, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}} = Q) -> + case queue:out(V1) of + {empty, _} -> + out_current_p(P + 1, Q); + {{value, X}, V2} -> + NewSize = Size - 1, + {{value, X, P}, + {if NewSize == 0 -> empty; true -> P end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V3}} + end). + +?OUT_CURRENT_P_Qn128(-128, + Qn128, NewQn128, + {NewQn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-127, + Qn127, NewQn127, + {Qn128, NewQn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-126, + Qn126, NewQn126, + {Qn128, Qn127, NewQn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-125, + Qn125, NewQn125, + {Qn128, Qn127, Qn126, NewQn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-124, + Qn124, NewQn124, + {Qn128, Qn127, Qn126, Qn125, NewQn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-123, + Qn123, NewQn123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + NewQn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-122, + Qn122, NewQn122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, NewQn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-121, + Qn121, NewQn121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, NewQn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-120, + Qn120, NewQn120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, NewQn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-119, + Qn119, NewQn119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, NewQn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-118, + Qn118, NewQn118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, NewQn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-117, + Qn117, NewQn117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + NewQn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-116, + Qn116, NewQn116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, NewQn116, Qn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-115, + Qn115, NewQn115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, NewQn115, Qn114, Qn113}); +?OUT_CURRENT_P_Qn128(-114, + Qn114, NewQn114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, NewQn114, Qn113}); +?OUT_CURRENT_P_Qn128(-113, + Qn113, NewQn113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, NewQn113}); +?OUT_CURRENT_P_Qn112(-112, + Qn112, NewQn112, + {NewQn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-111, + Qn111, NewQn111, + {Qn112, NewQn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-110, + Qn110, NewQn110, + {Qn112, Qn111, NewQn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-109, + Qn109, NewQn109, + {Qn112, Qn111, Qn110, NewQn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-108, + Qn108, NewQn108, + {Qn112, Qn111, Qn110, Qn109, NewQn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-107, + Qn107, NewQn107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + NewQn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-106, + Qn106, NewQn106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, NewQn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-105, + Qn105, NewQn105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, NewQn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-104, + Qn104, NewQn104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, NewQn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-103, + Qn103, NewQn103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, NewQn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-102, + Qn102, NewQn102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, NewQn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-101, + Qn101, NewQn101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + NewQn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-100, + Qn100, NewQn100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, NewQn100, Qn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-99, + Qn99, NewQn99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, NewQn99, Qn98, Qn97}); +?OUT_CURRENT_P_Qn112(-98, + Qn98, NewQn98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, NewQn98, Qn97}); +?OUT_CURRENT_P_Qn112(-97, + Qn97, NewQn97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, NewQn97}); +?OUT_CURRENT_P_Qn96(-96, + Qn96, NewQn96, + {NewQn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-95, + Qn95, NewQn95, + {Qn96, NewQn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-94, + Qn94, NewQn94, + {Qn96, Qn95, NewQn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-93, + Qn93, NewQn93, + {Qn96, Qn95, Qn94, NewQn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-92, + Qn92, NewQn92, + {Qn96, Qn95, Qn94, Qn93, NewQn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-91, + Qn91, NewQn91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + NewQn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-90, + Qn90, NewQn90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, NewQn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-89, + Qn89, NewQn89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, NewQn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-88, + Qn88, NewQn88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, NewQn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-87, + Qn87, NewQn87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, NewQn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-86, + Qn86, NewQn86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, NewQn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-85, + Qn85, NewQn85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + NewQn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-84, + Qn84, NewQn84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, NewQn84, Qn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-83, + Qn83, NewQn83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, NewQn83, Qn82, Qn81}); +?OUT_CURRENT_P_Qn96(-82, + Qn82, NewQn82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, NewQn82, Qn81}); +?OUT_CURRENT_P_Qn96(-81, + Qn81, NewQn81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, NewQn81}); +?OUT_CURRENT_P_Qn80(-80, + Qn80, NewQn80, + {NewQn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-79, + Qn79, NewQn79, + {Qn80, NewQn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-78, + Qn78, NewQn78, + {Qn80, Qn79, NewQn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-77, + Qn77, NewQn77, + {Qn80, Qn79, Qn78, NewQn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-76, + Qn76, NewQn76, + {Qn80, Qn79, Qn78, Qn77, NewQn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-75, + Qn75, NewQn75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + NewQn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-74, + Qn74, NewQn74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, NewQn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-73, + Qn73, NewQn73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, NewQn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-72, + Qn72, NewQn72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, NewQn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-71, + Qn71, NewQn71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, NewQn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-70, + Qn70, NewQn70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, NewQn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-69, + Qn69, NewQn69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + NewQn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-68, + Qn68, NewQn68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, NewQn68, Qn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-67, + Qn67, NewQn67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, NewQn67, Qn66, Qn65}); +?OUT_CURRENT_P_Qn80(-66, + Qn66, NewQn66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, NewQn66, Qn65}); +?OUT_CURRENT_P_Qn80(-65, + Qn65, NewQn65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, NewQn65}); +?OUT_CURRENT_P_Qn64(-64, + Qn64, NewQn64, + {NewQn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-63, + Qn63, NewQn63, + {Qn64, NewQn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-62, + Qn62, NewQn62, + {Qn64, Qn63, NewQn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-61, + Qn61, NewQn61, + {Qn64, Qn63, Qn62, NewQn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-60, + Qn60, NewQn60, + {Qn64, Qn63, Qn62, Qn61, NewQn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-59, + Qn59, NewQn59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + NewQn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-58, + Qn58, NewQn58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, NewQn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-57, + Qn57, NewQn57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, NewQn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-56, + Qn56, NewQn56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, NewQn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-55, + Qn55, NewQn55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, NewQn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-54, + Qn54, NewQn54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, NewQn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-53, + Qn53, NewQn53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + NewQn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-52, + Qn52, NewQn52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, NewQn52, Qn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-51, + Qn51, NewQn51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, NewQn51, Qn50, Qn49}); +?OUT_CURRENT_P_Qn64(-50, + Qn50, NewQn50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, NewQn50, Qn49}); +?OUT_CURRENT_P_Qn64(-49, + Qn49, NewQn49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, NewQn49}); +?OUT_CURRENT_P_Qn48(-48, + Qn48, NewQn48, + {NewQn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-47, + Qn47, NewQn47, + {Qn48, NewQn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-46, + Qn46, NewQn46, + {Qn48, Qn47, NewQn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-45, + Qn45, NewQn45, + {Qn48, Qn47, Qn46, NewQn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-44, + Qn44, NewQn44, + {Qn48, Qn47, Qn46, Qn45, NewQn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-43, + Qn43, NewQn43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + NewQn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-42, + Qn42, NewQn42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, NewQn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-41, + Qn41, NewQn41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, NewQn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-40, + Qn40, NewQn40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, NewQn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-39, + Qn39, NewQn39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, NewQn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-38, + Qn38, NewQn38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, NewQn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-37, + Qn37, NewQn37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + NewQn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-36, + Qn36, NewQn36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, NewQn36, Qn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-35, + Qn35, NewQn35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, NewQn35, Qn34, Qn33}); +?OUT_CURRENT_P_Qn48(-34, + Qn34, NewQn34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, NewQn34, Qn33}); +?OUT_CURRENT_P_Qn48(-33, + Qn33, NewQn33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, NewQn33}); +?OUT_CURRENT_P_Qn32(-32, + Qn32, NewQn32, + {NewQn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-31, + Qn31, NewQn31, + {Qn32, NewQn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-30, + Qn30, NewQn30, + {Qn32, Qn31, NewQn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-29, + Qn29, NewQn29, + {Qn32, Qn31, Qn30, NewQn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-28, + Qn28, NewQn28, + {Qn32, Qn31, Qn30, Qn29, NewQn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-27, + Qn27, NewQn27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + NewQn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-26, + Qn26, NewQn26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, NewQn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-25, + Qn25, NewQn25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, NewQn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-24, + Qn24, NewQn24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, NewQn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-23, + Qn23, NewQn23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, NewQn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-22, + Qn22, NewQn22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, NewQn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-21, + Qn21, NewQn21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + NewQn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-20, + Qn20, NewQn20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, NewQn20, Qn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-19, + Qn19, NewQn19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, NewQn19, Qn18, Qn17}); +?OUT_CURRENT_P_Qn32(-18, + Qn18, NewQn18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, NewQn18, Qn17}); +?OUT_CURRENT_P_Qn32(-17, + Qn17, NewQn17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, NewQn17}); +?OUT_CURRENT_P_Qn16(-16, + Qn16, NewQn16, + {NewQn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-15, + Qn15, NewQn15, + {Qn16, NewQn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-14, + Qn14, NewQn14, + {Qn16, Qn15, NewQn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-13, + Qn13, NewQn13, + {Qn16, Qn15, Qn14, NewQn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-12, + Qn12, NewQn12, + {Qn16, Qn15, Qn14, Qn13, NewQn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-11, + Qn11, NewQn11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + NewQn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-10, + Qn10, NewQn10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, NewQn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-9, + Qn9, NewQn9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, NewQn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-8, + Qn8, NewQn8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, NewQn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-7, + Qn7, NewQn7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, NewQn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-6, + Qn6, NewQn6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, NewQn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-5, + Qn5, NewQn5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + NewQn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-4, + Qn4, NewQn4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, NewQn4, Qn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-3, + Qn3, NewQn3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, NewQn3, Qn2, Qn1}); +?OUT_CURRENT_P_Qn16(-2, + Qn2, NewQn2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, NewQn2, Qn1}); +?OUT_CURRENT_P_Qn16(-1, + Qn1, NewQn1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, NewQn1}); +out_current_p(0, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128} = Q) -> + case queue:out(Q0) of + {empty, _} -> + out_current_p(1, Q); + {{value, X}, NewQ0} -> + NewSize = Size - 1, + {{value, X, 0}, + {if NewSize == 0 -> empty; true -> 0 end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + NewQ0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}} + end; +?OUT_CURRENT_P_Qp16(1, + Qp1, NewQp1, + {NewQp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(2, + Qp2, NewQp2, + {Qp1, NewQp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(3, + Qp3, NewQp3, + {Qp1, Qp2, NewQp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(4, + Qp4, NewQp4, + {Qp1, Qp2, Qp3, NewQp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(5, + Qp5, NewQp5, + {Qp1, Qp2, Qp3, Qp4, NewQp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(6, + Qp6, NewQp6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + NewQp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(7, + Qp7, NewQp7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, NewQp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(8, + Qp8, NewQp8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, NewQp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(9, + Qp9, NewQp9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, NewQp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(10, + Qp10, NewQp10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, NewQp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(11, + Qp11, NewQp11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, NewQp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(12, + Qp12, NewQp12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + NewQp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(13, + Qp13, NewQp13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, NewQp13, Qp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(14, + Qp14, NewQp14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, NewQp14, Qp15, Qp16}); +?OUT_CURRENT_P_Qp16(15, + Qp15, NewQp15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, NewQp15, Qp16}); +?OUT_CURRENT_P_Qp16(16, + Qp16, NewQp16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, NewQp16}); +?OUT_CURRENT_P_Qp32(17, + Qp17, NewQp17, + {NewQp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(18, + Qp18, NewQp18, + {Qp17, NewQp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(19, + Qp19, NewQp19, + {Qp17, Qp18, NewQp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(20, + Qp20, NewQp20, + {Qp17, Qp18, Qp19, NewQp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(21, + Qp21, NewQp21, + {Qp17, Qp18, Qp19, Qp20, NewQp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(22, + Qp22, NewQp22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + NewQp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(23, + Qp23, NewQp23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, NewQp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(24, + Qp24, NewQp24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, NewQp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(25, + Qp25, NewQp25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, NewQp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(26, + Qp26, NewQp26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, NewQp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(27, + Qp27, NewQp27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, NewQp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(28, + Qp28, NewQp28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + NewQp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(29, + Qp29, NewQp29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, NewQp29, Qp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(30, + Qp30, NewQp30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, NewQp30, Qp31, Qp32}); +?OUT_CURRENT_P_Qp32(31, + Qp31, NewQp31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, NewQp31, Qp32}); +?OUT_CURRENT_P_Qp32(32, + Qp32, NewQp32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, NewQp32}); +?OUT_CURRENT_P_Qp48(33, + Qp33, NewQp33, + {NewQp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(34, + Qp34, NewQp34, + {Qp33, NewQp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(35, + Qp35, NewQp35, + {Qp33, Qp34, NewQp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(36, + Qp36, NewQp36, + {Qp33, Qp34, Qp35, NewQp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(37, + Qp37, NewQp37, + {Qp33, Qp34, Qp35, Qp36, NewQp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(38, + Qp38, NewQp38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + NewQp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(39, + Qp39, NewQp39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, NewQp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(40, + Qp40, NewQp40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, NewQp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(41, + Qp41, NewQp41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, NewQp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(42, + Qp42, NewQp42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, NewQp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(43, + Qp43, NewQp43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, NewQp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(44, + Qp44, NewQp44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + NewQp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(45, + Qp45, NewQp45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, NewQp45, Qp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(46, + Qp46, NewQp46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, NewQp46, Qp47, Qp48}); +?OUT_CURRENT_P_Qp48(47, + Qp47, NewQp47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, NewQp47, Qp48}); +?OUT_CURRENT_P_Qp48(48, + Qp48, NewQp48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, NewQp48}); +?OUT_CURRENT_P_Qp64(49, + Qp49, NewQp49, + {NewQp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(50, + Qp50, NewQp50, + {Qp49, NewQp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(51, + Qp51, NewQp51, + {Qp49, Qp50, NewQp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(52, + Qp52, NewQp52, + {Qp49, Qp50, Qp51, NewQp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(53, + Qp53, NewQp53, + {Qp49, Qp50, Qp51, Qp52, NewQp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(54, + Qp54, NewQp54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + NewQp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(55, + Qp55, NewQp55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, NewQp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(56, + Qp56, NewQp56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, NewQp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(57, + Qp57, NewQp57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, NewQp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(58, + Qp58, NewQp58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, NewQp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(59, + Qp59, NewQp59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, NewQp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(60, + Qp60, NewQp60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + NewQp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(61, + Qp61, NewQp61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, NewQp61, Qp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(62, + Qp62, NewQp62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, NewQp62, Qp63, Qp64}); +?OUT_CURRENT_P_Qp64(63, + Qp63, NewQp63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, NewQp63, Qp64}); +?OUT_CURRENT_P_Qp64(64, + Qp64, NewQp64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, NewQp64}); +?OUT_CURRENT_P_Qp80(65, + Qp65, NewQp65, + {NewQp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(66, + Qp66, NewQp66, + {Qp65, NewQp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(67, + Qp67, NewQp67, + {Qp65, Qp66, NewQp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(68, + Qp68, NewQp68, + {Qp65, Qp66, Qp67, NewQp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(69, + Qp69, NewQp69, + {Qp65, Qp66, Qp67, Qp68, NewQp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(70, + Qp70, NewQp70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + NewQp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(71, + Qp71, NewQp71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, NewQp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(72, + Qp72, NewQp72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, NewQp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(73, + Qp73, NewQp73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, NewQp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(74, + Qp74, NewQp74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, NewQp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(75, + Qp75, NewQp75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, NewQp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(76, + Qp76, NewQp76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + NewQp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(77, + Qp77, NewQp77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, NewQp77, Qp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(78, + Qp78, NewQp78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, NewQp78, Qp79, Qp80}); +?OUT_CURRENT_P_Qp80(79, + Qp79, NewQp79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, NewQp79, Qp80}); +?OUT_CURRENT_P_Qp80(80, + Qp80, NewQp80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, NewQp80}); +?OUT_CURRENT_P_Qp96(81, + Qp81, NewQp81, + {NewQp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(82, + Qp82, NewQp82, + {Qp81, NewQp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(83, + Qp83, NewQp83, + {Qp81, Qp82, NewQp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(84, + Qp84, NewQp84, + {Qp81, Qp82, Qp83, NewQp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(85, + Qp85, NewQp85, + {Qp81, Qp82, Qp83, Qp84, NewQp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(86, + Qp86, NewQp86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + NewQp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(87, + Qp87, NewQp87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, NewQp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(88, + Qp88, NewQp88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, NewQp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(89, + Qp89, NewQp89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, NewQp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(90, + Qp90, NewQp90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, NewQp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(91, + Qp91, NewQp91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, NewQp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(92, + Qp92, NewQp92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + NewQp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(93, + Qp93, NewQp93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, NewQp93, Qp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(94, + Qp94, NewQp94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, NewQp94, Qp95, Qp96}); +?OUT_CURRENT_P_Qp96(95, + Qp95, NewQp95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, NewQp95, Qp96}); +?OUT_CURRENT_P_Qp96(96, + Qp96, NewQp96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, NewQp96}); +?OUT_CURRENT_P_Qp112(97, + Qp97, NewQp97, + {NewQp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(98, + Qp98, NewQp98, + {Qp97, NewQp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(99, + Qp99, NewQp99, + {Qp97, Qp98, NewQp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(100, + Qp100, NewQp100, + {Qp97, Qp98, Qp99, NewQp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(101, + Qp101, NewQp101, + {Qp97, Qp98, Qp99, Qp100, NewQp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(102, + Qp102, NewQp102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + NewQp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(103, + Qp103, NewQp103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, NewQp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(104, + Qp104, NewQp104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, NewQp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(105, + Qp105, NewQp105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, NewQp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(106, + Qp106, NewQp106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, NewQp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(107, + Qp107, NewQp107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, NewQp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(108, + Qp108, NewQp108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + NewQp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(109, + Qp109, NewQp109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, NewQp109, Qp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(110, + Qp110, NewQp110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, NewQp110, Qp111, Qp112}); +?OUT_CURRENT_P_Qp112(111, + Qp111, NewQp111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, NewQp111, Qp112}); +?OUT_CURRENT_P_Qp112(112, + Qp112, NewQp112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, NewQp112}); +?OUT_CURRENT_P_Qp128(113, + Qp113, NewQp113, + {NewQp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(114, + Qp114, NewQp114, + {Qp113, NewQp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(115, + Qp115, NewQp115, + {Qp113, Qp114, NewQp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(116, + Qp116, NewQp116, + {Qp113, Qp114, Qp115, NewQp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(117, + Qp117, NewQp117, + {Qp113, Qp114, Qp115, Qp116, NewQp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(118, + Qp118, NewQp118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + NewQp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(119, + Qp119, NewQp119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, NewQp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(120, + Qp120, NewQp120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, NewQp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(121, + Qp121, NewQp121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, NewQp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(122, + Qp122, NewQp122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, NewQp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(123, + Qp123, NewQp123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, NewQp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(124, + Qp124, NewQp124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + NewQp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(125, + Qp125, NewQp125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, NewQp125, Qp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(126, + Qp126, NewQp126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, NewQp126, Qp127, Qp128}); +?OUT_CURRENT_P_Qp128(127, + Qp127, NewQp127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, NewQp127, Qp128}); +out_current_p(128, + {_, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}) -> + case queue:out(Qp128) of + {empty, _} -> + {empty, + {empty, + 0, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}}; + {{value, X}, NewQp128} -> + NewSize = Size - 1, + {{value, X, 128}, + {if NewSize == 0 -> empty; true -> 128 end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, NewQp128}}} + end. + +%% @hidden +-define(OUT_SPECIFIC_Qn128(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + V3, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn112(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, + V3, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn96(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, + V3, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn80(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, + V3, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn64(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, + V3, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn48(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, + V3, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn32(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V3, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qn16(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V3, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp16(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V3, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp32(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V3, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp48(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V3, + Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp64(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V3, + Qp80, Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp80(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V3, + Qp96, Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp96(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V3, + Qp112, Qp128}}). +-define(OUT_SPECIFIC_Qp112(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V3, + Qp128}}). +-define(OUT_SPECIFIC_Qp128(P, V1, V2, V3), +out_specific(P, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}) -> + {Value, V2} = queue:out(V1), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V3}}). + +?OUT_SPECIFIC_Qn128(-128, + Qn128, NewQn128, + {NewQn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-127, + Qn127, NewQn127, + {Qn128, NewQn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-126, + Qn126, NewQn126, + {Qn128, Qn127, NewQn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-125, + Qn125, NewQn125, + {Qn128, Qn127, Qn126, NewQn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-124, + Qn124, NewQn124, + {Qn128, Qn127, Qn126, Qn125, NewQn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-123, + Qn123, NewQn123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + NewQn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-122, + Qn122, NewQn122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, NewQn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-121, + Qn121, NewQn121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, NewQn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-120, + Qn120, NewQn120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, NewQn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-119, + Qn119, NewQn119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, NewQn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-118, + Qn118, NewQn118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, NewQn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-117, + Qn117, NewQn117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + NewQn117, Qn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-116, + Qn116, NewQn116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, NewQn116, Qn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-115, + Qn115, NewQn115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, NewQn115, Qn114, Qn113}); +?OUT_SPECIFIC_Qn128(-114, + Qn114, NewQn114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, NewQn114, Qn113}); +?OUT_SPECIFIC_Qn128(-113, + Qn113, NewQn113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, NewQn113}); +?OUT_SPECIFIC_Qn112(-112, + Qn112, NewQn112, + {NewQn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-111, + Qn111, NewQn111, + {Qn112, NewQn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-110, + Qn110, NewQn110, + {Qn112, Qn111, NewQn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-109, + Qn109, NewQn109, + {Qn112, Qn111, Qn110, NewQn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-108, + Qn108, NewQn108, + {Qn112, Qn111, Qn110, Qn109, NewQn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-107, + Qn107, NewQn107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + NewQn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-106, + Qn106, NewQn106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, NewQn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-105, + Qn105, NewQn105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, NewQn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-104, + Qn104, NewQn104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, NewQn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-103, + Qn103, NewQn103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, NewQn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-102, + Qn102, NewQn102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, NewQn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-101, + Qn101, NewQn101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + NewQn101, Qn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-100, + Qn100, NewQn100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, NewQn100, Qn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-99, + Qn99, NewQn99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, NewQn99, Qn98, Qn97}); +?OUT_SPECIFIC_Qn112(-98, + Qn98, NewQn98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, NewQn98, Qn97}); +?OUT_SPECIFIC_Qn112(-97, + Qn97, NewQn97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, NewQn97}); +?OUT_SPECIFIC_Qn96(-96, + Qn96, NewQn96, + {NewQn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-95, + Qn95, NewQn95, + {Qn96, NewQn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-94, + Qn94, NewQn94, + {Qn96, Qn95, NewQn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-93, + Qn93, NewQn93, + {Qn96, Qn95, Qn94, NewQn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-92, + Qn92, NewQn92, + {Qn96, Qn95, Qn94, Qn93, NewQn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-91, + Qn91, NewQn91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + NewQn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-90, + Qn90, NewQn90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, NewQn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-89, + Qn89, NewQn89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, NewQn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-88, + Qn88, NewQn88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, NewQn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-87, + Qn87, NewQn87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, NewQn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-86, + Qn86, NewQn86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, NewQn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-85, + Qn85, NewQn85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + NewQn85, Qn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-84, + Qn84, NewQn84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, NewQn84, Qn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-83, + Qn83, NewQn83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, NewQn83, Qn82, Qn81}); +?OUT_SPECIFIC_Qn96(-82, + Qn82, NewQn82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, NewQn82, Qn81}); +?OUT_SPECIFIC_Qn96(-81, + Qn81, NewQn81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, NewQn81}); +?OUT_SPECIFIC_Qn80(-80, + Qn80, NewQn80, + {NewQn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-79, + Qn79, NewQn79, + {Qn80, NewQn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-78, + Qn78, NewQn78, + {Qn80, Qn79, NewQn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-77, + Qn77, NewQn77, + {Qn80, Qn79, Qn78, NewQn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-76, + Qn76, NewQn76, + {Qn80, Qn79, Qn78, Qn77, NewQn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-75, + Qn75, NewQn75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + NewQn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-74, + Qn74, NewQn74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, NewQn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-73, + Qn73, NewQn73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, NewQn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-72, + Qn72, NewQn72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, NewQn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-71, + Qn71, NewQn71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, NewQn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-70, + Qn70, NewQn70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, NewQn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-69, + Qn69, NewQn69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + NewQn69, Qn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-68, + Qn68, NewQn68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, NewQn68, Qn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-67, + Qn67, NewQn67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, NewQn67, Qn66, Qn65}); +?OUT_SPECIFIC_Qn80(-66, + Qn66, NewQn66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, NewQn66, Qn65}); +?OUT_SPECIFIC_Qn80(-65, + Qn65, NewQn65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, NewQn65}); +?OUT_SPECIFIC_Qn64(-64, + Qn64, NewQn64, + {NewQn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-63, + Qn63, NewQn63, + {Qn64, NewQn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-62, + Qn62, NewQn62, + {Qn64, Qn63, NewQn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-61, + Qn61, NewQn61, + {Qn64, Qn63, Qn62, NewQn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-60, + Qn60, NewQn60, + {Qn64, Qn63, Qn62, Qn61, NewQn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-59, + Qn59, NewQn59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + NewQn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-58, + Qn58, NewQn58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, NewQn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-57, + Qn57, NewQn57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, NewQn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-56, + Qn56, NewQn56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, NewQn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-55, + Qn55, NewQn55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, NewQn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-54, + Qn54, NewQn54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, NewQn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-53, + Qn53, NewQn53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + NewQn53, Qn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-52, + Qn52, NewQn52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, NewQn52, Qn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-51, + Qn51, NewQn51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, NewQn51, Qn50, Qn49}); +?OUT_SPECIFIC_Qn64(-50, + Qn50, NewQn50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, NewQn50, Qn49}); +?OUT_SPECIFIC_Qn64(-49, + Qn49, NewQn49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, NewQn49}); +?OUT_SPECIFIC_Qn48(-48, + Qn48, NewQn48, + {NewQn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-47, + Qn47, NewQn47, + {Qn48, NewQn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-46, + Qn46, NewQn46, + {Qn48, Qn47, NewQn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-45, + Qn45, NewQn45, + {Qn48, Qn47, Qn46, NewQn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-44, + Qn44, NewQn44, + {Qn48, Qn47, Qn46, Qn45, NewQn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-43, + Qn43, NewQn43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + NewQn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-42, + Qn42, NewQn42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, NewQn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-41, + Qn41, NewQn41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, NewQn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-40, + Qn40, NewQn40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, NewQn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-39, + Qn39, NewQn39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, NewQn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-38, + Qn38, NewQn38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, NewQn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-37, + Qn37, NewQn37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + NewQn37, Qn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-36, + Qn36, NewQn36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, NewQn36, Qn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-35, + Qn35, NewQn35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, NewQn35, Qn34, Qn33}); +?OUT_SPECIFIC_Qn48(-34, + Qn34, NewQn34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, NewQn34, Qn33}); +?OUT_SPECIFIC_Qn48(-33, + Qn33, NewQn33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, NewQn33}); +?OUT_SPECIFIC_Qn32(-32, + Qn32, NewQn32, + {NewQn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-31, + Qn31, NewQn31, + {Qn32, NewQn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-30, + Qn30, NewQn30, + {Qn32, Qn31, NewQn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-29, + Qn29, NewQn29, + {Qn32, Qn31, Qn30, NewQn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-28, + Qn28, NewQn28, + {Qn32, Qn31, Qn30, Qn29, NewQn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-27, + Qn27, NewQn27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + NewQn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-26, + Qn26, NewQn26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, NewQn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-25, + Qn25, NewQn25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, NewQn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-24, + Qn24, NewQn24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, NewQn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-23, + Qn23, NewQn23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, NewQn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-22, + Qn22, NewQn22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, NewQn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-21, + Qn21, NewQn21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + NewQn21, Qn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-20, + Qn20, NewQn20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, NewQn20, Qn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-19, + Qn19, NewQn19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, NewQn19, Qn18, Qn17}); +?OUT_SPECIFIC_Qn32(-18, + Qn18, NewQn18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, NewQn18, Qn17}); +?OUT_SPECIFIC_Qn32(-17, + Qn17, NewQn17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, NewQn17}); +?OUT_SPECIFIC_Qn16(-16, + Qn16, NewQn16, + {NewQn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-15, + Qn15, NewQn15, + {Qn16, NewQn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-14, + Qn14, NewQn14, + {Qn16, Qn15, NewQn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-13, + Qn13, NewQn13, + {Qn16, Qn15, Qn14, NewQn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-12, + Qn12, NewQn12, + {Qn16, Qn15, Qn14, Qn13, NewQn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-11, + Qn11, NewQn11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + NewQn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-10, + Qn10, NewQn10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, NewQn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-9, + Qn9, NewQn9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, NewQn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-8, + Qn8, NewQn8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, NewQn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-7, + Qn7, NewQn7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, NewQn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-6, + Qn6, NewQn6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, NewQn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-5, + Qn5, NewQn5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + NewQn5, Qn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-4, + Qn4, NewQn4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, NewQn4, Qn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-3, + Qn3, NewQn3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, NewQn3, Qn2, Qn1}); +?OUT_SPECIFIC_Qn16(-2, + Qn2, NewQn2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, NewQn2, Qn1}); +?OUT_SPECIFIC_Qn16(-1, + Qn1, NewQn1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, NewQn1}); +out_specific(0, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, NewQ0} = queue:out(Q0), + NewSize = if Value =/= empty -> Size - 1; true -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + NewQ0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}; +?OUT_SPECIFIC_Qp16(1, + Qp1, NewQp1, + {NewQp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(2, + Qp2, NewQp2, + {Qp1, NewQp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(3, + Qp3, NewQp3, + {Qp1, Qp2, NewQp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(4, + Qp4, NewQp4, + {Qp1, Qp2, Qp3, NewQp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(5, + Qp5, NewQp5, + {Qp1, Qp2, Qp3, Qp4, NewQp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(6, + Qp6, NewQp6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + NewQp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(7, + Qp7, NewQp7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, NewQp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(8, + Qp8, NewQp8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, NewQp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(9, + Qp9, NewQp9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, NewQp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(10, + Qp10, NewQp10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, NewQp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(11, + Qp11, NewQp11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, NewQp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(12, + Qp12, NewQp12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + NewQp12, Qp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(13, + Qp13, NewQp13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, NewQp13, Qp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(14, + Qp14, NewQp14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, NewQp14, Qp15, Qp16}); +?OUT_SPECIFIC_Qp16(15, + Qp15, NewQp15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, NewQp15, Qp16}); +?OUT_SPECIFIC_Qp16(16, + Qp16, NewQp16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, NewQp16}); +?OUT_SPECIFIC_Qp32(17, + Qp17, NewQp17, + {NewQp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(18, + Qp18, NewQp18, + {Qp17, NewQp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(19, + Qp19, NewQp19, + {Qp17, Qp18, NewQp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(20, + Qp20, NewQp20, + {Qp17, Qp18, Qp19, NewQp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(21, + Qp21, NewQp21, + {Qp17, Qp18, Qp19, Qp20, NewQp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(22, + Qp22, NewQp22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + NewQp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(23, + Qp23, NewQp23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, NewQp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(24, + Qp24, NewQp24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, NewQp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(25, + Qp25, NewQp25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, NewQp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(26, + Qp26, NewQp26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, NewQp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(27, + Qp27, NewQp27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, NewQp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(28, + Qp28, NewQp28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + NewQp28, Qp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(29, + Qp29, NewQp29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, NewQp29, Qp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(30, + Qp30, NewQp30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, NewQp30, Qp31, Qp32}); +?OUT_SPECIFIC_Qp32(31, + Qp31, NewQp31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, NewQp31, Qp32}); +?OUT_SPECIFIC_Qp32(32, + Qp32, NewQp32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, NewQp32}); +?OUT_SPECIFIC_Qp48(33, + Qp33, NewQp33, + {NewQp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(34, + Qp34, NewQp34, + {Qp33, NewQp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(35, + Qp35, NewQp35, + {Qp33, Qp34, NewQp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(36, + Qp36, NewQp36, + {Qp33, Qp34, Qp35, NewQp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(37, + Qp37, NewQp37, + {Qp33, Qp34, Qp35, Qp36, NewQp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(38, + Qp38, NewQp38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + NewQp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(39, + Qp39, NewQp39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, NewQp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(40, + Qp40, NewQp40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, NewQp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(41, + Qp41, NewQp41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, NewQp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(42, + Qp42, NewQp42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, NewQp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(43, + Qp43, NewQp43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, NewQp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(44, + Qp44, NewQp44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + NewQp44, Qp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(45, + Qp45, NewQp45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, NewQp45, Qp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(46, + Qp46, NewQp46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, NewQp46, Qp47, Qp48}); +?OUT_SPECIFIC_Qp48(47, + Qp47, NewQp47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, NewQp47, Qp48}); +?OUT_SPECIFIC_Qp48(48, + Qp48, NewQp48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, NewQp48}); +?OUT_SPECIFIC_Qp64(49, + Qp49, NewQp49, + {NewQp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(50, + Qp50, NewQp50, + {Qp49, NewQp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(51, + Qp51, NewQp51, + {Qp49, Qp50, NewQp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(52, + Qp52, NewQp52, + {Qp49, Qp50, Qp51, NewQp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(53, + Qp53, NewQp53, + {Qp49, Qp50, Qp51, Qp52, NewQp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(54, + Qp54, NewQp54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + NewQp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(55, + Qp55, NewQp55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, NewQp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(56, + Qp56, NewQp56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, NewQp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(57, + Qp57, NewQp57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, NewQp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(58, + Qp58, NewQp58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, NewQp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(59, + Qp59, NewQp59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, NewQp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(60, + Qp60, NewQp60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + NewQp60, Qp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(61, + Qp61, NewQp61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, NewQp61, Qp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(62, + Qp62, NewQp62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, NewQp62, Qp63, Qp64}); +?OUT_SPECIFIC_Qp64(63, + Qp63, NewQp63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, NewQp63, Qp64}); +?OUT_SPECIFIC_Qp64(64, + Qp64, NewQp64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, NewQp64}); +?OUT_SPECIFIC_Qp80(65, + Qp65, NewQp65, + {NewQp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(66, + Qp66, NewQp66, + {Qp65, NewQp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(67, + Qp67, NewQp67, + {Qp65, Qp66, NewQp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(68, + Qp68, NewQp68, + {Qp65, Qp66, Qp67, NewQp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(69, + Qp69, NewQp69, + {Qp65, Qp66, Qp67, Qp68, NewQp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(70, + Qp70, NewQp70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + NewQp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(71, + Qp71, NewQp71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, NewQp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(72, + Qp72, NewQp72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, NewQp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(73, + Qp73, NewQp73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, NewQp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(74, + Qp74, NewQp74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, NewQp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(75, + Qp75, NewQp75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, NewQp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(76, + Qp76, NewQp76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + NewQp76, Qp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(77, + Qp77, NewQp77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, NewQp77, Qp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(78, + Qp78, NewQp78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, NewQp78, Qp79, Qp80}); +?OUT_SPECIFIC_Qp80(79, + Qp79, NewQp79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, NewQp79, Qp80}); +?OUT_SPECIFIC_Qp80(80, + Qp80, NewQp80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, NewQp80}); +?OUT_SPECIFIC_Qp96(81, + Qp81, NewQp81, + {NewQp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(82, + Qp82, NewQp82, + {Qp81, NewQp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(83, + Qp83, NewQp83, + {Qp81, Qp82, NewQp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(84, + Qp84, NewQp84, + {Qp81, Qp82, Qp83, NewQp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(85, + Qp85, NewQp85, + {Qp81, Qp82, Qp83, Qp84, NewQp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(86, + Qp86, NewQp86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + NewQp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(87, + Qp87, NewQp87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, NewQp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(88, + Qp88, NewQp88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, NewQp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(89, + Qp89, NewQp89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, NewQp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(90, + Qp90, NewQp90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, NewQp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(91, + Qp91, NewQp91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, NewQp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(92, + Qp92, NewQp92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + NewQp92, Qp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(93, + Qp93, NewQp93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, NewQp93, Qp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(94, + Qp94, NewQp94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, NewQp94, Qp95, Qp96}); +?OUT_SPECIFIC_Qp96(95, + Qp95, NewQp95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, NewQp95, Qp96}); +?OUT_SPECIFIC_Qp96(96, + Qp96, NewQp96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, NewQp96}); +?OUT_SPECIFIC_Qp112(97, + Qp97, NewQp97, + {NewQp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(98, + Qp98, NewQp98, + {Qp97, NewQp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(99, + Qp99, NewQp99, + {Qp97, Qp98, NewQp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(100, + Qp100, NewQp100, + {Qp97, Qp98, Qp99, NewQp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(101, + Qp101, NewQp101, + {Qp97, Qp98, Qp99, Qp100, NewQp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(102, + Qp102, NewQp102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + NewQp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(103, + Qp103, NewQp103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, NewQp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(104, + Qp104, NewQp104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, NewQp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(105, + Qp105, NewQp105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, NewQp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(106, + Qp106, NewQp106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, NewQp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(107, + Qp107, NewQp107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, NewQp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(108, + Qp108, NewQp108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + NewQp108, Qp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(109, + Qp109, NewQp109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, NewQp109, Qp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(110, + Qp110, NewQp110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, NewQp110, Qp111, Qp112}); +?OUT_SPECIFIC_Qp112(111, + Qp111, NewQp111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, NewQp111, Qp112}); +?OUT_SPECIFIC_Qp112(112, + Qp112, NewQp112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, NewQp112}); +?OUT_SPECIFIC_Qp128(113, + Qp113, NewQp113, + {NewQp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(114, + Qp114, NewQp114, + {Qp113, NewQp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(115, + Qp115, NewQp115, + {Qp113, Qp114, NewQp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(116, + Qp116, NewQp116, + {Qp113, Qp114, Qp115, NewQp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(117, + Qp117, NewQp117, + {Qp113, Qp114, Qp115, Qp116, NewQp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(118, + Qp118, NewQp118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + NewQp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(119, + Qp119, NewQp119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, NewQp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(120, + Qp120, NewQp120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, NewQp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(121, + Qp121, NewQp121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, NewQp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(122, + Qp122, NewQp122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, NewQp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(123, + Qp123, NewQp123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, NewQp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(124, + Qp124, NewQp124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + NewQp124, Qp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(125, + Qp125, NewQp125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, NewQp125, Qp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(126, + Qp126, NewQp126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, NewQp126, Qp127, Qp128}); +?OUT_SPECIFIC_Qp128(127, + Qp127, NewQp127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, NewQp127, Qp128}); +?OUT_SPECIFIC_Qp128(128, + Qp128, NewQp128, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, NewQp128}). + +%% @hidden +-define(REMOVE_UNIQ_P_Qn128(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + {Qn128, Qn127, Qn126, Qn125, Qn124, Qn123, Qn122, Qn121, + Qn120, Qn119, Qn118, Qn117, Qn116, Qn115, Qn114, Qn113}, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + V3, + Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn112(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, + {Qn112, Qn111, Qn110, Qn109, Qn108, Qn107, Qn106, Qn105, + Qn104, Qn103, Qn102, Qn101, Qn100, Qn99, Qn98, Qn97}, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, + V3, + Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn96(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, + {Qn96, Qn95, Qn94, Qn93, Qn92, Qn91, Qn90, Qn89, + Qn88, Qn87, Qn86, Qn85, Qn84, Qn83, Qn82, Qn81}, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, + V3, + Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn80(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, + {Qn80, Qn79, Qn78, Qn77, Qn76, Qn75, Qn74, Qn73, + Qn72, Qn71, Qn70, Qn69, Qn68, Qn67, Qn66, Qn65}, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, + V3, + Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn64(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, + {Qn64, Qn63, Qn62, Qn61, Qn60, Qn59, Qn58, Qn57, + Qn56, Qn55, Qn54, Qn53, Qn52, Qn51, Qn50, Qn49}, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, + V3, + Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn48(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, + {Qn48, Qn47, Qn46, Qn45, Qn44, Qn43, Qn42, Qn41, + Qn40, Qn39, Qn38, Qn37, Qn36, Qn35, Qn34, Qn33}, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, + V3, + Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn32(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + {Qn32, Qn31, Qn30, Qn29, Qn28, Qn27, Qn26, Qn25, + Qn24, Qn23, Qn22, Qn21, Qn20, Qn19, Qn18, Qn17}, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, + V3, + Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qn16(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + {Qn16, Qn15, Qn14, Qn13, Qn12, Qn11, Qn10, Qn9, + Qn8, Qn7, Qn6, Qn5, Qn4, Qn3, Qn2, Qn1}, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, + V3, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp16(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + {Qp1, Qp2, Qp3, Qp4, Qp5, Qp6, Qp7, Qp8, + Qp9, Qp10, Qp11, Qp12, Qp13, Qp14, Qp15, Qp16}, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + V3, + Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp32(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + {Qp17, Qp18, Qp19, Qp20, Qp21, Qp22, Qp23, Qp24, + Qp25, Qp26, Qp27, Qp28, Qp29, Qp30, Qp31, Qp32}, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, + V3, + Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp48(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + {Qp33, Qp34, Qp35, Qp36, Qp37, Qp38, Qp39, Qp40, + Qp41, Qp42, Qp43, Qp44, Qp45, Qp46, Qp47, Qp48}, + Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, + V3, + Qp64, Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp64(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + {Qp49, Qp50, Qp51, Qp52, Qp53, Qp54, Qp55, Qp56, + Qp57, Qp58, Qp59, Qp60, Qp61, Qp62, Qp63, Qp64}, + Qp80, Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, + V3, + Qp80, Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp80(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + {Qp65, Qp66, Qp67, Qp68, Qp69, Qp70, Qp71, Qp72, + Qp73, Qp74, Qp75, Qp76, Qp77, Qp78, Qp79, Qp80}, + Qp96, Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, + V3, + Qp96, Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp96(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + {Qp81, Qp82, Qp83, Qp84, Qp85, Qp86, Qp87, Qp88, + Qp89, Qp90, Qp91, Qp92, Qp93, Qp94, Qp95, Qp96}, + Qp112, Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, + V3, + Qp112, Qp128}}). +-define(REMOVE_UNIQ_P_Qp112(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + {Qp97, Qp98, Qp99, Qp100, Qp101, Qp102, Qp103, Qp104, + Qp105, Qp106, Qp107, Qp108, Qp109, Qp110, Qp111, Qp112}, + Qp128}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, + V3, + Qp128}}). +-define(REMOVE_UNIQ_P_Qp128(P, V1, V2, V3), +remove_unique_p(P, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + {Qp113, Qp114, Qp115, Qp116, Qp117, Qp118, Qp119, Qp120, + Qp121, Qp122, Qp123, Qp124, Qp125, Qp126, Qp127, Qp128}}) -> + {Value, V2} = queue_remove_unique(F, V1), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, + V3}}). + +?REMOVE_UNIQ_P_Qn128(-128, + Qn128, NewQn128, + {NewQn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-127, + Qn127, NewQn127, + {Qn128, NewQn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-126, + Qn126, NewQn126, + {Qn128, Qn127, NewQn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-125, + Qn125, NewQn125, + {Qn128, Qn127, Qn126, NewQn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-124, + Qn124, NewQn124, + {Qn128, Qn127, Qn126, Qn125, NewQn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-123, + Qn123, NewQn123, + {Qn128, Qn127, Qn126, Qn125, Qn124, + NewQn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-122, + Qn122, NewQn122, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, NewQn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-121, + Qn121, NewQn121, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, NewQn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-120, + Qn120, NewQn120, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, NewQn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-119, + Qn119, NewQn119, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, NewQn119, Qn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-118, + Qn118, NewQn118, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, NewQn118, + Qn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-117, + Qn117, NewQn117, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + NewQn117, Qn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-116, + Qn116, NewQn116, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, NewQn116, Qn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-115, + Qn115, NewQn115, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, NewQn115, Qn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-114, + Qn114, NewQn114, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, NewQn114, Qn113}); +?REMOVE_UNIQ_P_Qn128(-113, + Qn113, NewQn113, + {Qn128, Qn127, Qn126, Qn125, Qn124, + Qn123, Qn122, Qn121, Qn120, Qn119, Qn118, + Qn117, Qn116, Qn115, Qn114, NewQn113}); +?REMOVE_UNIQ_P_Qn112(-112, + Qn112, NewQn112, + {NewQn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-111, + Qn111, NewQn111, + {Qn112, NewQn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-110, + Qn110, NewQn110, + {Qn112, Qn111, NewQn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-109, + Qn109, NewQn109, + {Qn112, Qn111, Qn110, NewQn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-108, + Qn108, NewQn108, + {Qn112, Qn111, Qn110, Qn109, NewQn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-107, + Qn107, NewQn107, + {Qn112, Qn111, Qn110, Qn109, Qn108, + NewQn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-106, + Qn106, NewQn106, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, NewQn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-105, + Qn105, NewQn105, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, NewQn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-104, + Qn104, NewQn104, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, NewQn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-103, + Qn103, NewQn103, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, NewQn103, Qn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-102, + Qn102, NewQn102, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, NewQn102, + Qn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-101, + Qn101, NewQn101, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + NewQn101, Qn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-100, + Qn100, NewQn100, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, NewQn100, Qn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-99, + Qn99, NewQn99, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, NewQn99, Qn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-98, + Qn98, NewQn98, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, NewQn98, Qn97}); +?REMOVE_UNIQ_P_Qn112(-97, + Qn97, NewQn97, + {Qn112, Qn111, Qn110, Qn109, Qn108, + Qn107, Qn106, Qn105, Qn104, Qn103, Qn102, + Qn101, Qn100, Qn99, Qn98, NewQn97}); +?REMOVE_UNIQ_P_Qn96(-96, + Qn96, NewQn96, + {NewQn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-95, + Qn95, NewQn95, + {Qn96, NewQn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-94, + Qn94, NewQn94, + {Qn96, Qn95, NewQn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-93, + Qn93, NewQn93, + {Qn96, Qn95, Qn94, NewQn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-92, + Qn92, NewQn92, + {Qn96, Qn95, Qn94, Qn93, NewQn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-91, + Qn91, NewQn91, + {Qn96, Qn95, Qn94, Qn93, Qn92, + NewQn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-90, + Qn90, NewQn90, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, NewQn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-89, + Qn89, NewQn89, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, NewQn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-88, + Qn88, NewQn88, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, NewQn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-87, + Qn87, NewQn87, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, NewQn87, Qn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-86, + Qn86, NewQn86, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, NewQn86, + Qn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-85, + Qn85, NewQn85, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + NewQn85, Qn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-84, + Qn84, NewQn84, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, NewQn84, Qn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-83, + Qn83, NewQn83, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, NewQn83, Qn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-82, + Qn82, NewQn82, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, NewQn82, Qn81}); +?REMOVE_UNIQ_P_Qn96(-81, + Qn81, NewQn81, + {Qn96, Qn95, Qn94, Qn93, Qn92, + Qn91, Qn90, Qn89, Qn88, Qn87, Qn86, + Qn85, Qn84, Qn83, Qn82, NewQn81}); +?REMOVE_UNIQ_P_Qn80(-80, + Qn80, NewQn80, + {NewQn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-79, + Qn79, NewQn79, + {Qn80, NewQn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-78, + Qn78, NewQn78, + {Qn80, Qn79, NewQn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-77, + Qn77, NewQn77, + {Qn80, Qn79, Qn78, NewQn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-76, + Qn76, NewQn76, + {Qn80, Qn79, Qn78, Qn77, NewQn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-75, + Qn75, NewQn75, + {Qn80, Qn79, Qn78, Qn77, Qn76, + NewQn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-74, + Qn74, NewQn74, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, NewQn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-73, + Qn73, NewQn73, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, NewQn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-72, + Qn72, NewQn72, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, NewQn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-71, + Qn71, NewQn71, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, NewQn71, Qn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-70, + Qn70, NewQn70, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, NewQn70, + Qn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-69, + Qn69, NewQn69, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + NewQn69, Qn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-68, + Qn68, NewQn68, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, NewQn68, Qn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-67, + Qn67, NewQn67, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, NewQn67, Qn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-66, + Qn66, NewQn66, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, NewQn66, Qn65}); +?REMOVE_UNIQ_P_Qn80(-65, + Qn65, NewQn65, + {Qn80, Qn79, Qn78, Qn77, Qn76, + Qn75, Qn74, Qn73, Qn72, Qn71, Qn70, + Qn69, Qn68, Qn67, Qn66, NewQn65}); +?REMOVE_UNIQ_P_Qn64(-64, + Qn64, NewQn64, + {NewQn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-63, + Qn63, NewQn63, + {Qn64, NewQn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-62, + Qn62, NewQn62, + {Qn64, Qn63, NewQn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-61, + Qn61, NewQn61, + {Qn64, Qn63, Qn62, NewQn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-60, + Qn60, NewQn60, + {Qn64, Qn63, Qn62, Qn61, NewQn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-59, + Qn59, NewQn59, + {Qn64, Qn63, Qn62, Qn61, Qn60, + NewQn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-58, + Qn58, NewQn58, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, NewQn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-57, + Qn57, NewQn57, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, NewQn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-56, + Qn56, NewQn56, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, NewQn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-55, + Qn55, NewQn55, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, NewQn55, Qn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-54, + Qn54, NewQn54, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, NewQn54, + Qn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-53, + Qn53, NewQn53, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + NewQn53, Qn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-52, + Qn52, NewQn52, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, NewQn52, Qn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-51, + Qn51, NewQn51, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, NewQn51, Qn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-50, + Qn50, NewQn50, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, NewQn50, Qn49}); +?REMOVE_UNIQ_P_Qn64(-49, + Qn49, NewQn49, + {Qn64, Qn63, Qn62, Qn61, Qn60, + Qn59, Qn58, Qn57, Qn56, Qn55, Qn54, + Qn53, Qn52, Qn51, Qn50, NewQn49}); +?REMOVE_UNIQ_P_Qn48(-48, + Qn48, NewQn48, + {NewQn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-47, + Qn47, NewQn47, + {Qn48, NewQn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-46, + Qn46, NewQn46, + {Qn48, Qn47, NewQn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-45, + Qn45, NewQn45, + {Qn48, Qn47, Qn46, NewQn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-44, + Qn44, NewQn44, + {Qn48, Qn47, Qn46, Qn45, NewQn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-43, + Qn43, NewQn43, + {Qn48, Qn47, Qn46, Qn45, Qn44, + NewQn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-42, + Qn42, NewQn42, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, NewQn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-41, + Qn41, NewQn41, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, NewQn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-40, + Qn40, NewQn40, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, NewQn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-39, + Qn39, NewQn39, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, NewQn39, Qn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-38, + Qn38, NewQn38, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, NewQn38, + Qn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-37, + Qn37, NewQn37, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + NewQn37, Qn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-36, + Qn36, NewQn36, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, NewQn36, Qn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-35, + Qn35, NewQn35, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, NewQn35, Qn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-34, + Qn34, NewQn34, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, NewQn34, Qn33}); +?REMOVE_UNIQ_P_Qn48(-33, + Qn33, NewQn33, + {Qn48, Qn47, Qn46, Qn45, Qn44, + Qn43, Qn42, Qn41, Qn40, Qn39, Qn38, + Qn37, Qn36, Qn35, Qn34, NewQn33}); +?REMOVE_UNIQ_P_Qn32(-32, + Qn32, NewQn32, + {NewQn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-31, + Qn31, NewQn31, + {Qn32, NewQn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-30, + Qn30, NewQn30, + {Qn32, Qn31, NewQn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-29, + Qn29, NewQn29, + {Qn32, Qn31, Qn30, NewQn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-28, + Qn28, NewQn28, + {Qn32, Qn31, Qn30, Qn29, NewQn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-27, + Qn27, NewQn27, + {Qn32, Qn31, Qn30, Qn29, Qn28, + NewQn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-26, + Qn26, NewQn26, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, NewQn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-25, + Qn25, NewQn25, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, NewQn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-24, + Qn24, NewQn24, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, NewQn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-23, + Qn23, NewQn23, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, NewQn23, Qn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-22, + Qn22, NewQn22, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, NewQn22, + Qn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-21, + Qn21, NewQn21, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + NewQn21, Qn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-20, + Qn20, NewQn20, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, NewQn20, Qn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-19, + Qn19, NewQn19, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, NewQn19, Qn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-18, + Qn18, NewQn18, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, NewQn18, Qn17}); +?REMOVE_UNIQ_P_Qn32(-17, + Qn17, NewQn17, + {Qn32, Qn31, Qn30, Qn29, Qn28, + Qn27, Qn26, Qn25, Qn24, Qn23, Qn22, + Qn21, Qn20, Qn19, Qn18, NewQn17}); +?REMOVE_UNIQ_P_Qn16(-16, + Qn16, NewQn16, + {NewQn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-15, + Qn15, NewQn15, + {Qn16, NewQn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-14, + Qn14, NewQn14, + {Qn16, Qn15, NewQn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-13, + Qn13, NewQn13, + {Qn16, Qn15, Qn14, NewQn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-12, + Qn12, NewQn12, + {Qn16, Qn15, Qn14, Qn13, NewQn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-11, + Qn11, NewQn11, + {Qn16, Qn15, Qn14, Qn13, Qn12, + NewQn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-10, + Qn10, NewQn10, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, NewQn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-9, + Qn9, NewQn9, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, NewQn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-8, + Qn8, NewQn8, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, NewQn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-7, + Qn7, NewQn7, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, NewQn7, Qn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-6, + Qn6, NewQn6, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, NewQn6, + Qn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-5, + Qn5, NewQn5, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + NewQn5, Qn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-4, + Qn4, NewQn4, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, NewQn4, Qn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-3, + Qn3, NewQn3, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, NewQn3, Qn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-2, + Qn2, NewQn2, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, NewQn2, Qn1}); +?REMOVE_UNIQ_P_Qn16(-1, + Qn1, NewQn1, + {Qn16, Qn15, Qn14, Qn13, Qn12, + Qn11, Qn10, Qn9, Qn8, Qn7, Qn6, + Qn5, Qn4, Qn3, Qn2, NewQn1}); +remove_unique_p(0, F, + {Pc, + Size, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + Q0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}) -> + {Value, NewQ0} = queue_remove_unique(F, Q0), + NewSize = if Value =:= true -> Size - 1; Value =:= false -> Size end, + {Value, + {if NewSize == 0 -> empty; true -> Pc end, + NewSize, + Qn128, Qn112, Qn96, Qn80, Qn64, Qn48, Qn32, Qn16, + NewQ0, + Qp16, Qp32, Qp48, Qp64, Qp80, Qp96, Qp112, Qp128}}; +?REMOVE_UNIQ_P_Qp16(1, + Qp1, NewQp1, + {NewQp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(2, + Qp2, NewQp2, + {Qp1, NewQp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(3, + Qp3, NewQp3, + {Qp1, Qp2, NewQp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(4, + Qp4, NewQp4, + {Qp1, Qp2, Qp3, NewQp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(5, + Qp5, NewQp5, + {Qp1, Qp2, Qp3, Qp4, NewQp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(6, + Qp6, NewQp6, + {Qp1, Qp2, Qp3, Qp4, Qp5, + NewQp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(7, + Qp7, NewQp7, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, NewQp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(8, + Qp8, NewQp8, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, NewQp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(9, + Qp9, NewQp9, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, NewQp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(10, + Qp10, NewQp10, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, NewQp10, Qp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(11, + Qp11, NewQp11, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, NewQp11, + Qp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(12, + Qp12, NewQp12, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + NewQp12, Qp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(13, + Qp13, NewQp13, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, NewQp13, Qp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(14, + Qp14, NewQp14, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, NewQp14, Qp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(15, + Qp15, NewQp15, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, NewQp15, Qp16}); +?REMOVE_UNIQ_P_Qp16(16, + Qp16, NewQp16, + {Qp1, Qp2, Qp3, Qp4, Qp5, + Qp6, Qp7, Qp8, Qp9, Qp10, Qp11, + Qp12, Qp13, Qp14, Qp15, NewQp16}); +?REMOVE_UNIQ_P_Qp32(17, + Qp17, NewQp17, + {NewQp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(18, + Qp18, NewQp18, + {Qp17, NewQp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(19, + Qp19, NewQp19, + {Qp17, Qp18, NewQp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(20, + Qp20, NewQp20, + {Qp17, Qp18, Qp19, NewQp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(21, + Qp21, NewQp21, + {Qp17, Qp18, Qp19, Qp20, NewQp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(22, + Qp22, NewQp22, + {Qp17, Qp18, Qp19, Qp20, Qp21, + NewQp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(23, + Qp23, NewQp23, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, NewQp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(24, + Qp24, NewQp24, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, NewQp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(25, + Qp25, NewQp25, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, NewQp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(26, + Qp26, NewQp26, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, NewQp26, Qp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(27, + Qp27, NewQp27, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, NewQp27, + Qp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(28, + Qp28, NewQp28, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + NewQp28, Qp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(29, + Qp29, NewQp29, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, NewQp29, Qp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(30, + Qp30, NewQp30, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, NewQp30, Qp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(31, + Qp31, NewQp31, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, NewQp31, Qp32}); +?REMOVE_UNIQ_P_Qp32(32, + Qp32, NewQp32, + {Qp17, Qp18, Qp19, Qp20, Qp21, + Qp22, Qp23, Qp24, Qp25, Qp26, Qp27, + Qp28, Qp29, Qp30, Qp31, NewQp32}); +?REMOVE_UNIQ_P_Qp48(33, + Qp33, NewQp33, + {NewQp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(34, + Qp34, NewQp34, + {Qp33, NewQp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(35, + Qp35, NewQp35, + {Qp33, Qp34, NewQp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(36, + Qp36, NewQp36, + {Qp33, Qp34, Qp35, NewQp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(37, + Qp37, NewQp37, + {Qp33, Qp34, Qp35, Qp36, NewQp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(38, + Qp38, NewQp38, + {Qp33, Qp34, Qp35, Qp36, Qp37, + NewQp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(39, + Qp39, NewQp39, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, NewQp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(40, + Qp40, NewQp40, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, NewQp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(41, + Qp41, NewQp41, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, NewQp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(42, + Qp42, NewQp42, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, NewQp42, Qp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(43, + Qp43, NewQp43, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, NewQp43, + Qp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(44, + Qp44, NewQp44, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + NewQp44, Qp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(45, + Qp45, NewQp45, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, NewQp45, Qp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(46, + Qp46, NewQp46, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, NewQp46, Qp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(47, + Qp47, NewQp47, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, NewQp47, Qp48}); +?REMOVE_UNIQ_P_Qp48(48, + Qp48, NewQp48, + {Qp33, Qp34, Qp35, Qp36, Qp37, + Qp38, Qp39, Qp40, Qp41, Qp42, Qp43, + Qp44, Qp45, Qp46, Qp47, NewQp48}); +?REMOVE_UNIQ_P_Qp64(49, + Qp49, NewQp49, + {NewQp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(50, + Qp50, NewQp50, + {Qp49, NewQp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(51, + Qp51, NewQp51, + {Qp49, Qp50, NewQp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(52, + Qp52, NewQp52, + {Qp49, Qp50, Qp51, NewQp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(53, + Qp53, NewQp53, + {Qp49, Qp50, Qp51, Qp52, NewQp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(54, + Qp54, NewQp54, + {Qp49, Qp50, Qp51, Qp52, Qp53, + NewQp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(55, + Qp55, NewQp55, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, NewQp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(56, + Qp56, NewQp56, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, NewQp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(57, + Qp57, NewQp57, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, NewQp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(58, + Qp58, NewQp58, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, NewQp58, Qp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(59, + Qp59, NewQp59, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, NewQp59, + Qp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(60, + Qp60, NewQp60, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + NewQp60, Qp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(61, + Qp61, NewQp61, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, NewQp61, Qp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(62, + Qp62, NewQp62, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, NewQp62, Qp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(63, + Qp63, NewQp63, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, NewQp63, Qp64}); +?REMOVE_UNIQ_P_Qp64(64, + Qp64, NewQp64, + {Qp49, Qp50, Qp51, Qp52, Qp53, + Qp54, Qp55, Qp56, Qp57, Qp58, Qp59, + Qp60, Qp61, Qp62, Qp63, NewQp64}); +?REMOVE_UNIQ_P_Qp80(65, + Qp65, NewQp65, + {NewQp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(66, + Qp66, NewQp66, + {Qp65, NewQp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(67, + Qp67, NewQp67, + {Qp65, Qp66, NewQp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(68, + Qp68, NewQp68, + {Qp65, Qp66, Qp67, NewQp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(69, + Qp69, NewQp69, + {Qp65, Qp66, Qp67, Qp68, NewQp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(70, + Qp70, NewQp70, + {Qp65, Qp66, Qp67, Qp68, Qp69, + NewQp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(71, + Qp71, NewQp71, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, NewQp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(72, + Qp72, NewQp72, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, NewQp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(73, + Qp73, NewQp73, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, NewQp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(74, + Qp74, NewQp74, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, NewQp74, Qp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(75, + Qp75, NewQp75, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, NewQp75, + Qp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(76, + Qp76, NewQp76, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + NewQp76, Qp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(77, + Qp77, NewQp77, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, NewQp77, Qp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(78, + Qp78, NewQp78, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, NewQp78, Qp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(79, + Qp79, NewQp79, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, NewQp79, Qp80}); +?REMOVE_UNIQ_P_Qp80(80, + Qp80, NewQp80, + {Qp65, Qp66, Qp67, Qp68, Qp69, + Qp70, Qp71, Qp72, Qp73, Qp74, Qp75, + Qp76, Qp77, Qp78, Qp79, NewQp80}); +?REMOVE_UNIQ_P_Qp96(81, + Qp81, NewQp81, + {NewQp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(82, + Qp82, NewQp82, + {Qp81, NewQp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(83, + Qp83, NewQp83, + {Qp81, Qp82, NewQp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(84, + Qp84, NewQp84, + {Qp81, Qp82, Qp83, NewQp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(85, + Qp85, NewQp85, + {Qp81, Qp82, Qp83, Qp84, NewQp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(86, + Qp86, NewQp86, + {Qp81, Qp82, Qp83, Qp84, Qp85, + NewQp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(87, + Qp87, NewQp87, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, NewQp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(88, + Qp88, NewQp88, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, NewQp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(89, + Qp89, NewQp89, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, NewQp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(90, + Qp90, NewQp90, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, NewQp90, Qp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(91, + Qp91, NewQp91, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, NewQp91, + Qp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(92, + Qp92, NewQp92, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + NewQp92, Qp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(93, + Qp93, NewQp93, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, NewQp93, Qp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(94, + Qp94, NewQp94, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, NewQp94, Qp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(95, + Qp95, NewQp95, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, NewQp95, Qp96}); +?REMOVE_UNIQ_P_Qp96(96, + Qp96, NewQp96, + {Qp81, Qp82, Qp83, Qp84, Qp85, + Qp86, Qp87, Qp88, Qp89, Qp90, Qp91, + Qp92, Qp93, Qp94, Qp95, NewQp96}); +?REMOVE_UNIQ_P_Qp112(97, + Qp97, NewQp97, + {NewQp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(98, + Qp98, NewQp98, + {Qp97, NewQp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(99, + Qp99, NewQp99, + {Qp97, Qp98, NewQp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(100, + Qp100, NewQp100, + {Qp97, Qp98, Qp99, NewQp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(101, + Qp101, NewQp101, + {Qp97, Qp98, Qp99, Qp100, NewQp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(102, + Qp102, NewQp102, + {Qp97, Qp98, Qp99, Qp100, Qp101, + NewQp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(103, + Qp103, NewQp103, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, NewQp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(104, + Qp104, NewQp104, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, NewQp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(105, + Qp105, NewQp105, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, NewQp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(106, + Qp106, NewQp106, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, NewQp106, Qp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(107, + Qp107, NewQp107, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, NewQp107, + Qp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(108, + Qp108, NewQp108, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + NewQp108, Qp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(109, + Qp109, NewQp109, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, NewQp109, Qp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(110, + Qp110, NewQp110, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, NewQp110, Qp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(111, + Qp111, NewQp111, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, NewQp111, Qp112}); +?REMOVE_UNIQ_P_Qp112(112, + Qp112, NewQp112, + {Qp97, Qp98, Qp99, Qp100, Qp101, + Qp102, Qp103, Qp104, Qp105, Qp106, Qp107, + Qp108, Qp109, Qp110, Qp111, NewQp112}); +?REMOVE_UNIQ_P_Qp128(113, + Qp113, NewQp113, + {NewQp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(114, + Qp114, NewQp114, + {Qp113, NewQp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(115, + Qp115, NewQp115, + {Qp113, Qp114, NewQp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(116, + Qp116, NewQp116, + {Qp113, Qp114, Qp115, NewQp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(117, + Qp117, NewQp117, + {Qp113, Qp114, Qp115, Qp116, NewQp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(118, + Qp118, NewQp118, + {Qp113, Qp114, Qp115, Qp116, Qp117, + NewQp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(119, + Qp119, NewQp119, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, NewQp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(120, + Qp120, NewQp120, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, NewQp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(121, + Qp121, NewQp121, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, NewQp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(122, + Qp122, NewQp122, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, NewQp122, Qp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(123, + Qp123, NewQp123, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, NewQp123, + Qp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(124, + Qp124, NewQp124, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + NewQp124, Qp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(125, + Qp125, NewQp125, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, NewQp125, Qp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(126, + Qp126, NewQp126, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, NewQp126, Qp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(127, + Qp127, NewQp127, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, NewQp127, Qp128}); +?REMOVE_UNIQ_P_Qp128(128, + Qp128, NewQp128, + {Qp113, Qp114, Qp115, Qp116, Qp117, + Qp118, Qp119, Qp120, Qp121, Qp122, Qp123, + Qp124, Qp125, Qp126, Qp127, NewQp128}). + +-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_pq4())} + ], ?CLOUDI_LONG_TEST_TIMEOUT). + +-endif. + +%%------------------------------------------------------------------------- +%% @hidden +%% remove a unique value from a queue based on a binary predicate, +%% traversal order is undefined to keep it efficient (i.e., shouldn't matter) +%% (based on the implementation of queue:filter/2 +%% which is under the Apache License 2.0) +%%------------------------------------------------------------------------- + +-spec queue_remove_unique(F :: fun((any()) -> boolean()), + Q :: {list(), list()}) -> + {boolean(), {list(), list()}}. + +queue_remove_unique(Fun, {R0, F0} = Q) + when is_function(Fun, 1), is_list(R0), is_list(F0) -> + case queue_remove_unique_f(Fun, F0) of + {true, []} -> + {true, queue_r2f(R0)}; + {true, F1} -> + {true, {R0, F1}}; + {false, F1} -> + %true = F1 == F0, + case queue_remove_unique_f(Fun, R0) of % backwards + {true, []} -> + {true, queue_f2r(F1)}; + {true, R1} -> + {true, {R1, F1}}; + {false, _} -> + {false, Q} + end + end; +queue_remove_unique(Fun, Q) -> + erlang:error(badarg, [Fun,Q]). + +% Call Fun in front to back order +queue_remove_unique_f(_, [] = F) -> + {false, F}; +queue_remove_unique_f(Fun, F) -> + queue_remove_unique_f(F, [], F, Fun). + +queue_remove_unique_f([], _, F, _) -> + {false, F}; +queue_remove_unique_f([X | F0], F1, F, Fun) -> + case Fun(X) of + true -> + {true, lists:reverse(F1, F0)}; + false -> + queue_remove_unique_f(F0, [X | F1], F, Fun) + end. + +-compile({inline, [{queue_r2f,1},{queue_f2r,1}]}). + +% Move half of elements from R to F, if there are at least three +queue_r2f([]) -> + {[],[]}; +queue_r2f([_]=R) -> + {[],R}; +queue_r2f([X,Y]) -> + {[X],[Y]}; +queue_r2f(List) -> + {FF,RR} = lists:split(length(List) div 2 + 1, List), + {FF,lists:reverse(RR, [])}. + +% Move half of elements from F to R, if there are enough +queue_f2r([]) -> + {[],[]}; +queue_f2r([_]=F) -> + {F,[]}; +queue_f2r([X,Y]) -> + {[Y],[X]}; +queue_f2r(List) -> + {FF,RR} = lists:split(length(List) div 2 + 1, List), + {lists:reverse(RR, []),FF}. + diff --git a/aoc2023/build/packages/pqueue/src/pqueue_test.hrl b/aoc2023/build/packages/pqueue/src/pqueue_test.hrl new file mode 100644 index 0000000..cedffe0 --- /dev/null +++ b/aoc2023/build/packages/pqueue/src/pqueue_test.hrl @@ -0,0 +1,49 @@ +%-*-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: +%%% +%%%------------------------------------------------------------------------ +%%% pqueue eunit common functionality +%%% +%%% MIT License +%%% +%%% Copyright (c) 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. +%%% +%%%------------------------------------------------------------------------ + +-ifndef(_assertOk). +-define(_assertOk(Expr), ?_assertEqual(ok, Expr)). +-endif. + +-ifdef(CLOUDI_TEST_TIMEOUT). +-define(TEST_TIMEOUT, ?CLOUDI_TEST_TIMEOUT). % seconds +-else. +-define(TEST_TIMEOUT, 10). % seconds +-endif. +-ifndef(CLOUDI_LONG_TEST_TIMEOUT). +-define(CLOUDI_LONG_TEST_TIMEOUT, 60). % minutes +-endif. + +test_condition(_, 0) -> + []; +test_condition(L, LongTestTimeout) + when LongTestTimeout > 0 -> + {timeout, LongTestTimeout * 60, L}. + diff --git a/aoc2023/build/packages/pqueue/test/pqueue_proper.erl b/aoc2023/build/packages/pqueue/test/pqueue_proper.erl new file mode 100644 index 0000000..6702960 --- /dev/null +++ b/aoc2023/build/packages/pqueue/test/pqueue_proper.erl @@ -0,0 +1,156 @@ +-module(pqueue_proper). +-ifdef(TEST). +-include_lib("proper/include/proper.hrl"). + +-behaviour(proper_statem). + +-export([qc_pq/0, qc_pq2/0, qc_pq3/0, qc_pq4/0, correct/1]). + +-export([command/1, initial_state/0, next_state/3, postcondition/3, + precondition/2]). + +-type value() :: integer(). +-record(state, { in_queue :: [{value(), term()}] }). +-define(SERVER, queue_srv). + +priority() -> + integer(-20, 20). + +%% Selects priorities we have added +priority(InQ) -> + elements([P || {P, _} <- InQ]). + +value() -> + integer(). + +initial_state() -> + #state { in_queue = [] }. + +command(#state { in_queue = InQ }) -> + oneof([{call, ?SERVER, in, [value()]}, + {call, ?SERVER, in, [value(), priority()]}, + {call, ?SERVER, is_empty, []}, + {call, ?SERVER, is_queue, []}, + {call, ?SERVER, len, []}, + {call, ?SERVER, out, []}] ++ + [{call, ?SERVER, out, [priority(InQ)]} || InQ =/= []] ++ + [{call, ?SERVER, pout, []}, + {call, ?SERVER, to_list, []}]). + +next_state(#state { in_queue = InQ } = S, _V, {call, _, out, []}) -> + S#state { in_queue = listq_rem(InQ) }; +next_state(#state { in_queue = InQ } = S, _V, {call, _, out, [Prio]}) -> + S#state { in_queue = listq_rem(InQ, Prio) }; +next_state(#state { in_queue = InQ } = S, _V, {call, _, pout, _}) -> + S#state { in_queue = listq_rem(InQ) }; +next_state(S, _V, {call, _, to_list, _}) -> S; +next_state(S, _V, {call, _, is_queue, _}) -> S; +next_state(S, _V, {call, _, is_empty, _}) -> S; +next_state(S, _V, {call, _, len, _}) -> S; +next_state(#state { in_queue = InQ } = S, _V, {call, _, in, [Value, Prio]}) -> + S#state { in_queue = listq_insert({Prio, Value}, InQ) }; +next_state(#state { in_queue = InQ } = S, _V, {call, _, in, [Value]}) -> + S#state { in_queue = listq_insert({0, Value}, InQ) }. + +precondition(_S, _Call) -> + true. % No limitation on the things we can call at all. + +postcondition(#state { in_queue = InQ }, {call, _, out, [Prio]}, R) -> + R == listq_prio_peek(InQ, Prio); +postcondition(#state { in_queue = InQ }, {call, _, pout, _}, R) -> + R == listq_ppeek(InQ); +postcondition(#state { in_queue = InQ }, {call, _, out, _}, R) -> + R == listq_peek(InQ); +postcondition(S, {call, _, to_list, _}, R) -> + R == listq_to_list(S#state.in_queue); +postcondition(S, {call, _, len, _}, L) -> + L == listq_length(S#state.in_queue); +postcondition(_S, {call, _, is_queue, _}, true) -> true; +postcondition(S, {call, _, is_empty, _}, Res) -> + Res == (S#state.in_queue == []); +postcondition(_S, {call, _, in, _}, _) -> + true; +postcondition(_, _, _) -> + false. + +correct(M) -> + ?FORALL(Cmds, commands(?MODULE), + ?TRAPEXIT( + begin + ?SERVER:start_link(M), + {History,State,Result} = run_commands(?MODULE, Cmds), + ?SERVER:stop(), + ?WHENFAIL(io:format("History: ~w\nState: ~w\nResult: ~w\n", + [History,State,Result]), + aggregate(command_names(Cmds), Result =:= ok)) + end)). + +qc_opts() -> + [{numtests, 10000}]. + +qc_pq() -> + proper:quickcheck(pqueue_proper:correct(pqueue), qc_opts()). + +qc_pq2() -> + proper:quickcheck(pqueue_proper:correct(pqueue2), qc_opts()). + +qc_pq3() -> + proper:quickcheck(pqueue_proper:correct(pqueue3), qc_opts()). + +qc_pq4() -> + proper:quickcheck(pqueue_proper:correct(pqueue4), qc_opts()). + +%% ---------------------------------------------------------------------- + +%% A listq is a sorted list of priorities +listq_insert({P, V}, []) -> + [{P, [V]}]; +listq_insert({P, V}, [{P1, _} | _] = LQ) when P < P1 -> + [{P, [V]} | LQ]; +listq_insert({P, V}, [{P1, Vs} | Next]) when P == P1 -> + [{P, Vs ++ [V]} | Next]; +listq_insert({P, V}, [{P1, Vs} | Next]) when P > P1 -> + [{P1, Vs} | listq_insert({P, V}, Next)]. + +listq_to_list(L) -> + lists:concat( + [ Vals || {_Prio, Vals} <- L]). + +listq_length(L) -> + lists:sum( + [ length(Vs) || {_Prio, Vs} <- L]). + +listq_rem([]) -> + []; +listq_rem([{_P, [_V]} | Next]) -> + Next; +listq_rem([{P, [_V1 | Vs]} | Next]) -> + [{P, Vs} | Next]. + +listq_rem([], _P) -> + []; +listq_rem([{P, [_]} | Next], P) -> + Next; +listq_rem([{P, [_ | Vs]} | Next], P) -> + [{P, Vs} | Next]; +listq_rem([{P1, Vs} | Next], P) -> + [{P1, Vs} | listq_rem(Next, P)]. + +listq_peek([]) -> + empty; +listq_peek([{_P, [V | _]} | _]) -> + {value, V}. + +listq_prio_peek([{P, [V | _]} | _], P) -> + {value, V}; +listq_prio_peek([{_P1, _} | Next], P) -> + listq_prio_peek(Next, P); +listq_prio_peek([], _P) -> + empty. + +listq_ppeek([]) -> + empty; +listq_ppeek([{P, [V | _]} | _]) -> + {value, V, P}. + +-endif. diff --git a/aoc2023/build/packages/pqueue/test/queue_srv.erl b/aoc2023/build/packages/pqueue/test/queue_srv.erl new file mode 100644 index 0000000..7fcb0a1 --- /dev/null +++ b/aoc2023/build/packages/pqueue/test/queue_srv.erl @@ -0,0 +1,183 @@ +%%%------------------------------------------------------------------- +%%% @author Jesper Louis andersen <> +%%% @copyright (C) 2011, Jesper Louis andersen +%%% @doc +%%% +%%% @end +%%% Created : 11 Nov 2011 by Jesper Louis andersen <> +%%%------------------------------------------------------------------- +-module(queue_srv). + +-behaviour(gen_server). + +%% API +-export([start_link/1, stop/0, len/0, in/1, in/2, is_empty/0, + out/0, out/1, pout/0, + is_queue/0, to_list/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-define(SERVER, ?MODULE). + +-record(state, { mod, q }). + +%%%=================================================================== +%%% API +%%%=================================================================== + +%%-------------------------------------------------------------------- +%% @doc +%% Starts the server +%% +%% @spec start_link(Mod) -> {ok, Pid} | ignore | {error, Error} +%% @end +%%-------------------------------------------------------------------- +start_link(Mod) -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [Mod], []). + +stop() -> + gen_server:stop(?SERVER). + +call(M) -> + gen_server:call(?SERVER, M, infinity). + +in(I) -> + call({in, I}). + +in(I, P) -> + call({in, I, P}). + +len() -> + call(len). + +is_empty() -> + call(is_empty). + +is_queue() -> + call(is_queue). + +to_list() -> + call(to_list). + +out() -> + call(out). + +out(P) -> + call({out, P}). + +pout() -> + call(pout). + +%%%=================================================================== +%%% gen_server callbacks +%%%=================================================================== + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Initializes the server +%% +%% @spec init(Args) -> {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%% @end +%%-------------------------------------------------------------------- +init([Mod]) -> + {ok, #state{ mod = Mod, + q = Mod:new() }}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Handling call messages +%% +%% @spec handle_call(Request, From, State) -> +%% {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | +%% {stop, Reason, State} +%% @end +%%-------------------------------------------------------------------- +handle_call({in, Item}, _F, #state { q = Q, mod = M } = S) -> + NQ = M:in(Item, Q), + {reply, ok, S#state { q = NQ }}; +handle_call({in, Item, Prio}, _F, #state { q = Q, mod = M } = S) -> + NQ = M:in(Item, Prio, Q), + {reply, ok, S#state { q = NQ }}; +handle_call({out, P}, _F, #state { q = Q, mod = M } = S) -> + {R, NQ} = M:out(P, Q), + {reply, R, S#state { q = NQ }}; +handle_call(Ty, _F, #state { q = Q, mod = M } = S) when Ty == out; + Ty == pout -> + {R, NQ} = M:Ty(Q), + {reply, R, S#state { q = NQ }}; +handle_call(Ty, _F, #state { q = Q, mod = M } = S) when Ty == is_queue; + Ty == is_empty; + Ty == len; + Ty == to_list -> + R = M:Ty(Q), + {reply, R, S}; +handle_call(Req, From, State) -> + error_logger:info_report([{handle_call, Req, From, State}]), + Reply = ok, + {reply, Reply, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Handling cast messages +%% +%% @spec handle_cast(Msg, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% @end +%%-------------------------------------------------------------------- +handle_cast(_Msg, State) -> + {noreply, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Handling all non call/cast messages +%% +%% @spec handle_info(Info, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% @end +%%-------------------------------------------------------------------- +handle_info(_Info, State) -> + {noreply, State}. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% This function is called by a gen_server when it is about to +%% terminate. It should be the opposite of Module:init/1 and do any +%% necessary cleaning up. When it returns, the gen_server terminates +%% with Reason. The return value is ignored. +%% +%% @spec terminate(Reason, State) -> void() +%% @end +%%-------------------------------------------------------------------- +terminate(_Reason, _State) -> + ok. + +%%-------------------------------------------------------------------- +%% @private +%% @doc +%% Convert process state when code is changed +%% +%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState} +%% @end +%%-------------------------------------------------------------------- +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== diff --git a/aoc2023/build/packages/simplifile/README.md b/aoc2023/build/packages/simplifile/README.md new file mode 100644 index 0000000..5e49113 --- /dev/null +++ b/aoc2023/build/packages/simplifile/README.md @@ -0,0 +1,29 @@ +# simplifile + +[](https://hex.pm/packages/simplifile) +[](https://hexdocs.pm/simplifile/) + +Simplifile provides basic file operations (read, write, append, and delete) that work +for all targets (Erlang, Node, and Deno). It also provides functions for working with directories. + +Note: When upgrading versions, be sure to check the changelog. + +## Example +```gleam +let filepath = "./test/hello.txt" +let assert Ok(_) = "Hello, World" |> write(to: filepath) +let assert Ok(_) = "Goodbye, Mars" |> append(to: filepath) +let assert Ok("Hello, WorldGoodbye, Mars") = read(from: filepath) +let assert Ok(_) = delete(filepath) +let assert Error(_) = read(from: filepath) +``` + +## Installation + +If available on Hex this package can be added to your Gleam project: + +```sh +gleam add simplifile +``` + +and its documentation can be found at <https://hexdocs.pm/simplifile>. diff --git a/aoc2023/build/packages/simplifile/gleam.toml b/aoc2023/build/packages/simplifile/gleam.toml new file mode 100644 index 0000000..8e7523d --- /dev/null +++ b/aoc2023/build/packages/simplifile/gleam.toml @@ -0,0 +1,17 @@ +name = "simplifile" +version = "1.0.0" +description = "Basic file operations that work on all targets" + +licences = ["Apache-2.0"] +repository = { type = "github", user = "bcpeinhardt", repo = "simplifile" } +gleam = ">= 0.32.0" +# links = [{ title = "Website", href = "https://gleam.run" }] + +[javascript.deno] +allow_all = true + +[dependencies] +gleam_stdlib = "~> 0.29" + +[dev-dependencies] +gleeunit = "~> 1.0" diff --git a/aoc2023/build/packages/simplifile/src/simplifile.app.src b/aoc2023/build/packages/simplifile/src/simplifile.app.src new file mode 100644 index 0000000..5b9d6ef --- /dev/null +++ b/aoc2023/build/packages/simplifile/src/simplifile.app.src @@ -0,0 +1,8 @@ +{application, simplifile, [ + {vsn, "1.0.0"}, + {applications, [gleam_stdlib, + gleeunit]}, + {description, "Basic file operations that work on all targets"}, + {modules, [simplifile]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/simplifile/src/simplifile.erl b/aoc2023/build/packages/simplifile/src/simplifile.erl new file mode 100644 index 0000000..0d3818c --- /dev/null +++ b/aoc2023/build/packages/simplifile/src/simplifile.erl @@ -0,0 +1,287 @@ +-module(simplifile). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([read/1, write/2, delete/1, delete_all/1, append/2, read_bits/1, write_bits/2, append_bits/2, is_directory/1, create_directory/1, read_directory/1, is_file/1, create_file/1, get_files/1, create_directory_all/1, copy_directory/2, rename_directory/2, copy_file/2, rename_file/2]). +-export_type([file_error/0]). + +-type file_error() :: eacces | + eagain | + ebadf | + ebadmsg | + ebusy | + edeadlk | + edeadlock | + edquot | + eexist | + efault | + efbig | + eftype | + eintr | + einval | + eio | + eisdir | + eloop | + emfile | + emlink | + emultihop | + enametoolong | + enfile | + enobufs | + enodev | + enolck | + enolink | + enoent | + enomem | + enospc | + enosr | + enostr | + enosys | + enotblk | + enotdir | + enotsup | + enxio | + eopnotsupp | + eoverflow | + eperm | + epipe | + erange | + erofs | + espipe | + esrch | + estale | + etxtbsy | + exdev | + not_utf8 | + unknown. + +-spec do_append(binary(), binary()) -> {ok, nil} | {error, file_error()}. +do_append(Content, Filepath) -> + _pipe = Content, + _pipe@1 = gleam_stdlib:identity(_pipe), + simplifile_erl:append_file(_pipe@1, Filepath). + +-spec do_write(binary(), binary()) -> {ok, nil} | {error, file_error()}. +do_write(Content, Filepath) -> + _pipe = Content, + _pipe@1 = gleam_stdlib:identity(_pipe), + simplifile_erl:write_file(_pipe@1, Filepath). + +-spec do_read(binary()) -> {ok, binary()} | {error, file_error()}. +do_read(Filepath) -> + case simplifile_erl:read_file(Filepath) of + {ok, Bits} -> + case gleam@bit_array:to_string(Bits) of + {ok, Str} -> + {ok, Str}; + + _ -> + {error, not_utf8} + end; + + {error, E} -> + {error, E} + end. + +-spec cast_error({ok, FIL} | {error, file_error()}) -> {ok, FIL} | + {error, file_error()}. +cast_error(Input) -> + Input. + +-spec read(binary()) -> {ok, binary()} | {error, file_error()}. +read(Filepath) -> + _pipe = do_read(Filepath), + cast_error(_pipe). + +-spec write(binary(), binary()) -> {ok, nil} | {error, file_error()}. +write(Filepath, Contents) -> + _pipe = do_write(Contents, Filepath), + cast_error(_pipe). + +-spec delete(binary()) -> {ok, nil} | {error, file_error()}. +delete(Path) -> + _pipe = simplifile_erl:recursive_delete(Path), + cast_error(_pipe). + +-spec delete_all(list(binary())) -> {ok, nil} | {error, file_error()}. +delete_all(Paths) -> + case Paths of + [] -> + {ok, nil}; + + [Path | Rest] -> + case delete(Path) of + {ok, nil} -> + delete_all(Rest); + + {error, enoent} -> + delete_all(Rest); + + E -> + E + end + end. + +-spec append(binary(), binary()) -> {ok, nil} | {error, file_error()}. +append(Filepath, Contents) -> + _pipe = do_append(Contents, Filepath), + cast_error(_pipe). + +-spec read_bits(binary()) -> {ok, bitstring()} | {error, file_error()}. +read_bits(Filepath) -> + _pipe = simplifile_erl:read_file(Filepath), + cast_error(_pipe). + +-spec write_bits(binary(), bitstring()) -> {ok, nil} | {error, file_error()}. +write_bits(Filepath, Bits) -> + _pipe = simplifile_erl:write_file(Bits, Filepath), + cast_error(_pipe). + +-spec append_bits(binary(), bitstring()) -> {ok, nil} | {error, file_error()}. +append_bits(Filepath, Bits) -> + _pipe = simplifile_erl:append_file(Bits, Filepath), + cast_error(_pipe). + +-spec is_directory(binary()) -> boolean(). +is_directory(Filepath) -> + filelib:is_dir(Filepath). + +-spec create_directory(binary()) -> {ok, nil} | {error, file_error()}. +create_directory(Filepath) -> + _pipe = simplifile_erl:make_directory(Filepath), + cast_error(_pipe). + +-spec read_directory(binary()) -> {ok, list(binary())} | {error, file_error()}. +read_directory(Path) -> + _pipe = simplifile_erl:list_directory(Path), + cast_error(_pipe). + +-spec is_file(binary()) -> boolean(). +is_file(Filepath) -> + simplifile_erl:is_file(Filepath). + +-spec create_file(binary()) -> {ok, nil} | {error, file_error()}. +create_file(Filepath) -> + case begin + _pipe = Filepath, + is_file(_pipe) + end + orelse begin + _pipe@1 = Filepath, + is_directory(_pipe@1) + end of + true -> + {error, eexist}; + + false -> + write_bits(Filepath, <<>>) + end. + +-spec do_copy_directory(binary(), binary()) -> {ok, nil} | {error, file_error()}. +do_copy_directory(Src, Dest) -> + gleam@result:'try'( + read_directory(Src), + fun(Segments) -> + _pipe = Segments, + gleam@list:each( + _pipe, + fun(Segment) -> + Src_path = <<<<Src/binary, "/"/utf8>>/binary, + Segment/binary>>, + Dest_path = <<<<Dest/binary, "/"/utf8>>/binary, + Segment/binary>>, + case {is_file(Src_path), is_directory(Src_path)} of + {true, false} -> + gleam@result:'try'( + read_bits(Src_path), + fun(Content) -> _pipe@1 = Content, + write_bits(Dest_path, _pipe@1) end + ); + + {false, true} -> + gleam@result:'try'( + create_directory(Dest_path), + fun(_) -> + do_copy_directory(Src_path, Dest_path) + end + ); + + {_, _} -> + erlang:error(#{gleam_error => panic, + message => <<"unreachable"/utf8>>, + module => <<"simplifile"/utf8>>, + function => <<"do_copy_directory"/utf8>>, + line => 341}) + end + end + ), + {ok, nil} + end + ). + +-spec get_files(binary()) -> {ok, list(binary())} | {error, file_error()}. +get_files(Directory) -> + gleam@result:'try'( + read_directory(Directory), + fun(Contents) -> + Paths = gleam@list:map( + Contents, + fun(Segment) -> + <<<<Directory/binary, "/"/utf8>>/binary, Segment/binary>> + end + ), + Files = gleam@list:filter(Paths, fun is_file/1), + case gleam@list:filter(Paths, fun is_directory/1) of + [] -> + {ok, Files}; + + Directories -> + gleam@result:'try'( + gleam@list:try_map(Directories, fun get_files/1), + fun(Nested_files) -> + {ok, + gleam@list:append( + Files, + gleam@list:flatten(Nested_files) + )} + end + ) + end + end + ). + +-spec create_directory_all(binary()) -> {ok, nil} | {error, file_error()}. +create_directory_all(Dirpath) -> + Path = case begin + _pipe = Dirpath, + gleam@string:ends_with(_pipe, <<"/"/utf8>>) + end of + true -> + Dirpath; + + false -> + <<Dirpath/binary, "/"/utf8>> + end, + _pipe@1 = simplifile_erl:create_dir_all(Path), + cast_error(_pipe@1). + +-spec copy_directory(binary(), binary()) -> {ok, nil} | {error, file_error()}. +copy_directory(Src, Dest) -> + gleam@result:'try'( + create_directory_all(Dest), + fun(_) -> do_copy_directory(Src, Dest) end + ). + +-spec rename_directory(binary(), binary()) -> {ok, nil} | {error, file_error()}. +rename_directory(Src, Dest) -> + gleam@result:'try'(copy_directory(Src, Dest), fun(_) -> delete(Src) end). + +-spec copy_file(binary(), binary()) -> {ok, nil} | {error, file_error()}. +copy_file(Src, Dest) -> + _pipe = file:copy(Src, Dest), + _pipe@1 = gleam@result:replace(_pipe, nil), + cast_error(_pipe@1). + +-spec rename_file(binary(), binary()) -> {ok, nil} | {error, file_error()}. +rename_file(Src, Dest) -> + _pipe = simplifile_erl:rename_file(Src, Dest), + cast_error(_pipe). diff --git a/aoc2023/build/packages/simplifile/src/simplifile.gleam b/aoc2023/build/packages/simplifile/src/simplifile.gleam new file mode 100644 index 0000000..eff0306 --- /dev/null +++ b/aoc2023/build/packages/simplifile/src/simplifile.gleam @@ -0,0 +1,580 @@ +import gleam/bit_array +import gleam/string +import gleam/result +import gleam/list + +/// This type represents all of the reasons for why a file system operation could fail. +/// +/// Most of these reasons are POSIX errors, which come from the operating system +/// and start with E. Others have been added to represent other issues that may +/// arise specific to this library. +/// +pub type FileError { + /// Permission denied. + Eacces + /// Resource temporarily unavailable. + Eagain + /// Bad file number + Ebadf + /// Bad message. + Ebadmsg + /// File busy. + Ebusy + /// Resource deadlock avoided. + Edeadlk + /// On most architectures, same as `Edeadlk`. On some architectures, it + /// means "File locking deadlock error." + Edeadlock + /// Disk quota exceeded. + Edquot + /// File already exists. + Eexist + /// Bad address in system call argument. + Efault + /// File too large. + Efbig + /// Inappropriate file type or format. Usually caused by trying to set the + /// "sticky bit" on a regular file (not a directory). + Eftype + /// Interrupted system call. + Eintr + /// Invalid argument. + Einval + /// I/O error. + Eio + /// Illegal operation on a directory. + Eisdir + /// Too many levels of symbolic links. + Eloop + /// Too many open files. + Emfile + /// Too many links. + Emlink + /// Multihop attempted. + Emultihop + /// Filename too long + Enametoolong + /// File table overflow + Enfile + /// No buffer space available. + Enobufs + /// No such device. + Enodev + /// No locks available. + Enolck + /// Link has been severed. + Enolink + /// No such file or directory. + Enoent + /// Not enough memory. + Enomem + /// No space left on device. + Enospc + /// No STREAM resources. + Enosr + /// Not a STREAM. + Enostr + /// Function not implemented. + Enosys + /// Block device required. + Enotblk + /// Not a directory. + Enotdir + /// Operation not supported. + Enotsup + /// No such device or address. + Enxio + /// Operation not supported on socket. + Eopnotsupp + /// Value too large to be stored in data type. + Eoverflow + /// Not owner. + Eperm + /// Broken pipe. + Epipe + /// Result too large. + Erange + /// Read-only file system. + Erofs + /// Invalid seek. + Espipe + /// No such process. + Esrch + /// Stale remote file handle. + Estale + /// Text file busy. + Etxtbsy + /// Cross-domain link. + Exdev + /// File was requested to be read as UTF-8, but is not UTF-8 encoded. + NotUtf8 + /// Any error not accounted for by this type + Unknown +} + +/// Read a files contents as a string +/// ## Example +/// ```gleam +/// let assert Ok(records) = read(from: "./users.csv") +/// ``` +/// +pub fn read(from filepath: String) -> Result(String, FileError) { + do_read(filepath) + |> cast_error +} + +/// Write a string to a file at the given path +/// ## Example +/// ```gleam +/// let assert Ok(Nil) = write("Hello, World!", to: "./hello_world.txt") +/// ``` +/// +pub fn write( + to filepath: String, + contents contents: String, +) -> Result(Nil, FileError) { + do_write(contents, to: filepath) + |> cast_error +} + +/// Delete a file or directory at a given path. Performs a recursive +/// delete on a directory. +/// Throws an error if the path does not exist. +/// ## Example +/// ```gleam +/// let assert Ok(Nil) = delete(file_at: "./delete_me.txt") +/// ``` +/// +pub fn delete(file_or_dir_at path: String) -> Result(Nil, FileError) { + do_delete(path) + |> cast_error +} + +/// Delete all files/directories specified in a list of paths. +/// Recursively deletes provided directories. +/// Does not return an error if one or more of the provided paths +/// do not exist. +/// +pub fn delete_all(paths paths: List(String)) -> Result(Nil, FileError) { + case paths { + [] -> Ok(Nil) + [path, ..rest] -> { + case delete(path) { + Ok(Nil) | Error(Enoent) -> delete_all(rest) + e -> e + } + } + } +} + +/// Append a string to the contents of a file at the given path +/// ## Example +/// ```gleam +/// let assert Ok(Nil) = append("more text", to: "./needs_more_text.txt") +/// ``` +/// +pub fn append( + to filepath: String, + contents contents: String, +) -> Result(Nil, FileError) { + do_append(contents, to: filepath) + |> cast_error +} + +/// Read a files contents as a bitstring +/// ## Example +/// ```gleam +/// let assert Ok(records) = read_bits(from: "./users.csv") +/// ``` +/// +pub fn read_bits(from filepath: String) -> Result(BitArray, FileError) { + do_read_bits(filepath) + |> cast_error +} + +/// Write a bitstring to a file at the given path +/// ## Example +/// ```gleam +/// let assert Ok(Nil) = write_bits(<<"Hello, World!":utf8>>, to: "./hello_world.txt") +/// ``` +/// +pub fn write_bits( + to filepath: String, + bits bits: BitArray, +) -> Result(Nil, FileError) { + do_write_bits(bits, filepath) + |> cast_error +} + +/// Append a bitstring to the contents of a file at the given path +/// ## Example +/// ```gleam +/// let assert Ok(Nil) = append_bits(<<"more text":utf8>>, to: "./needs_more_text.txt") +/// ``` +/// +pub fn append_bits( + to filepath: String, + bits bits: BitArray, +) -> Result(Nil, FileError) { + do_append_bits(bits, filepath) + |> cast_error +} + +/// Checks if the provided filepath is a directory +/// ## Example +/// ```gleam +/// let assert True = is_directory("./test") +/// ``` +pub fn is_directory(filepath: String) -> Bool { + do_is_directory(filepath) +} + +/// Create a directory at the provided filepath. Returns an error if +/// the directory already exists. +/// +/// ## Example +/// ```gleam +/// create_directory("./test") +/// ``` +pub fn create_directory(filepath: String) -> Result(Nil, FileError) { + do_make_directory(filepath) + |> cast_error +} + +/// Lists the contents of a directory. +/// The list contains directory and file names, and is not recursive. +/// +/// ## Example +/// ```gleam +/// let assert Ok(files_and_folders) = read_directory(at: "./Folder1") +/// ``` +/// +pub fn read_directory(at path: String) -> Result(List(String), FileError) { + do_read_directory(path) + |> cast_error +} + +/// Returns `True` if there is a file at the given path, false otherwise. +/// +pub fn is_file(filepath: String) -> Bool { + do_is_file(filepath) +} + +/// Creates an empty file at the given filepath. Returns an `Error(Eexist)` +/// if the file already exists. +/// +pub fn create_file(at filepath: String) -> Result(Nil, FileError) { + case + filepath + |> is_file || filepath + |> is_directory + { + True -> Error(Eexist) + False -> write_bits(<<>>, to: filepath) + } +} + +/// Recursively creates necessary directories for a given directory +/// path. Note that if you pass a path that "looks like" a file, i.e. +/// `./a/b.txt`, a folder named `b.txt` will be created, so be sure +/// to pass only the path to the required directory. +pub fn create_directory_all(dirpath: String) -> Result(Nil, FileError) { + let path = case + dirpath + |> string.ends_with("/") + { + True -> dirpath + False -> dirpath <> "/" + } + do_create_dir_all(path) + |> cast_error +} + +/// Copy a file at a given path to another path. +/// Note: destination should include the filename, not just the directory +pub fn copy_file(at src: String, to dest: String) -> Result(Nil, FileError) { + do_copy_file(src, dest) + |> result.replace(Nil) + |> cast_error +} + +/// Rename a file at a given path to another path. +/// Note: destination should include the filename, not just the directory +pub fn rename_file(at src: String, to dest: String) -> Result(Nil, FileError) { + do_rename_file(src, dest) + |> cast_error +} + +/// Copy a directory recursively +pub fn copy_directory(at src: String, to dest: String) -> Result(Nil, FileError) { + // Erlang does not provide a built in `copy_dir` function, + // and Deno doesn't support Node's `fs.cpSync`, so we'll just roll + // our own for now. + use _ <- result.try(create_directory_all(dest)) + do_copy_directory(src, dest) +} + +fn do_copy_directory(src: String, dest: String) -> Result(Nil, FileError) { + // Iterate over the segments of the file + use segments <- result.try(read_directory(src)) + segments + |> list.each(fn(segment) { + let src_path = src <> "/" <> segment + let dest_path = dest <> "/" <> segment + + case is_file(src_path), is_directory(src_path) { + True, False -> { + // For a file, create the file in the new directory + use content <- result.try(read_bits(src_path)) + content + |> write_bits(to: dest_path) + } + False, True -> { + // Create the target directory and recurs + use _ <- result.try(create_directory(dest_path)) + do_copy_directory(src_path, dest_path) + } + _, _ -> { + // This should be unreachable. The src_path can't be both a file + // and a directory, and it's definitely one of the two because it's + // coming from list_contents + panic as "unreachable" + } + } + }) + Ok(Nil) +} + +/// Copy a directory recursively and then delete the old one. +pub fn rename_directory( + at src: String, + to dest: String, +) -> Result(Nil, FileError) { + use _ <- result.try(copy_directory(src, dest)) + delete(src) +} + +/// Returns a list of filepaths for every file in the directory, including nested +/// files. +/// +pub fn get_files(in directory: String) -> Result(List(String), FileError) { + use contents <- result.try(read_directory(directory)) + let paths = list.map(contents, fn(segment) { directory <> "/" <> segment }) + let files = list.filter(paths, is_file) + case list.filter(paths, is_directory) { + [] -> Ok(files) + directories -> { + use nested_files <- result.try(list.try_map(directories, get_files)) + Ok(list.append(files, list.flatten(nested_files))) + } + } +} + +@target(javascript) +fn do_read(from filepath: String) -> Result(String, String) { + case do_read_bits(filepath) { + Ok(bits) -> { + case bit_array.to_string(bits) { + Ok(str) -> Ok(str) + _ -> Error("NOTUTF8") + } + } + Error(e) -> Error(e) + } +} + +@target(javascript) +fn do_write(content: String, to filepath: String) -> Result(Nil, String) { + content + |> bit_array.from_string + |> do_write_bits(to: filepath) +} + +@target(javascript) +@external(javascript, "./simplifile_js.mjs", "deleteFileOrDirRecursive") +fn do_delete(file_or_dir_at: String) -> Result(Nil, String) + +@target(javascript) +fn do_append(content: String, to filepath: String) -> Result(Nil, String) { + content + |> bit_array.from_string + |> do_append_bits(to: filepath) +} + +@target(javascript) +@external(javascript, "./simplifile_js.mjs", "readBits") +fn do_read_bits(from: String) -> Result(BitArray, String) + +@target(javascript) +@external(javascript, "./simplifile_js.mjs", "writeBits") +fn do_write_bits(content: BitArray, to filepath: String) -> Result(Nil, String) + +@target(javascript) +@external(javascript, "./simplifile_js.mjs", "appendBits") +fn do_append_bits(content: BitArray, to filepath: String) -> Result(Nil, String) + +@target(javascript) +@external(javascript, "./simplifile_js.mjs", "isDirectory") +fn do_is_directory(filepath: String) -> Bool + +@target(javascript) +@external(javascript, "./simplifile_js.mjs", "makeDirectory") +fn do_make_directory(filepath: String) -> Result(Nil, String) + +@target(javascript) +@external(javascript, "./simplifile_js.mjs", "createDirAll") +fn do_create_dir_all(dirpath: String) -> Result(Nil, String) + +@target(javascript) +@external(javascript, "./simplifile_js.mjs", "listContents") +fn do_read_directory(directory_path: String) -> Result(List(String), String) + +@target(javascript) +@external(javascript, "./simplifile_js.mjs", "copyFile") +fn do_copy_file(at: String, to: String) -> Result(Nil, String) + +@target(javascript) +@external(javascript, "./simplifile_js.mjs", "renameFile") +fn do_rename_file(at: String, to: String) -> Result(Nil, String) + +@target(javascript) +fn cast_error(input: Result(a, String)) -> Result(a, FileError) { + result.map_error( + input, + fn(e) { + case e { + "EACCES" -> Eacces + "EAGAIN" -> Eagain + "EBADF" -> Ebadf + "EBADMSG" -> Ebadmsg + "EBUSY" -> Ebusy + "EDEADLK" -> Edeadlk + "EDEADLOCK" -> Edeadlock + "EDQUOT" -> Edquot + "EEXIST" -> Eexist + "EFAULT" -> Efault + "EFBIG" -> Efbig + "EFTYPE" -> Eftype + "EINTR" -> Eintr + "EINVAL" -> Einval + "EIO" -> Eio + "EISDIR" -> Eisdir + "ELOOP" -> Eloop + "EMFILE" -> Emfile + "EMLINK" -> Emlink + "EMULTIHOP" -> Emultihop + "ENAMETOOLONG" -> Enametoolong + "ENFILE" -> Enfile + "ENOBUFS" -> Enobufs + "ENODEV" -> Enodev + "ENOLCK" -> Enolck + "ENOLINK" -> Enolink + "ENOENT" -> Enoent + "ENOMEM" -> Enomem + "ENOSPC" -> Enospc + "ENOSR" -> Enosr + "ENOSTR" -> Enostr + "ENOSYS" -> Enosys + "ENOBLK" -> Enotblk + "ENODIR" -> Enotdir + "ENOTSUP" -> Enotsup + "ENXIO" -> Enxio + "EOPNOTSUPP" -> Eopnotsupp + "EOVERFLOW" -> Eoverflow + "EPERM" -> Eperm + "EPIPE" -> Epipe + "ERANGE" -> Erange + "EROFS" -> Erofs + "ESPIPE" -> Espipe + "ESRCH" -> Esrch + "ESTALE" -> Estale + "ETXTBSY" -> Etxtbsy + "EXDEV" -> Exdev + "NOTUTF8" -> NotUtf8 + _ -> Unknown + } + }, + ) +} + +@target(erlang) +@external(erlang, "simplifile_erl", "append_file") +fn do_append_bits( + content: BitArray, + to filepath: String, +) -> Result(Nil, FileError) + +@target(erlang) +@external(erlang, "simplifile_erl", "write_file") +fn do_write_bits( + content: BitArray, + to filepath: String, +) -> Result(Nil, FileError) + +@target(erlang) +@external(erlang, "simplifile_erl", "read_file") +fn do_read_bits(from: String) -> Result(BitArray, FileError) + +@target(erlang) +@external(erlang, "simplifile_erl", "recursive_delete") +fn do_delete(file_or_dir_at: String) -> Result(Nil, FileError) + +@target(erlang) +fn do_append(content: String, to filepath: String) -> Result(Nil, FileError) { + content + |> bit_array.from_string + |> do_append_bits(filepath) +} + +@target(erlang) +fn do_write(content: String, to filepath: String) -> Result(Nil, FileError) { + content + |> bit_array.from_string + |> do_write_bits(filepath) +} + +@target(erlang) +fn do_read(from filepath: String) -> Result(String, FileError) { + case do_read_bits(filepath) { + Ok(bits) -> { + case bit_array.to_string(bits) { + Ok(str) -> Ok(str) + _ -> Error(NotUtf8) + } + } + Error(e) -> Error(e) + } +} + +@target(erlang) +fn cast_error(input: Result(a, FileError)) -> Result(a, FileError) { + input +} + +@target(erlang) +@external(erlang, "filelib", "is_dir") +fn do_is_directory(path: String) -> Bool + +@target(erlang) +@external(erlang, "simplifile_erl", "make_directory") +fn do_make_directory(directory: String) -> Result(Nil, FileError) + +@target(erlang) +@external(erlang, "simplifile_erl", "list_directory") +fn do_read_directory(directory: String) -> Result(List(String), FileError) + +@external(erlang, "simplifile_erl", "is_file") +@external(javascript, "./simplifile_js.mjs", "isFile") +fn do_is_file(filepath: String) -> Bool + +@target(erlang) +@external(erlang, "simplifile_erl", "create_dir_all") +fn do_create_dir_all(dirpath: String) -> Result(Nil, FileError) + +@target(erlang) +@external(erlang, "file", "copy") +fn do_copy_file(src: String, dest: String) -> Result(Int, FileError) + +@target(erlang) +@external(erlang, "simplifile_erl", "rename_file") +fn do_rename_file(src: String, dest: String) -> Result(Nil, FileError) diff --git a/aoc2023/build/packages/simplifile/src/simplifile_erl.erl b/aoc2023/build/packages/simplifile/src/simplifile_erl.erl new file mode 100644 index 0000000..dac135a --- /dev/null +++ b/aoc2023/build/packages/simplifile/src/simplifile_erl.erl @@ -0,0 +1,70 @@ +-module(simplifile_erl). +-export([ + read_file/1, + append_file/2, write_file/2, delete_file/1, delete_directory/1, recursive_delete/1, + list_directory/1, make_directory/1, is_file/1, create_dir_all/1, rename_file/2 +]). + +-define(is_posix_error(Error), + Error =:= eacces orelse Error =:= eagain orelse Error =:= ebadf orelse + Error =:= ebadmsg orelse Error =:= ebusy orelse Error =:= edeadlk orelse + Error =:= edeadlock orelse Error =:= edquot orelse Error =:= eexist orelse + Error =:= efault orelse Error =:= efbig orelse Error =:= eftype orelse + Error =:= eintr orelse Error =:= einval orelse Error =:= eio orelse + Error =:= eisdir orelse Error =:= eloop orelse Error =:= emfile orelse + Error =:= emlink orelse Error =:= emultihop orelse Error =:= enametoolong orelse + Error =:= enfile orelse Error =:= enobufs orelse Error =:= enodev orelse + Error =:= enolck orelse Error =:= enolink orelse Error =:= enoent orelse + Error =:= enomem orelse Error =:= enospc orelse Error =:= enosr orelse + Error =:= enostr orelse Error =:= enosys orelse Error =:= enotblk orelse + Error =:= enotdir orelse Error =:= enotsup orelse Error =:= enxio orelse + Error =:= eopnotsupp orelse Error =:= eoverflow orelse Error =:= eperm orelse + Error =:= epipe orelse Error =:= erange orelse Error =:= erofs orelse + Error =:= espipe orelse Error =:= esrch orelse Error =:= estale orelse + Error =:= etxtbsy orelse Error =:= exdev +). + +posix_result(Result) -> + case Result of + ok -> {ok, nil}; + {ok, Value} -> {ok, Value}; + {error, Reason} when ?is_posix_error(Reason) -> {error, Reason} + end. + +read_file(Filename) -> + posix_result(file:read_file(Filename)). + +write_file(Contents, Filename) -> + posix_result(file:write_file(Filename, Contents)). + +append_file(Contents, Filename) -> + posix_result(file:write_file(Filename, Contents, [append])). + +delete_file(Filename) -> + posix_result(file:delete(Filename)). + +make_directory(Dir) -> + posix_result(file:make_dir(Dir)). + +list_directory(Dir) -> + case file:list_dir(Dir) of + {ok, Filenames} -> + {ok, [list_to_binary(Filename) || Filename <- Filenames]}; + {error, Reason} when ?is_posix_error(Reason) -> + {error, Reason} + end. + +delete_directory(Dir) -> + posix_result(file:del_dir(Dir)). + +recursive_delete(Dir) -> + posix_result(file:del_dir_r(Dir)). + +is_file(Filename) -> + not (file:read_file_info(Filename) == {error, enoent}) and not filelib: is_dir(Filename). + +create_dir_all(Filename) -> + posix_result(filelib:ensure_dir(Filename)). + +rename_file(Source, Destination) -> + posix_result(file:rename(Source, Destination)). diff --git a/aoc2023/build/packages/simplifile/src/simplifile_js.mjs b/aoc2023/build/packages/simplifile/src/simplifile_js.mjs new file mode 100644 index 0000000..faf4109 --- /dev/null +++ b/aoc2023/build/packages/simplifile/src/simplifile_js.mjs @@ -0,0 +1,102 @@ +import fs from "node:fs" +import path from "node:path" +import { BitArray, Ok, Error as GError, toList} from "./gleam.mjs"; + +export function readBits(filepath) { + try { + const contents = fs.readFileSync(path.normalize(filepath)) + return new Ok(new BitArray(new Uint8Array(contents))) + } catch(e) { + return new GError(stringifyError(e)) + } +} + +export function writeBits(contents, filepath) { + try { + fs.writeFileSync(path.normalize(filepath), contents.buffer) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +export function appendBits(contents, filepath) { + try { + fs.appendFileSync(path.normalize(filepath), contents.buffer) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +function stringifyError(e) { + return e.code +} + +export function isFile(filepath) { + let fp = path.normalize(filepath) + return fs.existsSync(fp) && fs.lstatSync(fp).isFile(); +} + +export function isDirectory(filepath) { + let fp = path.normalize(filepath) + return fs.existsSync(fp) && fs.lstatSync(fp).isDirectory(); +} + +export function makeDirectory(filepath) { + try { + fs.mkdirSync(path.normalize(filepath)) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +export function createDirAll(filepath) { + try { + fs.mkdirSync(filepath, { recursive: true }) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +export function deleteFileOrDirRecursive(fileOrDirPath) { + try { + if (isDirectory(fileOrDirPath)) { + fs.rmSync(path.normalize(fileOrDirPath), { recursive: true }) + } else { + fs.unlinkSync(path.normalize(fileOrDirPath)) + } + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +export function listContents(filepath) { + try { + const stuff = toList(fs.readdirSync(path.normalize(filepath))) + return new Ok(stuff) + } catch(e) { + return new GError(stringifyError(e)) + } +} + +export function copyFile(srcpath, destpath) { + try { + fs.copyFileSync(path.normalize(srcpath), path.normalize(destpath)) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +} + +export function renameFile(srcpath, destpath) { + try { + fs.renameSync(path.normalize(srcpath), path.normalize(destpath)) + return new Ok(undefined) + } catch (e) { + return new GError(stringifyError(e)) + } +}
\ No newline at end of file diff --git a/aoc2023/build/packages/snag/LICENCE b/aoc2023/build/packages/snag/LICENCE new file mode 100644 index 0000000..b8c2e9e --- /dev/null +++ b/aoc2023/build/packages/snag/LICENCE @@ -0,0 +1,211 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2021 - present Louis Pilfold + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +## Runtime Library Exception to the Apache 2.0 License: ## + + + As an exception, if you use this Software to compile your source code and + portions of this Software are embedded into the binary product as a result, + you may redistribute such product without providing attribution as would + otherwise be required by Sections 4(a), 4(b) and 4(d) of the License. diff --git a/aoc2023/build/packages/snag/README.md b/aoc2023/build/packages/snag/README.md new file mode 100644 index 0000000..aaedcf5 --- /dev/null +++ b/aoc2023/build/packages/snag/README.md @@ -0,0 +1,81 @@ +# Snag + +A Snag is a boilerplate-free ad-hoc error type. + +Use `Result(value, Snag)` (or the `snag.Result(value)` alias) in functions +that may fail. + +A low level message like "Unexpected status 401" or "No such file or +directory" can be confusing or difficult to debug, so use the `snag.context` +function to add extra contextual information. + +```gleam +import gleam/io +import my_app.{User} +import snag.{Result} + +pub fn log_in(user_id: Int) -> Result(User) { + try api_key = + my_app.read_file("api_key.txt") + |> snag.context("Could not load API key") + + try session_token = + user_id + |> my_app.create_session(api_key) + |> snag.context("Session creation failed") + + Ok(session_token) +} + +pub fn main() { + case log_in(42) { + Ok(session) -> io.println("Logged in!") + Error(snag) -> { + io.print(snag.pretty_print(snag)) + my_app.exit(1) + } + } +} +``` + +In this code when an error occurs within the `create_session` function an +error message like this is printed using the added contextual information: + +```text +error: Session creation failed + +cause: + 0: Unable to exchange token with authentication service + 1: Service authentication failed + 2: Unexpected HTTP status 401 +``` + +## When should I use Snag? + +Snag is useful in code where it must either pass or fail, and when it fails we +want good debugging information to print to the user. i.e. Command line +tools, data processing pipelines, etc. Here Snag provides a convenient way to +create errors with a reasonable amount of debugging information, without the +boilerplate of a custom error type. + +It is not suited to code where the application needs to make a decision about +what to do in the event of an error, such as whether to give up or to try +again. i.e. Libraries, web application backends, API clients, etc. In these +situations it is recommended to create a custom type for your errors as it +can be pattern matched on and have any additional detail added as fields. + +## Installation + +Add `snag` to your Gleam project + +``` +gleam add snag +``` + +## Prior art + +This library is inspired by the following projects: + +- Rust's [`anyhow`](https://github.com/dtolnay/anyhow) and + [`std::error::Error`](https://doc.rust-lang.org/std/error/trait.Error.html) +- Go's [`error`](https://golang.org/pkg/errors/). diff --git a/aoc2023/build/packages/snag/gleam.toml b/aoc2023/build/packages/snag/gleam.toml new file mode 100644 index 0000000..4f2d670 --- /dev/null +++ b/aoc2023/build/packages/snag/gleam.toml @@ -0,0 +1,16 @@ +name = "snag" +version = "0.2.1" +licences = ["Apache-2.0"] +description = "A boilerplate-free ad-hoc error type" + +repository = { type = "github", user = "gleam-experiments", repo = "snag" } +links = [ + { title = "Website", href = "https://gleam.run" }, + { title = "Sponsor", href = "https://github.com/sponsors/lpil" }, +] + +[dependencies] +gleam_stdlib = "~> 0.18" + +[dev-dependencies] +gleeunit = "~> 0.5" diff --git a/aoc2023/build/packages/snag/include/snag_Snag.hrl b/aoc2023/build/packages/snag/include/snag_Snag.hrl new file mode 100644 index 0000000..5d6614e --- /dev/null +++ b/aoc2023/build/packages/snag/include/snag_Snag.hrl @@ -0,0 +1 @@ +-record(snag, {issue :: binary(), cause :: list(binary())}). diff --git a/aoc2023/build/packages/snag/src/snag.app.src b/aoc2023/build/packages/snag/src/snag.app.src new file mode 100644 index 0000000..175e326 --- /dev/null +++ b/aoc2023/build/packages/snag/src/snag.app.src @@ -0,0 +1,8 @@ +{application, snag, [ + {vsn, "0.2.1"}, + {applications, [gleam_stdlib, + gleeunit]}, + {description, "A boilerplate-free ad-hoc error type"}, + {modules, [snag]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/snag/src/snag.erl b/aoc2023/build/packages/snag/src/snag.erl new file mode 100644 index 0000000..a07f242 --- /dev/null +++ b/aoc2023/build/packages/snag/src/snag.erl @@ -0,0 +1,74 @@ +-module(snag). +-compile([no_auto_import, nowarn_unused_vars]). + +-export([new/1, error/1, layer/2, context/2, pretty_print/1, line_print/1]). +-export_type([snag/0]). + +-type snag() :: {snag, binary(), list(binary())}. + +-spec new(binary()) -> snag(). +new(Issue) -> + {snag, Issue, []}. + +-spec error(binary()) -> {ok, any()} | {error, snag()}. +error(Issue) -> + {error, new(Issue)}. + +-spec layer(snag(), binary()) -> snag(). +layer(Snag, Issue) -> + {snag, Issue, [erlang:element(2, Snag) | erlang:element(3, Snag)]}. + +-spec context({ok, EXX} | {error, snag()}, binary()) -> {ok, EXX} | + {error, snag()}. +context(Result, Issue) -> + case Result of + {ok, _} -> + Result; + + {error, Snag} -> + {error, layer(Snag, Issue)} + end. + +-spec pretty_print_cause(list(binary())) -> gleam@string_builder:string_builder(). +pretty_print_cause(Cause) -> + _pipe = Cause, + _pipe@1 = gleam@list:index_map( + _pipe, + fun(Index, Line) -> + gleam@string:concat( + [<<" "/utf8>>, + gleam@int:to_string(Index), + <<": "/utf8>>, + Line, + <<"\n"/utf8>>] + ) + end + ), + gleam@string_builder:from_strings(_pipe@1). + +-spec pretty_print(snag()) -> binary(). +pretty_print(Snag) -> + Builder = gleam@string_builder:from_strings( + [<<"error: "/utf8>>, erlang:element(2, Snag), <<"\n"/utf8>>] + ), + gleam@string_builder:to_string(case erlang:element(3, Snag) of + [] -> + Builder; + + Cause -> + _pipe = Builder, + _pipe@1 = gleam@string_builder:append( + _pipe, + <<"\ncause:\n"/utf8>> + ), + gleam@string_builder:append_builder( + _pipe@1, + pretty_print_cause(Cause) + ) + end). + +-spec line_print(snag()) -> binary(). +line_print(Snag) -> + _pipe = [gleam@string:append(<<"error: "/utf8>>, erlang:element(2, Snag)) | + erlang:element(3, Snag)], + gleam@string:join(_pipe, <<" <- "/utf8>>). diff --git a/aoc2023/build/packages/snag/src/snag.gleam b/aoc2023/build/packages/snag/src/snag.gleam new file mode 100644 index 0000000..8d39537 --- /dev/null +++ b/aoc2023/build/packages/snag/src/snag.gleam @@ -0,0 +1,141 @@ +import gleam +import gleam/string_builder +import gleam/string +import gleam/list +import gleam/int + +/// A Snag is a boilerplate-free error type that can be used to track why an +/// error happened, though does not store as much detail on specific errors as a +/// custom error type would. +/// +/// It is useful in code where it must either pass or fail, and when it fails we +/// want good debugging information to print to the user. i.e. Command line +/// tools, data processing pipelines, etc. +/// +/// If it not suited to code where the application needs to make a decision about +/// what to do in the event of an error, such as whether to give up or to try +/// again. i.e. Libraries, web application backends, API clients, etc. +/// In these situations it is recommended to create a custom type for your errors +/// as it can be pattern matched on and have any additional detail added as +/// fields. +pub type Snag { + Snag(issue: String, cause: List(String)) +} + +/// A concise alias for a `Result` that uses a `Snag` as the error value. +pub type Result(t) = + gleam.Result(t, Snag) + +/// Create a new `Snag` with the given issue text. +/// +/// See also the `error` function for creating a `Snag` wrapped in a `Result`. +/// +/// # Example +/// +/// ```gleam +/// > new("Not enough credit") +/// > |> line_print +/// "error: Not enough credit" +/// ``` +pub fn new(issue: String) -> Snag { + Snag(issue: issue, cause: []) +} + +/// Create a new `Snag` wrapped in a `Result` with the given issue text. +/// +/// # Example +/// +/// ```gleam +/// > error("Not enough credit") +/// Error(new("Not enough credit")) +/// ``` +pub fn error(issue: String) -> Result(success) { + Error(new(issue)) +} + +/// Add additional contextual information to a `Snag`. +/// +/// See also the `context` function for adding contextual information to a `Snag` +/// wrapped in a `Result`. +/// +/// # Example +/// +/// ```gleam +/// > new("Not enough credit") +/// > |> layer("Unable to make purchase") +/// > |> line_print +/// "error: Unable to make purchase <- Not enough credit" +/// ``` +pub fn layer(snag: Snag, issue: String) -> Snag { + Snag(issue: issue, cause: [snag.issue, ..snag.cause]) +} + +/// Add additional contextual information to a `Snag` wrapped in a `Result`. +/// +/// # Example +/// +/// ```gleam +/// > error("Not enough credit") +/// > |> context("Unable to make purchase") +/// > |> result.map_error(line_print) +/// Error("error: Unable to make purchase <- Not enough credit") +/// ``` +pub fn context(result: Result(success), issue: String) -> Result(success) { + case result { + Ok(_) -> result + Error(snag) -> Error(layer(snag, issue)) + } +} + +/// Turn a snag into a multi-line string, optimised for readability. +/// +/// # Example +/// +/// ```gleam +/// > new("Not enough credit") +/// > |> layer("Unable to make purchase") +/// > |> layer("Character creation failed") +/// > |> pretty_print +/// "error: Character creation failed +/// +/// cause: +/// 0: Unable to make purchase +/// 1: Not enough credit +/// " +/// ``` +pub fn pretty_print(snag: Snag) -> String { + let builder = string_builder.from_strings(["error: ", snag.issue, "\n"]) + + string_builder.to_string(case snag.cause { + [] -> builder + cause -> + builder + |> string_builder.append("\ncause:\n") + |> string_builder.append_builder(pretty_print_cause(cause)) + }) +} + +fn pretty_print_cause(cause) { + cause + |> list.index_map(fn(index, line) { + string.concat([" ", int.to_string(index), ": ", line, "\n"]) + }) + |> string_builder.from_strings +} + +/// Turn a snag into a single-line string, optimised for compactness. This may be +/// useful for logging snags. +/// +/// # Example +/// +/// ```gleam +/// > new("Not enough credit") +/// > |> layer("Unable to make purchase") +/// > |> layer("Character creation failed") +/// > |> pretty_print +/// "error: Character creation failed <- Unable to make purchase <- Not enough credit" +/// ``` +pub fn line_print(snag: Snag) -> String { + [string.append("error: ", snag.issue), ..snag.cause] + |> string.join(" <- ") +} diff --git a/aoc2023/build/packages/tom/README.md b/aoc2023/build/packages/tom/README.md new file mode 100644 index 0000000..e6adcbe --- /dev/null +++ b/aoc2023/build/packages/tom/README.md @@ -0,0 +1,47 @@ +# tom + +A Gleam TOML parser! + +[](https://hex.pm/packages/tom) +[](https://hexdocs.pm/tom/) + + +```sh +gleam add tom +``` +```gleam +import tom + +const config = " + [person] + name = \"Lucy\" + is_cool = true +" + +pub fn main() { + // Parse a string of TOML + let assert Ok(parsed) = tom.parse(config) + + // Now you can work with the data directly, or you can use the `get_*` + // functions to retrieve values. + + tom.get_string(parsed, ["person", "name"]) + // -> Ok("Lucy") + + let is_cool = tom.get_bool(parsed, ["person", "is_cool"]) + // -> Ok(True) +} +``` + +Further documentation can be found at <https://hexdocs.pm/tom>. + +## Status + +The following string escape sequences are not supported yet: + +- `\b` +- `\f` +- `\e` +- `\xHH` +- `\uHHHH` +- `\UHHHHHHHH` diff --git a/aoc2023/build/packages/tom/build/dev/erlang/gleam.lock b/aoc2023/build/packages/tom/build/dev/erlang/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/packages/tom/build/dev/erlang/gleam.lock diff --git a/aoc2023/build/packages/tom/build/dev/javascript/gleam.lock b/aoc2023/build/packages/tom/build/dev/javascript/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/packages/tom/build/dev/javascript/gleam.lock diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam.lock b/aoc2023/build/packages/tom/build/lsp/erlang/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam.lock diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache Binary files differnew file mode 100644 index 0000000..0a49e16 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta Binary files differnew file mode 100644 index 0000000..d03bd4e --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache Binary files differnew file mode 100644 index 0000000..e75aa37 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta Binary files differnew file mode 100644 index 0000000..831cdbd --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache Binary files differnew file mode 100644 index 0000000..e64afd2 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_meta Binary files differnew file mode 100644 index 0000000..b59a80e --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache Binary files differnew file mode 100644 index 0000000..3dd81d8 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_meta Binary files differnew file mode 100644 index 0000000..e7f013d --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache Binary files differnew file mode 100644 index 0000000..de4ee67 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta Binary files differnew file mode 100644 index 0000000..e616ec0 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache Binary files differnew file mode 100644 index 0000000..98608da --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_meta Binary files differnew file mode 100644 index 0000000..701db1f --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache Binary files differnew file mode 100644 index 0000000..2f469d1 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta Binary files differnew file mode 100644 index 0000000..277da6b --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache Binary files differnew file mode 100644 index 0000000..60712c7 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta Binary files differnew file mode 100644 index 0000000..91b39cc --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache Binary files differnew file mode 100644 index 0000000..b832a82 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta Binary files differnew file mode 100644 index 0000000..702d055 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache Binary files differnew file mode 100644 index 0000000..61d53d4 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta Binary files differnew file mode 100644 index 0000000..e7b9f9f --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache Binary files differnew file mode 100644 index 0000000..fdcf634 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta Binary files differnew file mode 100644 index 0000000..aad5629 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache Binary files differnew file mode 100644 index 0000000..70774f5 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta Binary files differnew file mode 100644 index 0000000..48ca73e --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache Binary files differnew file mode 100644 index 0000000..2ebb0ba --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta Binary files differnew file mode 100644 index 0000000..43c26de --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache Binary files differnew file mode 100644 index 0000000..f58495d --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta Binary files differnew file mode 100644 index 0000000..ec9035e --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache Binary files differnew file mode 100644 index 0000000..f5f5c1e --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta Binary files differnew file mode 100644 index 0000000..f1ed30f --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache Binary files differnew file mode 100644 index 0000000..f50856a --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta Binary files differnew file mode 100644 index 0000000..8b36f47 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache Binary files differnew file mode 100644 index 0000000..f10a597 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta Binary files differnew file mode 100644 index 0000000..2395015 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache Binary files differnew file mode 100644 index 0000000..c31d461 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta Binary files differnew file mode 100644 index 0000000..a2089a5 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache Binary files differnew file mode 100644 index 0000000..b1e9775 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta Binary files differnew file mode 100644 index 0000000..6ec02d2 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache Binary files differnew file mode 100644 index 0000000..e9ae9d8 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta Binary files differnew file mode 100644 index 0000000..d6129ae --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache Binary files differnew file mode 100644 index 0000000..c29fc16 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta Binary files differnew file mode 100644 index 0000000..f4e8874 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache Binary files differnew file mode 100644 index 0000000..47c7957 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta Binary files differnew file mode 100644 index 0000000..5d99ee5 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache Binary files differnew file mode 100644 index 0000000..4d87904 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta Binary files differnew file mode 100644 index 0000000..d4739c1 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache Binary files differnew file mode 100644 index 0000000..c0e91da --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_meta Binary files differnew file mode 100644 index 0000000..b367bfd --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache Binary files differnew file mode 100644 index 0000000..ba5daf8 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta Binary files differnew file mode 100644 index 0000000..2ae412b --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleam_version b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_version new file mode 100644 index 0000000..7d07a19 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_version @@ -0,0 +1 @@ +0.33.0
\ No newline at end of file diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit.cache Binary files differnew file mode 100644 index 0000000..8f060b4 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit.cache_meta Binary files differnew file mode 100644 index 0000000..1c4228b --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache Binary files differnew file mode 100644 index 0000000..7c85b7e --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache_meta Binary files differnew file mode 100644 index 0000000..1b7dad9 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/tom/_gleam_artefacts/tom.cache b/aoc2023/build/packages/tom/build/lsp/erlang/tom/_gleam_artefacts/tom.cache Binary files differnew file mode 100644 index 0000000..2bfceaf --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/tom/_gleam_artefacts/tom.cache diff --git a/aoc2023/build/packages/tom/build/lsp/erlang/tom/_gleam_artefacts/tom.cache_meta b/aoc2023/build/packages/tom/build/lsp/erlang/tom/_gleam_artefacts/tom.cache_meta Binary files differnew file mode 100644 index 0000000..3371771 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/erlang/tom/_gleam_artefacts/tom.cache_meta diff --git a/aoc2023/build/packages/tom/build/lsp/javascript/gleam.lock b/aoc2023/build/packages/tom/build/lsp/javascript/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/packages/tom/build/lsp/javascript/gleam.lock diff --git a/aoc2023/build/packages/tom/build/packages/gleam.lock b/aoc2023/build/packages/tom/build/packages/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam.lock diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/LICENCE b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/LICENCE new file mode 100644 index 0000000..c1dabd0 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/LICENCE @@ -0,0 +1,191 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2018, Louis Pilfold <louis@lpil.uk>. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/README.md b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/README.md new file mode 100644 index 0000000..05c68ca --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/README.md @@ -0,0 +1,39 @@ +# stdlib + +<a href="https://github.com/gleam-lang/stdlib/releases"><img src="https://img.shields.io/github/release/gleam-lang/stdlib" alt="GitHub release"></a> +<a href="https://discord.gg/Fm8Pwmy"><img src="https://img.shields.io/discord/768594524158427167?color=blue" alt="Discord chat"></a> + + +Gleam's standard library! +Documentation available on [HexDocs](https://hexdocs.pm/gleam_stdlib/). + +## Installation + +Add `gleam_stdlib` to your Gleam project. + +```sh +gleam add gleam_stdlib +``` + +## Usage + +Import the modules you want to use and write some code! + +```gleam +import gleam/string + +pub fn greet(name: String) -> String { + string.concat(["Hello ", name, "!"]) +} +``` + +## Targets + +Gleam's standard library supports both targets: Erlang and JavaScript. + +### Compatibility + +This library is compatible with all versions of Erlang/OTP, NodeJS, and +major browsers that are currently supported by their maintainers. If you +have a compatibility issue with any platform open an issue and we'll see +what we can do to help. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/gleam.toml b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/gleam.toml new file mode 100644 index 0000000..28efd9f --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/gleam.toml @@ -0,0 +1,16 @@ +name = "gleam_stdlib" +version = "0.34.0" +gleam = ">= 0.32.0" +licences = ["Apache-2.0"] +description = "A standard library for the Gleam programming language" + +repository = { type = "github", user = "gleam-lang", repo = "stdlib" } +links = [ + { title = "Website", href = "https://gleam.run" }, + { title = "Sponsor", href = "https://github.com/sponsors/lpil" }, +] + +[javascript.deno] +allow_read = [ + "./", +] diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl new file mode 100644 index 0000000..b1135f2 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl @@ -0,0 +1,5 @@ +-record(decode_error, { + expected :: binary(), + found :: binary(), + path :: list(binary()) +}). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@iterator_Iterator.hrl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@iterator_Iterator.hrl new file mode 100644 index 0000000..b0d08dc --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@iterator_Iterator.hrl @@ -0,0 +1 @@ +-record(iterator, {continuation :: fun(() -> gleam@iterator:action(any()))}). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@iterator_Next.hrl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@iterator_Next.hrl new file mode 100644 index 0000000..1f61922 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@iterator_Next.hrl @@ -0,0 +1 @@ +-record(next, {element :: any(), accumulator :: any()}). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@queue_Queue.hrl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@queue_Queue.hrl new file mode 100644 index 0000000..88ac25e --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@queue_Queue.hrl @@ -0,0 +1 @@ +-record(queue, {in :: list(any()), out :: list(any())}). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_CompileError.hrl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_CompileError.hrl new file mode 100644 index 0000000..ad5511e --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_CompileError.hrl @@ -0,0 +1 @@ +-record(compile_error, {error :: binary(), byte_index :: integer()}). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_Match.hrl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_Match.hrl new file mode 100644 index 0000000..4216619 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_Match.hrl @@ -0,0 +1,4 @@ +-record(match, { + content :: binary(), + submatches :: list(gleam@option:option(binary())) +}). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_Options.hrl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_Options.hrl new file mode 100644 index 0000000..0074603 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_Options.hrl @@ -0,0 +1 @@ +-record(options, {case_insensitive :: boolean(), multi_line :: boolean()}). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@set_Set.hrl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@set_Set.hrl new file mode 100644 index 0000000..6e1e226 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@set_Set.hrl @@ -0,0 +1 @@ +-record(set, {map :: gleam@dict:dict(any(), list(nil))}). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl new file mode 100644 index 0000000..50150f4 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl @@ -0,0 +1,9 @@ +-record(uri, { + scheme :: gleam@option:option(binary()), + userinfo :: gleam@option:option(binary()), + host :: gleam@option:option(binary()), + port :: gleam@option:option(integer()), + path :: binary(), + 'query' :: gleam@option:option(binary()), + fragment :: gleam@option:option(binary()) +}). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/dict.mjs b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/dict.mjs new file mode 100644 index 0000000..a8309e0 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/dict.mjs @@ -0,0 +1,957 @@ +/** + * This file uses jsdoc to annotate types. + * These types can be checked using the typescript compiler with "checkjs" option. + */ + +import { isEqual } from "./gleam.mjs"; + +const referenceMap = new WeakMap(); +const tempDataView = new DataView(new ArrayBuffer(8)); +let referenceUID = 0; +/** + * hash the object by reference using a weak map and incrementing uid + * @param {any} o + * @returns {number} + */ +function hashByReference(o) { + const known = referenceMap.get(o); + if (known !== undefined) { + return known; + } + const hash = referenceUID++; + if (referenceUID === 0x7fffffff) { + referenceUID = 0; + } + referenceMap.set(o, hash); + return hash; +} +/** + * merge two hashes in an order sensitive way + * @param {number} a + * @param {number} b + * @returns {number} + */ +function hashMerge(a, b) { + return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; +} +/** + * standard string hash popularised by java + * @param {string} s + * @returns {number} + */ +function hashString(s) { + let hash = 0; + const len = s.length; + for (let i = 0; i < len; i++) { + hash = (Math.imul(31, hash) + s.charCodeAt(i)) | 0; + } + return hash; +} +/** + * hash a number by converting to two integers and do some jumbling + * @param {number} n + * @returns {number} + */ +function hashNumber(n) { + tempDataView.setFloat64(0, n); + const i = tempDataView.getInt32(0); + const j = tempDataView.getInt32(4); + return Math.imul(0x45d9f3b, (i >> 16) ^ i) ^ j; +} +/** + * hash a BigInt by converting it to a string and hashing that + * @param {BigInt} n + * @returns {number} + */ +function hashBigInt(n) { + return hashString(n.toString()); +} +/** + * hash any js object + * @param {any} o + * @returns {number} + */ +function hashObject(o) { + const proto = Object.getPrototypeOf(o); + if (proto !== null && typeof proto.hashCode === "function") { + try { + const code = o.hashCode(o); + if (typeof code === "number") { + return code; + } + } catch {} + } + if (o instanceof Promise || o instanceof WeakSet || o instanceof WeakMap) { + return hashByReference(o); + } + if (o instanceof Date) { + return hashNumber(o.getTime()); + } + let h = 0; + if (o instanceof ArrayBuffer) { + o = new Uint8Array(o); + } + if (Array.isArray(o) || o instanceof Uint8Array) { + for (let i = 0; i < o.length; i++) { + h = (Math.imul(31, h) + getHash(o[i])) | 0; + } + } else if (o instanceof Set) { + o.forEach((v) => { + h = (h + getHash(v)) | 0; + }); + } else if (o instanceof Map) { + o.forEach((v, k) => { + h = (h + hashMerge(getHash(v), getHash(k))) | 0; + }); + } else { + const keys = Object.keys(o); + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; + const v = o[k]; + h = (h + hashMerge(getHash(v), hashString(k))) | 0; + } + } + return h; +} +/** + * hash any js value + * @param {any} u + * @returns {number} + */ +export function getHash(u) { + if (u === null) return 0x42108422; + if (u === undefined) return 0x42108423; + if (u === true) return 0x42108421; + if (u === false) return 0x42108420; + switch (typeof u) { + case "number": + return hashNumber(u); + case "string": + return hashString(u); + case "bigint": + return hashBigInt(u); + case "object": + return hashObject(u); + case "symbol": + return hashByReference(u); + case "function": + return hashByReference(u); + default: + return 0; // should be unreachable + } +} +/** + * @template K,V + * @typedef {ArrayNode<K,V> | IndexNode<K,V> | CollisionNode<K,V>} Node + */ +/** + * @template K,V + * @typedef {{ type: typeof ENTRY, k: K, v: V }} Entry + */ +/** + * @template K,V + * @typedef {{ type: typeof ARRAY_NODE, size: number, array: (undefined | Entry<K,V> | Node<K,V>)[] }} ArrayNode + */ +/** + * @template K,V + * @typedef {{ type: typeof INDEX_NODE, bitmap: number, array: (Entry<K,V> | Node<K,V>)[] }} IndexNode + */ +/** + * @template K,V + * @typedef {{ type: typeof COLLISION_NODE, hash: number, array: Entry<K, V>[] }} CollisionNode + */ +/** + * @typedef {{ val: boolean }} Flag + */ +const SHIFT = 5; // number of bits you need to shift by to get the next bucket +const BUCKET_SIZE = Math.pow(2, SHIFT); +const MASK = BUCKET_SIZE - 1; // used to zero out all bits not in the bucket +const MAX_INDEX_NODE = BUCKET_SIZE / 2; // when does index node grow into array node +const MIN_ARRAY_NODE = BUCKET_SIZE / 4; // when does array node shrink to index node +const ENTRY = 0; +const ARRAY_NODE = 1; +const INDEX_NODE = 2; +const COLLISION_NODE = 3; +/** @type {IndexNode<any,any>} */ +const EMPTY = { + type: INDEX_NODE, + bitmap: 0, + array: [], +}; +/** + * Mask the hash to get only the bucket corresponding to shift + * @param {number} hash + * @param {number} shift + * @returns {number} + */ +function mask(hash, shift) { + return (hash >>> shift) & MASK; +} +/** + * Set only the Nth bit where N is the masked hash + * @param {number} hash + * @param {number} shift + * @returns {number} + */ +function bitpos(hash, shift) { + return 1 << mask(hash, shift); +} +/** + * Count the number of 1 bits in a number + * @param {number} x + * @returns {number} + */ +function bitcount(x) { + x -= (x >> 1) & 0x55555555; + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0f0f0f0f; + x += x >> 8; + x += x >> 16; + return x & 0x7f; +} +/** + * Calculate the array index of an item in a bitmap index node + * @param {number} bitmap + * @param {number} bit + * @returns {number} + */ +function index(bitmap, bit) { + return bitcount(bitmap & (bit - 1)); +} +/** + * Efficiently copy an array and set one value at an index + * @template T + * @param {T[]} arr + * @param {number} at + * @param {T} val + * @returns {T[]} + */ +function cloneAndSet(arr, at, val) { + const len = arr.length; + const out = new Array(len); + for (let i = 0; i < len; ++i) { + out[i] = arr[i]; + } + out[at] = val; + return out; +} +/** + * Efficiently copy an array and insert one value at an index + * @template T + * @param {T[]} arr + * @param {number} at + * @param {T} val + * @returns {T[]} + */ +function spliceIn(arr, at, val) { + const len = arr.length; + const out = new Array(len + 1); + let i = 0; + let g = 0; + while (i < at) { + out[g++] = arr[i++]; + } + out[g++] = val; + while (i < len) { + out[g++] = arr[i++]; + } + return out; +} +/** + * Efficiently copy an array and remove one value at an index + * @template T + * @param {T[]} arr + * @param {number} at + * @returns {T[]} + */ +function spliceOut(arr, at) { + const len = arr.length; + const out = new Array(len - 1); + let i = 0; + let g = 0; + while (i < at) { + out[g++] = arr[i++]; + } + ++i; + while (i < len) { + out[g++] = arr[i++]; + } + return out; +} +/** + * Create a new node containing two entries + * @template K,V + * @param {number} shift + * @param {K} key1 + * @param {V} val1 + * @param {number} key2hash + * @param {K} key2 + * @param {V} val2 + * @returns {Node<K,V>} + */ +function createNode(shift, key1, val1, key2hash, key2, val2) { + const key1hash = getHash(key1); + if (key1hash === key2hash) { + return { + type: COLLISION_NODE, + hash: key1hash, + array: [ + { type: ENTRY, k: key1, v: val1 }, + { type: ENTRY, k: key2, v: val2 }, + ], + }; + } + const addedLeaf = { val: false }; + return assoc( + assocIndex(EMPTY, shift, key1hash, key1, val1, addedLeaf), + shift, + key2hash, + key2, + val2, + addedLeaf + ); +} +/** + * @template T,K,V + * @callback AssocFunction + * @param {T} root + * @param {number} shift + * @param {number} hash + * @param {K} key + * @param {V} val + * @param {Flag} addedLeaf + * @returns {Node<K,V>} + */ +/** + * Associate a node with a new entry, creating a new node + * @template T,K,V + * @type {AssocFunction<Node<K,V>,K,V>} + */ +function assoc(root, shift, hash, key, val, addedLeaf) { + switch (root.type) { + case ARRAY_NODE: + return assocArray(root, shift, hash, key, val, addedLeaf); + case INDEX_NODE: + return assocIndex(root, shift, hash, key, val, addedLeaf); + case COLLISION_NODE: + return assocCollision(root, shift, hash, key, val, addedLeaf); + } +} +/** + * @template T,K,V + * @type {AssocFunction<ArrayNode<K,V>,K,V>} + */ +function assocArray(root, shift, hash, key, val, addedLeaf) { + const idx = mask(hash, shift); + const node = root.array[idx]; + // if the corresponding index is empty set the index to a newly created node + if (node === undefined) { + addedLeaf.val = true; + return { + type: ARRAY_NODE, + size: root.size + 1, + array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }), + }; + } + if (node.type === ENTRY) { + // if keys are equal replace the entry + if (isEqual(key, node.k)) { + if (val === node.v) { + return root; + } + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet(root.array, idx, { + type: ENTRY, + k: key, + v: val, + }), + }; + } + // otherwise upgrade the entry to a node and insert + addedLeaf.val = true; + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet( + root.array, + idx, + createNode(shift + SHIFT, node.k, node.v, hash, key, val) + ), + }; + } + // otherwise call assoc on the child node + const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); + // if the child node hasn't changed just return the old root + if (n === node) { + return root; + } + // otherwise set the index to the new node + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet(root.array, idx, n), + }; +} +/** + * @template T,K,V + * @type {AssocFunction<IndexNode<K,V>,K,V>} + */ +function assocIndex(root, shift, hash, key, val, addedLeaf) { + const bit = bitpos(hash, shift); + const idx = index(root.bitmap, bit); + // if there is already a item at this hash index.. + if ((root.bitmap & bit) !== 0) { + // if there is a node at the index (not an entry), call assoc on the child node + const node = root.array[idx]; + if (node.type !== ENTRY) { + const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf); + if (n === node) { + return root; + } + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet(root.array, idx, n), + }; + } + // otherwise there is an entry at the index + // if the keys are equal replace the entry with the updated value + const nodeKey = node.k; + if (isEqual(key, nodeKey)) { + if (val === node.v) { + return root; + } + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet(root.array, idx, { + type: ENTRY, + k: key, + v: val, + }), + }; + } + // if the keys are not equal, replace the entry with a new child node + addedLeaf.val = true; + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet( + root.array, + idx, + createNode(shift + SHIFT, nodeKey, node.v, hash, key, val) + ), + }; + } else { + // else there is currently no item at the hash index + const n = root.array.length; + // if the number of nodes is at the maximum, expand this node into an array node + if (n >= MAX_INDEX_NODE) { + // create a 32 length array for the new array node (one for each bit in the hash) + const nodes = new Array(32); + // create and insert a node for the new entry + const jdx = mask(hash, shift); + nodes[jdx] = assocIndex(EMPTY, shift + SHIFT, hash, key, val, addedLeaf); + let j = 0; + let bitmap = root.bitmap; + // place each item in the index node into the correct spot in the array node + // loop through all 32 bits / array positions + for (let i = 0; i < 32; i++) { + if ((bitmap & 1) !== 0) { + const node = root.array[j++]; + nodes[i] = node; + } + // shift the bitmap to process the next bit + bitmap = bitmap >>> 1; + } + return { + type: ARRAY_NODE, + size: n + 1, + array: nodes, + }; + } else { + // else there is still space in this index node + // simply insert a new entry at the hash index + const newArray = spliceIn(root.array, idx, { + type: ENTRY, + k: key, + v: val, + }); + addedLeaf.val = true; + return { + type: INDEX_NODE, + bitmap: root.bitmap | bit, + array: newArray, + }; + } + } +} +/** + * @template T,K,V + * @type {AssocFunction<CollisionNode<K,V>,K,V>} + */ +function assocCollision(root, shift, hash, key, val, addedLeaf) { + // if there is a hash collision + if (hash === root.hash) { + const idx = collisionIndexOf(root, key); + // if this key already exists replace the entry with the new value + if (idx !== -1) { + const entry = root.array[idx]; + if (entry.v === val) { + return root; + } + return { + type: COLLISION_NODE, + hash: hash, + array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }), + }; + } + // otherwise insert the entry at the end of the array + const size = root.array.length; + addedLeaf.val = true; + return { + type: COLLISION_NODE, + hash: hash, + array: cloneAndSet(root.array, size, { type: ENTRY, k: key, v: val }), + }; + } + // if there is no hash collision, upgrade to an index node + return assoc( + { + type: INDEX_NODE, + bitmap: bitpos(root.hash, shift), + array: [root], + }, + shift, + hash, + key, + val, + addedLeaf + ); +} +/** + * Find the index of a key in the collision node's array + * @template K,V + * @param {CollisionNode<K,V>} root + * @param {K} key + * @returns {number} + */ +function collisionIndexOf(root, key) { + const size = root.array.length; + for (let i = 0; i < size; i++) { + if (isEqual(key, root.array[i].k)) { + return i; + } + } + return -1; +} +/** + * @template T,K,V + * @callback FindFunction + * @param {T} root + * @param {number} shift + * @param {number} hash + * @param {K} key + * @returns {undefined | Entry<K,V>} + */ +/** + * Return the found entry or undefined if not present in the root + * @template K,V + * @type {FindFunction<Node<K,V>,K,V>} + */ +function find(root, shift, hash, key) { + switch (root.type) { + case ARRAY_NODE: + return findArray(root, shift, hash, key); + case INDEX_NODE: + return findIndex(root, shift, hash, key); + case COLLISION_NODE: + return findCollision(root, key); + } +} +/** + * @template K,V + * @type {FindFunction<ArrayNode<K,V>,K,V>} + */ +function findArray(root, shift, hash, key) { + const idx = mask(hash, shift); + const node = root.array[idx]; + if (node === undefined) { + return undefined; + } + if (node.type !== ENTRY) { + return find(node, shift + SHIFT, hash, key); + } + if (isEqual(key, node.k)) { + return node; + } + return undefined; +} +/** + * @template K,V + * @type {FindFunction<IndexNode<K,V>,K,V>} + */ +function findIndex(root, shift, hash, key) { + const bit = bitpos(hash, shift); + if ((root.bitmap & bit) === 0) { + return undefined; + } + const idx = index(root.bitmap, bit); + const node = root.array[idx]; + if (node.type !== ENTRY) { + return find(node, shift + SHIFT, hash, key); + } + if (isEqual(key, node.k)) { + return node; + } + return undefined; +} +/** + * @template K,V + * @param {CollisionNode<K,V>} root + * @param {K} key + * @returns {undefined | Entry<K,V>} + */ +function findCollision(root, key) { + const idx = collisionIndexOf(root, key); + if (idx < 0) { + return undefined; + } + return root.array[idx]; +} +/** + * @template T,K,V + * @callback WithoutFunction + * @param {T} root + * @param {number} shift + * @param {number} hash + * @param {K} key + * @returns {undefined | Node<K,V>} + */ +/** + * Remove an entry from the root, returning the updated root. + * Returns undefined if the node should be removed from the parent. + * @template K,V + * @type {WithoutFunction<Node<K,V>,K,V>} + * */ +function without(root, shift, hash, key) { + switch (root.type) { + case ARRAY_NODE: + return withoutArray(root, shift, hash, key); + case INDEX_NODE: + return withoutIndex(root, shift, hash, key); + case COLLISION_NODE: + return withoutCollision(root, key); + } +} +/** + * @template K,V + * @type {WithoutFunction<ArrayNode<K,V>,K,V>} + */ +function withoutArray(root, shift, hash, key) { + const idx = mask(hash, shift); + const node = root.array[idx]; + if (node === undefined) { + return root; // already empty + } + let n = undefined; + // if node is an entry and the keys are not equal there is nothing to remove + // if node is not an entry do a recursive call + if (node.type === ENTRY) { + if (!isEqual(node.k, key)) { + return root; // no changes + } + } else { + n = without(node, shift + SHIFT, hash, key); + if (n === node) { + return root; // no changes + } + } + // if the recursive call returned undefined the node should be removed + if (n === undefined) { + // if the number of child nodes is at the minimum, pack into an index node + if (root.size <= MIN_ARRAY_NODE) { + const arr = root.array; + const out = new Array(root.size - 1); + let i = 0; + let j = 0; + let bitmap = 0; + while (i < idx) { + const nv = arr[i]; + if (nv !== undefined) { + out[j] = nv; + bitmap |= 1 << i; + ++j; + } + ++i; + } + ++i; // skip copying the removed node + while (i < arr.length) { + const nv = arr[i]; + if (nv !== undefined) { + out[j] = nv; + bitmap |= 1 << i; + ++j; + } + ++i; + } + return { + type: INDEX_NODE, + bitmap: bitmap, + array: out, + }; + } + return { + type: ARRAY_NODE, + size: root.size - 1, + array: cloneAndSet(root.array, idx, n), + }; + } + return { + type: ARRAY_NODE, + size: root.size, + array: cloneAndSet(root.array, idx, n), + }; +} +/** + * @template K,V + * @type {WithoutFunction<IndexNode<K,V>,K,V>} + */ +function withoutIndex(root, shift, hash, key) { + const bit = bitpos(hash, shift); + if ((root.bitmap & bit) === 0) { + return root; // already empty + } + const idx = index(root.bitmap, bit); + const node = root.array[idx]; + // if the item is not an entry + if (node.type !== ENTRY) { + const n = without(node, shift + SHIFT, hash, key); + if (n === node) { + return root; // no changes + } + // if not undefined, the child node still has items, so update it + if (n !== undefined) { + return { + type: INDEX_NODE, + bitmap: root.bitmap, + array: cloneAndSet(root.array, idx, n), + }; + } + // otherwise the child node should be removed + // if it was the only child node, remove this node from the parent + if (root.bitmap === bit) { + return undefined; + } + // otherwise just remove the child node + return { + type: INDEX_NODE, + bitmap: root.bitmap ^ bit, + array: spliceOut(root.array, idx), + }; + } + // otherwise the item is an entry, remove it if the key matches + if (isEqual(key, node.k)) { + if (root.bitmap === bit) { + return undefined; + } + return { + type: INDEX_NODE, + bitmap: root.bitmap ^ bit, + array: spliceOut(root.array, idx), + }; + } + return root; +} +/** + * @template K,V + * @param {CollisionNode<K,V>} root + * @param {K} key + * @returns {undefined | Node<K,V>} + */ +function withoutCollision(root, key) { + const idx = collisionIndexOf(root, key); + // if the key not found, no changes + if (idx < 0) { + return root; + } + // otherwise the entry was found, remove it + // if it was the only entry in this node, remove the whole node + if (root.array.length === 1) { + return undefined; + } + // otherwise just remove the entry + return { + type: COLLISION_NODE, + hash: root.hash, + array: spliceOut(root.array, idx), + }; +} +/** + * @template K,V + * @param {undefined | Node<K,V>} root + * @param {(value:V,key:K)=>void} fn + * @returns {void} + */ +function forEach(root, fn) { + if (root === undefined) { + return; + } + const items = root.array; + const size = items.length; + for (let i = 0; i < size; i++) { + const item = items[i]; + if (item === undefined) { + continue; + } + if (item.type === ENTRY) { + fn(item.v, item.k); + continue; + } + forEach(item, fn); + } +} +/** + * Extra wrapper to keep track of Dict size and clean up the API + * @template K,V + */ +export default class Dict { + /** + * @template V + * @param {Record<string,V>} o + * @returns {Dict<string,V>} + */ + static fromObject(o) { + const keys = Object.keys(o); + /** @type Dict<string,V> */ + let m = Dict.new(); + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; + m = m.set(k, o[k]); + } + return m; + } + /** + * @template K,V + * @param {Map<K,V>} o + * @returns {Dict<K,V>} + */ + static fromMap(o) { + /** @type Dict<K,V> */ + let m = Dict.new(); + o.forEach((v, k) => { + m = m.set(k, v); + }); + return m; + } + static new() { + return new Dict(undefined, 0); + } + /** + * @param {undefined | Node<K,V>} root + * @param {number} size + */ + constructor(root, size) { + this.root = root; + this.size = size; + } + /** + * @template NotFound + * @param {K} key + * @param {NotFound} notFound + * @returns {NotFound | V} + */ + get(key, notFound) { + if (this.root === undefined) { + return notFound; + } + const found = find(this.root, 0, getHash(key), key); + if (found === undefined) { + return notFound; + } + return found.v; + } + /** + * @param {K} key + * @param {V} val + * @returns {Dict<K,V>} + */ + set(key, val) { + const addedLeaf = { val: false }; + const root = this.root === undefined ? EMPTY : this.root; + const newRoot = assoc(root, 0, getHash(key), key, val, addedLeaf); + if (newRoot === this.root) { + return this; + } + return new Dict(newRoot, addedLeaf.val ? this.size + 1 : this.size); + } + /** + * @param {K} key + * @returns {Dict<K,V>} + */ + delete(key) { + if (this.root === undefined) { + return this; + } + const newRoot = without(this.root, 0, getHash(key), key); + if (newRoot === this.root) { + return this; + } + if (newRoot === undefined) { + return Dict.new(); + } + return new Dict(newRoot, this.size - 1); + } + /** + * @param {K} key + * @returns {boolean} + */ + has(key) { + if (this.root === undefined) { + return false; + } + return find(this.root, 0, getHash(key), key) !== undefined; + } + /** + * @returns {[K,V][]} + */ + entries() { + if (this.root === undefined) { + return []; + } + /** @type [K,V][] */ + const result = []; + this.forEach((v, k) => result.push([k, v])); + return result; + } + /** + * + * @param {(val:V,key:K)=>void} fn + */ + forEach(fn) { + forEach(this.root, fn); + } + hashCode() { + let h = 0; + this.forEach((v, k) => { + h = (h + hashMerge(getHash(v), getHash(k))) | 0; + }); + return h; + } + /** + * @param {unknown} o + * @returns {boolean} + */ + equals(o) { + if (!(o instanceof Dict) || this.size !== o.size) { + return false; + } + let equal = true; + this.forEach((v, k) => { + equal = equal && isEqual(o.get(k, !v), v); + }); + return equal; + } +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/base.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/base.gleam new file mode 100644 index 0000000..eab2f0b --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/base.gleam @@ -0,0 +1,21 @@ +import gleam/bit_array + +@deprecated("Please use `base64_encode` in the `gleam/bit_array` module instead.") +pub fn encode64(input: BitArray, padding: Bool) -> String { + bit_array.base64_encode(input, padding) +} + +@deprecated("Please use `base64_decode` in the `gleam/bit_array` module instead.") +pub fn decode64(encoded: String) -> Result(BitArray, Nil) { + bit_array.base64_decode(encoded) +} + +@deprecated("Please use `base64_url_encode` in the `gleam/bit_array` module instead.") +pub fn url_encode64(input: BitArray, padding: Bool) -> String { + bit_array.base64_url_encode(input, padding) +} + +@deprecated("Please use `base64_url_decode` in the `gleam/bit_array` module instead.") +pub fn url_decode64(encoded: String) -> Result(BitArray, Nil) { + bit_array.base64_url_decode(encoded) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_array.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_array.gleam new file mode 100644 index 0000000..79860e9 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_array.gleam @@ -0,0 +1,157 @@ +//// BitArrays are a sequence of binary data of any length. + +import gleam/string + +/// Converts a UTF-8 `String` type into a `BitArray`. +/// +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "bit_array_from_string") +pub fn from_string(x: String) -> BitArray + +/// Returns an integer which is the number of bytes in the bit array. +/// +@external(erlang, "erlang", "byte_size") +@external(javascript, "../gleam_stdlib.mjs", "length") +pub fn byte_size(x: BitArray) -> Int + +/// Creates a new bit array by joining two bit arrays. +/// +/// ## Examples +/// +/// ```gleam +/// > append(to: from_string("butter"), suffix: from_string("fly")) +/// from_string("butterfly") +/// ``` +/// +pub fn append(to first: BitArray, suffix second: BitArray) -> BitArray { + concat([first, second]) +} + +/// Extracts a sub-section of a bit array. +/// +/// The slice will start at given position and continue up to specified +/// length. +/// A negative length can be used to extract bytes at the end of a bit array. +/// +/// This function runs in constant time. +/// +@external(erlang, "gleam_stdlib", "bit_array_slice") +@external(javascript, "../gleam_stdlib.mjs", "bit_array_slice") +pub fn slice( + from string: BitArray, + at position: Int, + take length: Int, +) -> Result(BitArray, Nil) + +/// Tests to see whether a bit array is valid UTF-8. +/// +pub fn is_utf8(bits: BitArray) -> Bool { + do_is_utf8(bits) +} + +@target(erlang) +fn do_is_utf8(bits: BitArray) -> Bool { + case bits { + <<>> -> True + <<_:utf8, rest:bytes>> -> do_is_utf8(rest) + _ -> False + } +} + +@target(javascript) +fn do_is_utf8(bits: BitArray) -> Bool { + case to_string(bits) { + Ok(_) -> True + _ -> False + } +} + +/// Converts a bit array to a string. +/// +/// Returns an error if the bit array is invalid UTF-8 data. +/// +pub fn to_string(bits: BitArray) -> Result(String, Nil) { + do_to_string(bits) +} + +@target(erlang) +@external(erlang, "gleam_stdlib", "identity") +fn unsafe_to_string(a: BitArray) -> String + +@target(erlang) +fn do_to_string(bits: BitArray) -> Result(String, Nil) { + case is_utf8(bits) { + True -> Ok(unsafe_to_string(bits)) + False -> Error(Nil) + } +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "bit_array_to_string") +fn do_to_string(a: BitArray) -> Result(String, Nil) + +/// Creates a new bit array by joining multiple binaries. +/// +/// ## Examples +/// +/// ```gleam +/// > concat([from_string("butter"), from_string("fly")]) +/// from_string("butterfly") +/// ``` +/// +@external(erlang, "gleam_stdlib", "bit_array_concat") +@external(javascript, "../gleam_stdlib.mjs", "bit_array_concat") +pub fn concat(bit_arrays: List(BitArray)) -> BitArray + +/// Encodes a BitArray into a base 64 encoded string. +/// +pub fn base64_encode(input: BitArray, padding: Bool) -> String { + let encoded = encode64(input) + case padding { + True -> encoded + False -> string.replace(encoded, "=", "") + } +} + +@external(erlang, "base64", "encode") +@external(javascript, "../gleam_stdlib.mjs", "encode64") +fn encode64(a: BitArray) -> String + +/// Decodes a base 64 encoded string into a `BitArray`. +/// +pub fn base64_decode(encoded: String) -> Result(BitArray, Nil) { + let padded = case byte_size(from_string(encoded)) % 4 { + 0 -> encoded + n -> string.append(encoded, string.repeat("=", 4 - n)) + } + decode64(padded) +} + +@external(erlang, "gleam_stdlib", "base_decode64") +@external(javascript, "../gleam_stdlib.mjs", "decode64") +fn decode64(a: String) -> Result(BitArray, Nil) + +/// Encodes a `BitArray` into a base 64 encoded string with URL and filename safe alphabet. +/// +pub fn base64_url_encode(input: BitArray, padding: Bool) -> String { + base64_encode(input, padding) + |> string.replace("+", "-") + |> string.replace("/", "_") +} + +/// Decodes a base 64 encoded string with URL and filename safe alphabet into a `BitArray`. +/// +pub fn base64_url_decode(encoded: String) -> Result(BitArray, Nil) { + encoded + |> string.replace("-", "+") + |> string.replace("_", "/") + |> base64_decode() +} + +@external(erlang, "binary", "encode_hex") +@external(javascript, "../gleam_stdlib.mjs", "base16_encode") +pub fn base16_encode(input: BitArray) -> String + +@external(erlang, "gleam_stdlib", "base16_decode") +@external(javascript, "../gleam_stdlib.mjs", "base16_decode") +pub fn base16_decode(input: String) -> Result(BitArray, Nil) diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_builder.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_builder.gleam new file mode 100644 index 0000000..ce6fe52 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_builder.gleam @@ -0,0 +1,80 @@ +//// This module has been deprecated in favour of `gleam/bytes_builder`. + +import gleam/bytes_builder +import gleam/string_builder.{type StringBuilder} + +pub type BitBuilder = + bytes_builder.BytesBuilder + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn new() -> BitBuilder { + bytes_builder.new() +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn prepend(to: BitBuilder, prefix: BitArray) -> BitBuilder { + bytes_builder.prepend(to, prefix) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn append(to: BitBuilder, suffix: BitArray) -> BitBuilder { + bytes_builder.append(to, suffix) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn prepend_builder(to: BitBuilder, prefix: BitBuilder) -> BitBuilder { + bytes_builder.prepend_builder(to, prefix) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn append_builder( + to first: BitBuilder, + suffix second: BitBuilder, +) -> BitBuilder { + bytes_builder.append_builder(first, second) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn prepend_string(to: BitBuilder, prefix: String) -> BitBuilder { + bytes_builder.prepend_string(to, prefix) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn append_string(to: BitBuilder, suffix: String) -> BitBuilder { + bytes_builder.append_string(to, suffix) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn concat(builders: List(BitBuilder)) -> BitBuilder { + bytes_builder.concat(builders) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn concat_bit_strings(bits: List(BitArray)) -> BitBuilder { + bytes_builder.concat_bit_arrays(bits) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn from_string(string: String) -> BitBuilder { + bytes_builder.from_string(string) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn from_string_builder(builder: StringBuilder) -> BitBuilder { + bytes_builder.from_string_builder(builder) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn from_bit_string(bits: BitArray) -> BitBuilder { + bytes_builder.from_bit_array(bits) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn to_bit_string(builder: BitBuilder) -> BitArray { + bytes_builder.to_bit_array(builder) +} + +@deprecated("Please use the `gleam/bytes_builder` module instead.") +pub fn byte_size(builder: BitBuilder) -> Int { + bytes_builder.byte_size(builder) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_string.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_string.gleam new file mode 100644 index 0000000..b703da0 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_string.gleam @@ -0,0 +1,43 @@ +//// This module has been deprecated. Please use the `gleam/bit_array` module +//// instead. + +import gleam/bit_array + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn from_string(x: String) -> BitArray { + bit_array.from_string(x) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn byte_size(x: BitArray) -> Int { + bit_array.byte_size(x) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn append(to first: BitArray, suffix second: BitArray) -> BitArray { + bit_array.append(first, second) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn slice( + from string: BitArray, + at position: Int, + take length: Int, +) -> Result(BitArray, Nil) { + bit_array.slice(string, position, length) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn is_utf8(bits: BitArray) -> Bool { + bit_array.is_utf8(bits) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn to_string(bits: BitArray) -> Result(String, Nil) { + bit_array.to_string(bits) +} + +@deprecated("Please use the `gleam/bit_array` module instead.") +pub fn concat(bit_strings: List(BitArray)) -> BitArray { + bit_array.concat(bit_strings) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bool.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bool.gleam new file mode 100644 index 0000000..91bd6b7 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bool.gleam @@ -0,0 +1,428 @@ +//// A type with two possible values, `True` and `False`. Used to indicate whether +//// things are... true or false! +//// +//// Often is it clearer and offers more type safety to define a custom type +//// than to use `Bool`. For example, rather than having a `is_teacher: Bool` +//// field consider having a `role: SchoolRole` field where `SchoolRole` is a custom +//// type that can be either `Student` or `Teacher`. + +import gleam/order.{type Order} + +/// Returns the and of two bools, but it evaluates both arguments. +/// +/// It's the function equivalent of the `&&` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > and(True, True) +/// True +/// ``` +/// +/// ```gleam +/// > and(False, True) +/// False +/// ``` +/// +/// ```gleam +/// > False |> and(True) +/// False +/// ``` +/// +pub fn and(a: Bool, b: Bool) -> Bool { + a && b +} + +/// Returns the or of two bools, but it evaluates both arguments. +/// +/// It's the function equivalent of the `||` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > or(True, True) +/// True +/// ``` +/// +/// ```gleam +/// > or(False, True) +/// True +/// ``` +/// +/// ```gleam +/// > False |> or(True) +/// True +/// ``` +/// +pub fn or(a: Bool, b: Bool) -> Bool { + a || b +} + +/// Returns the opposite bool value. +/// +/// This is the same as the `!` or `not` operators in some other languages. +/// +/// ## Examples +/// +/// ```gleam +/// > negate(True) +/// False +/// ``` +/// +/// ```gleam +/// > negate(False) +/// True +/// ``` +/// +pub fn negate(bool: Bool) -> Bool { + case bool { + True -> False + False -> True + } +} + +/// Returns the nor of two bools. +/// +/// ## Examples +/// +/// ```gleam +/// > nor(False, False) +/// True +/// ``` +/// +/// ```gleam +/// > nor(False, True) +/// False +/// ``` +/// +/// ```gleam +/// > nor(True, False) +/// False +/// ``` +/// +/// ```gleam +/// > nor(True, True) +/// False +/// ``` +/// +pub fn nor(a: Bool, b: Bool) -> Bool { + case a, b { + False, False -> True + False, True -> False + True, False -> False + True, True -> False + } +} + +/// Returns the nand of two bools. +/// +/// ## Examples +/// +/// ```gleam +/// > nand(False, False) +/// True +/// ``` +/// +/// ```gleam +/// > nand(False, True) +/// True +/// ``` +/// +/// ```gleam +/// > nand(True, False) +/// True +/// ``` +/// +/// ```gleam +/// > nand(True, True) +/// False +/// ``` +/// +pub fn nand(a: Bool, b: Bool) -> Bool { + case a, b { + False, False -> True + False, True -> True + True, False -> True + True, True -> False + } +} + +/// Returns the exclusive or of two bools. +/// +/// ## Examples +/// +/// ```gleam +/// > exclusive_or(False, False) +/// False +/// ``` +/// +/// ```gleam +/// > exclusive_or(False, True) +/// True +/// ``` +/// +/// ```gleam +/// > exclusive_or(True, False) +/// True +/// ``` +/// +/// ```gleam +/// > exclusive_or(True, True) +/// False +/// ``` +/// +pub fn exclusive_or(a: Bool, b: Bool) -> Bool { + case a, b { + False, False -> False + False, True -> True + True, False -> True + True, True -> False + } +} + +/// Returns the exclusive nor of two bools. +/// +/// ## Examples +/// +/// ```gleam +/// > exclusive_nor(False, False) +/// True +/// ``` +/// +/// ```gleam +/// > exclusive_nor(False, True) +/// False +/// ``` +/// +/// ```gleam +/// > exclusive_nor(True, False) +/// False +/// ``` +/// +/// ```gleam +/// > exclusive_nor(True, True) +/// True +/// ``` +/// +pub fn exclusive_nor(a: Bool, b: Bool) -> Bool { + case a, b { + False, False -> True + False, True -> False + True, False -> False + True, True -> True + } +} + +/// Compares two bools and returns the first value's `Order` to the second. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/order +/// > compare(True, False) +/// order.Gt +/// ``` +/// +pub fn compare(a: Bool, with b: Bool) -> Order { + case a, b { + True, True -> order.Eq + True, False -> order.Gt + False, False -> order.Eq + False, True -> order.Lt + } +} + +/// Returns `True` if either argument's value is `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > max(True, False) +/// True +/// ``` +/// +/// ```gleam +/// > max(False, True) +/// True +/// ``` +/// +/// ```gleam +/// > max(False, False) +/// False +/// ``` +/// +pub fn max(a: Bool, b: Bool) -> Bool { + case a { + True -> True + False -> b + } +} + +/// Returns `False` if either bool value is `False`. +/// +/// ## Examples +/// +/// ```gleam +/// > min(True, False) +/// False +/// ``` +/// +/// ```gleam +/// > min(False, True) +/// False +/// +/// > min(False, False) +/// False +/// ``` +/// +pub fn min(a: Bool, b: Bool) -> Bool { + case a { + False -> False + True -> b + } +} + +/// Returns a numeric representation of the given bool. +/// +/// ## Examples +/// +/// ```gleam +/// > to_int(True) +/// 1 +/// +/// > to_int(False) +/// 0 +/// ``` +/// +pub fn to_int(bool: Bool) -> Int { + case bool { + False -> 0 + True -> 1 + } +} + +/// Returns a string representation of the given bool. +/// +/// ## Examples +/// +/// ```gleam +/// > to_string(True) +/// "True" +/// ``` +/// +/// ```gleam +/// > to_string(False) +/// "False" +/// ``` +/// +pub fn to_string(bool: Bool) -> String { + case bool { + False -> "False" + True -> "True" + } +} + +/// Run a callback function if the given bool is `False`, otherwise return a +/// default value. +/// +/// With a `use` expression this function can simulate the early-return pattern +/// found in some other programming languages. +/// +/// In a procedural language: +/// +/// ```js +/// if (predicate) return value; +/// // ... +/// ``` +/// +/// In Gleam with a `use` expression: +/// +/// ```gleam +/// use <- guard(when: predicate, return: value) +/// // ... +/// ``` +/// +/// Like everything in Gleam `use` is an expression, so it short circuits the +/// current block, not the entire function. As a result you can assign the value +/// to a variable: +/// +/// ```gleam +/// let x = { +/// use <- guard(when: predicate, return: value) +/// // ... +/// } +/// ``` +/// +/// Note that unlike in procedural languages the `return` value is evaluated +/// even when the predicate is `False`, so it is advisable not to perform +/// expensive computation there. +/// +/// +/// ## Examples +/// +/// ```gleam +/// > let name = "" +/// > use <- guard(when: name == "", return: "Welcome!") +/// > "Hello, " <> name +/// "Welcome!" +/// ``` +/// +/// ```gleam +/// > let name = "Kamaka" +/// > use <- guard(when: name == "", return: "Welcome!") +/// > "Hello, " <> name +/// "Hello, Kamaka" +/// ``` +/// +pub fn guard( + when requirement: Bool, + return consequence: t, + otherwise alternative: fn() -> t, +) -> t { + case requirement { + True -> consequence + False -> alternative() + } +} + +/// Runs a callback function if the given bool is `True`, otherwise runs an +/// alternative callback function. +/// +/// Useful when further computation should be delayed regardless of the given +/// bool's value. +/// +/// See [`guard`](#guard) for more info. +/// +/// ## Examples +/// +/// ```gleam +/// > let name = "Kamaka" +/// > let inquiry = fn() { "How may we address you?" } +/// > use <- lazy_guard(when: name == "", return: inquiry) +/// > "Hello, " <> name +/// "Hello, Kamaka" +/// ``` +/// +/// ```gleam +/// > import gleam/int +/// > let name = "" +/// > let greeting = fn() { "Hello, " <> name } +/// > use <- lazy_guard(when: name == "", otherwise: greeting) +/// > let number = int.random(1, 99) +/// > let name = "User " <> int.to_string(number) +/// > "Welcome, " <> name +/// "Welcome, User 54" +/// ``` +/// +pub fn lazy_guard( + when requirement: Bool, + return consequence: fn() -> a, + otherwise alternative: fn() -> a, +) -> a { + case requirement { + True -> consequence() + False -> alternative() + } +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bytes_builder.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bytes_builder.gleam new file mode 100644 index 0000000..20c145d --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bytes_builder.gleam @@ -0,0 +1,197 @@ +//// BytesBuilder is a type used for efficiently concatenating bytes together +//// without copying. +//// +//// If we append one bit array to another the bit arrays must be copied to a +//// new location in memory so that they can sit together. This behaviour +//// enables efficient reading of the string but copying can be expensive, +//// especially if we want to join many bit arrays together. +//// +//// BytesBuilder is different in that it can be joined together in constant +//// time using minimal memory, and then can be efficiently converted to a +//// bit array using the `to_bit_array` function. +//// +//// Byte builders are always byte aligned, so that a number of bits that is not +//// divisible by 8 will be padded with 0s. +//// +//// On Erlang this type is compatible with Erlang's iolists. + +// TODO: pad bit arrays to byte boundaries when adding to a builder. +import gleam/string_builder.{type StringBuilder} +import gleam/list +import gleam/bit_array + +pub opaque type BytesBuilder { + Bytes(BitArray) + Text(StringBuilder) + Many(List(BytesBuilder)) +} + +/// Create an empty `BytesBuilder`. Useful as the start of a pipe chaining many +/// builders together. +/// +pub fn new() -> BytesBuilder { + concat([]) +} + +/// Prepends a bit array to the start of a builder. +/// +/// Runs in constant time. +/// +pub fn prepend(to second: BytesBuilder, prefix first: BitArray) -> BytesBuilder { + append_builder(from_bit_array(first), second) +} + +/// Appends a bit array to the end of a builder. +/// +/// Runs in constant time. +/// +pub fn append(to first: BytesBuilder, suffix second: BitArray) -> BytesBuilder { + append_builder(first, from_bit_array(second)) +} + +/// Prepends a builder onto the start of another. +/// +/// Runs in constant time. +/// +pub fn prepend_builder( + to second: BytesBuilder, + prefix first: BytesBuilder, +) -> BytesBuilder { + append_builder(first, second) +} + +/// Appends a builder onto the end of another. +/// +/// Runs in constant time. +/// +@external(erlang, "gleam_stdlib", "iodata_append") +pub fn append_builder( + to first: BytesBuilder, + suffix second: BytesBuilder, +) -> BytesBuilder { + case second { + Many(builders) -> Many([first, ..builders]) + _ -> Many([first, second]) + } +} + +/// Prepends a string onto the start of a builder. +/// +/// Runs in constant time when running on Erlang. +/// Runs in linear time with the length of the string otherwise. +/// +pub fn prepend_string( + to second: BytesBuilder, + prefix first: String, +) -> BytesBuilder { + append_builder(from_string(first), second) +} + +/// Appends a string onto the end of a builder. +/// +/// Runs in constant time when running on Erlang. +/// Runs in linear time with the length of the string otherwise. +/// +pub fn append_string( + to first: BytesBuilder, + suffix second: String, +) -> BytesBuilder { + append_builder(first, from_string(second)) +} + +/// Joins a list of builders into a single builder. +/// +/// Runs in constant time. +/// +@external(erlang, "gleam_stdlib", "identity") +pub fn concat(builders: List(BytesBuilder)) -> BytesBuilder { + Many(builders) +} + +/// Joins a list of bit arrays into a single builder. +/// +/// Runs in constant time. +/// +@external(erlang, "gleam_stdlib", "identity") +pub fn concat_bit_arrays(bits: List(BitArray)) -> BytesBuilder { + bits + |> list.map(fn(b) { from_bit_array(b) }) + |> concat() +} + +/// Creates a new builder from a string. +/// +/// Runs in constant time when running on Erlang. +/// Runs in linear time otherwise. +/// +@external(erlang, "gleam_stdlib", "wrap_list") +pub fn from_string(string: String) -> BytesBuilder { + Text(string_builder.from_string(string)) +} + +/// Creates a new builder from a string builder. +/// +/// Runs in constant time when running on Erlang. +/// Runs in linear time otherwise. +/// +@external(erlang, "gleam_stdlib", "wrap_list") +pub fn from_string_builder(builder: StringBuilder) -> BytesBuilder { + Text(builder) +} + +/// Creates a new builder from a bit array. +/// +/// Runs in constant time. +/// +@external(erlang, "gleam_stdlib", "wrap_list") +pub fn from_bit_array(bits: BitArray) -> BytesBuilder { + Bytes(bits) +} + +/// Turns an builder into a bit array. +/// +/// Runs in linear time. +/// +/// When running on Erlang this function is implemented natively by the +/// virtual machine and is highly optimised. +/// +@external(erlang, "erlang", "list_to_bitstring") +pub fn to_bit_array(builder: BytesBuilder) -> BitArray { + [[builder]] + |> to_list([]) + |> list.reverse + |> bit_array.concat +} + +fn to_list( + stack: List(List(BytesBuilder)), + acc: List(BitArray), +) -> List(BitArray) { + case stack { + [] -> acc + + [[], ..remaining_stack] -> to_list(remaining_stack, acc) + + [[Bytes(bits), ..rest], ..remaining_stack] -> + to_list([rest, ..remaining_stack], [bits, ..acc]) + + [[Text(builder), ..rest], ..remaining_stack] -> { + let bits = bit_array.from_string(string_builder.to_string(builder)) + to_list([rest, ..remaining_stack], [bits, ..acc]) + } + + [[Many(builders), ..rest], ..remaining_stack] -> + to_list([builders, rest, ..remaining_stack], acc) + } +} + +/// Returns the size of the builder's content in bytes. +/// +/// Runs in linear time. +/// +@external(erlang, "erlang", "iolist_size") +pub fn byte_size(builder: BytesBuilder) -> Int { + [[builder]] + |> to_list([]) + |> list.fold(0, fn(acc, builder) { bit_array.byte_size(builder) + acc }) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/dict.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/dict.gleam new file mode 100644 index 0000000..cecb2ca --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/dict.gleam @@ -0,0 +1,493 @@ +import gleam/option.{type Option} + +/// A dictionary of keys and values. +/// +/// Any type can be used for the keys and values of a dict, but all the keys +/// must be of the same type and all the values must be of the same type. +/// +/// Each key can only be present in a dict once. +/// +/// Dicts are not ordered in any way, and any unintentional ordering is not to +/// be relied upon in your code as it may change in future versions of Erlang +/// or Gleam. +/// +/// See [the Erlang map module](https://erlang.org/doc/man/maps.html) for more +/// information. +/// +pub type Dict(key, value) + +/// Determines the number of key-value pairs in the dict. +/// This function runs in constant time and does not need to iterate the dict. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> size() +/// 0 +/// ``` +/// +/// ```gleam +/// > new() |> insert("key", "value") |> size() +/// 1 +/// ``` +/// +@external(erlang, "maps", "size") +@external(javascript, "../gleam_stdlib.mjs", "map_size") +pub fn size(dict: Dict(k, v)) -> Int + +/// Converts the dict to a list of 2-element tuples `#(key, value)`, one for +/// each key-value pair in the dict. +/// +/// The tuples in the list have no specific order. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> to_list() +/// [] +/// ``` +/// +/// ```gleam +/// > new() |> insert("key", 0) |> to_list() +/// [#("key", 0)] +/// ``` +/// +@external(erlang, "maps", "to_list") +@external(javascript, "../gleam_stdlib.mjs", "map_to_list") +pub fn to_list(dict: Dict(key, value)) -> List(#(key, value)) + +/// Converts a list of 2-element tuples `#(key, value)` to a dict. +/// +/// If two tuples have the same key the last one in the list will be the one +/// that is present in the dict. +/// +@external(erlang, "maps", "from_list") +pub fn from_list(list: List(#(k, v))) -> Dict(k, v) { + fold_list_of_pair(list, new()) +} + +fn fold_list_of_pair( + over list: List(#(k, v)), + from initial: Dict(k, v), +) -> Dict(k, v) { + case list { + [] -> initial + [x, ..rest] -> fold_list_of_pair(rest, insert(initial, x.0, x.1)) + } +} + +/// Determines whether or not a value present in the dict for a given key. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> insert("a", 0) |> has_key("a") +/// True +/// ``` +/// +/// ```gleam +/// > new() |> insert("a", 0) |> has_key("b") +/// False +/// ``` +/// +pub fn has_key(dict: Dict(k, v), key: k) -> Bool { + do_has_key(key, dict) +} + +@external(erlang, "maps", "is_key") +fn do_has_key(key: k, dict: Dict(k, v)) -> Bool { + get(dict, key) != Error(Nil) +} + +/// Creates a fresh dict that contains no values. +/// +pub fn new() -> Dict(key, value) { + do_new() +} + +@external(erlang, "maps", "new") +@external(javascript, "../gleam_stdlib.mjs", "new_map") +fn do_new() -> Dict(key, value) + +/// Fetches a value from a dict for a given key. +/// +/// The dict may not have a value for the key, so the value is wrapped in a +/// `Result`. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> insert("a", 0) |> get("a") +/// Ok(0) +/// ``` +/// +/// ```gleam +/// > new() |> insert("a", 0) |> get("b") +/// Error(Nil) +/// ``` +/// +pub fn get(from: Dict(key, value), get: key) -> Result(value, Nil) { + do_get(from, get) +} + +@external(erlang, "gleam_stdlib", "map_get") +@external(javascript, "../gleam_stdlib.mjs", "map_get") +fn do_get(a: Dict(key, value), b: key) -> Result(value, Nil) + +/// Inserts a value into the dict with the given key. +/// +/// If the dict already has a value for the given key then the value is +/// replaced with the new value. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> insert("a", 0) |> to_list +/// [#("a", 0)] +/// ``` +/// +/// ```gleam +/// > new() |> insert("a", 0) |> insert("a", 5) |> to_list +/// [#("a", 5)] +/// ``` +/// +pub fn insert(into dict: Dict(k, v), for key: k, insert value: v) -> Dict(k, v) { + do_insert(key, value, dict) +} + +@external(erlang, "maps", "put") +@external(javascript, "../gleam_stdlib.mjs", "map_insert") +fn do_insert(a: key, b: value, c: Dict(key, value)) -> Dict(key, value) + +/// Updates all values in a given dict by calling a given function on each key +/// and value. +/// +/// ## Examples +/// +/// ```gleam +/// > [#(3, 3), #(2, 4)] +/// > |> from_list +/// > |> map_values(fn(key, value) { key * value }) +/// [#(3, 9), #(2, 8)] +/// ``` +/// +pub fn map_values(in dict: Dict(k, v), with fun: fn(k, v) -> w) -> Dict(k, w) { + do_map_values(fun, dict) +} + +@external(erlang, "maps", "map") +fn do_map_values(f: fn(key, value) -> b, dict: Dict(key, value)) -> Dict(key, b) { + let f = fn(dict, k, v) { insert(dict, k, f(k, v)) } + dict + |> fold(from: new(), with: f) +} + +/// Gets a list of all keys in a given dict. +/// +/// Dicts are not ordered so the keys are not returned in any specific order. Do +/// not write code that relies on the order keys are returned by this function +/// as it may change in later versions of Gleam or Erlang. +/// +/// ## Examples +/// +/// ```gleam +/// > keys([#("a", 0), #("b", 1)]) +/// ["a", "b"] +/// ``` +/// +pub fn keys(dict: Dict(keys, v)) -> List(keys) { + do_keys(dict) +} + +@external(erlang, "maps", "keys") +fn do_keys(dict: Dict(k, v)) -> List(k) { + let list_of_pairs = to_list(dict) + do_keys_acc(list_of_pairs, []) +} + +fn reverse_and_concat(remaining, accumulator) { + case remaining { + [] -> accumulator + [item, ..rest] -> reverse_and_concat(rest, [item, ..accumulator]) + } +} + +fn do_keys_acc(list: List(#(k, v)), acc: List(k)) -> List(k) { + case list { + [] -> reverse_and_concat(acc, []) + [x, ..xs] -> do_keys_acc(xs, [x.0, ..acc]) + } +} + +/// Gets a list of all values in a given dict. +/// +/// Dicts are not ordered so the values are not returned in any specific order. Do +/// not write code that relies on the order values are returned by this function +/// as it may change in later versions of Gleam or Erlang. +/// +/// ## Examples +/// +/// ```gleam +/// > values(from_list([#("a", 0), #("b", 1)])) +/// [0, 1] +/// ``` +/// +pub fn values(dict: Dict(k, values)) -> List(values) { + do_values(dict) +} + +@external(erlang, "maps", "values") +fn do_values(dict: Dict(k, v)) -> List(v) { + let list_of_pairs = to_list(dict) + do_values_acc(list_of_pairs, []) +} + +fn do_values_acc(list: List(#(k, v)), acc: List(v)) -> List(v) { + case list { + [] -> reverse_and_concat(acc, []) + [x, ..xs] -> do_values_acc(xs, [x.1, ..acc]) + } +} + +/// Creates a new dict from a given dict, minus any entries that a given function +/// returns `False` for. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([#("a", 0), #("b", 1)]) +/// > |> filter(fn(key, value) { value != 0 }) +/// from_list([#("b", 1)]) +/// ``` +/// +/// ```gleam +/// > from_list([#("a", 0), #("b", 1)]) +/// > |> filter(fn(key, value) { True }) +/// from_list([#("a", 0), #("b", 1)]) +/// ``` +/// +pub fn filter( + in dict: Dict(k, v), + keeping predicate: fn(k, v) -> Bool, +) -> Dict(k, v) { + do_filter(predicate, dict) +} + +@external(erlang, "maps", "filter") +fn do_filter( + f: fn(key, value) -> Bool, + dict: Dict(key, value), +) -> Dict(key, value) { + let insert = fn(dict, k, v) { + case f(k, v) { + True -> insert(dict, k, v) + _ -> dict + } + } + dict + |> fold(from: new(), with: insert) +} + +/// Creates a new dict from a given dict, only including any entries for which the +/// keys are in a given list. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([#("a", 0), #("b", 1)]) +/// > |> take(["b"]) +/// from_list([#("b", 1)]) +/// ``` +/// +/// ```gleam +/// > from_list([#("a", 0), #("b", 1)]) +/// > |> take(["a", "b", "c"]) +/// from_list([#("a", 0), #("b", 1)]) +/// ``` +/// +pub fn take(from dict: Dict(k, v), keeping desired_keys: List(k)) -> Dict(k, v) { + do_take(desired_keys, dict) +} + +@external(erlang, "maps", "with") +fn do_take(desired_keys: List(k), dict: Dict(k, v)) -> Dict(k, v) { + insert_taken(dict, desired_keys, new()) +} + +fn insert_taken( + dict: Dict(k, v), + desired_keys: List(k), + acc: Dict(k, v), +) -> Dict(k, v) { + let insert = fn(taken, key) { + case get(dict, key) { + Ok(value) -> insert(taken, key, value) + _ -> taken + } + } + case desired_keys { + [] -> acc + [x, ..xs] -> insert_taken(dict, xs, insert(acc, x)) + } +} + +/// Creates a new dict from a pair of given dicts by combining their entries. +/// +/// If there are entries with the same keys in both dicts the entry from the +/// second dict takes precedence. +/// +/// ## Examples +/// +/// ```gleam +/// > let a = from_list([#("a", 0), #("b", 1)]) +/// > let b = from_list([#("b", 2), #("c", 3)]) +/// > merge(a, b) +/// from_list([#("a", 0), #("b", 2), #("c", 3)]) +/// ``` +/// +pub fn merge(into dict: Dict(k, v), from new_entries: Dict(k, v)) -> Dict(k, v) { + do_merge(dict, new_entries) +} + +@external(erlang, "maps", "merge") +fn do_merge(dict: Dict(k, v), new_entries: Dict(k, v)) -> Dict(k, v) { + new_entries + |> to_list + |> fold_inserts(dict) +} + +fn insert_pair(dict: Dict(k, v), pair: #(k, v)) -> Dict(k, v) { + insert(dict, pair.0, pair.1) +} + +fn fold_inserts(new_entries: List(#(k, v)), dict: Dict(k, v)) -> Dict(k, v) { + case new_entries { + [] -> dict + [x, ..xs] -> fold_inserts(xs, insert_pair(dict, x)) + } +} + +/// Creates a new dict from a given dict with all the same entries except for the +/// one with a given key, if it exists. +/// +/// ## Examples +/// +/// ```gleam +/// > delete([#("a", 0), #("b", 1)], "a") +/// from_list([#("b", 1)]) +/// ``` +/// +/// ```gleam +/// > delete([#("a", 0), #("b", 1)], "c") +/// from_list([#("a", 0), #("b", 1)]) +/// ``` +/// +pub fn delete(from dict: Dict(k, v), delete key: k) -> Dict(k, v) { + do_delete(key, dict) +} + +@external(erlang, "maps", "remove") +@external(javascript, "../gleam_stdlib.mjs", "map_remove") +fn do_delete(a: k, b: Dict(k, v)) -> Dict(k, v) + +/// Creates a new dict from a given dict with all the same entries except any with +/// keys found in a given list. +/// +/// ## Examples +/// +/// ```gleam +/// > drop([#("a", 0), #("b", 1)], ["a"]) +/// from_list([#("b", 2)]) +/// ``` +/// +/// ```gleam +/// > delete([#("a", 0), #("b", 1)], ["c"]) +/// from_list([#("a", 0), #("b", 1)]) +/// ``` +/// +/// ```gleam +/// > drop([#("a", 0), #("b", 1)], ["a", "b", "c"]) +/// from_list([]) +/// ``` +/// +pub fn drop(from dict: Dict(k, v), drop disallowed_keys: List(k)) -> Dict(k, v) { + case disallowed_keys { + [] -> dict + [x, ..xs] -> drop(delete(dict, x), xs) + } +} + +/// Creates a new dict with one entry updated using a given function. +/// +/// If there was not an entry in the dict for the given key then the function +/// gets `None` as its argument, otherwise it gets `Some(value)`. +/// +/// ## Example +/// +/// ```gleam +/// > let increment = fn(x) { +/// > case x { +/// > Some(i) -> i + 1 +/// > None -> 0 +/// > } +/// > } +/// > let dict = from_list([#("a", 0)]) +/// > +/// > update(dict, "a", increment) +/// from_list([#("a", 1)]) +/// ``` +/// +/// ```gleam +/// > update(dict, "b", increment) +/// from_list([#("a", 0), #("b", 0)]) +/// ``` +/// +pub fn update( + in dict: Dict(k, v), + update key: k, + with fun: fn(Option(v)) -> v, +) -> Dict(k, v) { + dict + |> get(key) + |> option.from_result + |> fun + |> insert(dict, key, _) +} + +fn do_fold(list: List(#(k, v)), initial: acc, fun: fn(acc, k, v) -> acc) -> acc { + case list { + [] -> initial + [#(k, v), ..rest] -> do_fold(rest, fun(initial, k, v), fun) + } +} + +/// Combines all entries into a single value by calling a given function on each +/// one. +/// +/// Dicts are not ordered so the values are not returned in any specific order. Do +/// not write code that relies on the order entries are used by this function +/// as it may change in later versions of Gleam or Erlang. +/// +/// # Examples +/// +/// ```gleam +/// > let dict = from_list([#("a", 1), #("b", 3), #("c", 9)]) +/// > fold(dict, 0, fn(accumulator, key, value) { accumulator + value }) +/// 13 +/// ``` +/// +/// ```gleam +/// > import gleam/string.{append} +/// > fold(dict, "", fn(accumulator, key, value) { append(accumulator, key) }) +/// "abc" +/// ``` +/// +pub fn fold( + over dict: Dict(k, v), + from initial: acc, + with fun: fn(acc, k, v) -> acc, +) -> acc { + dict + |> to_list + |> do_fold(initial, fun) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/dynamic.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/dynamic.gleam new file mode 100644 index 0000000..1c4b431 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/dynamic.gleam @@ -0,0 +1,1520 @@ +import gleam/int +import gleam/list +import gleam/dict.{type Dict} +import gleam/option.{type Option} +import gleam/result +import gleam/string_builder +@target(erlang) +import gleam/bit_array + +/// `Dynamic` data is data that we don't know the type of yet. +/// We likely get data like this from interop with Erlang, or from +/// IO with the outside world. +/// +pub type Dynamic + +/// Error returned when unexpected data is encountered +/// +pub type DecodeError { + DecodeError(expected: String, found: String, path: List(String)) +} + +pub type DecodeErrors = + List(DecodeError) + +pub type Decoder(t) = + fn(Dynamic) -> Result(t, DecodeErrors) + +/// Converts any Gleam data into `Dynamic` data. +/// +pub fn from(a) -> Dynamic { + do_from(a) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_from(a: anything) -> Dynamic + +/// Unsafely casts a Dynamic value into any other type. +/// +/// This is an escape hatch for the type system that may be useful when wrapping +/// native Erlang APIs. It is to be used as a last measure only! +/// +/// If you can avoid using this function, do! +/// +pub fn unsafe_coerce(a: Dynamic) -> anything { + do_unsafe_coerce(a) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_unsafe_coerce(a: Dynamic) -> a + +/// Decodes a `Dynamic` value from a `Dynamic` value. +/// +/// This function doesn't seem very useful at first, but it can be convenient +/// when you need to give a decoder function but you don't actually care what +/// the to-decode value is. +/// +pub fn dynamic(value: Dynamic) -> Result(Dynamic, List(DecodeError)) { + Ok(value) +} + +/// Checks to see whether a `Dynamic` value is a bit array, and returns that bit +/// array if it is. +/// +/// ## Examples +/// +/// ```gleam +/// > bit_array(from("Hello")) == bit_array.from_string("Hello") +/// True +/// ``` +/// +/// ```gleam +/// > bit_array(from(123)) +/// Error([DecodeError(expected: "BitArray", found: "Int", path: [])]) +/// ``` +/// +pub fn bit_array(from data: Dynamic) -> Result(BitArray, DecodeErrors) { + decode_bit_array(data) +} + +@deprecated("Please use `bit_array` instead") +pub fn bit_string(from data: Dynamic) -> Result(BitArray, DecodeErrors) { + bit_array(data) +} + +@external(erlang, "gleam_stdlib", "decode_bit_array") +@external(javascript, "../gleam_stdlib.mjs", "decode_bit_array") +fn decode_bit_array(a: Dynamic) -> Result(BitArray, DecodeErrors) + +/// Checks to see whether a `Dynamic` value is a string, and returns that string if +/// it is. +/// +/// ## Examples +/// +/// ```gleam +/// > string(from("Hello")) +/// Ok("Hello") +/// ``` +/// +/// ```gleam +/// > string(from(123)) +/// Error([DecodeError(expected: "String", found: "Int", path: [])]) +/// ``` +/// +pub fn string(from data: Dynamic) -> Result(String, DecodeErrors) { + decode_string(data) +} + +fn map_errors( + result: Result(t, DecodeErrors), + f: fn(DecodeError) -> DecodeError, +) -> Result(t, DecodeErrors) { + result.map_error(result, list.map(_, f)) +} + +@target(erlang) +fn decode_string(data: Dynamic) -> Result(String, DecodeErrors) { + bit_array(data) + |> map_errors(put_expected(_, "String")) + |> result.try(fn(raw) { + case bit_array.to_string(raw) { + Ok(string) -> Ok(string) + Error(Nil) -> + Error([DecodeError(expected: "String", found: "BitArray", path: [])]) + } + }) +} + +@target(erlang) +fn put_expected(error: DecodeError, expected: String) -> DecodeError { + DecodeError(..error, expected: expected) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "decode_string") +fn decode_string(a: Dynamic) -> Result(String, DecodeErrors) + +/// Return a string indicating the type of the dynamic value. +/// +/// ```gleam +/// > classify(from("Hello")) +/// "String" +/// ``` +/// +pub fn classify(data: Dynamic) -> String { + do_classify(data) +} + +@external(erlang, "gleam_stdlib", "classify_dynamic") +@external(javascript, "../gleam_stdlib.mjs", "classify_dynamic") +fn do_classify(a: Dynamic) -> String + +/// Checks to see whether a `Dynamic` value is an int, and returns that int if it +/// is. +/// +/// ## Examples +/// +/// ```gleam +/// > int(from(123)) +/// Ok(123) +/// ``` +/// +/// ```gleam +/// > int(from("Hello")) +/// Error([DecodeError(expected: "Int", found: "String", path: [])]) +/// ``` +/// +pub fn int(from data: Dynamic) -> Result(Int, DecodeErrors) { + decode_int(data) +} + +@external(erlang, "gleam_stdlib", "decode_int") +@external(javascript, "../gleam_stdlib.mjs", "decode_int") +fn decode_int(a: Dynamic) -> Result(Int, DecodeErrors) + +/// Checks to see whether a `Dynamic` value is a float, and returns that float if +/// it is. +/// +/// ## Examples +/// +/// ```gleam +/// > float(from(2.0)) +/// Ok(2.0) +/// ``` +/// +/// ```gleam +/// > float(from(123)) +/// Error([DecodeError(expected: "Float", found: "Int", path: [])]) +/// ``` +/// +pub fn float(from data: Dynamic) -> Result(Float, DecodeErrors) { + decode_float(data) +} + +@external(erlang, "gleam_stdlib", "decode_float") +@external(javascript, "../gleam_stdlib.mjs", "decode_float") +fn decode_float(a: Dynamic) -> Result(Float, DecodeErrors) + +/// Checks to see whether a `Dynamic` value is a bool, and returns that bool if +/// it is. +/// +/// ## Examples +/// +/// ```gleam +/// > bool(from(True)) +/// Ok(True) +/// ``` +/// +/// ```gleam +/// > bool(from(123)) +/// Error([DecodeError(expected: "Bool", found: "Int", path: [])]) +/// ``` +/// +pub fn bool(from data: Dynamic) -> Result(Bool, DecodeErrors) { + decode_bool(data) +} + +@external(erlang, "gleam_stdlib", "decode_bool") +@external(javascript, "../gleam_stdlib.mjs", "decode_bool") +fn decode_bool(a: Dynamic) -> Result(Bool, DecodeErrors) + +/// Checks to see whether a `Dynamic` value is a list, and returns that list if it +/// is. The types of the elements are not checked. +/// +/// If you wish to decode all the elements in the list use the `list` function +/// instead. +/// +/// ## Examples +/// +/// ```gleam +/// > shallow_list(from(["a", "b", "c"])) +/// Ok([from("a"), from("b"), from("c")]) +/// ``` +/// +/// ```gleam +/// > shallow_list(1) +/// Error([DecodeError(expected: "List", found: "Int", path: [])]) +/// ``` +/// +pub fn shallow_list(from value: Dynamic) -> Result(List(Dynamic), DecodeErrors) { + decode_list(value) +} + +@external(erlang, "gleam_stdlib", "decode_list") +@external(javascript, "../gleam_stdlib.mjs", "decode_list") +fn decode_list(a: Dynamic) -> Result(List(Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_result") +@external(javascript, "../gleam_stdlib.mjs", "decode_result") +fn decode_result(a: Dynamic) -> Result(Result(a, e), DecodeErrors) + +/// Checks to see whether a `Dynamic` value is a result of a particular type, and +/// returns that result if it is. +/// +/// The `ok` and `error` arguments are decoders for decoding the `Ok` and +/// `Error` values of the result. +/// +/// ## Examples +/// +/// ```gleam +/// > from(Ok(1)) +/// > |> result(ok: int, error: string) +/// Ok(Ok(1)) +/// ``` +/// +/// ```gleam +/// > from(Error("boom")) +/// > |> result(ok: int, error: string) +/// Ok(Error("boom")) +/// ``` +/// +/// ```gleam +/// > from(123) +/// > |> result(ok: int, error: string) +/// Error([DecodeError(expected: "Result", found: "Int", path: [])]) +/// ``` +/// +pub fn result( + ok decode_ok: Decoder(a), + error decode_error: Decoder(e), +) -> Decoder(Result(a, e)) { + fn(value) { + use inner_result <- result.try(decode_result(value)) + + case inner_result { + Ok(raw) -> { + use value <- result.try( + decode_ok(raw) + |> map_errors(push_path(_, "ok")), + ) + Ok(Ok(value)) + } + Error(raw) -> { + use value <- result.try( + decode_error(raw) + |> map_errors(push_path(_, "error")), + ) + Ok(Error(value)) + } + } + } +} + +/// Checks to see whether a `Dynamic` value is a list of a particular type, and +/// returns that list if it is. +/// +/// The second argument is a decoder function used to decode the elements of +/// the list. The list is only decoded if all elements in the list can be +/// successfully decoded using this function. +/// +/// If you do not wish to decode all the elements in the list use the `shallow_list` +/// function instead. +/// +/// ## Examples +/// +/// ```gleam +/// > from(["a", "b", "c"]) +/// > |> list(of: string) +/// Ok(["a", "b", "c"]) +/// ``` +/// +/// ```gleam +/// > from([1, 2, 3]) +/// > |> list(of: string) +/// Error([DecodeError(expected: "String", found: "Int", path: ["*"])]) +/// ``` +/// +/// ```gleam +/// > from("ok") +/// > |> list(of: string) +/// Error([DecodeError(expected: "List", found: "String", path: [])]) +/// ``` +/// +pub fn list( + of decoder_type: fn(Dynamic) -> Result(inner, DecodeErrors), +) -> Decoder(List(inner)) { + fn(dynamic) { + use list <- result.try(shallow_list(dynamic)) + list + |> list.try_map(decoder_type) + |> map_errors(push_path(_, "*")) + } +} + +/// Checks to see if a `Dynamic` value is a nullable version of a particular +/// type, and returns a corresponding `Option` if it is. +/// +/// ## Examples +/// +/// ```gleam +/// > from("Hello") +/// > |> optional(string) +/// Ok(Some("Hello")) +/// ``` +/// +/// ```gleam +/// > from("Hello") +/// > |> optional(string) +/// Ok(Some("Hello")) +/// ``` +/// +/// ```gleam +/// > from(atom.from_string("null")) +/// > |> optional(string) +/// Ok(None) +/// ``` +/// +/// ```gleam +/// > from(atom.from_string("nil")) +/// > |> optional(string) +/// Ok(None) +/// ``` +/// +/// ```gleam +/// > from(atom.from_string("undefined")) +/// > |> optional(string) +/// Ok(None) +/// ``` +/// +/// ```gleam +/// > from(123) +/// > |> optional(string) +/// Error([DecodeError(expected: "String", found: "Int", path: [])]) +/// ``` +/// +pub fn optional(of decode: Decoder(inner)) -> Decoder(Option(inner)) { + fn(value) { decode_optional(value, decode) } +} + +@external(erlang, "gleam_stdlib", "decode_option") +@external(javascript, "../gleam_stdlib.mjs", "decode_option") +fn decode_optional(a: Dynamic, b: Decoder(a)) -> Result(Option(a), DecodeErrors) + +/// Checks to see if a `Dynamic` value is a map with a specific field, and returns +/// the value of that field if it is. +/// +/// This will not succeed on a record. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/dict +/// > dict.new() +/// > |> dict.insert("Hello", "World") +/// > |> from +/// > |> field(named: "Hello", of: string) +/// Ok("World") +/// ``` +/// +/// ```gleam +/// > from(123) +/// > |> field("Hello", string) +/// Error([DecodeError(expected: "Map", found: "Int", path: [])]) +/// ``` +/// +pub fn field(named name: a, of inner_type: Decoder(t)) -> Decoder(t) { + fn(value) { + let missing_field_error = + DecodeError(expected: "field", found: "nothing", path: []) + + use maybe_inner <- result.try(decode_field(value, name)) + maybe_inner + |> option.to_result([missing_field_error]) + |> result.try(inner_type) + |> map_errors(push_path(_, name)) + } +} + +/// Checks to see if a `Dynamic` value is a map with a specific field. +/// If the map does not have the specified field, returns an `Ok(None)` instead of failing; otherwise, +/// returns the decoded field wrapped in `Some(_)`. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/dict +/// > dict.new() +/// > |> dict.insert("Hello", "World") +/// > |> from +/// > |> field(named: "Hello", of: string) +/// Ok(Some("World")) +/// ``` +/// +/// ```gleam +/// > import gleam/dict +/// > dict.new() +/// > |> from +/// > |> field(named: "Hello", of: string) +/// Ok(None) +/// ``` +/// +/// ```gleam +/// > from(123) +/// > |> field("Hello", string) +/// Error([DecodeError(expected: "Map", found: "Int", path: [])]) +/// ``` +/// +pub fn optional_field( + named name: a, + of inner_type: Decoder(t), +) -> Decoder(Option(t)) { + fn(value) { + use maybe_inner <- result.try(decode_field(value, name)) + case maybe_inner { + option.None -> Ok(option.None) + option.Some(dynamic_inner) -> + dynamic_inner + |> decode_optional(inner_type) + |> map_errors(push_path(_, name)) + } + } +} + +@external(erlang, "gleam_stdlib", "decode_field") +@external(javascript, "../gleam_stdlib.mjs", "decode_field") +fn decode_field(a: Dynamic, b: name) -> Result(Option(Dynamic), DecodeErrors) + +/// Checks to see if a `Dynamic` value is a tuple large enough to have a certain +/// index, and returns the value of that index if it is. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> element(0, int) +/// Ok(from(1)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> element(2, int) +/// Error([ +/// DecodeError( +/// expected: "Tuple of at least 3 elements", +/// found: "Tuple of 2 elements", +/// path: [], +/// ), +/// ]) +/// ``` +/// +pub fn element(at index: Int, of inner_type: Decoder(t)) -> Decoder(t) { + fn(data: Dynamic) { + use tuple <- result.try(decode_tuple(data)) + let size = tuple_size(tuple) + use data <- result.try(case index >= 0 { + True -> + case index < size { + True -> tuple_get(tuple, index) + False -> at_least_decode_tuple_error(index + 1, data) + } + False -> + case int.absolute_value(index) <= size { + True -> tuple_get(tuple, size + index) + False -> at_least_decode_tuple_error(int.absolute_value(index), data) + } + }) + inner_type(data) + |> map_errors(push_path(_, index)) + } +} + +fn at_least_decode_tuple_error( + size: Int, + data: Dynamic, +) -> Result(a, DecodeErrors) { + let s = case size { + 1 -> "" + _ -> "s" + } + let error = + ["Tuple of at least ", int.to_string(size), " element", s] + |> string_builder.from_strings + |> string_builder.to_string + |> DecodeError(found: classify(data), path: []) + Error([error]) +} + +// A tuple of unknown size +type UnknownTuple + +@external(erlang, "gleam_stdlib", "decode_tuple") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple") +fn decode_tuple(a: Dynamic) -> Result(UnknownTuple, DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple2") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple2") +fn decode_tuple2(a: Dynamic) -> Result(#(Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple3") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple3") +fn decode_tuple3( + a: Dynamic, +) -> Result(#(Dynamic, Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple4") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple4") +fn decode_tuple4( + a: Dynamic, +) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple5") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple5") +fn decode_tuple5( + a: Dynamic, +) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), DecodeErrors) + +@external(erlang, "gleam_stdlib", "decode_tuple6") +@external(javascript, "../gleam_stdlib.mjs", "decode_tuple6") +fn decode_tuple6( + a: Dynamic, +) -> Result( + #(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), + DecodeErrors, +) + +@external(erlang, "gleam_stdlib", "tuple_get") +@external(javascript, "../gleam_stdlib.mjs", "tuple_get") +fn tuple_get(a: UnknownTuple, b: Int) -> Result(Dynamic, DecodeErrors) + +@external(erlang, "gleam_stdlib", "size_of_tuple") +@external(javascript, "../gleam_stdlib.mjs", "length") +fn tuple_size(a: UnknownTuple) -> Int + +fn tuple_errors( + result: Result(a, List(DecodeError)), + name: String, +) -> List(DecodeError) { + case result { + Ok(_) -> [] + Error(errors) -> list.map(errors, push_path(_, name)) + } +} + +fn push_path(error: DecodeError, name: t) -> DecodeError { + let name = from(name) + let decoder = any([string, fn(x) { result.map(int(x), int.to_string) }]) + let name = case decoder(name) { + Ok(name) -> name + Error(_) -> + ["<", classify(name), ">"] + |> string_builder.from_strings + |> string_builder.to_string + } + DecodeError(..error, path: [name, ..error.path]) +} + +/// Checks to see if a `Dynamic` value is a 2-element tuple, list or array containing +/// specifically typed elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> tuple2(int, int) +/// Ok(#(1, 2)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2.0)) +/// > |> tuple2(int, float) +/// Ok(#(1, 2.0)) +/// ``` +/// +/// ```gleam +/// > from([1, 2]) +/// > |> tuple2(int, int) +/// Ok(#(1, 2)) +/// ``` +/// +/// ```gleam +/// > from([from(1), from(2.0)]) +/// > |> tuple2(int, float) +/// Ok(#(1, 2.0)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2, 3)) +/// > |> tuple2(int, float) +/// Error([ +/// DecodeError(expected: "Tuple of 2 elements", found: "Tuple of 3 elements", path: []), +/// ]) +/// ``` +/// +/// ```gleam +/// > from("") +/// > |> tuple2(int, float) +/// Error([DecodeError(expected: "Tuple of 2 elements", found: "String", path: [])]) +/// ``` +/// +pub fn tuple2( + first decode1: Decoder(a), + second decode2: Decoder(b), +) -> Decoder(#(a, b)) { + fn(value) { + use #(a, b) <- result.try(decode_tuple2(value)) + case decode1(a), decode2(b) { + Ok(a), Ok(b) -> Ok(#(a, b)) + a, b -> + tuple_errors(a, "0") + |> list.append(tuple_errors(b, "1")) + |> Error + } + } +} + +/// Checks to see if a `Dynamic` value is a 3-element tuple, list or array containing +/// specifically typed elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2, 3)) +/// > |> tuple3(int, int, int) +/// Ok(#(1, 2, 3)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2.0, "3")) +/// > |> tuple3(int, float, string) +/// Ok(#(1, 2.0, "3")) +/// ``` +/// +/// ```gleam +/// > from([1, 2, 3]) +/// > |> tuple3(int, int, int) +/// Ok(#(1, 2, 3)) +/// ``` +/// +/// ```gleam +/// > from([from(1), from(2.0), from("3")]) +/// > |> tuple3(int, float, string) +/// Ok(#(1, 2.0, "3")) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> tuple3(int, float, string) +/// Error([ +/// DecodeError(expected: "Tuple of 3 elements", found: "Tuple of 2 elements", path: [])), +/// ]) +/// ``` +/// +/// ```gleam +/// > from("") +/// > |> tuple3(int, float, string) +/// Error([ +/// DecodeError(expected: "Tuple of 3 elements", found: "String", path: []), +/// ]) +/// ``` +/// +pub fn tuple3( + first decode1: Decoder(a), + second decode2: Decoder(b), + third decode3: Decoder(c), +) -> Decoder(#(a, b, c)) { + fn(value) { + use #(a, b, c) <- result.try(decode_tuple3(value)) + case decode1(a), decode2(b), decode3(c) { + Ok(a), Ok(b), Ok(c) -> Ok(#(a, b, c)) + a, b, c -> + tuple_errors(a, "0") + |> list.append(tuple_errors(b, "1")) + |> list.append(tuple_errors(c, "2")) + |> Error + } + } +} + +/// Checks to see if a `Dynamic` value is a 4-element tuple, list or array containing +/// specifically typed elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2, 3, 4)) +/// > |> tuple4(int, int, int, int) +/// Ok(#(1, 2, 3, 4)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2.0, "3", 4)) +/// > |> tuple4(int, float, string, int) +/// Ok(#(1, 2.0, "3", 4)) +/// ``` +/// +/// ```gleam +/// > from([1, 2, 3, 4]) +/// > |> tuple4(int, int, int, int) +/// Ok(#(1, 2, 3, 4)) +/// ``` +/// +/// ```gleam +/// > from([from(1), from(2.0), from("3"), from(4)]) +/// > |> tuple4(int, float, string, int) +/// Ok(#(1, 2.0, "3", 4)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> tuple4(int, float, string, int) +/// Error([ +/// DecodeError(expected: "Tuple of 4 elements", found: "Tuple of 2 elements", path: []), +/// ]) +/// ``` +/// +/// ```gleam +/// > from("") +/// > |> tuple4(int, float, string, int) +/// Error([ +/// DecodeError(expected: "Tuple of 4 elements", found: "String", path: []), +/// ]) +/// ``` +/// +pub fn tuple4( + first decode1: Decoder(a), + second decode2: Decoder(b), + third decode3: Decoder(c), + fourth decode4: Decoder(d), +) -> Decoder(#(a, b, c, d)) { + fn(value) { + use #(a, b, c, d) <- result.try(decode_tuple4(value)) + case decode1(a), decode2(b), decode3(c), decode4(d) { + Ok(a), Ok(b), Ok(c), Ok(d) -> Ok(#(a, b, c, d)) + a, b, c, d -> + tuple_errors(a, "0") + |> list.append(tuple_errors(b, "1")) + |> list.append(tuple_errors(c, "2")) + |> list.append(tuple_errors(d, "3")) + |> Error + } + } +} + +/// Checks to see if a `Dynamic` value is a 5-element tuple, list or array containing +/// specifically typed elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2, 3, 4, 5)) +/// > |> tuple5(int, int, int, int, int) +/// Ok(#(1, 2, 3, 4, 5)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2.0, "3", 4, 5)) +/// > |> tuple5(int, float, string, int, int) +/// Ok(#(1, 2.0, "3", 4, 5)) +/// ``` +/// +/// ```gleam +/// > from([1, 2, 3, 4, 5]) +/// > |> tuple5(int, int, int, int, int) +/// Ok(#(1, 2, 3, 4, 5)) +/// ``` +/// +/// ```gleam +/// > from([from(1), from(2.0), from("3"), from(4), from(True)]) +/// > |> tuple5(int, float, string, int, bool) +/// Ok(#(1, 2.0, "3", 4, True)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> tuple5(int, float, string, int, int) +/// Error([ +/// DecodeError(expected: "Tuple of 5 elements", found: "Tuple of 2 elements", path: [])), +/// ]) +/// ``` +/// +/// ```gleam +/// > from("") +/// > |> tuple5(int, float, string, int, int) +/// Error([DecodeError(expected: "Tuple of 5 elements", found: "String", path: [])]) +/// ``` +/// +pub fn tuple5( + first decode1: Decoder(a), + second decode2: Decoder(b), + third decode3: Decoder(c), + fourth decode4: Decoder(d), + fifth decode5: Decoder(e), +) -> Decoder(#(a, b, c, d, e)) { + fn(value) { + use #(a, b, c, d, e) <- result.try(decode_tuple5(value)) + case decode1(a), decode2(b), decode3(c), decode4(d), decode5(e) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e) -> Ok(#(a, b, c, d, e)) + a, b, c, d, e -> + tuple_errors(a, "0") + |> list.append(tuple_errors(b, "1")) + |> list.append(tuple_errors(c, "2")) + |> list.append(tuple_errors(d, "3")) + |> list.append(tuple_errors(e, "4")) + |> Error + } + } +} + +/// Checks to see if a `Dynamic` value is a 6-element tuple, list or array containing +/// specifically typed elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2, 3, 4, 5, 6)) +/// > |> tuple6(int, int, int, int, int, int) +/// Ok(#(1, 2, 3, 4, 5, 6)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2.0, "3", 4, 5, 6)) +/// > |> tuple6(int, float, string, int, int, int) +/// Ok(#(1, 2.0, "3", 4, 5, 6)) +/// ``` +/// +/// ```gleam +/// > from([1, 2, 3, 4, 5, 6]) +/// > |> tuple6(int, int, int, int, int, int) +/// Ok(#(1, 2, 3, 4, 5, 6)) +/// ``` +/// +/// ```gleam +/// > from([from(1), from(2.0), from("3"), from(4), from(True), from(False)]) +/// > |> tuple6(int, float, string, int, bool, bool) +/// Ok(#(1, 2.0, "3", 4, True, False)) +/// ``` +/// +/// ```gleam +/// > from(#(1, 2)) +/// > |> tuple6(int, float, string, int, int, int) +/// Error([ +/// DecodeError(expected: "Tuple of 6 elements", found: "Tuple of 2 elements", path: []), +/// ]) +/// ``` +/// +/// ```gleam +/// > from("") +/// > |> tuple6(int, float, string, int, int, int) +/// Error([DecodeError(expected: "Tuple of 6 elements", found: "String", path: [])]) +/// ``` +/// +pub fn tuple6( + first decode1: Decoder(a), + second decode2: Decoder(b), + third decode3: Decoder(c), + fourth decode4: Decoder(d), + fifth decode5: Decoder(e), + sixth decode6: Decoder(f), +) -> Decoder(#(a, b, c, d, e, f)) { + fn(value) { + use #(a, b, c, d, e, f) <- result.try(decode_tuple6(value)) + case + decode1(a), + decode2(b), + decode3(c), + decode4(d), + decode5(e), + decode6(f) + { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e), Ok(f) -> Ok(#(a, b, c, d, e, f)) + a, b, c, d, e, f -> + tuple_errors(a, "0") + |> list.append(tuple_errors(b, "1")) + |> list.append(tuple_errors(c, "2")) + |> list.append(tuple_errors(d, "3")) + |> list.append(tuple_errors(e, "4")) + |> list.append(tuple_errors(f, "5")) + |> Error + } + } +} + +/// Checks to see if a `Dynamic` value is a dict. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/dict +/// > dict.new() |> from |> map(string, int) +/// Ok(dict.new()) +/// ``` +/// +/// ```gleam +/// > from(1) |> map(string, int) +/// Error(DecodeError(expected: "Map", found: "Int", path: [])) +/// ``` +/// +/// ```gleam +/// > from("") |> map(string, int) +/// Error(DecodeError(expected: "Map", found: "String", path: [])) +/// ``` +/// +pub fn dict( + of key_type: Decoder(k), + to value_type: Decoder(v), +) -> Decoder(Dict(k, v)) { + fn(value) { + use map <- result.try(decode_map(value)) + use pairs <- result.try( + map + |> dict.to_list + |> list.try_map(fn(pair) { + let #(k, v) = pair + use k <- result.try( + key_type(k) + |> map_errors(push_path(_, "keys")), + ) + use v <- result.try( + value_type(v) + |> map_errors(push_path(_, "values")), + ) + Ok(#(k, v)) + }), + ) + Ok(dict.from_list(pairs)) + } +} + +@deprecated("Use `dict` instead") +pub fn map( + of key_type: Decoder(k), + to value_type: Decoder(v), +) -> Decoder(Dict(k, v)) { + dict(key_type, value_type) +} + +@external(erlang, "gleam_stdlib", "decode_map") +@external(javascript, "../gleam_stdlib.mjs", "decode_map") +fn decode_map(a: Dynamic) -> Result(Dict(Dynamic, Dynamic), DecodeErrors) + +/// Joins multiple decoders into one. When run they will each be tried in turn +/// until one succeeds, or they all fail. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/result +/// > let bool_or_string = any(of: [ +/// > string, +/// > fn(x) { result.map(bool(x), fn(_) { "a bool" }) } +/// > ]) +/// > bool_or_string(from("ok")) +/// Ok("ok") +/// ``` +/// +/// ```gleam +/// > bool_or_string(from(True)) +/// Ok("a bool") +/// ``` +/// +/// ```gleam +/// > bool_or_string(from(1)) +/// Error(DecodeError(expected: "another type", found: "Int", path: [])) +/// ``` +/// +pub fn any(of decoders: List(Decoder(t))) -> Decoder(t) { + fn(data) { + case decoders { + [] -> + Error([ + DecodeError(found: classify(data), expected: "another type", path: []), + ]) + + [decoder, ..decoders] -> + case decoder(data) { + Ok(decoded) -> Ok(decoded) + Error(_) -> any(decoders)(data) + } + } + } +} + +/// Decode 1 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.0, "3")) +/// > |> decode1(MyRecord, element(0, int)) +/// Ok(MyRecord(1)) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "")) +/// > |> decode1(MyRecord, element(0, int)) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// ]) +/// ``` +/// +pub fn decode1(constructor: fn(t1) -> t, t1: Decoder(t1)) -> Decoder(t) { + fn(value) { + case t1(value) { + Ok(a) -> Ok(constructor(a)) + a -> Error(all_errors(a)) + } + } +} + +/// Decode 2 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.0, "3")) +/// > |> decode2(MyRecord, element(0, int), element(1, float)) +/// Ok(MyRecord(1, 2.0)) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "")) +/// > |> decode2(MyRecord, element(0, int), element(1, float)) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode2( + constructor: fn(t1, t2) -> t, + t1: Decoder(t1), + t2: Decoder(t2), +) -> Decoder(t) { + fn(value) { + case t1(value), t2(value) { + Ok(a), Ok(b) -> Ok(constructor(a, b)) + a, b -> Error(list.concat([all_errors(a), all_errors(b)])) + } + } +} + +/// Decode 3 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.0, "3")) +/// > |> decode3(MyRecord, element(0, int), element(1, float), element(2, string)) +/// Ok(MyRecord(1, 2.0, "3")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "")) +/// > |> decode3(MyRecord, element(0, int), element(1, float), element(2, string)) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode3( + constructor: fn(t1, t2, t3) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), +) -> Decoder(t) { + fn(value) { + case t1(value), t2(value), t3(value) { + Ok(a), Ok(b), Ok(c) -> Ok(constructor(a, b, c)) + a, b, c -> + Error(list.concat([all_errors(a), all_errors(b), all_errors(c)])) + } + } +} + +/// Decode 4 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4")) +/// > |> decode4( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "")) +/// > |> decode4( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode4( + constructor: fn(t1, t2, t3, t4) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x) { + Ok(a), Ok(b), Ok(c), Ok(d) -> Ok(constructor(a, b, c, d)) + a, b, c, d -> + Error( + list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + ]), + ) + } + } +} + +/// Decode 5 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4", "5")) +/// > |> decode5( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4", "5")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "", "")) +/// > |> decode5( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode5( + constructor: fn(t1, t2, t3, t4, t5) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), + t5: Decoder(t5), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x), t5(x) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e) -> Ok(constructor(a, b, c, d, e)) + a, b, c, d, e -> + Error( + list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + all_errors(e), + ]), + ) + } + } +} + +/// Decode 6 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4", "5", "6")) +/// > |> decode6( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4", "5", "6")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "", "", "")) +/// > |> decode6( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode6( + constructor: fn(t1, t2, t3, t4, t5, t6) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), + t5: Decoder(t5), + t6: Decoder(t6), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x), t5(x), t6(x) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e), Ok(f) -> + Ok(constructor(a, b, c, d, e, f)) + a, b, c, d, e, f -> + Error( + list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + all_errors(e), + all_errors(f), + ]), + ) + } + } +} + +/// Decode 7 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4", "5", "6")) +/// > |> decode7( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4", "5", "6", "7")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "", "", "", "")) +/// > |> decode7( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode7( + constructor: fn(t1, t2, t3, t4, t5, t6, t7) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), + t5: Decoder(t5), + t6: Decoder(t6), + t7: Decoder(t7), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x), t5(x), t6(x), t7(x) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e), Ok(f), Ok(g) -> + Ok(constructor(a, b, c, d, e, f, g)) + a, b, c, d, e, f, g -> + Error( + list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + all_errors(e), + all_errors(f), + all_errors(g), + ]), + ) + } + } +} + +/// Decode 8 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4", "5", "6", "7", "8")) +/// > |> decode8( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > element(7, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4", "5", "6", "7", "8")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "", "", "", "", "")) +/// > |> decode8( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > element(7, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode8( + constructor: fn(t1, t2, t3, t4, t5, t6, t7, t8) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), + t5: Decoder(t5), + t6: Decoder(t6), + t7: Decoder(t7), + t8: Decoder(t8), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x), t5(x), t6(x), t7(x), t8(x) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e), Ok(f), Ok(g), Ok(h) -> + Ok(constructor(a, b, c, d, e, f, g, h)) + a, b, c, d, e, f, g, h -> + Error( + list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + all_errors(e), + all_errors(f), + all_errors(g), + all_errors(h), + ]), + ) + } + } +} + +/// Decode 9 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.1, "3", "4", "5", "6", "7", "8", "9")) +/// > |> decode9( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > element(7, string), +/// > element(8, string), +/// > ) +/// Ok(MyRecord(1, 2.1, "3", "4", "5", "6", "7", "8", "9")) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "", "", "", "", "", "", "")) +/// > |> decode9( +/// > MyRecord, +/// > element(0, int), +/// > element(1, float), +/// > element(2, string), +/// > element(3, string), +/// > element(4, string), +/// > element(5, string), +/// > element(6, string), +/// > element(7, string), +/// > element(8, string), +/// > ) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode9( + constructor: fn(t1, t2, t3, t4, t5, t6, t7, t8, t9) -> t, + t1: Decoder(t1), + t2: Decoder(t2), + t3: Decoder(t3), + t4: Decoder(t4), + t5: Decoder(t5), + t6: Decoder(t6), + t7: Decoder(t7), + t8: Decoder(t8), + t9: Decoder(t9), +) -> Decoder(t) { + fn(x: Dynamic) { + case t1(x), t2(x), t3(x), t4(x), t5(x), t6(x), t7(x), t8(x), t9(x) { + Ok(a), Ok(b), Ok(c), Ok(d), Ok(e), Ok(f), Ok(g), Ok(h), Ok(i) -> + Ok(constructor(a, b, c, d, e, f, g, h, i)) + a, b, c, d, e, f, g, h, i -> + Error( + list.concat([ + all_errors(a), + all_errors(b), + all_errors(c), + all_errors(d), + all_errors(e), + all_errors(f), + all_errors(g), + all_errors(h), + all_errors(i), + ]), + ) + } + } +} + +fn all_errors(result: Result(a, List(DecodeError))) -> List(DecodeError) { + case result { + Ok(_) -> [] + Error(errors) -> errors + } +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/float.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/float.gleam new file mode 100644 index 0000000..e53074d --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/float.gleam @@ -0,0 +1,541 @@ +//// Functions for working with floats. +//// +//// ## Division by zero +//// +//// Gleam runs on the Erlang virtual machine, which does not follow the IEEE +//// 754 standard for floating point arithmetic and does not have an `Infinity` +//// value. In Erlang division by zero results in a crash, however Gleam does +//// not have partial functions and operators in core so instead division by zero +//// returns zero, a behaviour taken from Pony, Coq, and Lean. +//// +//// This may seem unexpected at first, but it is no less mathematically valid +//// than crashing or returning a special value. Division by zero is undefined +//// in mathematics. + +import gleam/order.{type Order} + +/// Attempts to parse a string as a `Float`, returning `Error(Nil)` if it was +/// not possible. +/// +/// ## Examples +/// +/// ```gleam +/// > parse("2.3") +/// Ok(2.3) +/// ``` +/// +/// ```gleam +/// > parse("ABC") +/// Error(Nil) +/// ``` +/// +pub fn parse(string: String) -> Result(Float, Nil) { + do_parse(string) +} + +@external(erlang, "gleam_stdlib", "parse_float") +@external(javascript, "../gleam_stdlib.mjs", "parse_float") +fn do_parse(a: String) -> Result(Float, Nil) + +/// Returns the string representation of the provided `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > to_string(2.3) +/// "2.3" +/// ``` +/// +pub fn to_string(x: Float) -> String { + do_to_string(x) +} + +@external(erlang, "gleam_stdlib", "float_to_string") +@external(javascript, "../gleam_stdlib.mjs", "float_to_string") +fn do_to_string(a: Float) -> String + +/// Restricts a `Float` between a lower and upper bound. +/// +/// ## Examples +/// +/// ```gleam +/// > clamp(1.2, min: 1.4, max: 1.6) +/// 1.4 +/// ``` +/// +pub fn clamp(x: Float, min min_bound: Float, max max_bound: Float) -> Float { + x + |> min(max_bound) + |> max(min_bound) +} + +/// Compares two `Float`s, returning an `Order`: +/// `Lt` for lower than, `Eq` for equals, or `Gt` for greater than. +/// +/// ## Examples +/// +/// ```gleam +/// > compare(2.0, 2.3) +/// Lt +/// ``` +/// +/// To handle +/// [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems) +/// you may use [`loosely_compare`](#loosely_compare) instead. +/// +pub fn compare(a: Float, with b: Float) -> Order { + case a == b { + True -> order.Eq + False -> + case a <. b { + True -> order.Lt + False -> order.Gt + } + } +} + +/// Compares two `Float`s within a tolerance, returning an `Order`: +/// `Lt` for lower than, `Eq` for equals, or `Gt` for greater than. +/// +/// This function allows Float comparison while handling +/// [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems). +/// +/// Notice: For `Float`s the tolerance won't be exact: +/// `5.3 - 5.0` is not exactly `0.3`. +/// +/// ## Examples +/// +/// ```gleam +/// > loosely_compare(5.0, with: 5.3, tolerating: 0.5) +/// Eq +/// ``` +/// +/// If you want to check only for equality you may use +/// [`loosely_equals`](#loosely_equals) instead. +/// +pub fn loosely_compare( + a: Float, + with b: Float, + tolerating tolerance: Float, +) -> Order { + let difference = absolute_value(a -. b) + case difference <=. tolerance { + True -> order.Eq + False -> compare(a, b) + } +} + +/// Checks for equality of two `Float`s within a tolerance, +/// returning an `Bool`. +/// +/// This function allows Float comparison while handling +/// [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems). +/// +/// Notice: For `Float`s the tolerance won't be exact: +/// `5.3 - 5.0` is not exactly `0.3`. +/// +/// ## Examples +/// +/// ```gleam +/// > loosely_equals(5.0, with: 5.3, tolerating: 0.5) +/// True +/// ``` +/// +/// ```gleam +/// > loosely_equals(5.0, with: 5.1, tolerating: 0.1) +/// False +/// ``` +/// +pub fn loosely_equals( + a: Float, + with b: Float, + tolerating tolerance: Float, +) -> Bool { + let difference = absolute_value(a -. b) + difference <=. tolerance +} + +/// Compares two `Float`s, returning the smaller of the two. +/// +/// ## Examples +/// +/// ```gleam +/// > min(2.0, 2.3) +/// 2.0 +/// ``` +/// +pub fn min(a: Float, b: Float) -> Float { + case a <. b { + True -> a + False -> b + } +} + +/// Compares two `Float`s, returning the larger of the two. +/// +/// ## Examples +/// +/// ```gleam +/// > max(2.0, 2.3) +/// 2.3 +/// ``` +/// +pub fn max(a: Float, b: Float) -> Float { + case a >. b { + True -> a + False -> b + } +} + +/// Rounds the value to the next highest whole number as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > ceiling(2.3) +/// 3.0 +/// ``` +/// +pub fn ceiling(x: Float) -> Float { + do_ceiling(x) +} + +@external(erlang, "math", "ceil") +@external(javascript, "../gleam_stdlib.mjs", "ceiling") +fn do_ceiling(a: Float) -> Float + +/// Rounds the value to the next lowest whole number as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > floor(2.3) +/// 2.0 +/// ``` +/// +pub fn floor(x: Float) -> Float { + do_floor(x) +} + +@external(erlang, "math", "floor") +@external(javascript, "../gleam_stdlib.mjs", "floor") +fn do_floor(a: Float) -> Float + +/// Rounds the value to the nearest whole number as an `Int`. +/// +/// ## Examples +/// +/// ```gleam +/// > round(2.3) +/// 2 +/// ``` +/// +/// ```gleam +/// > round(2.5) +/// 3 +/// ``` +/// +pub fn round(x: Float) -> Int { + do_round(x) +} + +@target(erlang) +@external(erlang, "erlang", "round") +fn do_round(a: Float) -> Int + +@target(javascript) +fn do_round(x: Float) -> Int { + case x >=. 0.0 { + True -> js_round(x) + _ -> 0 - js_round(negate(x)) + } +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "round") +fn js_round(a: Float) -> Int + +/// Returns the value as an `Int`, truncating all decimal digits. +/// +/// ## Examples +/// +/// ```gleam +/// > truncate(2.4343434847383438) +/// 2 +/// ``` +/// +pub fn truncate(x: Float) -> Int { + do_truncate(x) +} + +@external(erlang, "erlang", "trunc") +@external(javascript, "../gleam_stdlib.mjs", "truncate") +fn do_truncate(a: Float) -> Int + +/// Returns the absolute value of the input as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > absolute_value(-12.5) +/// 12.5 +/// ``` +/// +/// ```gleam +/// > absolute_value(10.2) +/// 10.2 +/// ``` +/// +pub fn absolute_value(x: Float) -> Float { + case x >=. 0.0 { + True -> x + _ -> 0.0 -. x + } +} + +/// Returns the results of the base being raised to the power of the +/// exponent, as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > power(2.0, -1.0) +/// Ok(0.5) +/// ``` +/// +/// ```gleam +/// > power(2.0, 2.0) +/// Ok(4.0) +/// ``` +/// +/// ```gleam +/// > power(8.0, 1.5) +/// Ok(22.627416997969522) +/// ``` +/// +/// ```gleam +/// > 4.0 |> power(of: 2.0) +/// Ok(16.0) +/// ``` +/// +/// ```gleam +/// > power(-1.0, 0.5) +/// Error(Nil) +/// ``` +/// +pub fn power(base: Float, of exponent: Float) -> Result(Float, Nil) { + let fractional: Bool = ceiling(exponent) -. exponent >. 0.0 + // In the following check: + // 1. If the base is negative and the exponent is fractional then + // return an error as it will otherwise be an imaginary number + // 2. If the base is 0 and the exponent is negative then the expression + // is equivalent to the exponent divided by 0 and an error should be + // returned + case base <. 0.0 && fractional || base == 0.0 && exponent <. 0.0 { + True -> Error(Nil) + False -> Ok(do_power(base, exponent)) + } +} + +@external(erlang, "math", "pow") +@external(javascript, "../gleam_stdlib.mjs", "power") +fn do_power(a: Float, b: Float) -> Float + +/// Returns the square root of the input as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > square_root(4.0) +/// Ok(2.0) +/// ``` +/// +/// ```gleam +/// > square_root(-16.0) +/// Error(Nil) +/// ``` +/// +pub fn square_root(x: Float) -> Result(Float, Nil) { + power(x, 0.5) +} + +/// Returns the negative of the value provided. +/// +/// ## Examples +/// +/// ```gleam +/// > negate(1.0) +/// -1.0 +/// ``` +/// +pub fn negate(x: Float) -> Float { + -1.0 *. x +} + +/// Sums a list of `Float`s. +/// +/// ## Example +/// +/// ```gleam +/// > sum([1.0, 2.2, 3.3]) +/// 6.5 +/// ``` +/// +pub fn sum(numbers: List(Float)) -> Float { + numbers + |> do_sum(0.0) +} + +fn do_sum(numbers: List(Float), initial: Float) -> Float { + case numbers { + [] -> initial + [x, ..rest] -> do_sum(rest, x +. initial) + } +} + +/// Multiplies a list of `Float`s and returns the product. +/// +/// ## Example +/// +/// ```gleam +/// > product([2.5, 3.2, 4.2]) +/// 33.6 +/// ``` +/// +pub fn product(numbers: List(Float)) -> Float { + case numbers { + [] -> 1.0 + _ -> do_product(numbers, 1.0) + } +} + +fn do_product(numbers: List(Float), initial: Float) -> Float { + case numbers { + [] -> initial + [x, ..rest] -> do_product(rest, x *. initial) + } +} + +/// Generates a random float between the given zero (inclusive) and one +/// (exclusive). +/// +/// On Erlang this updates the random state in the process dictionary. +/// See: <https://www.erlang.org/doc/man/rand.html#uniform-0> +/// +/// ## Examples +/// +/// ```gleam +/// > random() +/// 0.646355926896028 +/// ``` +/// +@external(erlang, "rand", "uniform") +@external(javascript, "../gleam_stdlib.mjs", "random_uniform") +pub fn random() -> Float + +/// Returns division of the inputs as a `Result`. +/// +/// ## Examples +/// +/// ```gleam +/// > divide(0.0, 1.0) +/// Ok(1.0) +/// ``` +/// +/// ```gleam +/// > divide(1.0, 0.0) +/// Error(Nil) +/// ``` +/// +pub fn divide(a: Float, by b: Float) -> Result(Float, Nil) { + case b { + 0.0 -> Error(Nil) + b -> Ok(a /. b) + } +} + +/// Adds two floats together. +/// +/// It's the function equivalent of the `+.` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > add(1.0, 2.0) +/// 3.0 +/// ``` +/// +/// ```gleam +/// > import gleam/list +/// > list.fold([1.0, 2.0, 3.0], 0.0, add) +/// 6.0 +/// ``` +/// +/// ```gleam +/// > 3.0 |> add(2.0) +/// 5.0 +/// ``` +/// +pub fn add(a: Float, b: Float) -> Float { + a +. b +} + +/// Multiplies two floats together. +/// +/// It's the function equivalent of the `*.` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > multiply(2.0, 4.0) +/// 8.0 +/// ``` +/// +/// ```gleam +/// import gleam/list +/// > list.fold([2.0, 3.0, 4.0], 1.0, multiply) +/// 24.0 +/// ``` +/// +/// ```gleam +/// > 3.0 |> multiply(2.0) +/// 6.0 +/// ``` +/// +pub fn multiply(a: Float, b: Float) -> Float { + a *. b +} + +/// Subtracts one float from another. +/// +/// It's the function equivalent of the `-.` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > subtract(3.0, 1.0) +/// 2.0 +/// ``` +/// +/// ```gleam +/// > import gleam/list +/// > list.fold([1.0, 2.0, 3.0], 10.0, subtract) +/// 4.0 +/// ``` +/// +/// ```gleam +/// > 3.0 |> subtract(_, 2.0) +/// 1.0 +/// ``` +/// +/// ```gleam +/// > 3.0 |> subtract(2.0, _) +/// -1.0 +/// ``` +/// +pub fn subtract(a: Float, b: Float) -> Float { + a -. b +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/function.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/function.gleam new file mode 100644 index 0000000..daa997d --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/function.gleam @@ -0,0 +1,162 @@ +/// Takes two functions and chains them together to form one function that +/// takes the input from the first and returns the output of the second. +/// +pub fn compose(fun1: fn(a) -> b, fun2: fn(b) -> c) -> fn(a) -> c { + fn(a) { fun2(fun1(a)) } +} + +/// Takes a function with `2` arguments (an arity of `2`), and returns the +/// curried equivalent. +/// +/// `fn(a, b) -> c` becomes `fn(a) -> fn(b) -> c`. +/// +/// ## Examples +/// +/// *Currying* creates a new function that is identical to the given function +/// except that arguments must now be supplied one by one over several function +/// calls. It thus is the process of taking a function with `n` arguments +/// and producing a sequence of `n` single-argument functions. Given: +/// +/// ```gleam +/// > fn my_fun(i: Int, s: String) -> String { ... } +/// ``` +/// +/// …calling `curry2(my_fun)` would return the curried equivalent, like so: +/// +/// ```gleam +/// > curry2(my_fun) +/// fn(Int) -> fn(String) -> String +/// ``` +/// +/// Currying is useful when you want to partially apply a function with +/// some arguments and then pass it somewhere else, for example: +/// +/// ```gleam +/// > import gleam/list +/// > let multiply = curry2(fn(x, y) { x * y }) +/// > let doubles = list.map([1, 2, 3], multiply(2)) +/// [2, 4, 6] +/// ``` +/// +pub fn curry2(fun: fn(a, b) -> value) { + fn(a) { fn(b) { fun(a, b) } } +} + +/// Takes a function with `3` arguments (an arity of `3`), and returns the +/// curried equivalent. +/// +/// `fn(a, b, c) -> d` becomes `fn(a) -> fn(b) -> fn(c) -> d`. +/// +/// See [`curry2`](#curry2) for a detailed explanation. +/// +pub fn curry3(fun: fn(a, b, c) -> value) { + fn(a) { fn(b) { fn(c) { fun(a, b, c) } } } +} + +/// Takes a function with `4` arguments (an arity of `4`), and returns the +/// curried equivalent. +/// +/// `fn(a, b, c, d) -> e` becomes `fn(a) -> fn(b) -> fn(c) -> fn(d) -> e`. +/// +/// See [`curry2`](#curry2) for a detailed explanation. +/// +pub fn curry4(fun: fn(a, b, c, d) -> value) { + fn(a) { fn(b) { fn(c) { fn(d) { fun(a, b, c, d) } } } } +} + +/// Takes a function with `5` arguments (an arity of `5`), and returns the +/// curried equivalent. +/// +/// `fn(a, b, c, d, e) -> f` becomes +/// `fn(a) -> fn(b) -> fn(c) -> fn(d) -> fn(e) -> f`. +/// +/// See [`curry2`](#curry2) for a detailed explanation. +/// +pub fn curry5(fun: fn(a, b, c, d, e) -> value) { + fn(a) { fn(b) { fn(c) { fn(d) { fn(e) { fun(a, b, c, d, e) } } } } } +} + +/// Takes a function with `6` arguments (an arity of `6`), and returns the +/// curried equivalent. +/// +/// `fn(a, b, c, d, e, f) -> g` becomes +/// `fn(a) -> fn(b) -> fn(c) -> fn(d) -> fn(e) -> fn(f) -> g`. +/// +/// See [`curry2`](#curry2) for a detailed explanation. +/// +pub fn curry6(fun: fn(a, b, c, d, e, f) -> value) { + fn(a) { + fn(b) { fn(c) { fn(d) { fn(e) { fn(f) { fun(a, b, c, d, e, f) } } } } } + } +} + +/// Takes a function that takes two arguments and returns a new function that +/// takes the same two arguments, but in reverse order. +/// +pub fn flip(fun: fn(a, b) -> c) -> fn(b, a) -> c { + fn(b, a) { fun(a, b) } +} + +/// Takes a single argument and always returns its input value. +/// +pub fn identity(x: a) -> a { + x +} + +/// Takes a single argument and returns a new function that +/// ignores its argument and always returns the input value. +/// +pub fn constant(value: a) -> fn(b) -> a { + fn(_) { value } +} + +/// Takes an argument and a single function, +/// calls that function with that argument +/// and returns that argument instead of the function return value. +/// Useful for running synchronous side effects in a pipeline. +/// +pub fn tap(arg: a, effect: fn(a) -> b) -> a { + effect(arg) + arg +} + +/// Takes a function with arity one and an argument, +/// calls that function with the argument and returns the function return value. +/// +/// Useful for concisely calling functions returned as a part of a pipeline. +/// +/// ## Example +/// +/// ```gleam +/// > let doubler = fn() { +/// > fn(x: Int) { x * 2 } +/// > } +/// > +/// > doubler() +/// > |> apply1(2) +/// 4 +/// ``` +/// +pub fn apply1(fun: fn(a) -> value, arg1: a) -> value { + fun(arg1) +} + +/// Takes a function with arity two and two arguments, +/// calls that function with the arguments +/// and returns the function return value. +/// +/// See [`apply1`](#apply1) for more details. +/// +pub fn apply2(fun: fn(a, b) -> value, arg1: a, arg2: b) -> value { + fun(arg1, arg2) +} + +/// Takes a function with arity three and three arguments, +/// calls that function with the arguments +/// and returns the function return value. +/// +/// See [`apply1`](#apply1) for more details. +/// +pub fn apply3(fun: fn(a, b, c) -> value, arg1: a, arg2: b, arg3: c) -> value { + fun(arg1, arg2, arg3) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/int.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/int.gleam new file mode 100644 index 0000000..86c77fa --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/int.gleam @@ -0,0 +1,886 @@ +//// Functions for working with integers. +//// +//// ## Division by zero +//// +//// In Erlang division by zero results in a crash, however Gleam does not have +//// partial functions and operators in core so instead division by zero returns +//// zero, a behaviour taken from Pony, Coq, and Lean. +//// +//// This may seem unexpected at first, but it is no less mathematically valid +//// than crashing or returning a special value. Division by zero is undefined +//// in mathematics. + +import gleam/float +import gleam/order.{type Order} + +/// Returns the absolute value of the input. +/// +/// ## Examples +/// +/// ```gleam +/// > absolute_value(-12) +/// 12 +/// ``` +/// +/// ```gleam +/// > absolute_value(10) +/// 10 +/// ``` +/// +pub fn absolute_value(x: Int) -> Int { + case x >= 0 { + True -> x + False -> x * -1 + } +} + +/// Returns the results of the base being raised to the power of the +/// exponent, as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > power(2, -1.0) +/// Ok(0.5) +/// ``` +/// +/// ```gleam +/// > power(2, 2.0) +/// Ok(4.0) +/// ``` +/// +/// ```gleam +/// > power(8, 1.5) +/// Ok(22.627416997969522) +/// ``` +/// +/// ```gleam +/// > 4 |> power(of: 2.0) +/// Ok(16.0) +/// ``` +/// +/// ```gleam +/// > power(-1, 0.5) +/// Error(Nil) +/// ``` +/// +pub fn power(base: Int, of exponent: Float) -> Result(Float, Nil) { + base + |> to_float() + |> float.power(exponent) +} + +/// Returns the square root of the input as a `Float`. +/// +/// ## Examples +/// +/// ```gleam +/// > square_root(4) +/// Ok(2.0) +/// ``` +/// +/// ```gleam +/// > square_root(-16) +/// Error(Nil) +/// ``` +/// +pub fn square_root(x: Int) -> Result(Float, Nil) { + x + |> to_float() + |> float.square_root() +} + +/// Parses a given string as an int if possible. +/// +/// ## Examples +/// +/// ```gleam +/// > parse("2") +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > parse("ABC") +/// Error(Nil) +/// ``` +/// +pub fn parse(string: String) -> Result(Int, Nil) { + do_parse(string) +} + +@external(erlang, "gleam_stdlib", "parse_int") +@external(javascript, "../gleam_stdlib.mjs", "parse_int") +fn do_parse(a: String) -> Result(Int, Nil) + +/// Parses a given string as an int in a given base if possible. +/// Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`. +/// +/// ## Examples +/// +/// ```gleam +/// > base_parse("10", 2) +/// Ok(2) +/// +/// > base_parse("30", 16) +/// Ok(48) +/// +/// > base_parse("1C", 36) +/// Ok(48) +/// +/// > base_parse("48", 1) +/// Error(Nil) +/// +/// > base_parse("48", 37) +/// Error(Nil) +/// ``` +/// +pub fn base_parse(string: String, base: Int) -> Result(Int, Nil) { + case base >= 2 && base <= 36 { + True -> do_base_parse(string, base) + False -> Error(Nil) + } +} + +@external(erlang, "gleam_stdlib", "int_from_base_string") +@external(javascript, "../gleam_stdlib.mjs", "int_from_base_string") +fn do_base_parse(a: String, b: Int) -> Result(Int, Nil) + +/// Prints a given int to a string. +/// +/// ## Examples +/// +/// ```gleam +/// > to_string(2) +/// "2" +/// ``` +/// +pub fn to_string(x: Int) { + do_to_string(x) +} + +@external(erlang, "erlang", "integer_to_binary") +@external(javascript, "../gleam_stdlib.mjs", "to_string") +fn do_to_string(a: Int) -> String + +/// Error value when trying to operate with a base out of the allowed range. +/// +pub type InvalidBase { + InvalidBase +} + +/// Prints a given int to a string using the base number provided. +/// Supports only bases 2 to 36, for values outside of which this function returns an `Error(InvalidBase)`. +/// For common bases (2, 8, 16, 36), use the `to_baseN` functions. +/// +/// ## Examples +/// +/// ```gleam +/// > to_base_string(2, 2) +/// Ok("10") +/// ``` +/// +/// ```gleam +/// > to_base_string(48, 16) +/// Ok("30") +/// ``` +/// +/// ```gleam +/// > to_base_string(48, 36) +/// Ok("1C") +/// ``` +/// +/// ```gleam +/// > to_base_string(48, 1) +/// Error(InvalidBase) +/// ``` +/// +/// ```gleam +/// > to_base_string(48, 37) +/// Error(InvalidBase) +/// ``` +/// +pub fn to_base_string(x: Int, base: Int) -> Result(String, InvalidBase) { + case base >= 2 && base <= 36 { + True -> Ok(do_to_base_string(x, base)) + False -> Error(InvalidBase) + } +} + +@external(erlang, "erlang", "integer_to_binary") +@external(javascript, "../gleam_stdlib.mjs", "int_to_base_string") +fn do_to_base_string(a: Int, b: Int) -> String + +/// Prints a given int to a string using base-2. +/// +/// ## Examples +/// +/// ```gleam +/// > to_base2(2) +/// "10" +/// ``` +/// +pub fn to_base2(x: Int) -> String { + do_to_base_string(x, 2) +} + +/// Prints a given int to a string using base-8. +/// +/// ## Examples +/// +/// ```gleam +/// > to_base8(15) +/// "17" +/// ``` +/// +pub fn to_base8(x: Int) -> String { + do_to_base_string(x, 8) +} + +/// Prints a given int to a string using base-16. +/// +/// ## Examples +/// +/// ```gleam +/// > to_base16(48) +/// "30" +/// ``` +/// +pub fn to_base16(x: Int) -> String { + do_to_base_string(x, 16) +} + +/// Prints a given int to a string using base-36. +/// +/// ## Examples +/// +/// ```gleam +/// > to_base36(48) +/// "1C" +/// ``` +/// +pub fn to_base36(x: Int) -> String { + do_to_base_string(x, 36) +} + +/// Takes an int and returns its value as a float. +/// +/// ## Examples +/// +/// ```gleam +/// > to_float(5) +/// 5.0 +/// ``` +/// +/// ```gleam +/// > to_float(0) +/// 0.0 +/// ``` +/// +/// ```gleam +/// > to_float(-3) +/// -3.0 +/// ``` +/// +pub fn to_float(x: Int) -> Float { + do_to_float(x) +} + +@external(erlang, "erlang", "float") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_to_float(a: Int) -> Float + +/// Restricts an int between a lower and upper bound. +/// +/// ## Examples +/// +/// ```gleam +/// > clamp(40, min: 50, max: 60) +/// 50 +/// ``` +/// +pub fn clamp(x: Int, min min_bound: Int, max max_bound: Int) -> Int { + x + |> min(max_bound) + |> max(min_bound) +} + +/// Compares two ints, returning an order. +/// +/// ## Examples +/// +/// ```gleam +/// > compare(2, 3) +/// Lt +/// ``` +/// +/// ```gleam +/// > compare(4, 3) +/// Gt +/// ``` +/// +/// ```gleam +/// > compare(3, 3) +/// Eq +/// ``` +/// +pub fn compare(a: Int, with b: Int) -> Order { + case a == b { + True -> order.Eq + False -> + case a < b { + True -> order.Lt + False -> order.Gt + } + } +} + +/// Compares two ints, returning the smaller of the two. +/// +/// ## Examples +/// +/// ```gleam +/// > min(2, 3) +/// 2 +/// ``` +/// +pub fn min(a: Int, b: Int) -> Int { + case a < b { + True -> a + False -> b + } +} + +/// Compares two ints, returning the larger of the two. +/// +/// ## Examples +/// +/// ```gleam +/// > max(2, 3) +/// 3 +/// ``` +/// +pub fn max(a: Int, b: Int) -> Int { + case a > b { + True -> a + False -> b + } +} + +/// Returns whether the value provided is even. +/// +/// ## Examples +/// +/// ```gleam +/// > is_even(2) +/// True +/// ``` +/// +/// ```gleam +/// > is_even(3) +/// False +/// ``` +/// +pub fn is_even(x: Int) -> Bool { + x % 2 == 0 +} + +/// Returns whether the value provided is odd. +/// +/// ## Examples +/// +/// ```gleam +/// > is_odd(3) +/// True +/// ``` +/// +/// ```gleam +/// > is_odd(2) +/// False +/// ``` +/// +pub fn is_odd(x: Int) -> Bool { + x % 2 != 0 +} + +/// Returns the negative of the value provided. +/// +/// ## Examples +/// +/// ```gleam +/// > negate(1) +/// -1 +/// ``` +/// +pub fn negate(x: Int) -> Int { + -1 * x +} + +/// Sums a list of ints. +/// +/// ## Example +/// +/// ```gleam +/// > sum([1, 2, 3]) +/// 6 +/// ``` +/// +pub fn sum(numbers: List(Int)) -> Int { + numbers + |> do_sum(0) +} + +fn do_sum(numbers: List(Int), initial: Int) -> Int { + case numbers { + [] -> initial + [x, ..rest] -> do_sum(rest, x + initial) + } +} + +/// Multiplies a list of ints and returns the product. +/// +/// ## Example +/// +/// ```gleam +/// > product([2, 3, 4]) +/// 24 +/// ``` +/// +pub fn product(numbers: List(Int)) -> Int { + case numbers { + [] -> 1 + _ -> do_product(numbers, 1) + } +} + +fn do_product(numbers: List(Int), initial: Int) -> Int { + case numbers { + [] -> initial + [x, ..rest] -> do_product(rest, x * initial) + } +} + +/// Splits an integer into its digit representation in the specified base +/// +/// ## Examples +/// +/// ```gleam +/// > digits(234, 10) +/// Ok([2,3,4]) +/// ``` +/// +/// ```gleam +/// > digits(234, 1) +/// Error(InvalidBase) +/// ``` +/// +pub fn digits(x: Int, base: Int) -> Result(List(Int), InvalidBase) { + case base < 2 { + True -> Error(InvalidBase) + False -> Ok(do_digits(x, base, [])) + } +} + +fn do_digits(x: Int, base: Int, acc: List(Int)) -> List(Int) { + case absolute_value(x) < base { + True -> [x, ..acc] + False -> do_digits(x / base, base, [x % base, ..acc]) + } +} + +/// Joins a list of digits into a single value. +/// Returns an error if the base is less than 2 or if the list contains a digit greater than or equal to the specified base. +/// +/// ## Examples +/// +/// ```gleam +/// > undigits([2,3,4], 10) +/// Ok(234) +/// ``` +/// +/// ```gleam +/// > undigits([2,3,4], 1) +/// Error(InvalidBase) +/// ``` +/// +/// ```gleam +/// > undigits([2,3,4], 2) +/// Error(InvalidBase) +/// ``` +/// +pub fn undigits(numbers: List(Int), base: Int) -> Result(Int, InvalidBase) { + case base < 2 { + True -> Error(InvalidBase) + False -> do_undigits(numbers, base, 0) + } +} + +fn do_undigits( + numbers: List(Int), + base: Int, + acc: Int, +) -> Result(Int, InvalidBase) { + case numbers { + [] -> Ok(acc) + [digit, ..] if digit >= base -> Error(InvalidBase) + [digit, ..rest] -> do_undigits(rest, base, acc * base + digit) + } +} + +/// Generates a random int between zero and the given maximum. +/// +/// The lower number is inclusive, the upper number is exclusive. +/// +/// ## Examples +/// +/// ```gleam +/// > random(10) +/// 4 +/// ``` +/// +/// ```gleam +/// > random(1) +/// 0 +/// ``` +/// +/// ```gleam +/// > random(-1) +/// -1 +/// ``` +/// +pub fn random(max: Int) -> Int { + { float.random() *. to_float(max) } + |> float.floor() + |> float.round() +} + +/// Performs a truncated integer division. +/// +/// Returns division of the inputs as a `Result`: If the given divisor equals +/// `0`, this function returns an `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > divide(0, 1) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > divide(1, 0) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > divide(5, 2) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > divide(-99, 2) +/// Ok(-49) +/// ``` +/// +pub fn divide(dividend: Int, by divisor: Int) -> Result(Int, Nil) { + case divisor { + 0 -> Error(Nil) + divisor -> Ok(dividend / divisor) + } +} + +/// Computes the remainder of an integer division of inputs as a `Result`. +/// +/// Returns division of the inputs as a `Result`: If the given divisor equals +/// `0`, this function returns an `Error`. +/// +/// Most the time you will want to use the `%` operator instead of this +/// function. +/// +/// ## Examples +/// +/// ```gleam +/// > remainder(3, 2) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > remainder(1, 0) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > remainder(10, -1) +/// Ok(0) +/// ``` +/// +/// ```gleam +/// > remainder(13, by: 3) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > remainder(-13, by: 3) +/// Ok(-1) +/// ``` +/// +/// ```gleam +/// > remainder(13, by: -3) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > remainder(-13, by: -3) +/// Ok(-1) +/// ``` +/// +pub fn remainder(dividend: Int, by divisor: Int) -> Result(Int, Nil) { + case divisor { + 0 -> Error(Nil) + divisor -> Ok(dividend % divisor) + } +} + +/// Computes the modulo of an integer division of inputs as a `Result`. +/// +/// Returns division of the inputs as a `Result`: If the given divisor equals +/// `0`, this function returns an `Error`. +/// +/// Most the time you will want to use the `%` operator instead of this +/// function. +/// +/// ## Examples +/// +/// ```gleam +/// > modulo(3, 2) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > modulo(1, 0) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > modulo(10, -1) +/// Ok(0) +/// ``` +/// +/// ```gleam +/// > modulo(13, by: 3) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > modulo(-13, by: 3) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > modulo(13, by: -3) +/// Ok(-2) +/// ``` +/// +/// ```gleam +/// > modulo(-13, by: -3) +/// Ok(-1) +/// ``` +/// +pub fn modulo(dividend: Int, by divisor: Int) -> Result(Int, Nil) { + case divisor { + 0 -> Error(Nil) + _ -> { + let remainder = dividend % divisor + case remainder * divisor < 0 { + True -> Ok(remainder + divisor) + False -> Ok(remainder) + } + } + } +} + +/// Performs a *floored* integer division, which means that the result will +/// always be rounded towards negative infinity. +/// +/// If you want to perform truncated integer division (rounding towards zero), +/// use `int.divide()` or the `/` operator instead. +/// +/// Returns division of the inputs as a `Result`: If the given divisor equals +/// `0`, this function returns an `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > floor_divide(1, 0) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > floor_divide(5, 2) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > floor_divide(6, -4) +/// Ok(-2) +/// ``` +/// +/// ```gleam +/// > floor_divide(-99, 2) +/// Ok(-50) +/// ``` +/// +pub fn floor_divide(dividend: Int, by divisor: Int) -> Result(Int, Nil) { + case divisor { + 0 -> Error(Nil) + divisor -> + case dividend * divisor < 0 && dividend % divisor != 0 { + True -> Ok(dividend / divisor - 1) + False -> Ok(dividend / divisor) + } + } +} + +/// Adds two integers together. +/// +/// It's the function equivalent of the `+` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > add(1, 2) +/// 3 +/// ``` +/// +/// ```gleam +/// import gleam/list +/// > list.fold([1, 2, 3], 0, add) +/// 6 +/// ``` +/// +/// ```gleam +/// > 3 |> add(2) +/// 5 +/// ``` +/// +pub fn add(a: Int, b: Int) -> Int { + a + b +} + +/// Multiplies two integers together. +/// +/// It's the function equivalent of the `*` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > multiply(2, 4) +/// 8 +/// ``` +/// +/// ```gleam +/// import gleam/list +/// > list.fold([2, 3, 4], 1, multiply) +/// 24 +/// ``` +/// +/// ```gleam +/// > 3 |> multiply(2) +/// 6 +/// ``` +/// +pub fn multiply(a: Int, b: Int) -> Int { + a * b +} + +/// Subtracts one int from another. +/// +/// It's the function equivalent of the `-` operator. +/// This function is useful in higher order functions or pipes. +/// +/// ## Examples +/// +/// ```gleam +/// > subtract(3, 1) +/// 2.0 +/// ``` +/// +/// ```gleam +/// import gleam/list +/// > list.fold([1, 2, 3], 10, subtract) +/// 4 +/// ``` +/// +/// ```gleam +/// > 3 |> subtract(2) +/// 1 +/// ``` +/// +/// ```gleam +/// > 3 |> subtract(2, _) +/// -1 +/// ``` +/// +pub fn subtract(a: Int, b: Int) -> Int { + a - b +} + +/// Calculates the bitwise AND of its arguments. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "band") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_and") +pub fn bitwise_and(x: Int, y: Int) -> Int + +/// Calculates the bitwise NOT of its argument. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "bnot") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_not") +pub fn bitwise_not(x: Int) -> Int + +/// Calculates the bitwise OR of its arguments. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "bor") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_or") +pub fn bitwise_or(x: Int, y: Int) -> Int + +/// Calculates the bitwise XOR of its arguments. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "bxor") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_exclusive_or") +pub fn bitwise_exclusive_or(x: Int, y: Int) -> Int + +/// Calculates the result of an arithmetic left bitshift. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "bsl") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_shift_left") +pub fn bitwise_shift_left(x: Int, y: Int) -> Int + +/// Calculates the result of an arithmetic right bitshift. +/// +/// The exact behaviour of this function depends on the target platform. +/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it +/// is equivalent to bitwise operations on big-ints. +/// +@external(erlang, "erlang", "bsr") +@external(javascript, "../gleam_stdlib.mjs", "bitwise_shift_right") +pub fn bitwise_shift_right(x: Int, y: Int) -> Int diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/io.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/io.gleam new file mode 100644 index 0000000..0c0a3ee --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/io.gleam @@ -0,0 +1,117 @@ +import gleam/string + +/// Writes a string to standard output. +/// +/// If you want your output to be printed on its own line see `println`. +/// +/// ## Example +/// +/// ```gleam +/// > io.print("Hi mum") +/// // -> Hi mum +/// Nil +/// ``` +/// +pub fn print(string: String) -> Nil { + do_print(string) +} + +@external(erlang, "gleam_stdlib", "print") +@external(javascript, "../gleam_stdlib.mjs", "print") +fn do_print(string string: String) -> Nil + +/// Writes a string to standard error. +/// +/// If you want your output to be printed on its own line see `println_error`. +/// +/// ## Example +/// +/// ``` +/// > io.print_error("Hi pop") +/// // -> Hi pop +/// Nil +/// ``` +/// +pub fn print_error(string: String) -> Nil { + do_print_error(string) +} + +@external(erlang, "gleam_stdlib", "print_error") +@external(javascript, "../gleam_stdlib.mjs", "print_error") +fn do_print_error(string string: String) -> Nil + +/// Writes a string to standard output, appending a newline to the end. +/// +/// ## Example +/// +/// ```gleam +/// > io.println("Hi mum") +/// // -> Hi mum +/// Nil +/// ``` +/// +pub fn println(string: String) -> Nil { + do_println(string) +} + +@external(erlang, "gleam_stdlib", "println") +@external(javascript, "../gleam_stdlib.mjs", "console_log") +fn do_println(string string: String) -> Nil + +/// Writes a string to standard error, appending a newline to the end. +/// +/// ## Example +/// +/// ```gleam +/// > io.println_error("Hi pop") +/// // -> Hi mum +/// Nil +/// ``` +/// +pub fn println_error(string: String) -> Nil { + do_println_error(string) +} + +@external(erlang, "gleam_stdlib", "println_error") +@external(javascript, "../gleam_stdlib.mjs", "console_error") +fn do_println_error(string string: String) -> Nil + +/// Prints a value to standard error (stderr) yielding Gleam syntax. +/// +/// The value is returned after being printed so it can be used in pipelines. +/// +/// ## Example +/// +/// ```gleam +/// > debug("Hi mum") +/// // -> <<"Hi mum">> +/// "Hi mum" +/// ``` +/// +/// ```gleam +/// > debug(Ok(1)) +/// // -> {ok, 1} +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > import list +/// > [1, 2] +/// > |> list.map(fn(x) { x + 1 }) +/// > |> debug +/// > |> list.map(fn(x) { x * 2 }) +/// // -> [2, 3] +/// [4, 6] +/// ``` +/// +pub fn debug(term: anything) -> anything { + term + |> string.inspect + |> do_debug_println + + term +} + +@external(erlang, "gleam_stdlib", "println_error") +@external(javascript, "../gleam_stdlib.mjs", "print_debug") +fn do_debug_println(string string: String) -> Nil diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/iterator.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/iterator.gleam new file mode 100644 index 0000000..4cbb6f5 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/iterator.gleam @@ -0,0 +1,1524 @@ +import gleam/result +import gleam/int +import gleam/list +import gleam/dict.{type Dict} +import gleam/option.{type Option, None, Some} +import gleam/order + +// Internal private representation of an Iterator +type Action(element) { + // Dedicated to Electric Six + // https://youtu.be/_30t2dzEgiw?t=162 + Stop + Continue(element, fn() -> Action(element)) +} + +/// An iterator is a lazily evaluated sequence of element. +/// +/// Iterators are useful when working with collections that are too large to +/// fit in memory (or those that are infinite in size) as they only require the +/// elements currently being processed to be in memory. +/// +/// As a lazy data structure no work is done when an iterator is filters, +/// mapped, etc, instead a new iterator is returned with these transformations +/// applied to the stream. Once the stream has all the required transformations +/// applied it can be evaluated using functions such as `fold` and `to_list`. +/// +pub opaque type Iterator(element) { + Iterator(continuation: fn() -> Action(element)) +} + +// Public API for iteration +pub type Step(element, accumulator) { + Next(element: element, accumulator: accumulator) + Done +} + +// Shortcut for an empty iterator. +fn stop() -> Action(element) { + Stop +} + +// Creating Iterators +fn do_unfold( + initial: acc, + f: fn(acc) -> Step(element, acc), +) -> fn() -> Action(element) { + fn() { + case f(initial) { + Next(x, acc) -> Continue(x, do_unfold(acc, f)) + Done -> Stop + } + } +} + +/// Creates an iterator from a given function and accumulator. +/// +/// The function is called on the accumulator and returns either `Done`, +/// indicating the iterator has no more elements, or `Next` which contains a +/// new element and accumulator. The element is yielded by the iterator and the +/// new accumulator is used with the function to compute the next element in +/// the sequence. +/// +/// ## Examples +/// +/// ```gleam +/// > unfold(from: 5, with: fn(n) { +/// > case n { +/// > 0 -> Done +/// > n -> Next(element: n, accumulator: n - 1) +/// > } +/// > }) +/// > |> to_list +/// [5, 4, 3, 2, 1] +/// ``` +/// +pub fn unfold( + from initial: acc, + with f: fn(acc) -> Step(element, acc), +) -> Iterator(element) { + initial + |> do_unfold(f) + |> Iterator +} + +// TODO: test +/// Creates an iterator that yields values created by calling a given function +/// repeatedly. +/// +pub fn repeatedly(f: fn() -> element) -> Iterator(element) { + unfold(Nil, fn(_) { Next(f(), Nil) }) +} + +/// Creates an iterator that returns the same value infinitely. +/// +/// ## Examples +/// +/// ```gleam +/// > repeat(10) +/// > |> take(4) +/// > |> to_list +/// [10, 10, 10, 10] +/// ``` +/// +pub fn repeat(x: element) -> Iterator(element) { + repeatedly(fn() { x }) +} + +/// Creates an iterator that yields each element from the given list. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) +/// > |> to_list +/// [1, 2, 3, 4] +/// ``` +/// +pub fn from_list(list: List(element)) -> Iterator(element) { + let yield = fn(acc) { + case acc { + [] -> Done + [head, ..tail] -> Next(head, tail) + } + } + unfold(list, yield) +} + +// Consuming Iterators +fn do_transform( + continuation: fn() -> Action(a), + state: acc, + f: fn(acc, a) -> Step(b, acc), +) -> fn() -> Action(b) { + fn() { + case continuation() { + Stop -> Stop + Continue(el, next) -> + case f(state, el) { + Done -> Stop + Next(yield, next_state) -> + Continue(yield, do_transform(next, next_state, f)) + } + } + } +} + +/// Creates an iterator from an existing iterator +/// and a stateful function that may short-circuit. +/// +/// `f` takes arguments `acc` for current state and `el` for current element from underlying iterator, +/// and returns either `Next` with yielded element and new state value, or `Done` to halt the iterator. +/// +/// ## Examples +/// +/// Approximate implementation of `index` in terms of `transform`: +/// +/// ```gleam +/// > from_list(["a", "b", "c"]) +/// > |> transform(0, fn(i, el) { Next(#(i, el), i + 1) }) +/// > |> to_list +/// [#(0, "a"), #(1, "b"), #(2, "c")] +/// ``` +pub fn transform( + over iterator: Iterator(a), + from initial: acc, + with f: fn(acc, a) -> Step(b, acc), +) -> Iterator(b) { + do_transform(iterator.continuation, initial, f) + |> Iterator +} + +fn do_fold( + continuation: fn() -> Action(e), + f: fn(acc, e) -> acc, + accumulator: acc, +) -> acc { + case continuation() { + Continue(elem, next) -> do_fold(next, f, f(accumulator, elem)) + Stop -> accumulator + } +} + +/// Reduces an iterator of elements into a single value by calling a given +/// function on each element in turn. +/// +/// If called on an iterator of infinite length then this function will never +/// return. +/// +/// If you do not care about the end value and only wish to evaluate the +/// iterator for side effects consider using the `run` function instead. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4] +/// > |> from_list +/// > |> fold(from: 0, with: fn(acc, element) { element + acc }) +/// 10 +/// ``` +/// +pub fn fold( + over iterator: Iterator(e), + from initial: acc, + with f: fn(acc, e) -> acc, +) -> acc { + iterator.continuation + |> do_fold(f, initial) +} + +// TODO: test +/// Evaluates all elements emitted by the given iterator. This function is useful for when +/// you wish to trigger any side effects that would occur when evaluating +/// the iterator. +/// +pub fn run(iterator: Iterator(e)) -> Nil { + fold(iterator, Nil, fn(_, _) { Nil }) +} + +/// Evaluates an iterator and returns all the elements as a list. +/// +/// If called on an iterator of infinite length then this function will never +/// return. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3] +/// > |> from_list +/// > |> map(fn(x) { x * 2 }) +/// > |> to_list +/// [2, 4, 6] +/// ``` +/// +pub fn to_list(iterator: Iterator(element)) -> List(element) { + iterator + |> fold([], fn(acc, e) { [e, ..acc] }) + |> list.reverse +} + +/// Eagerly accesses the first value of an iterator, returning a `Next` +/// that contains the first value and the rest of the iterator. +/// +/// If called on an empty iterator, `Done` is returned. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Next(first, rest) = [1, 2, 3, 4] +/// > |> from_list +/// > |> step +/// > first +/// 1 +/// ``` +/// +/// ```gleam +/// > rest |> to_list +/// [2, 3, 4] +/// ``` +/// +/// ```gleam +/// > empty() |> step +/// Done +/// ``` +/// +pub fn step(iterator: Iterator(e)) -> Step(e, Iterator(e)) { + case iterator.continuation() { + Stop -> Done + Continue(e, a) -> Next(e, Iterator(a)) + } +} + +fn do_take(continuation: fn() -> Action(e), desired: Int) -> fn() -> Action(e) { + fn() { + case desired > 0 { + False -> Stop + True -> + case continuation() { + Stop -> Stop + Continue(e, next) -> Continue(e, do_take(next, desired - 1)) + } + } + } +} + +/// Creates an iterator that only yields the first `desired` elements. +/// +/// If the iterator does not have enough elements all of them are yielded. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4, 5] +/// > |> from_list +/// > |> take(up_to: 3) +/// > |> to_list +/// [1, 2, 3] +/// ``` +/// +/// ```gleam +/// > [1, 2] +/// > |> from_list +/// > |> take(up_to: 3) +/// > |> to_list +/// [1, 2] +/// ``` +/// +pub fn take(from iterator: Iterator(e), up_to desired: Int) -> Iterator(e) { + iterator.continuation + |> do_take(desired) + |> Iterator +} + +fn do_drop(continuation: fn() -> Action(e), desired: Int) -> Action(e) { + case continuation() { + Stop -> Stop + Continue(e, next) -> + case desired > 0 { + True -> do_drop(next, desired - 1) + False -> Continue(e, next) + } + } +} + +/// Evaluates and discards the first N elements in an iterator, returning a new +/// iterator. +/// +/// If the iterator does not have enough elements an empty iterator is +/// returned. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4, 5] +/// > |> from_list +/// > |> drop(up_to: 3) +/// > |> to_list +/// [4, 5] +/// ``` +/// +/// ```gleam +/// > [1, 2] +/// > |> from_list +/// > |> drop(up_to: 3) +/// > |> to_list +/// [] +/// ``` +/// +pub fn drop(from iterator: Iterator(e), up_to desired: Int) -> Iterator(e) { + fn() { do_drop(iterator.continuation, desired) } + |> Iterator +} + +fn do_map(continuation: fn() -> Action(a), f: fn(a) -> b) -> fn() -> Action(b) { + fn() { + case continuation() { + Stop -> Stop + Continue(e, continuation) -> Continue(f(e), do_map(continuation, f)) + } + } +} + +/// Creates an iterator from an existing iterator and a transformation function. +/// +/// Each element in the new iterator will be the result of calling the given +/// function on the elements in the given iterator. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3] +/// > |> from_list +/// > |> map(fn(x) { x * 2 }) +/// > |> to_list +/// [2, 4, 6] +/// ``` +/// +pub fn map(over iterator: Iterator(a), with f: fn(a) -> b) -> Iterator(b) { + iterator.continuation + |> do_map(f) + |> Iterator +} + +fn do_map2( + continuation1: fn() -> Action(a), + continuation2: fn() -> Action(b), + with fun: fn(a, b) -> c, +) -> fn() -> Action(c) { + fn() { + case continuation1() { + Stop -> Stop + Continue(a, next_a) -> + case continuation2() { + Stop -> Stop + Continue(b, next_b) -> + Continue(fun(a, b), do_map2(next_a, next_b, fun)) + } + } + } +} + +/// Combines two interators into a single one using the given function. +/// +/// If an iterator is longer than the other the extra elements are dropped. +/// +/// This function does not evaluate the elements of the two iterators, the +/// computation is performed when the resulting iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// let first = from_list([1, 2, 3]) +/// let second = from_list([4, 5, 6]) +/// map2(first, second, fn(x, y) { x + y }) |> to_list +/// // -> [5, 7, 9] +/// ``` +/// +/// ```gleam +/// let first = from_list([1, 2]) +/// let second = from_list(["a", "b", "c"]) +/// map2(first, second, fn(i, x) { #(i, x) }) |> to_list +/// // -> [#(1, "a"), #(2, "b")] +/// ``` +/// +pub fn map2( + iterator1: Iterator(a), + iterator2: Iterator(b), + with fun: fn(a, b) -> c, +) -> Iterator(c) { + do_map2(iterator1.continuation, iterator2.continuation, fun) + |> Iterator +} + +fn do_append(first: fn() -> Action(a), second: fn() -> Action(a)) -> Action(a) { + case first() { + Continue(e, first) -> Continue(e, fn() { do_append(first, second) }) + Stop -> second() + } +} + +/// Appends two iterators, producing a new iterator. +/// +/// This function does not evaluate the elements of the iterators, the +/// computation is performed when the resulting iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2] +/// > |> from_list +/// > |> append([3, 4] |> from_list) +/// > |> to_list +/// [1, 2, 3, 4] +/// ``` +/// +pub fn append(to first: Iterator(a), suffix second: Iterator(a)) -> Iterator(a) { + fn() { do_append(first.continuation, second.continuation) } + |> Iterator +} + +fn do_flatten(flattened: fn() -> Action(Iterator(a))) -> Action(a) { + case flattened() { + Stop -> Stop + Continue(it, next_iterator) -> + do_append(it.continuation, fn() { do_flatten(next_iterator) }) + } +} + +/// Flattens an iterator of iterators, creating a new iterator. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([[1, 2], [3, 4]]) +/// > |> map(from_list) +/// > |> flatten +/// > |> to_list +/// [1, 2, 3, 4] +/// ``` +/// +pub fn flatten(iterator: Iterator(Iterator(a))) -> Iterator(a) { + fn() { do_flatten(iterator.continuation) } + |> Iterator +} + +/// Joins a list of iterators into a single iterator. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > [[1, 2], [3, 4]] +/// > |> map(from_list) +/// > |> concat +/// > |> to_list +/// [1, 2, 3, 4] +/// ``` +/// +pub fn concat(iterators: List(Iterator(a))) -> Iterator(a) { + flatten(from_list(iterators)) +} + +/// Creates an iterator from an existing iterator and a transformation function. +/// +/// Each element in the new iterator will be the result of calling the given +/// function on the elements in the given iterator and then flattening the +/// results. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2] +/// > |> from_list +/// > |> flat_map(fn(x) { from_list([x, x + 1]) }) +/// > |> to_list +/// [1, 2, 2, 3] +/// ``` +/// +pub fn flat_map( + over iterator: Iterator(a), + with f: fn(a) -> Iterator(b), +) -> Iterator(b) { + iterator + |> map(f) + |> flatten +} + +fn do_filter( + continuation: fn() -> Action(e), + predicate: fn(e) -> Bool, +) -> Action(e) { + case continuation() { + Stop -> Stop + Continue(e, iterator) -> + case predicate(e) { + True -> Continue(e, fn() { do_filter(iterator, predicate) }) + False -> do_filter(iterator, predicate) + } + } +} + +/// Creates an iterator from an existing iterator and a predicate function. +/// +/// The new iterator will contain elements from the first iterator for which +/// the given function returns `True`. +/// +/// This function does not evaluate the elements of the iterator, the +/// computation is performed when the iterator is later run. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/int +/// > [1, 2, 3, 4] +/// > |> from_list +/// > |> filter(int.is_even) +/// > |> to_list +/// [2, 4] +/// ``` +/// +pub fn filter( + iterator: Iterator(a), + keeping predicate: fn(a) -> Bool, +) -> Iterator(a) { + fn() { do_filter(iterator.continuation, predicate) } + |> Iterator +} + +/// Creates an iterator that repeats a given iterator infinitely. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2] +/// > |> from_list +/// > |> cycle +/// > |> take(6) +/// > |> to_list +/// [1, 2, 1, 2, 1, 2] +/// ``` +/// +pub fn cycle(iterator: Iterator(a)) -> Iterator(a) { + repeat(iterator) + |> flatten +} + +/// Creates an iterator of ints, starting at a given start int and stepping by +/// one to a given end int. +/// +/// ## Examples +/// +/// ```gleam +/// > range(from: 1, to: 5) |> to_list +/// [1, 2, 3, 4, 5] +/// ``` +/// +/// ```gleam +/// > range(from: 1, to: -2) |> to_list +/// [1, 0, -1, -2] +/// ``` +/// +/// ```gleam +/// > range(from: 0, to: 0) |> to_list +/// [0] +/// ``` +/// +pub fn range(from start: Int, to stop: Int) -> Iterator(Int) { + case int.compare(start, stop) { + order.Eq -> once(fn() { start }) + order.Gt -> + unfold(from: start, with: fn(current) { + case current < stop { + False -> Next(current, current - 1) + True -> Done + } + }) + + order.Lt -> + unfold(from: start, with: fn(current) { + case current > stop { + False -> Next(current, current + 1) + True -> Done + } + }) + } +} + +fn do_find(continuation: fn() -> Action(a), f: fn(a) -> Bool) -> Result(a, Nil) { + case continuation() { + Stop -> Error(Nil) + Continue(e, next) -> + case f(e) { + True -> Ok(e) + False -> do_find(next, f) + } + } +} + +/// Finds the first element in a given iterator for which the given function returns +/// `True`. +/// +/// Returns `Error(Nil)` if the function does not return `True` for any of the +/// elements. +/// +/// ## Examples +/// +/// ```gleam +/// > find(from_list([1, 2, 3]), fn(x) { x > 2 }) +/// Ok(3) +/// ``` +/// +/// ```gleam +/// > find(from_list([1, 2, 3]), fn(x) { x > 4 }) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > find(empty(), fn(_) { True }) +/// Error(Nil) +/// ``` +/// +pub fn find( + in haystack: Iterator(a), + one_that is_desired: fn(a) -> Bool, +) -> Result(a, Nil) { + haystack.continuation + |> do_find(is_desired) +} + +fn do_index( + continuation: fn() -> Action(element), + next: Int, +) -> fn() -> Action(#(element, Int)) { + fn() { + case continuation() { + Stop -> Stop + Continue(e, continuation) -> + Continue(#(e, next), do_index(continuation, next + 1)) + } + } +} + +/// Wraps values yielded from an iterator with indices, starting from 0. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list(["a", "b", "c"]) |> index |> to_list +/// [#("a", 0), #("b", 1), #("c", 2)] +/// ``` +/// +pub fn index(over iterator: Iterator(element)) -> Iterator(#(element, Int)) { + iterator.continuation + |> do_index(0) + |> Iterator +} + +/// Creates an iterator that inifinitely applies a function to a value. +/// +/// ## Examples +/// +/// ```gleam +/// > iterate(1, fn(n) { n * 3 }) |> take(5) |> to_list +/// [1, 3, 9, 27, 81] +/// ``` +/// +pub fn iterate( + from initial: element, + with f: fn(element) -> element, +) -> Iterator(element) { + unfold(initial, fn(element) { Next(element, f(element)) }) +} + +fn do_take_while( + continuation: fn() -> Action(element), + predicate: fn(element) -> Bool, +) -> fn() -> Action(element) { + fn() { + case continuation() { + Stop -> Stop + Continue(e, next) -> + case predicate(e) { + False -> Stop + True -> Continue(e, do_take_while(next, predicate)) + } + } + } +} + +/// Creates an iterator that yields elements while the predicate returns `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 2, 4]) +/// > |> take_while(satisfying: fn(x) { x < 3 }) +/// > |> to_list +/// [1, 2] +/// ``` +/// +pub fn take_while( + in iterator: Iterator(element), + satisfying predicate: fn(element) -> Bool, +) -> Iterator(element) { + iterator.continuation + |> do_take_while(predicate) + |> Iterator +} + +fn do_drop_while( + continuation: fn() -> Action(element), + predicate: fn(element) -> Bool, +) -> Action(element) { + case continuation() { + Stop -> Stop + Continue(e, next) -> + case predicate(e) { + False -> Continue(e, next) + True -> do_drop_while(next, predicate) + } + } +} + +/// Creates an iterator that drops elements while the predicate returns `True`, +/// and then yields the remaining elements. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4, 2, 5]) +/// > |> drop_while(satisfying: fn(x) { x < 4 }) +/// > |> to_list +/// [4, 2, 5] +/// ``` +/// +pub fn drop_while( + in iterator: Iterator(element), + satisfying predicate: fn(element) -> Bool, +) -> Iterator(element) { + fn() { do_drop_while(iterator.continuation, predicate) } + |> Iterator +} + +fn do_scan( + continuation: fn() -> Action(element), + f: fn(acc, element) -> acc, + accumulator: acc, +) -> fn() -> Action(acc) { + fn() { + case continuation() { + Stop -> Stop + Continue(el, next) -> { + let accumulated = f(accumulator, el) + Continue(accumulated, do_scan(next, f, accumulated)) + } + } + } +} + +/// Creates an iterator from an existing iterator and a stateful function. +/// +/// Specifically, this behaves like `fold`, but yields intermediate results. +/// +/// ## Examples +/// +/// ```gleam +/// // Generate a sequence of partial sums +/// > from_list([1, 2, 3, 4, 5]) +/// > |> scan(from: 0, with: fn(acc, el) { acc + el }) +/// > |> to_list +/// [1, 3, 6, 10, 15] +/// ``` +/// +pub fn scan( + over iterator: Iterator(element), + from initial: acc, + with f: fn(acc, element) -> acc, +) -> Iterator(acc) { + iterator.continuation + |> do_scan(f, initial) + |> Iterator +} + +fn do_zip( + left: fn() -> Action(a), + right: fn() -> Action(b), +) -> fn() -> Action(#(a, b)) { + fn() { + case left() { + Stop -> Stop + Continue(el_left, next_left) -> + case right() { + Stop -> Stop + Continue(el_right, next_right) -> + Continue(#(el_left, el_right), do_zip(next_left, next_right)) + } + } + } +} + +/// Zips two iterators together, emitting values from both +/// until the shorter one runs out. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list(["a", "b", "c"]) +/// > |> zip(range(20, 30)) +/// > |> to_list +/// [#("a", 20), #("b", 21), #("c", 22)] +/// ``` +/// +pub fn zip(left: Iterator(a), right: Iterator(b)) -> Iterator(#(a, b)) { + do_zip(left.continuation, right.continuation) + |> Iterator +} + +// Result of collecting a single chunk by key +type Chunk(element, key) { + AnotherBy(List(element), key, element, fn() -> Action(element)) + LastBy(List(element)) +} + +fn next_chunk( + continuation: fn() -> Action(element), + f: fn(element) -> key, + previous_key: key, + current_chunk: List(element), +) -> Chunk(element, key) { + case continuation() { + Stop -> LastBy(list.reverse(current_chunk)) + Continue(e, next) -> { + let key = f(e) + case key == previous_key { + True -> next_chunk(next, f, key, [e, ..current_chunk]) + False -> AnotherBy(list.reverse(current_chunk), key, e, next) + } + } + } +} + +fn do_chunk( + continuation: fn() -> Action(element), + f: fn(element) -> key, + previous_key: key, + previous_element: element, +) -> Action(List(element)) { + case next_chunk(continuation, f, previous_key, [previous_element]) { + LastBy(chunk) -> Continue(chunk, stop) + AnotherBy(chunk, key, el, next) -> + Continue(chunk, fn() { do_chunk(next, f, key, el) }) + } +} + +/// Creates an iterator that emits chunks of elements +/// for which `f` returns the same value. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 2, 3, 4, 4, 6, 7, 7]) +/// > |> chunk(by: fn(n) { n % 2 }) +/// > |> to_list +/// [[1], [2, 2], [3], [4, 4, 6], [7, 7]] +/// ``` +/// +pub fn chunk( + over iterator: Iterator(element), + by f: fn(element) -> key, +) -> Iterator(List(element)) { + fn() { + case iterator.continuation() { + Stop -> Stop + Continue(e, next) -> do_chunk(next, f, f(e), e) + } + } + |> Iterator +} + +// Result of collecting a single sized chunk +type SizedChunk(element) { + Another(List(element), fn() -> Action(element)) + Last(List(element)) + NoMore +} + +fn next_sized_chunk( + continuation: fn() -> Action(element), + left: Int, + current_chunk: List(element), +) -> SizedChunk(element) { + case continuation() { + Stop -> + case current_chunk { + [] -> NoMore + remaining -> Last(list.reverse(remaining)) + } + Continue(e, next) -> { + let chunk = [e, ..current_chunk] + case left > 1 { + False -> Another(list.reverse(chunk), next) + True -> next_sized_chunk(next, left - 1, chunk) + } + } + } +} + +fn do_sized_chunk( + continuation: fn() -> Action(element), + count: Int, +) -> fn() -> Action(List(element)) { + fn() { + case next_sized_chunk(continuation, count, []) { + NoMore -> Stop + Last(chunk) -> Continue(chunk, stop) + Another(chunk, next_element) -> + Continue(chunk, do_sized_chunk(next_element, count)) + } + } +} + +/// Creates an iterator that emits chunks of given size. +/// +/// If the last chunk does not have `count` elements, it is yielded +/// as a partial chunk, with less than `count` elements. +/// +/// For any `count` less than 1 this function behaves as if it was set to 1. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4, 5, 6]) +/// > |> sized_chunk(into: 2) +/// > |> to_list +/// [[1, 2], [3, 4], [5, 6]] +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 3, 4, 5, 6, 7, 8]) +/// > |> sized_chunk(into: 3) +/// > |> to_list +/// [[1, 2, 3], [4, 5, 6], [7, 8]] +/// ``` +/// +pub fn sized_chunk( + over iterator: Iterator(element), + into count: Int, +) -> Iterator(List(element)) { + iterator.continuation + |> do_sized_chunk(count) + |> Iterator +} + +fn do_intersperse( + continuation: fn() -> Action(element), + separator: element, +) -> Action(element) { + case continuation() { + Stop -> Stop + Continue(e, next) -> { + let next_interspersed = fn() { do_intersperse(next, separator) } + Continue(separator, fn() { Continue(e, next_interspersed) }) + } + } +} + +/// Creates an iterator that yields the given `elem` element +/// between elements emitted by the underlying iterator. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() +/// > |> intersperse(with: 0) +/// > |> to_list +/// [] +/// +/// > from_list([1]) +/// > |> intersperse(with: 0) +/// > |> to_list +/// [1] +/// +/// > from_list([1, 2, 3, 4, 5]) +/// > |> intersperse(with: 0) +/// > |> to_list +/// [1, 0, 2, 0, 3, 0, 4, 0, 5] +/// ``` +/// +pub fn intersperse( + over iterator: Iterator(element), + with elem: element, +) -> Iterator(element) { + fn() { + case iterator.continuation() { + Stop -> Stop + Continue(e, next) -> Continue(e, fn() { do_intersperse(next, elem) }) + } + } + |> Iterator +} + +fn do_any( + continuation: fn() -> Action(element), + predicate: fn(element) -> Bool, +) -> Bool { + case continuation() { + Stop -> False + Continue(e, next) -> + case predicate(e) { + True -> True + False -> do_any(next, predicate) + } + } +} + +/// Returns `True` if any element emitted by the iterator satisfies the given predicate, +/// `False` otherwise. +/// +/// This function short-circuits once it finds a satisfying element. +/// +/// An empty iterator results in `False`. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> any(fn(n) { n % 2 == 0 }) +/// False +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 5, 7, 9]) |> any(fn(n) { n % 2 == 0 }) +/// True +/// ``` +/// +/// ```gleam +/// > from_list([1, 3, 5, 7, 9]) |> any(fn(n) { n % 2 == 0 }) +/// False +/// ``` +/// +pub fn any( + in iterator: Iterator(element), + satisfying predicate: fn(element) -> Bool, +) -> Bool { + iterator.continuation + |> do_any(predicate) +} + +fn do_all( + continuation: fn() -> Action(element), + predicate: fn(element) -> Bool, +) -> Bool { + case continuation() { + Stop -> True + Continue(e, next) -> + case predicate(e) { + True -> do_all(next, predicate) + False -> False + } + } +} + +/// Returns `True` if all elements emitted by the iterator satisfy the given predicate, +/// `False` otherwise. +/// +/// This function short-circuits once it finds a non-satisfying element. +/// +/// An empty iterator results in `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> all(fn(n) { n % 2 == 0 }) +/// True +/// ``` +/// +/// ```gleam +/// > from_list([2, 4, 6, 8]) |> all(fn(n) { n % 2 == 0 }) +/// True +/// ``` +/// +/// ```gleam +/// > from_list([2, 4, 5, 8]) |> all(fn(n) { n % 2 == 0 }) +/// False +/// ``` +/// +pub fn all( + in iterator: Iterator(element), + satisfying predicate: fn(element) -> Bool, +) -> Bool { + iterator.continuation + |> do_all(predicate) +} + +fn update_group_with(el: element) -> fn(Option(List(element))) -> List(element) { + fn(maybe_group) { + case maybe_group { + Some(group) -> [el, ..group] + None -> [el] + } + } +} + +fn group_updater( + f: fn(element) -> key, +) -> fn(Dict(key, List(element)), element) -> Dict(key, List(element)) { + fn(groups, elem) { + groups + |> dict.update(f(elem), update_group_with(elem)) + } +} + +/// Returns a `Dict(k, List(element))` of elements from the given iterator +/// grouped with the given key function. +/// +/// The order within each group is preserved from the iterator. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4, 5, 6]) |> group(by: fn(n) { n % 3 }) +/// dict.from_list([#(0, [3, 6]), #(1, [1, 4]), #(2, [2, 5])]) +/// ``` +/// +pub fn group( + in iterator: Iterator(element), + by key: fn(element) -> key, +) -> Dict(key, List(element)) { + iterator + |> fold(dict.new(), group_updater(key)) + |> dict.map_values(fn(_, group) { list.reverse(group) }) +} + +/// This function acts similar to fold, but does not take an initial state. +/// Instead, it starts from the first yielded element +/// and combines it with each subsequent element in turn using the given function. +/// The function is called as `f(accumulator, current_element)`. +/// +/// Returns `Ok` to indicate a successful run, and `Error` if called on an empty iterator. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([]) |> reduce(fn(acc, x) { acc + x }) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 3, 4, 5]) |> reduce(fn(acc, x) { acc + x }) +/// Ok(15) +/// ``` +/// +pub fn reduce( + over iterator: Iterator(e), + with f: fn(e, e) -> e, +) -> Result(e, Nil) { + case iterator.continuation() { + Stop -> Error(Nil) + Continue(e, next) -> + do_fold(next, f, e) + |> Ok + } +} + +/// Returns the last element in the given iterator. +/// +/// Returns `Error(Nil)` if the iterator is empty. +/// +/// This function runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> last +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > range(1, 10) |> last +/// Ok(9) +/// ``` +/// +pub fn last(iterator: Iterator(element)) -> Result(element, Nil) { + iterator + |> reduce(fn(_, elem) { elem }) +} + +/// Creates an iterator that yields no elements. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> to_list +/// [] +/// ``` +/// +pub fn empty() -> Iterator(element) { + Iterator(stop) +} + +/// Creates an iterator that yields exactly one element provided by calling the given function. +/// +/// ## Examples +/// +/// ```gleam +/// > once(fn() { 1 }) |> to_list +/// [1] +/// ``` +/// +pub fn once(f: fn() -> element) -> Iterator(element) { + fn() { Continue(f(), stop) } + |> Iterator +} + +/// Creates an iterator that yields the given element exactly once. +/// +/// ## Examples +/// +/// ```gleam +/// > single(1) |> to_list +/// [1] +/// ``` +/// +pub fn single(elem: element) -> Iterator(element) { + once(fn() { elem }) +} + +fn do_interleave( + current: fn() -> Action(element), + next: fn() -> Action(element), +) -> Action(element) { + case current() { + Stop -> next() + Continue(e, next_other) -> + Continue(e, fn() { do_interleave(next, next_other) }) + } +} + +/// Creates an iterator that alternates between the two given iterators +/// until both have run out. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) |> interleave(from_list([11, 12, 13, 14])) |> to_list +/// [1, 11, 2, 12, 3, 13, 4, 14] +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) |> interleave(from_list([100])) |> to_list +/// [1, 100, 2, 3, 4] +/// ``` +/// +pub fn interleave( + left: Iterator(element), + with right: Iterator(element), +) -> Iterator(element) { + fn() { do_interleave(left.continuation, right.continuation) } + |> Iterator +} + +fn do_fold_until( + continuation: fn() -> Action(e), + f: fn(acc, e) -> list.ContinueOrStop(acc), + accumulator: acc, +) -> acc { + case continuation() { + Stop -> accumulator + Continue(elem, next) -> + case f(accumulator, elem) { + list.Continue(accumulator) -> do_fold_until(next, f, accumulator) + list.Stop(accumulator) -> accumulator + } + } +} + +/// Like `fold`, `fold_until` reduces an iterator of elements into a single value by calling a given +/// function on each element in turn, but uses `list.ContinueOrStop` to determine +/// whether or not to keep iterating. +/// +/// If called on an iterator of infinite length then this function will only ever +/// return if the function returns `list.Stop`. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/list +/// > let f = fn(acc, e) { +/// > case e { +/// > _ if e < 4 -> list.Continue(e + acc) +/// > _ -> list.Stop(acc) +/// > } +/// > } +/// > +/// > [1, 2, 3, 4] +/// > |> from_list +/// > |> fold_until(from: acc, with: f) +/// 6 +/// ``` +/// +pub fn fold_until( + over iterator: Iterator(e), + from initial: acc, + with f: fn(acc, e) -> list.ContinueOrStop(acc), +) -> acc { + iterator.continuation + |> do_fold_until(f, initial) +} + +fn do_try_fold( + over continuation: fn() -> Action(a), + with f: fn(acc, a) -> Result(acc, err), + from accumulator: acc, +) -> Result(acc, err) { + case continuation() { + Stop -> Ok(accumulator) + Continue(elem, next) -> { + use accumulator <- result.try(f(accumulator, elem)) + do_try_fold(next, f, accumulator) + } + } +} + +/// A variant of fold that might fail. +/// +/// The folding function should return `Result(accumulator, error)`. +/// If the returned value is `Ok(accumulator)` try_fold will try the next value in the iterator. +/// If the returned value is `Error(error)` try_fold will stop and return that error. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4] +/// > |> iterator.from_list() +/// > |> try_fold(0, fn(acc, i) { +/// > case i < 3 { +/// > True -> Ok(acc + i) +/// > False -> Error(Nil) +/// > } +/// > }) +/// Error(Nil) +/// ``` +/// +pub fn try_fold( + over iterator: Iterator(e), + from initial: acc, + with f: fn(acc, e) -> Result(acc, err), +) -> Result(acc, err) { + iterator.continuation + |> do_try_fold(f, initial) +} + +/// Returns the first element yielded by the given iterator, if it exists, +/// or `Error(Nil)` otherwise. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3]) |> first +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > empty() |> first +/// Error(Nil) +/// ``` +pub fn first(from iterator: Iterator(e)) -> Result(e, Nil) { + case iterator.continuation() { + Stop -> Error(Nil) + Continue(e, _) -> Ok(e) + } +} + +/// Returns nth element yielded by the given iterator, where `0` means the first element. +/// +/// If there are not enough elements in the iterator, `Error(Nil)` is returned. +/// +/// For any `index` less than `0` this function behaves as if it was set to `0`. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) |> at(2) +/// Ok(3) +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) |> at(4) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > empty() |> at(0) +/// Error(Nil) +/// ``` +/// +pub fn at(in iterator: Iterator(e), get index: Int) -> Result(e, Nil) { + iterator + |> drop(index) + |> first +} + +fn do_length(over continuation: fn() -> Action(e), with length: Int) -> Int { + case continuation() { + Stop -> length + Continue(_, next) -> do_length(next, length + 1) + } +} + +/// Counts the number of elements in the given iterator. +/// +/// This function has to traverse the entire iterator to count its elements, +/// so it runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> length +/// 0 +/// ``` +/// +/// ```gleam +/// > from_list([1, 2, 3, 4]) |> length +/// 4 +/// ``` +/// +pub fn length(over iterator: Iterator(e)) -> Int { + iterator.continuation + |> do_length(0) +} + +/// Traverse an iterator, calling a function on each element. +/// +/// ## Examples +/// +/// ```gleam +/// > empty() |> each(io.println) +/// Nil +/// ``` +/// +/// ```gleam +/// > from_list(["Tom", "Malory", "Louis"]) |> each(io.println) +/// // -> Tom +/// // -> Malory +/// // -> Louis +/// Nil +/// ``` +/// +pub fn each(over iterator: Iterator(a), with f: fn(a) -> b) -> Nil { + iterator + |> map(f) + |> run +} + +/// Add a new element to the start of an iterator. +/// +/// This function is for use with `use` expressions, to replicate the behaviour +/// of the `yield` keyword found in other languages. +/// +/// ## Examples +/// +/// ```gleam +/// > use <- iterator.yield(1) +/// > use <- iterator.yield(2) +/// > use <- iterator.yield(3) +/// > iterator.empty() +/// iterator.from_list([1, 2, 3]) +/// ``` +/// +pub fn yield(element: a, next: fn() -> Iterator(a)) -> Iterator(a) { + Iterator(fn() { Continue(element, next().continuation) }) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/list.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/list.gleam new file mode 100644 index 0000000..c58ce8c --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/list.gleam @@ -0,0 +1,2134 @@ +//// Lists are an ordered sequence of elements and are one of the most common +//// data types in Gleam. +//// +//// New elements can be added and removed from the front of a list in +//// constant time, while adding and removing from the end requires traversing +//// the copying the whole list, so keep this in mind when designing your +//// programs. +//// +//// There is a dedicated syntax for prefixing to a list: +//// +//// ```gleam +//// let new_list = [1, 2, ..existing_list] +//// ``` +//// +//// And a matching syntax for getting the first elements of a list: +//// +//// ```gleam +//// case list { +//// [first_element, ..rest] -> first_element +//// _ -> "this pattern matches when the list is empty" +//// } +//// ``` +//// + +import gleam/int +import gleam/float +import gleam/order.{type Order} +import gleam/pair +import gleam/dict.{type Dict} + +/// An error value returned by the `strict_zip` function. +/// +pub type LengthMismatch { + LengthMismatch +} + +/// Counts the number of elements in a given list. +/// +/// This function has to traverse the list to determine the number of elements, +/// so it runs in linear time. +/// +/// This function is natively implemented by the virtual machine and is highly +/// optimised. +/// +/// ## Examples +/// +/// ```gleam +/// > length([]) +/// 0 +/// ``` +/// +/// ```gleam +/// > length([1]) +/// 1 +/// ``` +/// +/// ```gleam +/// > length([1, 2]) +/// 2 +/// ``` +/// +pub fn length(of list: List(a)) -> Int { + do_length(list) +} + +@target(erlang) +@external(erlang, "erlang", "length") +fn do_length(a: List(a)) -> Int + +@target(javascript) +fn do_length(list: List(a)) -> Int { + do_length_acc(list, 0) +} + +@target(javascript) +fn do_length_acc(list: List(a), count: Int) -> Int { + case list { + [_, ..list] -> do_length_acc(list, count + 1) + _ -> count + } +} + +/// Creates a new list from a given list containing the same elements but in the +/// opposite order. +/// +/// This function has to traverse the list to create the new reversed list, so +/// it runs in linear time. +/// +/// This function is natively implemented by the virtual machine and is highly +/// optimised. +/// +/// ## Examples +/// +/// ```gleam +/// > reverse([]) +/// [] +/// ``` +/// +/// ```gleam +/// > reverse([1]) +/// [1] +/// ``` +/// +/// ```gleam +/// > reverse([1, 2]) +/// [2, 1] +/// ``` +/// +pub fn reverse(xs: List(a)) -> List(a) { + do_reverse(xs) +} + +@target(erlang) +@external(erlang, "lists", "reverse") +fn do_reverse(a: List(a)) -> List(a) + +@target(javascript) +fn do_reverse(list) { + do_reverse_acc(list, []) +} + +@target(javascript) +fn do_reverse_acc(remaining, accumulator) { + case remaining { + [] -> accumulator + [item, ..rest] -> do_reverse_acc(rest, [item, ..accumulator]) + } +} + +/// Determines whether or not the list is empty. +/// +/// This function runs in constant time. +/// +/// ## Examples +/// +/// ```gleam +/// > is_empty([]) +/// True +/// ``` +/// +/// ```gleam +/// > is_empty([1]) +/// False +/// ``` +/// +/// ```gleam +/// > is_empty([1, 1]) +/// False +/// ``` +/// +pub fn is_empty(list: List(a)) -> Bool { + list == [] +} + +/// Determines whether or not a given element exists within a given list. +/// +/// This function traverses the list to find the element, so it runs in linear +/// time. +/// +/// ## Examples +/// +/// ```gleam +/// > [] |> contains(any: 0) +/// False +/// ``` +/// +/// ```gleam +/// > [0] |> contains(any: 0) +/// True +/// ``` +/// +/// ```gleam +/// > [1] |> contains(any: 0) +/// False +/// ``` +/// +/// ```gleam +/// > [1, 1] |> contains(any: 0) +/// False +/// ``` +/// +/// ```gleam +/// > [1, 0] |> contains(any: 0) +/// True +/// ``` +/// +pub fn contains(list: List(a), any elem: a) -> Bool { + case list { + [] -> False + [first, ..] if first == elem -> True + [_, ..rest] -> contains(rest, elem) + } +} + +/// Gets the first element from the start of the list, if there is one. +/// +/// ## Examples +/// +/// ```gleam +/// > first([]) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > first([0]) +/// Ok(0) +/// ``` +/// +/// ```gleam +/// > first([1, 2]) +/// Ok(1) +/// ``` +/// +pub fn first(list: List(a)) -> Result(a, Nil) { + case list { + [] -> Error(Nil) + [x, ..] -> Ok(x) + } +} + +/// Returns the list minus the first element. If the list is empty, `Error(Nil)` is +/// returned. +/// +/// This function runs in constant time and does not make a copy of the list. +/// +/// ## Examples +/// +/// ```gleam +/// > rest([]) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > rest([0]) +/// Ok([]) +/// ``` +/// +/// ```gleam +/// > rest([1, 2]) +/// Ok([2]) +/// ``` +/// +pub fn rest(list: List(a)) -> Result(List(a), Nil) { + case list { + [] -> Error(Nil) + [_, ..xs] -> Ok(xs) + } +} + +fn update_group( + f: fn(element) -> key, +) -> fn(Dict(key, List(element)), element) -> Dict(key, List(element)) { + fn(groups, elem) { + case dict.get(groups, f(elem)) { + Ok(existing) -> dict.insert(groups, f(elem), [elem, ..existing]) + Error(_) -> dict.insert(groups, f(elem), [elem]) + } + } +} + +/// Takes a list and groups the values by a key +/// which is built from a key function. +/// +/// Does not preserve the initial value order. +/// +/// ## Examples +/// +/// ```gleam +/// > [Ok(3), Error("Wrong"), Ok(200), Ok(73)] +/// |> group(by: fn(i) { +/// case i { +/// Ok(_) -> "Successful" +/// Error(_) -> "Failed" +/// } +/// }) +/// |> dict.to_list +/// +/// [ +/// #("Failed", [Error("Wrong")]), +/// #("Successful", [Ok(73), Ok(200), Ok(3)]) +/// ] +/// +/// > group([1,2,3,4,5], by: fn(i) { i - i / 3 * 3 }) +/// |> dict.to_list +/// [#(0, [3]), #(1, [4, 1]), #(2, [5, 2])] +/// ``` +/// +pub fn group(list: List(v), by key: fn(v) -> k) -> Dict(k, List(v)) { + fold(list, dict.new(), update_group(key)) +} + +fn do_filter(list: List(a), fun: fn(a) -> Bool, acc: List(a)) -> List(a) { + case list { + [] -> reverse(acc) + [x, ..xs] -> { + let new_acc = case fun(x) { + True -> [x, ..acc] + False -> acc + } + do_filter(xs, fun, new_acc) + } + } +} + +/// Returns a new list containing only the elements from the first list for +/// which the given functions returns `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > filter([2, 4, 6, 1], fn(x) { x > 2 }) +/// [4, 6] +/// ``` +/// +/// ```gleam +/// > filter([2, 4, 6, 1], fn(x) { x > 6 }) +/// [] +/// ``` +/// +pub fn filter(list: List(a), keeping predicate: fn(a) -> Bool) -> List(a) { + do_filter(list, predicate, []) +} + +fn do_filter_map( + list: List(a), + fun: fn(a) -> Result(b, e), + acc: List(b), +) -> List(b) { + case list { + [] -> reverse(acc) + [x, ..xs] -> { + let new_acc = case fun(x) { + Ok(x) -> [x, ..acc] + Error(_) -> acc + } + do_filter_map(xs, fun, new_acc) + } + } +} + +/// Returns a new list containing only the elements from the first list for +/// which the given functions returns `Ok(_)`. +/// +/// ## Examples +/// +/// ```gleam +/// > filter_map([2, 4, 6, 1], Error) +/// [] +/// ``` +/// +/// ```gleam +/// > filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) }) +/// [3, 5, 7, 2] +/// ``` +/// +pub fn filter_map(list: List(a), with fun: fn(a) -> Result(b, e)) -> List(b) { + do_filter_map(list, fun, []) +} + +fn do_map(list: List(a), fun: fn(a) -> b, acc: List(b)) -> List(b) { + case list { + [] -> reverse(acc) + [x, ..xs] -> do_map(xs, fun, [fun(x), ..acc]) + } +} + +/// Returns a new list containing only the elements of the first list after the +/// function has been applied to each one. +/// +/// ## Examples +/// +/// ```gleam +/// > map([2, 4, 6], fn(x) { x * 2 }) +/// [4, 8, 12] +/// ``` +/// +pub fn map(list: List(a), with fun: fn(a) -> b) -> List(b) { + do_map(list, fun, []) +} + +/// Combines two lists into a single list using the given function. +/// +/// If a list is longer than the other the extra elements are dropped. +/// +/// ## Examples +/// +/// ```gleam +/// > map2([1, 2, 3], [4, 5, 6], fn(x, y) { x + y }) +/// [5, 7, 9] +/// ``` +/// +/// ```gleam +/// > map2([1, 2], ["a", "b", "c"], fn(i, x) { #(i, x) }) +/// [#(1, "a"), #(2, "b")] +/// ``` +/// +pub fn map2(list1: List(a), list2: List(b), with fun: fn(a, b) -> c) -> List(c) { + do_map2(list1, list2, fun, []) +} + +fn do_map2( + list1: List(a), + list2: List(b), + fun: fn(a, b) -> c, + acc: List(c), +) -> List(c) { + case list1, list2 { + [], _ | _, [] -> reverse(acc) + [a, ..as_], [b, ..bs] -> do_map2(as_, bs, fun, [fun(a, b), ..acc]) + } +} + +/// Similar to `map` but also lets you pass around an accumulated value. +/// +/// ## Examples +/// +/// ```gleam +/// > map_fold( +/// over: [1, 2, 3], +/// from: 100, +/// with: fn(memo, i) { #(memo + i, i * 2) } +/// ) +/// #(106, [2, 4, 6]) +/// ``` +/// +pub fn map_fold( + over list: List(a), + from acc: acc, + with fun: fn(acc, a) -> #(acc, b), +) -> #(acc, List(b)) { + fold(over: list, from: #(acc, []), with: fn(acc, item) { + let #(current_acc, items) = acc + let #(next_acc, next_item) = fun(current_acc, item) + #(next_acc, [next_item, ..items]) + }) + |> pair.map_second(reverse) +} + +fn do_index_map( + list: List(a), + fun: fn(a, Int) -> b, + index: Int, + acc: List(b), +) -> List(b) { + case list { + [] -> reverse(acc) + [x, ..xs] -> { + let acc = [fun(x, index), ..acc] + do_index_map(xs, fun, index + 1, acc) + } + } +} + +/// Returns a new list containing only the elements of the first list after the +/// function has been applied to each one and their index. +/// +/// The index starts at 0, so the first element is 0, the second is 1, and so +/// on. +/// +/// ## Examples +/// +/// ```gleam +/// > index_map(["a", "b"], fn(x, i) { #(i, x) }) +/// [#(0, "a"), #(1, "b")] +/// ``` +/// +pub fn index_map(list: List(a), with fun: fn(a, Int) -> b) -> List(b) { + do_index_map(list, fun, 0, []) +} + +fn do_try_map( + list: List(a), + fun: fn(a) -> Result(b, e), + acc: List(b), +) -> Result(List(b), e) { + case list { + [] -> Ok(reverse(acc)) + [x, ..xs] -> + case fun(x) { + Ok(y) -> do_try_map(xs, fun, [y, ..acc]) + Error(error) -> Error(error) + } + } +} + +/// Takes a function that returns a `Result` and applies it to each element in a +/// given list in turn. +/// +/// If the function returns `Ok(new_value)` for all elements in the list then a +/// list of the new values is returned. +/// +/// If the function returns `Error(reason)` for any of the elements then it is +/// returned immediately. None of the elements in the list are processed after +/// one returns an `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > try_map([1, 2, 3], fn(x) { Ok(x + 2) }) +/// Ok([3, 4, 5]) +/// ``` +/// +/// ```gleam +/// > try_map([1, 2, 3], fn(_) { Error(0) }) +/// Error(0) +/// ``` +/// +/// ```gleam +/// > try_map([[1], [2, 3]], first) +/// Ok([1, 2]) +/// ``` +/// +/// ```gleam +/// > try_map([[1], [], [2]], first) +/// Error(Nil) +/// ``` +/// +pub fn try_map( + over list: List(a), + with fun: fn(a) -> Result(b, e), +) -> Result(List(b), e) { + do_try_map(list, fun, []) +} + +/// Returns a list that is the given list with up to the given number of +/// elements removed from the front of the list. +/// +/// If the element has less than the number of elements an empty list is +/// returned. +/// +/// This function runs in linear time but does not copy the list. +/// +/// ## Examples +/// +/// ```gleam +/// > drop([1, 2, 3, 4], 2) +/// [3, 4] +/// ``` +/// +/// ```gleam +/// > drop([1, 2, 3, 4], 9) +/// [] +/// ``` +/// +pub fn drop(from list: List(a), up_to n: Int) -> List(a) { + case n <= 0 { + True -> list + False -> + case list { + [] -> [] + [_, ..xs] -> drop(xs, n - 1) + } + } +} + +fn do_take(list: List(a), n: Int, acc: List(a)) -> List(a) { + case n <= 0 { + True -> reverse(acc) + False -> + case list { + [] -> reverse(acc) + [x, ..xs] -> do_take(xs, n - 1, [x, ..acc]) + } + } +} + +/// Returns a list containing the first given number of elements from the given +/// list. +/// +/// If the element has less than the number of elements then the full list is +/// returned. +/// +/// This function runs in linear time but does not copy the list. +/// +/// ## Examples +/// +/// ```gleam +/// > take([1, 2, 3, 4], 2) +/// [1, 2] +/// ``` +/// +/// ```gleam +/// > take([1, 2, 3, 4], 9) +/// [1, 2, 3, 4] +/// ``` +/// +pub fn take(from list: List(a), up_to n: Int) -> List(a) { + do_take(list, n, []) +} + +/// Returns a new empty list. +/// +/// ## Examples +/// +/// ```gleam +/// > new() +/// [] +/// ``` +/// +pub fn new() -> List(a) { + [] +} + +/// Joins one list onto the end of another. +/// +/// This function runs in linear time, and it traverses and copies the first +/// list. +/// +/// ## Examples +/// +/// ```gleam +/// > append([1, 2], [3]) +/// [1, 2, 3] +/// ``` +/// +pub fn append(first: List(a), second: List(a)) -> List(a) { + do_append(first, second) +} + +@target(erlang) +@external(erlang, "lists", "append") +fn do_append(a: List(a), b: List(a)) -> List(a) + +@target(javascript) +fn do_append(first: List(a), second: List(a)) -> List(a) { + do_append_acc(reverse(first), second) +} + +@target(javascript) +fn do_append_acc(first: List(a), second: List(a)) -> List(a) { + case first { + [] -> second + [item, ..rest] -> do_append_acc(rest, [item, ..second]) + } +} + +/// Prefixes an item to a list. This can also be done using the dedicated +/// syntax instead +/// +/// ```gleam +/// let new_list = [1, ..existing_list] +/// ``` +/// +pub fn prepend(to list: List(a), this item: a) -> List(a) { + [item, ..list] +} + +// Reverses a list and prepends it to another list +fn reverse_and_prepend(list prefix: List(a), to suffix: List(a)) -> List(a) { + case prefix { + [] -> suffix + [first, ..rest] -> reverse_and_prepend(list: rest, to: [first, ..suffix]) + } +} + +fn do_concat(lists: List(List(a)), acc: List(a)) -> List(a) { + case lists { + [] -> reverse(acc) + [list, ..further_lists] -> + do_concat(further_lists, reverse_and_prepend(list: list, to: acc)) + } +} + +/// Joins a list of lists into a single list. +/// +/// This function traverses all elements twice. +/// +/// ## Examples +/// +/// ```gleam +/// > concat([[1], [2, 3], []]) +/// [1, 2, 3] +/// ``` +/// +pub fn concat(lists: List(List(a))) -> List(a) { + do_concat(lists, []) +} + +/// This is the same as `concat`: it joins a list of lists into a single +/// list. +/// +/// This function traverses all elements twice. +/// +/// ## Examples +/// +/// ```gleam +/// > flatten([[1], [2, 3], []]) +/// [1, 2, 3] +/// ``` +/// +pub fn flatten(lists: List(List(a))) -> List(a) { + do_concat(lists, []) +} + +/// Maps the list with the given function into a list of lists, and then flattens it. +/// +/// ## Examples +/// +/// ```gleam +/// > flat_map([2, 4, 6], fn(x) { [x, x + 1] }) +/// [2, 3, 4, 5, 6, 7] +/// ``` +/// +pub fn flat_map(over list: List(a), with fun: fn(a) -> List(b)) -> List(b) { + map(list, fun) + |> concat +} + +/// Reduces a list of elements into a single value by calling a given function +/// on each element, going from left to right. +/// +/// `fold([1, 2, 3], 0, add)` is the equivalent of +/// `add(add(add(0, 1), 2), 3)`. +/// +/// This function runs in linear time. +/// +pub fn fold( + over list: List(a), + from initial: acc, + with fun: fn(acc, a) -> acc, +) -> acc { + case list { + [] -> initial + [x, ..rest] -> fold(rest, fun(initial, x), fun) + } +} + +/// Reduces a list of elements into a single value by calling a given function +/// on each element, going from right to left. +/// +/// `fold_right([1, 2, 3], 0, add)` is the equivalent of +/// `add(add(add(0, 3), 2), 1)`. +/// +/// This function runs in linear time. +/// +/// Unlike `fold` this function is not tail recursive. Where possible use +/// `fold` instead as it will use less memory. +/// +pub fn fold_right( + over list: List(a), + from initial: acc, + with fun: fn(acc, a) -> acc, +) -> acc { + case list { + [] -> initial + [x, ..rest] -> fun(fold_right(rest, initial, fun), x) + } +} + +fn do_index_fold( + over: List(a), + acc: acc, + with: fn(acc, a, Int) -> acc, + index: Int, +) -> acc { + case over { + [] -> acc + [first, ..rest] -> + do_index_fold(rest, with(acc, first, index), with, index + 1) + } +} + +/// Like fold but the folding function also receives the index of the current element. +/// +/// ## Examples +/// +/// ```gleam +/// ["a", "b", "c"] +/// |> index_fold([], fn(acc, item, index) { ... }) +/// ``` +/// +pub fn index_fold( + over over: List(a), + from initial: acc, + with fun: fn(acc, a, Int) -> acc, +) -> acc { + do_index_fold(over, initial, fun, 0) +} + +/// A variant of fold that might fail. +/// +/// The folding function should return `Result(accumulator, error)`. +/// If the returned value is `Ok(accumulator)` try_fold will try the next value in the list. +/// If the returned value is `Error(error)` try_fold will stop and return that error. +/// +/// ## Examples +/// +/// ```gleam +/// [1, 2, 3, 4] +/// |> try_fold(0, fn(acc, i) { +/// case i < 3 { +/// True -> Ok(acc + i) +/// False -> Error(Nil) +/// } +/// }) +/// ``` +/// +pub fn try_fold( + over collection: List(a), + from accumulator: acc, + with fun: fn(acc, a) -> Result(acc, e), +) -> Result(acc, e) { + case collection { + [] -> Ok(accumulator) + [first, ..rest] -> + case fun(accumulator, first) { + Ok(result) -> try_fold(rest, result, fun) + Error(_) as error -> error + } + } +} + +pub type ContinueOrStop(a) { + Continue(a) + Stop(a) +} + +/// A variant of fold that allows to stop folding earlier. +/// +/// The folding function should return `ContinueOrStop(accumulator)`. +/// If the returned value is `Continue(accumulator)` fold_until will try the next value in the list. +/// If the returned value is `Stop(accumulator)` fold_until will stop and return that accumulator. +/// +/// ## Examples +/// +/// ```gleam +/// [1, 2, 3, 4] +/// |> fold_until(0, fn(acc, i) { +/// case i < 3 { +/// True -> Continue(acc + i) +/// False -> Stop(acc) +/// } +/// }) +/// ``` +/// +pub fn fold_until( + over collection: List(a), + from accumulator: acc, + with fun: fn(acc, a) -> ContinueOrStop(acc), +) -> acc { + case collection { + [] -> accumulator + [first, ..rest] -> + case fun(accumulator, first) { + Continue(next_accumulator) -> fold_until(rest, next_accumulator, fun) + Stop(b) -> b + } + } +} + +/// Finds the first element in a given list for which the given function returns +/// `True`. +/// +/// Returns `Error(Nil)` if no such element is found. +/// +/// ## Examples +/// +/// ```gleam +/// > find([1, 2, 3], fn(x) { x > 2 }) +/// Ok(3) +/// ``` +/// +/// ```gleam +/// > find([1, 2, 3], fn(x) { x > 4 }) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > find([], fn(_) { True }) +/// Error(Nil) +/// ``` +/// +pub fn find( + in haystack: List(a), + one_that is_desired: fn(a) -> Bool, +) -> Result(a, Nil) { + case haystack { + [] -> Error(Nil) + [x, ..rest] -> + case is_desired(x) { + True -> Ok(x) + _ -> find(in: rest, one_that: is_desired) + } + } +} + +/// Finds the first element in a given list for which the given function returns +/// `Ok(new_value)`, then returns the wrapped `new_value`. +/// +/// Returns `Error(Nil)` if no such element is found. +/// +/// ## Examples +/// +/// ```gleam +/// > find_map([[], [2], [3]], first) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > find_map([[], []], first) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > find_map([], first) +/// Error(Nil) +/// ``` +/// +pub fn find_map( + in haystack: List(a), + with fun: fn(a) -> Result(b, c), +) -> Result(b, Nil) { + case haystack { + [] -> Error(Nil) + [x, ..rest] -> + case fun(x) { + Ok(x) -> Ok(x) + _ -> find_map(in: rest, with: fun) + } + } +} + +/// Returns `True` if the given function returns `True` for all the elements in +/// the given list. If the function returns `False` for any of the elements it +/// immediately returns `False` without checking the rest of the list. +/// +/// ## Examples +/// +/// ```gleam +/// > all([], fn(x) { x > 3 }) +/// True +/// ``` +/// +/// ```gleam +/// > all([4, 5], fn(x) { x > 3 }) +/// True +/// ``` +/// +/// ```gleam +/// > all([4, 3], fn(x) { x > 3 }) +/// False +/// ``` +/// +pub fn all(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool { + case list { + [] -> True + [first, ..rest] -> + case predicate(first) { + True -> all(rest, predicate) + False -> False + } + } +} + +/// Returns `True` if the given function returns `True` for any the elements in +/// the given list. If the function returns `True` for any of the elements it +/// immediately returns `True` without checking the rest of the list. +/// +/// ## Examples +/// +/// ```gleam +/// > any([], fn(x) { x > 3 }) +/// False +/// ``` +/// +/// ```gleam +/// > any([4, 5], fn(x) { x > 3 }) +/// True +/// ``` +/// +/// ```gleam +/// > any([4, 3], fn(x) { x > 4 }) +/// False +/// ``` +/// +/// ```gleam +/// > any([3, 4], fn(x) { x > 3 }) +/// True +/// ``` +/// +pub fn any(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool { + case list { + [] -> False + [first, ..rest] -> + case predicate(first) { + True -> True + False -> any(rest, predicate) + } + } +} + +fn do_zip(xs: List(a), ys: List(b), acc: List(#(a, b))) -> List(#(a, b)) { + case xs, ys { + [x, ..xs], [y, ..ys] -> do_zip(xs, ys, [#(x, y), ..acc]) + _, _ -> reverse(acc) + } +} + +/// Takes two lists and returns a single list of 2-element tuples. +/// +/// If one of the lists is longer than the other, the remaining elements from +/// the longer list are not used. +/// +/// ## Examples +/// +/// ```gleam +/// > zip([], []) +/// [] +/// ``` +/// +/// ```gleam +/// > zip([1, 2], [3]) +/// [#(1, 3)] +/// ``` +/// +/// ```gleam +/// > zip([1], [3, 4]) +/// [#(1, 3)] +/// ``` +/// +/// ```gleam +/// > zip([1, 2], [3, 4]) +/// [#(1, 3), #(2, 4)] +/// ``` +/// +pub fn zip(list: List(a), with other: List(b)) -> List(#(a, b)) { + do_zip(list, other, []) +} + +/// Takes two lists and returns a single list of 2-element tuples. +/// +/// If one of the lists is longer than the other, an `Error` is returned. +/// +/// ## Examples +/// +/// ```gleam +/// > strict_zip([], []) +/// Ok([]) +/// ``` +/// +/// ```gleam +/// > strict_zip([1, 2], [3]) +/// Error(LengthMismatch) +/// ``` +/// +/// ```gleam +/// > strict_zip([1], [3, 4]) +/// Error(LengthMismatch) +/// ``` +/// +/// ```gleam +/// > strict_zip([1, 2], [3, 4]) +/// Ok([#(1, 3), #(2, 4)]) +/// ``` +/// +pub fn strict_zip( + list: List(a), + with other: List(b), +) -> Result(List(#(a, b)), LengthMismatch) { + case length(of: list) == length(of: other) { + True -> Ok(zip(list, other)) + False -> Error(LengthMismatch) + } +} + +fn do_unzip(input, xs, ys) { + case input { + [] -> #(reverse(xs), reverse(ys)) + [#(x, y), ..rest] -> do_unzip(rest, [x, ..xs], [y, ..ys]) + } +} + +/// Takes a single list of 2-element tuples and returns two lists. +/// +/// ## Examples +/// +/// ```gleam +/// > unzip([#(1, 2), #(3, 4)]) +/// #([1, 3], [2, 4]) +/// ``` +/// +/// ```gleam +/// > unzip([]) +/// #([], []) +/// ``` +/// +pub fn unzip(input: List(#(a, b))) -> #(List(a), List(b)) { + do_unzip(input, [], []) +} + +fn do_intersperse(list: List(a), separator: a, acc: List(a)) -> List(a) { + case list { + [] -> reverse(acc) + [x, ..rest] -> do_intersperse(rest, separator, [x, separator, ..acc]) + } +} + +/// Inserts a given value between each existing element in a given list. +/// +/// This function runs in linear time and copies the list. +/// +/// ## Examples +/// +/// ```gleam +/// > intersperse([1, 1, 1], 2) +/// [1, 2, 1, 2, 1] +/// ``` +/// +/// ```gleam +/// > intersperse([], 2) +/// [] +/// ``` +/// +pub fn intersperse(list: List(a), with elem: a) -> List(a) { + case list { + [] | [_] -> list + [x, ..rest] -> do_intersperse(rest, elem, [x]) + } +} + +/// Returns the element in the Nth position in the list, with 0 being the first +/// position. +/// +/// `Error(Nil)` is returned if the list is not long enough for the given index +/// or if the index is less than 0. +/// +/// ## Examples +/// +/// ```gleam +/// > at([1, 2, 3], 1) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > at([1, 2, 3], 5) +/// Error(Nil) +/// ``` +/// +pub fn at(in list: List(a), get index: Int) -> Result(a, Nil) { + case index >= 0 { + True -> + list + |> drop(index) + |> first + False -> Error(Nil) + } +} + +/// Removes any duplicate elements from a given list. +/// +/// This function returns in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > unique([1, 1, 1, 4, 7, 3, 3, 4]) +/// [1, 4, 7, 3] +/// ``` +/// +pub fn unique(list: List(a)) -> List(a) { + case list { + [] -> [] + [x, ..rest] -> [x, ..unique(filter(rest, fn(y) { y != x }))] + } +} + +/// Merge lists `a` and `b` in ascending order +/// but only up to `na` and `nb` number of items respectively. +/// +fn merge_up( + na: Int, + nb: Int, + a: List(a), + b: List(a), + acc: List(a), + compare: fn(a, a) -> Order, +) { + case na, nb, a, b { + 0, 0, _, _ -> acc + _, 0, [ax, ..ar], _ -> merge_up(na - 1, nb, ar, b, [ax, ..acc], compare) + 0, _, _, [bx, ..br] -> merge_up(na, nb - 1, a, br, [bx, ..acc], compare) + _, _, [ax, ..ar], [bx, ..br] -> + case compare(ax, bx) { + order.Gt -> merge_up(na, nb - 1, a, br, [bx, ..acc], compare) + _ -> merge_up(na - 1, nb, ar, b, [ax, ..acc], compare) + } + _, _, _, _ -> acc + } +} + +/// Merge lists `a` and `b` in descending order +/// but only up to `na` and `nb` number of items respectively. +/// +fn merge_down( + na: Int, + nb: Int, + a: List(a), + b: List(a), + acc: List(a), + compare: fn(a, a) -> Order, +) { + case na, nb, a, b { + 0, 0, _, _ -> acc + _, 0, [ax, ..ar], _ -> merge_down(na - 1, nb, ar, b, [ax, ..acc], compare) + 0, _, _, [bx, ..br] -> merge_down(na, nb - 1, a, br, [bx, ..acc], compare) + _, _, [ax, ..ar], [bx, ..br] -> + case compare(bx, ax) { + order.Lt -> merge_down(na - 1, nb, ar, b, [ax, ..acc], compare) + _ -> merge_down(na, nb - 1, a, br, [bx, ..acc], compare) + } + _, _, _, _ -> acc + } +} + +/// Merge sort that alternates merging in ascending and descending order +/// because the merge process also reverses the list. +/// +/// Some copying is avoided by merging only a subset of the lists +/// instead of creating and merging new smaller lists. +/// +fn merge_sort( + l: List(a), + ln: Int, + compare: fn(a, a) -> Order, + down: Bool, +) -> List(a) { + let n = ln / 2 + let a = l + let b = drop(l, n) + case ln < 3 { + True -> + case down { + True -> merge_down(n, ln - n, a, b, [], compare) + False -> merge_up(n, ln - n, a, b, [], compare) + } + False -> + case down { + True -> + merge_down( + n, + ln + - n, + merge_sort(a, n, compare, False), + merge_sort(b, ln - n, compare, False), + [], + compare, + ) + False -> + merge_up( + n, + ln + - n, + merge_sort(a, n, compare, True), + merge_sort(b, ln - n, compare, True), + [], + compare, + ) + } + } +} + +/// Sorts from smallest to largest based upon the ordering specified by a given +/// function. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/int +/// > list.sort([4, 3, 6, 5, 4, 1, 2], by: int.compare) +/// [1, 2, 3, 4, 4, 5, 6] +/// ``` +/// +pub fn sort(list: List(a), by compare: fn(a, a) -> Order) -> List(a) { + merge_sort(list, length(list), compare, True) +} + +/// Creates a list of ints ranging from a given start and finish. +/// +/// ## Examples +/// +/// ```gleam +/// > range(0, 0) +/// [0] +/// ``` +/// +/// ```gleam +/// > range(0, 5) +/// [0, 1, 2, 3, 4, 5] +/// ``` +/// +/// ```gleam +/// > range(1, -5) +/// [1, 0, -1, -2, -3, -4, -5] +/// ``` +/// +pub fn range(from start: Int, to stop: Int) -> List(Int) { + tail_recursive_range(start, stop, []) +} + +fn tail_recursive_range(start: Int, stop: Int, acc: List(Int)) -> List(Int) { + case int.compare(start, stop) { + order.Eq -> [stop, ..acc] + order.Gt -> tail_recursive_range(start, stop + 1, [stop, ..acc]) + order.Lt -> tail_recursive_range(start, stop - 1, [stop, ..acc]) + } +} + +fn do_repeat(a: a, times: Int, acc: List(a)) -> List(a) { + case times <= 0 { + True -> acc + False -> do_repeat(a, times - 1, [a, ..acc]) + } +} + +/// Builds a list of a given value a given number of times. +/// +/// ## Examples +/// +/// ```gleam +/// > repeat("a", times: 0) +/// [] +/// ``` +/// +/// ```gleam +/// > repeat("a", times: 5) +/// ["a", "a", "a", "a", "a"] +/// ``` +/// +pub fn repeat(item a: a, times times: Int) -> List(a) { + do_repeat(a, times, []) +} + +fn do_split(list: List(a), n: Int, taken: List(a)) -> #(List(a), List(a)) { + case n <= 0 { + True -> #(reverse(taken), list) + False -> + case list { + [] -> #(reverse(taken), []) + [x, ..xs] -> do_split(xs, n - 1, [x, ..taken]) + } + } +} + +/// Splits a list in two before the given index. +/// +/// If the list is not long enough to have the given index the before list will +/// be the input list, and the after list will be empty. +/// +/// ## Examples +/// +/// ```gleam +/// > split([6, 7, 8, 9], 0) +/// #([], [6, 7, 8, 9]) +/// ``` +/// +/// ```gleam +/// > split([6, 7, 8, 9], 2) +/// #([6, 7], [8, 9]) +/// ``` +/// +/// ```gleam +/// > split([6, 7, 8, 9], 4) +/// #([6, 7, 8, 9], []) +/// ``` +/// +pub fn split(list list: List(a), at index: Int) -> #(List(a), List(a)) { + do_split(list, index, []) +} + +fn do_split_while( + list: List(a), + f: fn(a) -> Bool, + acc: List(a), +) -> #(List(a), List(a)) { + case list { + [] -> #(reverse(acc), []) + [x, ..xs] -> + case f(x) { + False -> #(reverse(acc), list) + _ -> do_split_while(xs, f, [x, ..acc]) + } + } +} + +/// Splits a list in two before the first element that a given function returns +/// `False` for. +/// +/// If the function returns `True` for all elements the first list will be the +/// input list, and the second list will be empty. +/// +/// ## Examples +/// +/// ```gleam +/// > split_while([1, 2, 3, 4, 5], fn(x) { x <= 3 }) +/// #([1, 2, 3], [4, 5]) +/// ``` +/// +/// ```gleam +/// > split_while([1, 2, 3, 4, 5], fn(x) { x <= 5 }) +/// #([1, 2, 3, 4, 5], []) +/// ``` +/// +pub fn split_while( + list list: List(a), + satisfying predicate: fn(a) -> Bool, +) -> #(List(a), List(a)) { + do_split_while(list, predicate, []) +} + +/// Given a list of 2-element tuples, finds the first tuple that has a given +/// key as the first element and returns the second element. +/// +/// If no tuple is found with the given key then `Error(Nil)` is returned. +/// +/// This function may be useful for interacting with Erlang code where lists of +/// tuples are common. +/// +/// ## Examples +/// +/// ```gleam +/// > key_find([#("a", 0), #("b", 1)], "a") +/// Ok(0) +/// ``` +/// +/// ```gleam +/// > key_find([#("a", 0), #("b", 1)], "b") +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > key_find([#("a", 0), #("b", 1)], "c") +/// Error(Nil) +/// ``` +/// +pub fn key_find( + in keyword_list: List(#(k, v)), + find desired_key: k, +) -> Result(v, Nil) { + find_map(keyword_list, fn(keyword) { + let #(key, value) = keyword + case key == desired_key { + True -> Ok(value) + False -> Error(Nil) + } + }) +} + +/// Given a list of 2-element tuples, finds all tuples that have a given +/// key as the first element and returns the second element. +/// +/// This function may be useful for interacting with Erlang code where lists of +/// tuples are common. +/// +/// ## Examples +/// +/// ```gleam +/// > key_filter([#("a", 0), #("b", 1), #("a", 2)], "a") +/// [0, 2] +/// ``` +/// +/// ```gleam +/// > key_filter([#("a", 0), #("b", 1)], "c") +/// [] +/// ``` +/// +pub fn key_filter( + in keyword_list: List(#(k, v)), + find desired_key: k, +) -> List(v) { + filter_map(keyword_list, fn(keyword) { + let #(key, value) = keyword + case key == desired_key { + True -> Ok(value) + False -> Error(Nil) + } + }) +} + +fn do_pop(haystack, predicate, checked) { + case haystack { + [] -> Error(Nil) + [x, ..rest] -> + case predicate(x) { + True -> Ok(#(x, append(reverse(checked), rest))) + False -> do_pop(rest, predicate, [x, ..checked]) + } + } +} + +/// Removes the first element in a given list for which the predicate function returns `True`. +/// +/// Returns `Error(Nil)` if no such element is found. +/// +/// ## Examples +/// +/// ```gleam +/// > pop([1, 2, 3], fn(x) { x > 2 }) +/// Ok(#(3, [1, 2])) +/// ``` +/// +/// ```gleam +/// > pop([1, 2, 3], fn(x) { x > 4 }) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > pop([], fn(_) { True }) +/// Error(Nil) +/// ``` +/// +pub fn pop( + in haystack: List(a), + one_that is_desired: fn(a) -> Bool, +) -> Result(#(a, List(a)), Nil) { + do_pop(haystack, is_desired, []) +} + +fn do_pop_map(haystack, mapper, checked) { + case haystack { + [] -> Error(Nil) + [x, ..rest] -> + case mapper(x) { + Ok(y) -> Ok(#(y, append(reverse(checked), rest))) + Error(_) -> do_pop_map(rest, mapper, [x, ..checked]) + } + } +} + +/// Removes the first element in a given list for which the given function returns +/// `Ok(new_value)`, then returns the wrapped `new_value` as well as list with the value removed. +/// +/// Returns `Error(Nil)` if no such element is found. +/// +/// ## Examples +/// +/// ```gleam +/// > pop_map([[], [2], [3]], first) +/// Ok(#(2, [[], [3]])) +/// ``` +/// +/// ```gleam +/// > pop_map([[], []], first) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > pop_map([], first) +/// Error(Nil) +/// ``` +/// +pub fn pop_map( + in haystack: List(a), + one_that is_desired: fn(a) -> Result(b, c), +) -> Result(#(b, List(a)), Nil) { + do_pop_map(haystack, is_desired, []) +} + +/// Given a list of 2-element tuples, finds the first tuple that has a given +/// key as the first element. This function will return the second element +/// of the found tuple and list with tuple removed. +/// +/// If no tuple is found with the given key then `Error(Nil)` is returned. +/// +/// ## Examples +/// +/// ```gleam +/// > key_pop([#("a", 0), #("b", 1)], "a") +/// Ok(#(0, [#("b", 1)])) +/// ``` +/// +/// ```gleam +/// > key_pop([#("a", 0), #("b", 1)], "b") +/// Ok(#(1, [#("a", 0)])) +/// ``` +/// +/// ```gleam +/// > key_pop([#("a", 0), #("b", 1)], "c") +/// Error(Nil) +/// ``` +/// +pub fn key_pop( + haystack: List(#(k, v)), + key: k, +) -> Result(#(v, List(#(k, v))), Nil) { + pop_map(haystack, fn(entry) { + let #(k, v) = entry + case k { + k if k == key -> Ok(v) + _ -> Error(Nil) + } + }) +} + +/// Given a list of 2-element tuples, inserts a key and value into the list. +/// +/// If there was already a tuple with the key then it is replaced, otherwise it +/// is added to the end of the list. +/// +/// ## Examples +/// +/// ```gleam +/// > key_set([#(5, 0), #(4, 1)], 4, 100) +/// [#(5, 0), #(4, 100)] +/// ``` +/// +/// ```gleam +/// > key_set([#(5, 0), #(4, 1)], 1, 100) +/// [#(5, 0), #(4, 1), #(1, 100)] +/// ``` +/// +pub fn key_set(list: List(#(a, b)), key: a, value: b) -> List(#(a, b)) { + case list { + [] -> [#(key, value)] + [#(k, _), ..rest] if k == key -> [#(key, value), ..rest] + [first, ..rest] -> [first, ..key_set(rest, key, value)] + } +} + +/// Calls a function for each element in a list, discarding the return value. +/// +/// Useful for calling a side effect for every item of a list. +/// +/// ```gleam +/// > list.each([1, 2, 3], io.println) +/// Nil +/// ``` +/// +pub fn each(list: List(a), f: fn(a) -> b) -> Nil { + case list { + [] -> Nil + [x, ..xs] -> { + f(x) + each(xs, f) + } + } +} + +/// Calls a `Result` returning function for each element in a list, discarding +/// the return value. If the function returns `Error` then the iteration is +/// stopped and the error is returned. +/// +/// Useful for calling a side effect for every item of a list. +/// +/// ## Examples +/// +/// ```gleam +/// > try_each( +/// > over: [1, 2, 3], +/// > with: function_that_might_fail, +/// > ) +/// Ok(Nil) +/// ``` +/// +pub fn try_each( + over list: List(a), + with fun: fn(a) -> Result(b, e), +) -> Result(Nil, e) { + case list { + [] -> Ok(Nil) + [x, ..xs] -> + case fun(x) { + Ok(_) -> try_each(over: xs, with: fun) + Error(e) -> Error(e) + } + } +} + +fn do_partition(list, categorise, trues, falses) { + case list { + [] -> #(reverse(trues), reverse(falses)) + [x, ..xs] -> + case categorise(x) { + True -> do_partition(xs, categorise, [x, ..trues], falses) + False -> do_partition(xs, categorise, trues, [x, ..falses]) + } + } +} + +/// Partitions a list into a tuple/pair of lists +/// by a given categorisation function. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4, 5] |> list.partition(int.is_odd) +/// #([1, 3, 5], [2, 4]) +/// ``` +/// +pub fn partition( + list: List(a), + with categorise: fn(a) -> Bool, +) -> #(List(a), List(a)) { + do_partition(list, categorise, [], []) +} + +/// Returns all the permutations of a list. +/// +/// ## Examples +/// +/// ```gleam +/// > permutations([1, 2]) +/// [[1, 2], [2, 1]] +/// ``` +/// +pub fn permutations(l: List(a)) -> List(List(a)) { + case l { + [] -> [[]] + _ -> + l + |> index_map(fn(i, i_idx) { + l + |> index_fold([], fn(acc, j, j_idx) { + case i_idx == j_idx { + True -> acc + False -> [j, ..acc] + } + }) + |> reverse + |> permutations + |> map(fn(permutation) { [i, ..permutation] }) + }) + |> concat + } +} + +fn do_window(acc: List(List(a)), l: List(a), n: Int) -> List(List(a)) { + let window = take(l, n) + + case length(window) == n { + True -> do_window([window, ..acc], drop(l, 1), n) + False -> acc + } +} + +/// Returns a list of sliding windows. +/// +/// ## Examples +/// +/// ```gleam +/// > window([1,2,3,4,5], 3) +/// [[1, 2, 3], [2, 3, 4], [3, 4, 5]] +/// ``` +/// +/// ```gleam +/// > window([1, 2], 4) +/// [] +/// ``` +/// +pub fn window(l: List(a), by n: Int) -> List(List(a)) { + do_window([], l, n) + |> reverse +} + +/// Returns a list of tuples containing two contiguous elements. +/// +/// ## Examples +/// +/// ```gleam +/// > window_by_2([1,2,3,4]) +/// [#(1, 2), #(2, 3), #(3, 4)] +/// ``` +/// +/// ```gleam +/// > window_by_2([1]) +/// [] +/// ``` +/// +pub fn window_by_2(l: List(a)) -> List(#(a, a)) { + zip(l, drop(l, 1)) +} + +/// Drops the first elements in a given list for which the predicate function returns `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > drop_while([1, 2, 3, 4], fn (x) { x < 3 }) +/// [3, 4] +/// ``` +/// +pub fn drop_while( + in list: List(a), + satisfying predicate: fn(a) -> Bool, +) -> List(a) { + case list { + [] -> [] + [x, ..xs] -> + case predicate(x) { + True -> drop_while(xs, predicate) + False -> [x, ..xs] + } + } +} + +fn do_take_while( + list: List(a), + predicate: fn(a) -> Bool, + acc: List(a), +) -> List(a) { + case list { + [] -> reverse(acc) + [first, ..rest] -> + case predicate(first) { + True -> do_take_while(rest, predicate, [first, ..acc]) + False -> reverse(acc) + } + } +} + +/// Takes the first elements in a given list for which the predicate function returns `True`. +/// +/// ## Examples +/// +/// ```gleam +/// > take_while([1, 2, 3, 2, 4], fn (x) { x < 3 }) +/// [1, 2] +/// ``` +/// +pub fn take_while( + in list: List(a), + satisfying predicate: fn(a) -> Bool, +) -> List(a) { + do_take_while(list, predicate, []) +} + +fn do_chunk( + list: List(a), + f: fn(a) -> key, + previous_key: key, + current_chunk: List(a), + acc: List(List(a)), +) -> List(List(a)) { + case list { + [first, ..rest] -> { + let key = f(first) + case key == previous_key { + False -> { + let new_acc = [reverse(current_chunk), ..acc] + do_chunk(rest, f, key, [first], new_acc) + } + _true -> do_chunk(rest, f, key, [first, ..current_chunk], acc) + } + } + _empty -> reverse([reverse(current_chunk), ..acc]) + } +} + +/// Returns a list of chunks in which +/// the return value of calling `f` on each element is the same. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk(by: fn(n) { n % 2 }) +/// [[1], [2, 2], [3], [4, 4, 6], [7, 7]] +/// ``` +/// +pub fn chunk(in list: List(a), by f: fn(a) -> key) -> List(List(a)) { + case list { + [] -> [] + [first, ..rest] -> do_chunk(rest, f, f(first), [first], []) + } +} + +fn do_sized_chunk( + list: List(a), + count: Int, + left: Int, + current_chunk: List(a), + acc: List(List(a)), +) -> List(List(a)) { + case list { + [] -> + case current_chunk { + [] -> reverse(acc) + remaining -> reverse([reverse(remaining), ..acc]) + } + [first, ..rest] -> { + let chunk = [first, ..current_chunk] + case left > 1 { + False -> do_sized_chunk(rest, count, count, [], [reverse(chunk), ..acc]) + True -> do_sized_chunk(rest, count, left - 1, chunk, acc) + } + } + } +} + +/// Returns a list of chunks containing `count` elements each. +/// +/// If the last chunk does not have `count` elements, it is instead +/// a partial chunk, with less than `count` elements. +/// +/// For any `count` less than 1 this function behaves as if it was set to 1. +/// +/// ## Examples +/// +/// ```gleam +/// > [1, 2, 3, 4, 5, 6] |> sized_chunk(into: 2) +/// [[1, 2], [3, 4], [5, 6]] +/// ``` +/// +/// ```gleam +/// > [1, 2, 3, 4, 5, 6, 7, 8] |> sized_chunk(into: 3) +/// [[1, 2, 3], [4, 5, 6], [7, 8]] +/// ``` +/// +pub fn sized_chunk(in list: List(a), into count: Int) -> List(List(a)) { + do_sized_chunk(list, count, count, [], []) +} + +/// This function acts similar to fold, but does not take an initial state. +/// Instead, it starts from the first element in the list +/// and combines it with each subsequent element in turn using the given +/// function. The function is called as `fun(accumulator, current_element)`. +/// +/// Returns `Ok` to indicate a successful run, and `Error` if called on an +/// empty list. +/// +/// ## Examples +/// +/// ```gleam +/// > [] |> reduce(fn(acc, x) { acc + x }) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > [1, 2, 3, 4, 5] |> reduce(fn(acc, x) { acc + x }) +/// Ok(15) +/// ``` +/// +pub fn reduce(over list: List(a), with fun: fn(a, a) -> a) -> Result(a, Nil) { + case list { + [] -> Error(Nil) + [first, ..rest] -> Ok(fold(rest, first, fun)) + } +} + +fn do_scan( + list: List(a), + accumulator: acc, + accumulated: List(acc), + fun: fn(acc, a) -> acc, +) -> List(acc) { + case list { + [] -> reverse(accumulated) + [x, ..xs] -> { + let next = fun(accumulator, x) + do_scan(xs, next, [next, ..accumulated], fun) + } + } +} + +/// Similar to `fold`, but yields the state of the accumulator at each stage. +/// +/// ## Examples +/// +/// ```gleam +/// > scan(over: [1, 2, 3], from: 100, with: fn(acc, i) { acc + i }) +/// [101, 103, 106] +/// ``` +/// +pub fn scan( + over list: List(a), + from initial: acc, + with fun: fn(acc, a) -> acc, +) -> List(acc) { + do_scan(list, initial, [], fun) +} + +/// Returns the last element in the given list. +/// +/// Returns `Error(Nil)` if the list is empty. +/// +/// This function runs in linear time. +/// For a collection oriented around performant access at either end, +/// see `gleam/queue.Queue`. +/// +/// ## Examples +/// +/// ```gleam +/// > last([]) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > last([1, 2, 3, 4, 5]) +/// Ok(5) +/// ``` +/// +pub fn last(list: List(a)) -> Result(a, Nil) { + list + |> reduce(fn(_, elem) { elem }) +} + +/// Return unique combinations of elements in the list. +/// +/// ## Examples +/// +/// ```gleam +/// > combinations([1, 2, 3], 2) +/// [[1, 2], [1, 3], [2, 3]] +/// ``` +/// +/// ```gleam +/// > combinations([1, 2, 3, 4], 3) +/// [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]] +/// ``` +/// +pub fn combinations(items: List(a), by n: Int) -> List(List(a)) { + case n { + 0 -> [[]] + _ -> + case items { + [] -> [] + [x, ..xs] -> { + let first_combinations = + map(combinations(xs, n - 1), with: fn(com) { [x, ..com] }) + |> reverse + fold(first_combinations, combinations(xs, n), fn(acc, c) { + [c, ..acc] + }) + } + } + } +} + +fn do_combination_pairs(items: List(a)) -> List(List(#(a, a))) { + case items { + [] -> [] + [x, ..xs] -> { + let first_combinations = map(xs, with: fn(other) { #(x, other) }) + [first_combinations, ..do_combination_pairs(xs)] + } + } +} + +/// Return unique pair combinations of elements in the list +/// +/// ## Examples +/// +/// ```gleam +/// > combination_pairs([1, 2, 3]) +/// [#(1, 2), #(1, 3), #(2, 3)] +/// ``` +/// +pub fn combination_pairs(items: List(a)) -> List(#(a, a)) { + do_combination_pairs(items) + |> concat +} + +/// Make a list alternating the elements from the given lists +/// +/// ## Examples +/// +/// ```gleam +/// > list.interleave([[1, 2], [101, 102], [201, 202]]) +/// [1, 101, 201, 2, 102, 202] +/// ``` +/// +pub fn interleave(list: List(List(a))) -> List(a) { + transpose(list) + |> concat +} + +/// Transpose rows and columns of the list of lists. +/// +/// Notice: This function is not tail recursive, +/// and thus may exceed stack size if called, +/// with large lists (on target JavaScript). +/// +/// ## Examples +/// +/// ```gleam +/// > transpose([[1, 2, 3], [101, 102, 103]]) +/// [[1, 101], [2, 102], [3, 103]] +/// ``` +/// +pub fn transpose(list_of_list: List(List(a))) -> List(List(a)) { + let take_first = fn(list) { + case list { + [] -> [] + [f] -> [f] + [f, ..] -> [f] + } + } + + case list_of_list { + [] -> [] + [[], ..xss] -> transpose(xss) + rows -> { + let firsts = + rows + |> map(take_first) + |> concat + let rest = transpose(map(rows, drop(_, 1))) + [firsts, ..rest] + } + } +} + +fn do_shuffle_pair_unwrap(list: List(#(Float, a)), acc: List(a)) -> List(a) { + case list { + [] -> acc + [elem_pair, ..enumerable] -> + do_shuffle_pair_unwrap(enumerable, [elem_pair.1, ..acc]) + } +} + +fn do_shuffle_by_pair_indexes( + list_of_pairs: List(#(Float, a)), +) -> List(#(Float, a)) { + sort(list_of_pairs, fn(a_pair: #(Float, a), b_pair: #(Float, a)) -> Order { + float.compare(a_pair.0, b_pair.0) + }) +} + +/// Takes a list, randomly sorts all items and returns the shuffled list. +/// +/// This function uses `float.random` to decide the order of the elements. +/// +/// ## Example +/// +/// ```gleam +/// > range(1, 10) +/// > |> shuffle() +/// [1, 6, 9, 10, 3, 8, 4, 2, 7, 5] +/// ``` +/// +pub fn shuffle(list: List(a)) -> List(a) { + list + |> fold(from: [], with: fn(acc, a) { [#(float.random(), a), ..acc] }) + |> do_shuffle_by_pair_indexes() + |> do_shuffle_pair_unwrap([]) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/map.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/map.gleam new file mode 100644 index 0000000..b3d0e0f --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/map.gleam @@ -0,0 +1,107 @@ +import gleam/option.{type Option} +import gleam/dict + +@deprecated("Please use the `gleam/dict` module instead") +pub type Map(key, value) = + dict.Dict(key, value) + +@deprecated("Please use the `gleam/dict` module instead") +pub fn size(map) -> Int { + dict.size(map) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn to_list(map) -> List(#(key, value)) { + dict.to_list(map) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn from_list(list: List(#(k, v))) { + dict.from_list(list) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn has_key(map, key: k) -> Bool { + dict.has_key(map, key) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn new() { + dict.new() +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn get(from, get: key) -> Result(value, Nil) { + dict.get(from, get) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn insert(into map, for key: k, insert value: v) { + dict.insert(map, key, value) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn map_values(in map, with fun: fn(k, v) -> w) { + dict.map_values(map, fun) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn keys(map) -> List(keys) { + dict.keys(map) +} + +@target(javascript) +fn reverse_and_concat(remaining, accumulator) { + case remaining { + [] -> accumulator + [item, ..rest] -> reverse_and_concat(rest, [item, ..accumulator]) + } +} + +@target(javascript) +fn do_keys_acc(list: List(#(k, v)), acc: List(k)) -> List(k) { + case list { + [] -> reverse_and_concat(acc, []) + [x, ..xs] -> do_keys_acc(xs, [x.0, ..acc]) + } +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn values(map) -> List(values) { + dict.values(map) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn filter(in map, keeping predicate: fn(k, v) -> Bool) { + dict.filter(map, predicate) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn take(from map, keeping desired_keys: List(k)) { + dict.take(map, desired_keys) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn merge(into map, from new_entries) { + dict.merge(map, new_entries) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn delete(from map, delete key: k) { + dict.delete(map, key) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn drop(from map, drop disallowed_keys: List(k)) { + dict.drop(map, disallowed_keys) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn update(in map, update key: k, with fun: fn(Option(v)) -> v) { + dict.update(map, key, fun) +} + +@deprecated("Please use the `gleam/dict` module instead") +pub fn fold(over map, from initial: acc, with fun: fn(acc, k, v) -> acc) -> acc { + dict.fold(map, initial, fun) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/option.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/option.gleam new file mode 100644 index 0000000..6015c0f --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/option.gleam @@ -0,0 +1,346 @@ +/// `Option` represents a value that may be present or not. `Some` means the value is +/// present, `None` means the value is not. +/// +/// This is Gleam's alternative to having a value that could be Null, as is +/// possible in some other languages. +/// +pub type Option(a) { + Some(a) + None +} + +fn do_all(list: List(Option(a)), acc: List(a)) -> Option(List(a)) { + case list { + [] -> Some(acc) + [x, ..rest] -> { + let accumulate = fn(acc, item) { + case acc, item { + Some(values), Some(value) -> Some([value, ..values]) + _, _ -> None + } + } + accumulate(do_all(rest, acc), x) + } + } +} + +/// Combines a list of `Option`s into a single `Option`. +/// If all elements in the list are `Some` then returns a `Some` holding the list of values. +/// If any element is `None` then returns`None`. +/// +/// ## Examples +/// +/// ```gleam +/// > all([Some(1), Some(2)]) +/// Some([1, 2]) +/// ``` +/// +/// ```gleam +/// > all([Some(1), None]) +/// None +/// ``` +/// +pub fn all(list: List(Option(a))) -> Option(List(a)) { + do_all(list, []) +} + +/// Checks whether the `Option` is a `Some` value. +/// +/// ## Examples +/// +/// ```gleam +/// > is_some(Some(1)) +/// True +/// ``` +/// +/// ```gleam +/// > is_some(None) +/// False +/// ``` +/// +pub fn is_some(option: Option(a)) -> Bool { + option != None +} + +/// Checks whether the `Option` is a `None` value. +/// +/// ## Examples +/// +/// ```gleam +/// > is_none(Some(1)) +/// False +/// ``` +/// +/// ```gleam +/// > is_none(None) +/// True +/// ``` +/// +pub fn is_none(option: Option(a)) -> Bool { + option == None +} + +/// Converts an `Option` type to a `Result` type. +/// +/// ## Examples +/// +/// ```gleam +/// > to_result(Some(1), "some_error") +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > to_result(None, "some_error") +/// Error("some_error") +/// ``` +/// +pub fn to_result(option: Option(a), e) -> Result(a, e) { + case option { + Some(a) -> Ok(a) + _ -> Error(e) + } +} + +/// Converts a `Result` type to an `Option` type. +/// +/// ## Examples +/// +/// ```gleam +/// > from_result(Ok(1)) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > from_result(Error("some_error")) +/// None +/// ``` +/// +pub fn from_result(result: Result(a, e)) -> Option(a) { + case result { + Ok(a) -> Some(a) + _ -> None + } +} + +/// Extracts the value from an `Option`, returning a default value if there is none. +/// +/// ## Examples +/// +/// ```gleam +/// > unwrap(Some(1), 0) +/// 1 +/// ``` +/// +/// ```gleam +/// > unwrap(None, 0) +/// 0 +/// ``` +/// +pub fn unwrap(option: Option(a), or default: a) -> a { + case option { + Some(x) -> x + None -> default + } +} + +/// Extracts the value from an `Option`, evaluating the default function if the option is `None`. +/// +/// ## Examples +/// +/// ```gleam +/// > lazy_unwrap(Some(1), fn() { 0 }) +/// 1 +/// ``` +/// +/// ```gleam +/// > lazy_unwrap(None, fn() { 0 }) +/// 0 +/// ``` +/// +pub fn lazy_unwrap(option: Option(a), or default: fn() -> a) -> a { + case option { + Some(x) -> x + None -> default() + } +} + +/// Updates a value held within the `Some` of an `Option` by calling a given function +/// on it. +/// +/// If the `Option` is a `None` rather than `Some`, the function is not called and the +/// `Option` stays the same. +/// +/// ## Examples +/// +/// ```gleam +/// > map(over: Some(1), with: fn(x) { x + 1 }) +/// Some(2) +/// ``` +/// +/// ```gleam +/// > map(over: None, with: fn(x) { x + 1 }) +/// None +/// ``` +/// +pub fn map(over option: Option(a), with fun: fn(a) -> b) -> Option(b) { + case option { + Some(x) -> Some(fun(x)) + None -> None + } +} + +/// Merges a nested `Option` into a single layer. +/// +/// ## Examples +/// +/// ```gleam +/// > flatten(Some(Some(1))) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > flatten(Some(None)) +/// None +/// ``` +/// +/// ```gleam +/// > flatten(None) +/// None +/// ``` +/// +pub fn flatten(option: Option(Option(a))) -> Option(a) { + case option { + Some(x) -> x + None -> None + } +} + +/// Updates a value held within the `Some` of an `Option` by calling a given function +/// on it, where the given function also returns an `Option`. The two options are +/// then merged together into one `Option`. +/// +/// If the `Option` is a `None` rather than `Some` the function is not called and the +/// option stays the same. +/// +/// This function is the equivalent of calling `map` followed by `flatten`, and +/// it is useful for chaining together multiple functions that return `Option`. +/// +/// ## Examples +/// +/// ```gleam +/// > then(Some(1), fn(x) { Some(x + 1) }) +/// Some(2) +/// ``` +/// +/// ```gleam +/// > then(Some(1), fn(x) { Some(#("a", x)) }) +/// Some(#("a", 1)) +/// ``` +/// +/// ```gleam +/// > then(Some(1), fn(_) { None }) +/// None +/// ``` +/// +/// ```gleam +/// > then(None, fn(x) { Some(x + 1) }) +/// None +/// ``` +/// +pub fn then(option: Option(a), apply fun: fn(a) -> Option(b)) -> Option(b) { + case option { + Some(x) -> fun(x) + None -> None + } +} + +/// Returns the first value if it is `Some`, otherwise returns the second value. +/// +/// ## Examples +/// +/// ```gleam +/// > or(Some(1), Some(2)) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > or(Some(1), None) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > or(None, Some(2)) +/// Some(2) +/// ``` +/// +/// ```gleam +/// > or(None, None) +/// None +/// ``` +/// +pub fn or(first: Option(a), second: Option(a)) -> Option(a) { + case first { + Some(_) -> first + None -> second + } +} + +/// Returns the first value if it is `Some`, otherwise evaluates the given function for a fallback value. +/// +/// ## Examples +/// +/// ```gleam +/// > lazy_or(Some(1), fn() { Some(2) }) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > lazy_or(Some(1), fn() { None }) +/// Some(1) +/// ``` +/// +/// ```gleam +/// > lazy_or(None, fn() { Some(2) }) +/// Some(2) +/// ``` +/// +/// ```gleam +/// > lazy_or(None, fn() { None }) +/// None +/// ``` +/// +pub fn lazy_or(first: Option(a), second: fn() -> Option(a)) -> Option(a) { + case first { + Some(_) -> first + None -> second() + } +} + +fn do_values(list: List(Option(a)), acc: List(a)) -> List(a) { + case list { + [] -> acc + [x, ..xs] -> { + let accumulate = fn(acc, item) { + case item { + Some(value) -> [value, ..acc] + None -> acc + } + } + accumulate(do_values(xs, acc), x) + } + } +} + +/// Given a list of `Option`s, +/// returns only the values inside `Some`. +/// +/// ## Examples +/// +/// ```gleam +/// > values([Some(1), None, Some(3)]) +/// [1, 3] +/// ``` +/// +pub fn values(options: List(Option(a))) -> List(a) { + do_values(options, []) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/order.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/order.gleam new file mode 100644 index 0000000..12ce011 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/order.gleam @@ -0,0 +1,133 @@ +/// Represents the result of a single comparison to determine the precise +/// ordering of two values. +/// +pub type Order { + /// Less-than + Lt + + /// Equal + Eq + + /// Greater than + Gt +} + +/// Inverts an order, so less-than becomes greater-than and greater-than +/// becomes less-than. +/// +/// ## Examples +/// +/// ```gleam +/// > negate(Lt) +/// Gt +/// ``` +/// +/// ```gleam +/// > negate(Eq) +/// Eq +/// ``` +/// +/// ```gleam +/// > negate(Lt) +/// Gt +/// ``` +/// +pub fn negate(order: Order) -> Order { + case order { + Lt -> Gt + Eq -> Eq + Gt -> Lt + } +} + +/// Produces a numeric representation of the order. +/// +/// ## Examples +/// +/// ```gleam +/// > to_int(Lt) +/// -1 +/// ``` +/// +/// ```gleam +/// > to_int(Eq) +/// 0 +/// ``` +/// +/// ```gleam +/// > to_int(Gt) +/// 1 +/// ``` +/// +pub fn to_int(order: Order) -> Int { + case order { + Lt -> -1 + Eq -> 0 + Gt -> 1 + } +} + +/// Compares two `Order` values to one another, producing a new `Order`. +/// +/// ## Examples +/// +/// ```gleam +/// > compare(Eq, with: Lt) +/// Gt +/// ``` +/// +pub fn compare(a: Order, with b: Order) -> Order { + case a, b { + x, y if x == y -> Eq + Lt, _ | Eq, Gt -> Lt + _, _ -> Gt + } +} + +/// Returns the largest of two orders given that `Gt > Eq > Lt`. +/// +/// ## Examples +/// +/// ```gleam +/// > max(Eq, Lt) +/// Eq +/// ``` +/// +pub fn max(a: Order, b: Order) -> Order { + case a, b { + Gt, _ -> Gt + Eq, Lt -> Eq + _, _ -> b + } +} + +/// Returns the smallest of two orders given that `Gt > Eq > Lt`. +/// +/// ## Examples +/// +/// ```gleam +/// > min(Eq, Lt) +/// Lt +/// ``` +/// +pub fn min(a: Order, b: Order) -> Order { + case a, b { + Lt, _ -> Lt + Eq, Gt -> Eq + _, _ -> b + } +} + +/// Inverts an ordering function, so less-than becomes greater-than and greater-than +/// becomes less-than. +/// +/// ## Examples +/// +/// ```gleam +/// > list.sort([1, 5, 4], by: reverse(int.compare)) +/// [5, 4, 1] +/// ``` +/// +pub fn reverse(orderer: fn(a, a) -> Order) -> fn(a, a) -> Order { + fn(a, b) { orderer(b, a) } +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/pair.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/pair.gleam new file mode 100644 index 0000000..894e6a8 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/pair.gleam @@ -0,0 +1,85 @@ +/// Returns the first element in a pair. +/// +/// ## Examples +/// +/// ```gleam +/// > first(#(1, 2)) +/// 1 +/// ``` +/// +pub fn first(pair: #(a, b)) -> a { + let #(a, _) = pair + a +} + +/// Returns the second element in a pair. +/// +/// ## Examples +/// +/// ```gleam +/// > second(#(1, 2)) +/// 2 +/// ``` +/// +pub fn second(pair: #(a, b)) -> b { + let #(_, a) = pair + a +} + +/// Returns a new pair with the elements swapped. +/// +/// ## Examples +/// +/// ```gleam +/// > swap(#(1, 2)) +/// #(2, 1) +/// ``` +/// +pub fn swap(pair: #(a, b)) -> #(b, a) { + let #(a, b) = pair + #(b, a) +} + +/// Returns a new pair with the first element having had `with` applied to +/// it. +/// +/// ## Examples +/// +/// ```gleam +/// > #(1, 2) |> map_first(fn(n) { n * 2 }) +/// #(2, 2) +/// ``` +/// +pub fn map_first(of pair: #(a, b), with fun: fn(a) -> c) -> #(c, b) { + let #(a, b) = pair + #(fun(a), b) +} + +/// Returns a new pair with the second element having had `with` applied to +/// it. +/// +/// ## Examples +/// +/// ```gleam +/// > #(1, 2) |> map_second(fn(n) { n * 2 }) +/// #(1, 4) +/// ``` +/// +pub fn map_second(of pair: #(a, b), with fun: fn(b) -> c) -> #(a, c) { + let #(a, b) = pair + #(a, fun(b)) +} + +/// Returns a new pair with the given elements. This can also be done using the dedicated +/// syntax instead: `new(1, 2) == #(1, 2)`. +/// +/// ## Examples +/// +/// ```gleam +/// > new(1, 2) +/// #(1, 2) +/// ``` +/// +pub fn new(first: a, second: b) -> #(a, b) { + #(first, second) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/queue.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/queue.gleam new file mode 100644 index 0000000..5bf60c8 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/queue.gleam @@ -0,0 +1,292 @@ +import gleam/list + +/// A queue is an ordered collection of elements. It is similar to a list, but +/// unlike a list elements can be added to or removed from either the front or +/// the back in a performant fashion. +/// +/// The internal representation may be different for two queues with the same +/// elements in the same order if the queues were constructed in different +/// ways. This is the price paid for a queue's fast access at both the front +/// and the back. +/// +/// Because of unpredictable internal representation the equality operator `==` +/// may return surprising results, and the `is_equal` and `is_logically_equal` +/// functions are the recommended way to test queues for equality. +/// +pub opaque type Queue(element) { + Queue(in: List(element), out: List(element)) +} + +/// Creates a fresh queue that contains no values. +/// +pub fn new() -> Queue(a) { + Queue(in: [], out: []) +} + +/// Converts a list of elements into a queue of the same elements in the same +/// order. The first element in the list becomes the front element in the queue. +/// +/// This function runs in constant time. +/// +/// # Examples +/// +/// ```gleam +/// > [1, 2, 3] |> from_list |> length +/// 3 +/// ``` +/// +pub fn from_list(list: List(a)) -> Queue(a) { + Queue(in: [], out: list) +} + +/// Converts a queue of elements into a list of the same elements in the same +/// order. The front element in the queue becomes the first element in the list. +/// +/// This function runs in linear time. +/// +/// # Examples +/// +/// ```gleam +/// > new() |> push_back(1) |> push_back(2) |> to_list +/// [1, 2] +/// ``` +/// +pub fn to_list(queue: Queue(a)) -> List(a) { + queue.out + |> list.append(list.reverse(queue.in)) +} + +/// Determines whether or not the queue is empty. +/// +/// This function runs in constant time. +/// +/// ## Examples +/// +/// ```gleam +/// > [] |> from_list |> is_empty +/// True +/// ``` +/// +/// ```gleam +/// > [1] |> from_list |> is_empty +/// False +/// ``` +/// +/// ```gleam +/// > [1, 2] |> from_list |> is_empty +/// False +/// ``` +/// +pub fn is_empty(queue: Queue(a)) -> Bool { + queue.in == [] && queue.out == [] +} + +/// Counts the number of elements in a given queue. +/// +/// This function has to traverse the queue to determine the number of elements, +/// so it runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > length(from_list([])) +/// 0 +/// ``` +/// +/// ```gleam +/// > length(from_list([1])) +/// 1 +/// ``` +/// +/// ```gleam +/// > length(from_list([1, 2])) +/// 2 +/// ``` +/// +pub fn length(queue: Queue(a)) -> Int { + list.length(queue.in) + list.length(queue.out) +} + +/// Pushes an element onto the back of the queue. +/// +/// # Examples +/// +/// ```gleam +/// > [1, 2] |> from_list |> push_back(3) |> to_list +/// [1, 2, 3] +/// ``` +/// +pub fn push_back(onto queue: Queue(a), this item: a) -> Queue(a) { + Queue(in: [item, ..queue.in], out: queue.out) +} + +/// Pushes an element onto the front of the queue. +/// +/// # Examples +/// +/// ```gleam +/// > [0, 0] |> from_list |> push_front(1) |> to_list +/// [1, 0, 0] +/// ``` +/// +pub fn push_front(onto queue: Queue(a), this item: a) -> Queue(a) { + Queue(in: queue.in, out: [item, ..queue.out]) +} + +/// Gets the last element from the queue, returning the +/// element and a new queue without that element. +/// +/// This function typically runs in constant time, but will occasionally run in +/// linear time. +/// +/// # Examples +/// +/// ```gleam +/// > new() +/// > |> push_back(0) +/// > |> push_back(1) +/// > |> pop_back() +/// Ok(#(1, push_front(new(), 0))) +/// ``` +/// +/// ```gleam +/// > new() +/// > |> push_front(0) +/// > |> pop_back() +/// Ok(#(0, new())) +/// ``` +/// +/// ```gleam +/// > new() +/// > |> pop_back() +/// Error(Nil) +/// ``` +/// +pub fn pop_back(from queue: Queue(a)) -> Result(#(a, Queue(a)), Nil) { + case queue { + Queue(in: [], out: []) -> Error(Nil) + Queue(in: [], out: out) -> pop_back(Queue(in: list.reverse(out), out: [])) + Queue(in: [first, ..rest], out: out) -> { + let queue = Queue(in: rest, out: out) + Ok(#(first, queue)) + } + } +} + +/// Gets the first element from the queue, returning the +/// element and a new queue without that element. +/// +/// This function typically runs in constant time, but will occasionally run in +/// linear time. +/// +/// # Examples +/// +/// ```gleam +/// > queue.new() +/// > |> queue.push_front(1) +/// > |> queue.push_front(0) +/// > |> queue.pop_front() +/// Ok(#(0, queue.push_back(queue.new(), 1))) +/// ``` +/// +/// ```gleam +/// > queue.new() +/// > |> queue.push_back(0) +/// > |> queue.pop_front() +/// Ok(#(0, queue.new())) +/// ``` +/// +/// ```gleam +/// > queue.new() +/// > |> queue.pop_back() +/// Error(Nil) +/// ``` +/// +pub fn pop_front(from queue: Queue(a)) -> Result(#(a, Queue(a)), Nil) { + case queue { + Queue(in: [], out: []) -> Error(Nil) + Queue(in: in, out: []) -> pop_front(Queue(in: [], out: list.reverse(in))) + Queue(in: in, out: [first, ..rest]) -> { + let queue = Queue(in: in, out: rest) + Ok(#(first, queue)) + } + } +} + +/// Creates a new queue from a given queue containing the same elements, but in +/// the opposite order. +/// +/// This function runs in constant time. +/// +/// ## Examples +/// +/// ```gleam +/// > [] |> from_list |> reverse |> to_list +/// [] +/// ``` +/// +/// ```gleam +/// > [1] |> from_list |> reverse |> to_list +/// [1] +/// ``` +/// +/// ```gleam +/// > [1, 2] |> from_list |> reverse |> to_list +/// [2, 1] +/// ``` +/// +pub fn reverse(queue: Queue(a)) -> Queue(a) { + Queue(in: queue.out, out: queue.in) +} + +fn check_equal( + xs: List(t), + x_tail: List(t), + ys: List(t), + y_tail: List(t), + eq: fn(t, t) -> Bool, +) -> Bool { + case xs, x_tail, ys, y_tail { + [], [], [], [] -> True + [x, ..xs], _, [y, ..ys], _ -> + case eq(x, y) { + False -> False + True -> check_equal(xs, x_tail, ys, y_tail, eq) + } + [], [_, ..], _, _ -> check_equal(list.reverse(x_tail), [], ys, y_tail, eq) + _, _, [], [_, ..] -> check_equal(xs, x_tail, list.reverse(y_tail), [], eq) + _, _, _, _ -> False + } +} + +/// Checks whether two queues have equal elements in the same order, where the +/// equality of elements is determined by a given equality checking function. +/// +/// This function is useful as the internal representation may be different for +/// two queues with the same elements in the same order depending on how they +/// were constructed, so the equality operator `==` may return surprising +/// results. +/// +/// This function runs in linear time multiplied by the time taken by the +/// element equality checking function. +/// +pub fn is_logically_equal( + a: Queue(t), + to b: Queue(t), + checking element_is_equal: fn(t, t) -> Bool, +) -> Bool { + check_equal(a.out, a.in, b.out, b.in, element_is_equal) +} + +/// Checks whether two queues have the same elements in the same order. +/// +/// This function is useful as the internal representation may be different for +/// two queues with the same elements in the same order depending on how they +/// were constructed, so the equality operator `==` may return surprising +/// results. +/// +/// This function runs in linear time. +/// +pub fn is_equal(a: Queue(t), to b: Queue(t)) -> Bool { + check_equal(a.out, a.in, b.out, b.in, fn(a, b) { a == b }) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/regex.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/regex.gleam new file mode 100644 index 0000000..9ffda78 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/regex.gleam @@ -0,0 +1,214 @@ +//// This module contains regular expression matching functions for strings. +//// The matching algorithms of the library are based on the PCRE library, but not +//// all of the PCRE library is interfaced and some parts of the library go beyond +//// what PCRE offers. Currently PCRE version 8.40 (release date 2017-01-11) is used. + +import gleam/option.{type Option} + +pub type Regex + +/// The details about a particular match: +/// +pub type Match { + Match( + /// The full string of the match. + content: String, + /// A `Regex` can have subpatterns, sup-parts that are in parentheses. + submatches: List(Option(String)), + ) +} + +/// When a regular expression fails to compile: +/// +pub type CompileError { + CompileError( + /// The problem encountered that caused the compilation to fail + error: String, + /// The byte index into the string to where the problem was found + /// This value may not be correct in JavaScript environments. + byte_index: Int, + ) +} + +pub type Options { + Options(case_insensitive: Bool, multi_line: Bool) +} + +/// Creates a `Regex` with some additional options. +/// +/// ## Examples +/// +/// ```gleam +/// > let options = Options(case_insensitive: False, multi_line: True) +/// > let assert Ok(re) = compile("^[0-9]", with: options) +/// > check(re, "abc\n123") +/// True +/// ``` +/// +/// ```gleam +/// > let options = Options(case_insensitive: True, multi_line: False) +/// > let assert Ok(re) = compile("[A-Z]", with: options) +/// > check(re, "abc123") +/// True +/// ``` +/// +pub fn compile( + pattern: String, + with options: Options, +) -> Result(Regex, CompileError) { + do_compile(pattern, options) +} + +@external(erlang, "gleam_stdlib", "compile_regex") +@external(javascript, "../gleam_stdlib.mjs", "compile_regex") +fn do_compile(a: String, with with: Options) -> Result(Regex, CompileError) + +/// Creates a new `Regex`. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Ok(re) = from_string("[0-9]") +/// > check(re, "abc123") +/// True +/// ``` +/// +/// ```gleam +/// > check(re, "abcxyz") +/// False +/// ``` +/// +/// ```gleam +/// > from_string("[0-9") +/// Error( +/// CompileError( +/// error: "missing terminating ] for character class", +/// byte_index: 4 +/// ) +/// ) +/// ``` +/// +pub fn from_string(pattern: String) -> Result(Regex, CompileError) { + compile(pattern, Options(case_insensitive: False, multi_line: False)) +} + +/// Returns a boolean indicating whether there was a match or not. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Ok(re) = from_string("^f.o.?") +/// > check(with: re, content: "foo") +/// True +/// ``` +/// +/// ```gleam +/// > check(with: re, content: "boo") +/// False +/// ``` +/// +pub fn check(with regex: Regex, content content: String) -> Bool { + do_check(regex, content) +} + +@external(erlang, "gleam_stdlib", "regex_check") +@external(javascript, "../gleam_stdlib.mjs", "regex_check") +fn do_check(a: Regex, b: String) -> Bool + +/// Splits a string. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Ok(re) = from_string(" *, *") +/// > split(with: re, content: "foo,32, 4, 9 ,0") +/// ["foo", "32", "4", "9", "0"] +/// ``` +/// +pub fn split(with regex: Regex, content string: String) -> List(String) { + do_split(regex, string) +} + +@target(erlang) +@external(erlang, "gleam_stdlib", "regex_split") +fn do_split(a: Regex, b: String) -> List(String) + +@target(javascript) +fn do_split(regex, string) -> List(String) { + js_split(string, regex) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "split") +fn js_split(a: String, b: Regex) -> List(String) + +/// Collects all matches of the regular expression. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Ok(re) = from_string("[oi]n a (\\w+)") +/// > scan(with: re, content: "I am on a boat in a lake.") +/// [ +/// Match( +/// content: "on a boat", +/// submatches: [Some("boat")] +/// ), +/// Match( +/// content: "in a lake", +/// submatches: [Some("lake")] +/// ) +/// ] +/// ``` +/// +/// ```gleam +/// > let assert Ok(re) = regex.from_string("([+|\\-])?(\\d+)(\\w+)?") +/// > scan(with: re, content: "-36") +/// [ +/// Match( +/// content: "-36", +/// submatches: [Some("-"), Some("36")] +/// ) +/// ] +/// +/// > scan(with: re, content: "36") +/// [ +/// Match( +/// content: "36", +/// submatches: [None, Some("36")] +/// ) +/// ] +/// ``` +/// +/// ```gleam +/// > let assert Ok(re) = regex.from_string("var\\s*(\\w+)\\s*(int|string)?\\s*=\\s*(.*)") +/// > scan(with: re, content: "var age = 32") +/// [ +/// Match( +/// content: "var age = 32", +/// submatches: [Some("age"), None, Some("32")] +/// ) +/// ] +/// ``` +/// +/// ```gleam +/// > let assert Ok(re) = regex.from_string("let (\\w+) = (\\w+)") +/// > scan(with: re, content: "let age = 32") +/// [ +/// Match( +/// content: "let age = 32", +/// submatches: [Some("age"), Some("32")] +/// ) +/// ] +/// +/// > scan(with: re, content: "const age = 32") +/// [] +/// ``` +/// +pub fn scan(with regex: Regex, content string: String) -> List(Match) { + do_scan(regex, string) +} + +@external(erlang, "gleam_stdlib", "regex_scan") +@external(javascript, "../gleam_stdlib.mjs", "regex_scan") +fn do_scan(a: Regex, b: String) -> List(Match) diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/result.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/result.gleam new file mode 100644 index 0000000..fb6dddb --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/result.gleam @@ -0,0 +1,482 @@ +//// Result represents the result of something that may succeed or not. +//// `Ok` means it was successful, `Error` means it was not successful. + +import gleam/list + +/// Checks whether the result is an `Ok` value. +/// +/// ## Examples +/// +/// ```gleam +/// > is_ok(Ok(1)) +/// True +/// ``` +/// +/// ```gleam +/// > is_ok(Error(Nil)) +/// False +/// ``` +/// +pub fn is_ok(result: Result(a, e)) -> Bool { + case result { + Error(_) -> False + Ok(_) -> True + } +} + +/// Checks whether the result is an `Error` value. +/// +/// ## Examples +/// +/// ```gleam +/// > is_error(Ok(1)) +/// False +/// ``` +/// +/// ```gleam +/// > is_error(Error(Nil)) +/// True +/// ``` +/// +pub fn is_error(result: Result(a, e)) -> Bool { + case result { + Ok(_) -> False + Error(_) -> True + } +} + +/// Updates a value held within the `Ok` of a result by calling a given function +/// on it. +/// +/// If the result is an `Error` rather than `Ok` the function is not called and the +/// result stays the same. +/// +/// ## Examples +/// +/// ```gleam +/// > map(over: Ok(1), with: fn(x) { x + 1 }) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > map(over: Error(1), with: fn(x) { x + 1 }) +/// Error(1) +/// ``` +/// +pub fn map(over result: Result(a, e), with fun: fn(a) -> b) -> Result(b, e) { + case result { + Ok(x) -> Ok(fun(x)) + Error(e) -> Error(e) + } +} + +/// Updates a value held within the `Error` of a result by calling a given function +/// on it. +/// +/// If the result is `Ok` rather than `Error` the function is not called and the +/// result stays the same. +/// +/// ## Examples +/// +/// ```gleam +/// > map_error(over: Error(1), with: fn(x) { x + 1 }) +/// Error(2) +/// ``` +/// +/// ```gleam +/// > map_error(over: Ok(1), with: fn(x) { x + 1 }) +/// Ok(1) +/// ``` +/// +pub fn map_error( + over result: Result(a, e), + with fun: fn(e) -> f, +) -> Result(a, f) { + case result { + Ok(x) -> Ok(x) + Error(error) -> Error(fun(error)) + } +} + +/// Merges a nested `Result` into a single layer. +/// +/// ## Examples +/// +/// ```gleam +/// > flatten(Ok(Ok(1))) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > flatten(Ok(Error(""))) +/// Error("") +/// ``` +/// +/// ```gleam +/// > flatten(Error(Nil)) +/// Error(Nil) +/// ``` +/// +pub fn flatten(result: Result(Result(a, e), e)) -> Result(a, e) { + case result { + Ok(x) -> x + Error(error) -> Error(error) + } +} + +/// "Updates" an `Ok` result by passing its value to a function that yields a result, +/// and returning the yielded result. (This may "replace" the `Ok` with an `Error`.) +/// +/// If the input is an `Error` rather than an `Ok`, the function is not called and +/// the original `Error` is returned. +/// +/// This function is the equivalent of calling `map` followed by `flatten`, and +/// it is useful for chaining together multiple functions that may fail. +/// +/// ## Examples +/// +/// ```gleam +/// > try(Ok(1), fn(x) { Ok(x + 1) }) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > try(Ok(1), fn(x) { Ok(#("a", x)) }) +/// Ok(#("a", 1)) +/// ``` +/// +/// ```gleam +/// > try(Ok(1), fn(_) { Error("Oh no") }) +/// Error("Oh no") +/// ``` +/// +/// ```gleam +/// > try(Error(Nil), fn(x) { Ok(x + 1) }) +/// Error(Nil) +/// ``` +/// +pub fn try( + result: Result(a, e), + apply fun: fn(a) -> Result(b, e), +) -> Result(b, e) { + case result { + Ok(x) -> fun(x) + Error(e) -> Error(e) + } +} + +/// An alias for `try`. See the documentation for that function for more information. +/// +pub fn then( + result: Result(a, e), + apply fun: fn(a) -> Result(b, e), +) -> Result(b, e) { + try(result, fun) +} + +/// Extracts the `Ok` value from a result, returning a default value if the result +/// is an `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > unwrap(Ok(1), 0) +/// 1 +/// ``` +/// +/// ```gleam +/// > unwrap(Error(""), 0) +/// 0 +/// ``` +/// +pub fn unwrap(result: Result(a, e), or default: a) -> a { + case result { + Ok(v) -> v + Error(_) -> default + } +} + +/// Extracts the `Ok` value from a result, evaluating the default function if the result +/// is an `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > lazy_unwrap(Ok(1), fn() { 0 }) +/// 1 +/// ``` +/// +/// ```gleam +/// > lazy_unwrap(Error(""), fn() { 0 }) +/// 0 +/// ``` +/// +pub fn lazy_unwrap(result: Result(a, e), or default: fn() -> a) -> a { + case result { + Ok(v) -> v + Error(_) -> default() + } +} + +/// Extracts the `Error` value from a result, returning a default value if the result +/// is an `Ok`. +/// +/// ## Examples +/// +/// ```gleam +/// > unwrap_error(Error(1), 0) +/// 1 +/// ``` +/// +/// ```gleam +/// > unwrap_error(Ok(""), 0) +/// 0 +/// ``` +/// +pub fn unwrap_error(result: Result(a, e), or default: e) -> e { + case result { + Ok(_) -> default + Error(e) -> e + } +} + +/// Extracts the inner value from a result. Both the value and error must be of +/// the same type. +/// +/// ## Examples +/// +/// ```gleam +/// > unwrap_both(Error(1)) +/// 1 +/// ``` +/// +/// ```gleam +/// > unwrap_both(Ok(2)) +/// 2 +/// ``` +/// +pub fn unwrap_both(result: Result(a, a)) -> a { + case result { + Ok(a) -> a + Error(a) -> a + } +} + +/// Transforms any error into `Error(Nil)`. +/// +/// ## Examples +/// +/// ```gleam +/// > nil_error(Error(1)) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > nil_error(Ok(1)) +/// Ok(1) +/// ``` +/// +pub fn nil_error(result: Result(a, e)) -> Result(a, Nil) { + map_error(result, fn(_) { Nil }) +} + +/// Returns the first value if it is `Ok`, otherwise returns the second value. +/// +/// ## Examples +/// +/// ```gleam +/// > or(Ok(1), Ok(2)) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > or(Ok(1), Error("Error 2")) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > or(Error("Error 1"), Ok(2)) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > or(Error("Error 1"), Error("Error 2")) +/// Error("Error 2") +/// ``` +/// +pub fn or(first: Result(a, e), second: Result(a, e)) -> Result(a, e) { + case first { + Ok(_) -> first + Error(_) -> second + } +} + +/// Returns the first value if it is `Ok`, otherwise evaluates the given function for a fallback value. +/// +/// ## Examples +/// +/// ```gleam +/// > lazy_or(Ok(1), fn() { Ok(2) }) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > lazy_or(Ok(1), fn() { Error("Error 2") }) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > lazy_or(Error("Error 1"), fn() { Ok(2) }) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > lazy_or(Error("Error 1"), fn() { Error("Error 2") }) +/// Error("Error 2") +/// ``` +/// +pub fn lazy_or( + first: Result(a, e), + second: fn() -> Result(a, e), +) -> Result(a, e) { + case first { + Ok(_) -> first + Error(_) -> second() + } +} + +/// Combines a list of results into a single result. +/// If all elements in the list are `Ok` then returns an `Ok` holding the list of values. +/// If any element is `Error` then returns the first error. +/// +/// ## Examples +/// +/// ```gleam +/// > all([Ok(1), Ok(2)]) +/// Ok([1, 2]) +/// ``` +/// +/// ```gleam +/// > all([Ok(1), Error("e")]) +/// Error("e") +/// ``` +/// +pub fn all(results: List(Result(a, e))) -> Result(List(a), e) { + list.try_map(results, fn(x) { x }) +} + +/// Given a list of results, returns a pair where the first element is a list +/// of all the values inside `Ok` and the second element is a list with all the +/// values inside `Error`. The values in both lists appear in reverse order with +/// respect to their position in the original list of results. +/// +/// ## Examples +/// +/// ```gleam +/// > partition([Ok(1), Error("a"), Error("b"), Ok(2)]) +/// #([2, 1], ["b", "a"]) +/// ``` +/// +pub fn partition(results: List(Result(a, e))) -> #(List(a), List(e)) { + do_partition(results, [], []) +} + +fn do_partition(results: List(Result(a, e)), oks: List(a), errors: List(e)) { + case results { + [] -> #(oks, errors) + [Ok(a), ..rest] -> do_partition(rest, [a, ..oks], errors) + [Error(e), ..rest] -> do_partition(rest, oks, [e, ..errors]) + } +} + +/// Replace the value within a result +/// +/// ## Examples +/// +/// ```gleam +/// > replace(Ok(1), Nil) +/// Ok(Nil) +/// ``` +/// +/// ```gleam +/// > replace(Error(1), Nil) +/// Error(1) +/// ``` +/// +pub fn replace(result: Result(a, e), value: b) -> Result(b, e) { + case result { + Ok(_) -> Ok(value) + Error(error) -> Error(error) + } +} + +/// Replace the error within a result +/// +/// ## Examples +/// +/// ```gleam +/// > replace_error(Error(1), Nil) +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > replace_error(Ok(1), Nil) +/// Ok(1) +/// ``` +/// +pub fn replace_error(result: Result(a, e1), error: e2) -> Result(a, e2) { + case result { + Ok(x) -> Ok(x) + Error(_) -> Error(error) + } +} + +/// Given a list of results, returns only the values inside `Ok`. +/// +/// ## Examples +/// +/// ```gleam +/// > values([Ok(1), Error("a"), Ok(3)]) +/// [1, 3] +/// ``` +/// +pub fn values(results: List(Result(a, e))) -> List(a) { + list.filter_map(results, fn(r) { r }) +} + +/// Updates a value held within the `Error` of a result by calling a given function +/// on it, where the given function also returns a result. The two results are +/// then merged together into one result. +/// +/// If the result is an `Ok` rather than `Error` the function is not called and the +/// result stays the same. +/// +/// This function is useful for chaining together computations that may fail +/// and trying to recover from possible errors. +/// +/// ## Examples +/// +/// ```gleam +/// > Ok(1) |> try_recover(with: fn(_) { Error("failed to recover") }) +/// Ok(1) +/// ``` +/// +/// ```gleam +/// > Error(1) |> try_recover(with: fn(error) { Ok(error + 1) }) +/// Ok(2) +/// ``` +/// +/// ```gleam +/// > Error(1) |> try_recover(with: fn(error) { Error("failed to recover") }) +/// Error("failed to recover") +/// ``` +/// +pub fn try_recover( + result: Result(a, e), + with fun: fn(e) -> Result(a, f), +) -> Result(a, f) { + case result { + Ok(value) -> Ok(value) + Error(error) -> fun(error) + } +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/set.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/set.gleam new file mode 100644 index 0000000..4fd7545 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/set.gleam @@ -0,0 +1,262 @@ +import gleam/list +import gleam/dict.{type Dict} +import gleam/result + +// A list is used as the map value as an empty list has the smallest +// representation in Erlang's binary format +@target(erlang) +type Token = + List(Nil) + +@target(erlang) +const token = [] + +@target(javascript) +type Token = + Nil + +@target(javascript) +const token = Nil + +/// A set is a collection of unique members of the same type. +/// +/// It is implemented using the `gleam/map` module, so inserts and lookups have +/// logarithmic time complexity. +/// +pub opaque type Set(member) { + Set(map: Dict(member, Token)) +} + +/// Creates a new empty set. +/// +pub fn new() -> Set(member) { + Set(dict.new()) +} + +/// Gets the number of members in a set. +/// +/// This function runs in constant time. +/// +/// ## Examples +/// +/// ```gleam +/// > new() +/// > |> insert(1) +/// > |> insert(2) +/// > |> size +/// 2 +/// ``` +/// +pub fn size(set: Set(member)) -> Int { + dict.size(set.map) +} + +/// Inserts an member into the set. +/// +/// This function runs in logarithmic time. +/// +/// ## Examples +/// +/// ```gleam +/// > new() +/// > |> insert(1) +/// > |> insert(2) +/// > |> size +/// 2 +/// ``` +/// +pub fn insert(into set: Set(member), this member: member) -> Set(member) { + Set(map: dict.insert(set.map, member, token)) +} + +/// Checks whether a set contains a given member. +/// +/// This function runs in logarithmic time. +/// +/// ## Examples +/// +/// ```gleam +/// > new() +/// > |> insert(2) +/// > |> contains(2) +/// True +/// ``` +/// +/// ```gleam +/// > new() +/// > |> insert(2) +/// > |> contains(1) +/// False +/// ``` +/// +pub fn contains(in set: Set(member), this member: member) -> Bool { + set.map + |> dict.get(member) + |> result.is_ok +} + +/// Removes a member from a set. If the set does not contain the member then +/// the set is returned unchanged. +/// +/// This function runs in logarithmic time. +/// +/// ## Examples +/// +/// ```gleam +/// > new() +/// > |> insert(2) +/// > |> delete(2) +/// > |> contains(1) +/// False +/// ``` +/// +pub fn delete(from set: Set(member), this member: member) -> Set(member) { + Set(map: dict.delete(set.map, member)) +} + +/// Converts the set into a list of the contained members. +/// +/// The list has no specific ordering, any unintentional ordering may change in +/// future versions of Gleam or Erlang. +/// +/// This function runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > new() |> insert(2) |> to_list +/// [2] +/// ``` +/// +pub fn to_list(set: Set(member)) -> List(member) { + dict.keys(set.map) +} + +/// Creates a new set of the members in a given list. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/list +/// > [1, 1, 2, 4, 3, 2] |> from_list |> to_list |> list.sort +/// [1, 3, 3, 4] +/// ``` +/// +pub fn from_list(members: List(member)) -> Set(member) { + let map = + list.fold(over: members, from: dict.new(), with: fn(m, k) { + dict.insert(m, k, token) + }) + Set(map) +} + +/// Combines all entries into a single value by calling a given function on each +/// one. +/// +/// Sets are not ordered so the values are not returned in any specific order. +/// Do not write code that relies on the order entries are used by this +/// function as it may change in later versions of Gleam or Erlang. +/// +/// # Examples +/// +/// ```gleam +/// > from_list([1, 3, 9]) +/// > |> fold(0, fn(member, accumulator) { accumulator + member }) +/// 13 +/// ``` +/// +pub fn fold( + over set: Set(member), + from initial: acc, + with reducer: fn(acc, member) -> acc, +) -> acc { + dict.fold(over: set.map, from: initial, with: fn(a, k, _) { reducer(a, k) }) +} + +/// Creates a new set from an existing set, minus any members that a given +/// function returns `False` for. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > import gleam/int +/// > from_list([1, 4, 6, 3, 675, 44, 67]) +/// > |> filter(for: int.is_even) +/// > |> to_list +/// [4, 6, 44] +/// ``` +/// +pub fn filter( + in set: Set(member), + keeping predicate: fn(member) -> Bool, +) -> Set(member) { + Set(dict.filter(in: set.map, keeping: fn(m, _) { predicate(m) })) +} + +pub fn drop(from set: Set(member), drop disallowed: List(member)) -> Set(member) { + list.fold(over: disallowed, from: set, with: delete) +} + +/// Creates a new map from a given map, only including any members which are in +/// a given list. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > from_list([1, 2, 3]) +/// > |> take([1, 3, 5]) +/// > |> to_list +/// [1, 3] +/// ``` +/// +pub fn take(from set: Set(member), keeping desired: List(member)) -> Set(member) { + Set(dict.take(from: set.map, keeping: desired)) +} + +fn order(first: Set(member), second: Set(member)) -> #(Set(member), Set(member)) { + case dict.size(first.map) > dict.size(second.map) { + True -> #(first, second) + False -> #(second, first) + } +} + +/// Creates a new set that contains all members of both given sets. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > union(from_list([1, 2]), from_list([2, 3])) |> to_list +/// [1, 2, 3] +/// ``` +/// +pub fn union(of first: Set(member), and second: Set(member)) -> Set(member) { + let #(larger, smaller) = order(first, second) + fold(over: smaller, from: larger, with: insert) +} + +/// Creates a new set that contains members that are present in both given sets. +/// +/// This function runs in loglinear time. +/// +/// ## Examples +/// +/// ```gleam +/// > intersection(from_list([1, 2]), from_list([2, 3])) |> to_list +/// [2] +/// ``` +/// +pub fn intersection( + of first: Set(member), + and second: Set(member), +) -> Set(member) { + let #(larger, smaller) = order(first, second) + take(from: larger, keeping: to_list(smaller)) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/string.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/string.gleam new file mode 100644 index 0000000..652784d --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/string.gleam @@ -0,0 +1,905 @@ +//// Strings in Gleam are UTF-8 binaries. They can be written in your code as +//// text surrounded by `"double quotes"`. + +import gleam/iterator.{type Iterator} +import gleam/list +import gleam/option.{type Option, None, Some} +import gleam/order +import gleam/string_builder.{type StringBuilder} + +/// Determines if a `String` is empty. +/// +/// ## Examples +/// +/// ```gleam +/// > is_empty("") +/// True +/// ``` +/// +/// ```gleam +/// > is_empty("the world") +/// False +/// ``` +/// +pub fn is_empty(str: String) -> Bool { + str == "" +} + +/// Gets the number of grapheme clusters in a given `String`. +/// +/// This function has to iterate across the whole string to count the number of +/// graphemes, so it runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > length("Gleam") +/// 5 +/// ``` +/// +/// ```gleam +/// > length("ß↑e̊") +/// 3 +/// ``` +/// +/// ```gleam +/// > length("") +/// 0 +/// ``` +/// +pub fn length(string: String) -> Int { + do_length(string) +} + +@external(erlang, "string", "length") +@external(javascript, "../gleam_stdlib.mjs", "string_length") +fn do_length(a: String) -> Int + +/// Reverses a `String`. +/// +/// This function has to iterate across the whole `String` so it runs in linear +/// time. +/// +/// ## Examples +/// +/// ```gleam +/// > reverse("stressed") +/// "desserts" +/// ``` +/// +pub fn reverse(string: String) -> String { + do_reverse(string) +} + +@target(erlang) +fn do_reverse(string: String) -> String { + string + |> string_builder.from_string + |> string_builder.reverse + |> string_builder.to_string +} + +@target(javascript) +fn do_reverse(string: String) -> String { + string + |> to_graphemes + |> list.reverse + |> concat +} + +/// Creates a new `String` by replacing all occurrences of a given substring. +/// +/// ## Examples +/// +/// ```gleam +/// > replace("www.example.com", each: ".", with: "-") +/// "www-example-com" +/// ``` +/// +/// ```gleam +/// > replace("a,b,c,d,e", each: ",", with: "/") +/// "a/b/c/d/e" +/// ``` +/// +pub fn replace( + in string: String, + each pattern: String, + with substitute: String, +) -> String { + string + |> string_builder.from_string + |> string_builder.replace(each: pattern, with: substitute) + |> string_builder.to_string +} + +/// Creates a new `String` with all the graphemes in the input `String` converted to +/// lowercase. +/// +/// Useful for case-insensitive comparisons. +/// +/// ## Examples +/// +/// ```gleam +/// > lowercase("X-FILES") +/// "x-files" +/// ``` +/// +pub fn lowercase(string: String) -> String { + do_lowercase(string) +} + +@external(erlang, "string", "lowercase") +@external(javascript, "../gleam_stdlib.mjs", "lowercase") +fn do_lowercase(a: String) -> String + +/// Creates a new `String` with all the graphemes in the input `String` converted to +/// uppercase. +/// +/// Useful for case-insensitive comparisons and VIRTUAL YELLING. +/// +/// ## Examples +/// +/// ```gleam +/// > uppercase("skinner") +/// "SKINNER" +/// ``` +/// +pub fn uppercase(string: String) -> String { + do_uppercase(string) +} + +@external(erlang, "string", "uppercase") +@external(javascript, "../gleam_stdlib.mjs", "uppercase") +fn do_uppercase(a: String) -> String + +/// Compares two `String`s to see which is "larger" by comparing their graphemes. +/// +/// This does not compare the size or length of the given `String`s. +/// +/// ## Examples +/// +/// ```gleam +/// > compare("Anthony", "Anthony") +/// order.Eq +/// ``` +/// +/// ```gleam +/// > compare("A", "B") +/// order.Lt +/// ``` +/// +pub fn compare(a: String, b: String) -> order.Order { + case a == b { + True -> order.Eq + _ -> + case less_than(a, b) { + True -> order.Lt + _ -> order.Gt + } + } +} + +@external(erlang, "gleam_stdlib", "less_than") +@external(javascript, "../gleam_stdlib.mjs", "less_than") +fn less_than(a: String, b: String) -> Bool + +/// Takes a substring given a start grapheme index and a length. Negative indexes +/// are taken starting from the *end* of the list. +/// +/// ## Examples +/// +/// ```gleam +/// > slice(from: "gleam", at_index: 1, length: 2) +/// "le" +/// ``` +/// +/// ```gleam +/// > slice(from: "gleam", at_index: 1, length: 10) +/// "leam" +/// ``` +/// +/// ```gleam +/// > slice(from: "gleam", at_index: 10, length: 3) +/// "" +/// ``` +/// +/// ```gleam +/// > slice(from: "gleam", at_index: -2, length: 2) +/// "am" +/// ``` +/// +/// ```gleam +/// > slice(from: "gleam", at_index: -12, length: 2) +/// "" +/// ``` +/// +pub fn slice(from string: String, at_index idx: Int, length len: Int) -> String { + case len < 0 { + True -> "" + False -> + case idx < 0 { + True -> { + let translated_idx = length(string) + idx + case translated_idx < 0 { + True -> "" + False -> do_slice(string, translated_idx, len) + } + } + False -> do_slice(string, idx, len) + } + } +} + +@external(erlang, "string", "slice") +fn do_slice(string: String, idx: Int, len: Int) -> String { + string + |> to_graphemes + |> list.drop(idx) + |> list.take(len) + |> concat +} + +/// Drops contents of the first `String` that occur before the second `String`. +/// If the `from` string does not contain the `before` string, `from` is returned unchanged. +/// +/// ## Examples +/// +/// ```gleam +/// > crop(from: "The Lone Gunmen", before: "Lone") +/// "Lone Gunmen" +/// ``` +/// +@external(erlang, "gleam_stdlib", "crop_string") +@external(javascript, "../gleam_stdlib.mjs", "crop_string") +pub fn crop(from string: String, before substring: String) -> String + +/// Drops *n* graphemes from the left side of a `String`. +/// +/// ## Examples +/// +/// ```gleam +/// > drop_left(from: "The Lone Gunmen", up_to: 2) +/// "e Lone Gunmen" +/// ``` +/// +pub fn drop_left(from string: String, up_to num_graphemes: Int) -> String { + case num_graphemes < 0 { + True -> string + False -> slice(string, num_graphemes, length(string) - num_graphemes) + } +} + +/// Drops *n* graphemes from the right side of a `String`. +/// +/// ## Examples +/// +/// ```gleam +/// > drop_right(from: "Cigarette Smoking Man", up_to: 2) +/// "Cigarette Smoking M" +/// ``` +/// +pub fn drop_right(from string: String, up_to num_graphemes: Int) -> String { + case num_graphemes < 0 { + True -> string + False -> slice(string, 0, length(string) - num_graphemes) + } +} + +/// Checks if the first `String` contains the second. +/// +/// ## Examples +/// +/// ```gleam +/// > contains(does: "theory", contain: "ory") +/// True +/// ``` +/// +/// ```gleam +/// > contains(does: "theory", contain: "the") +/// True +/// ``` +/// +/// ```gleam +/// > contains(does: "theory", contain: "THE") +/// False +/// ``` +/// +@external(erlang, "gleam_stdlib", "contains_string") +@external(javascript, "../gleam_stdlib.mjs", "contains_string") +pub fn contains(does haystack: String, contain needle: String) -> Bool + +/// Checks whether the first `String` starts with the second one. +/// +/// ## Examples +/// +/// ```gleam +/// > starts_with("theory", "ory") +/// False +/// ``` +/// +pub fn starts_with(string: String, prefix: String) -> Bool { + do_starts_with(string, prefix) +} + +@external(erlang, "gleam_stdlib", "string_starts_with") +@external(javascript, "../gleam_stdlib.mjs", "starts_with") +fn do_starts_with(a: String, b: String) -> Bool + +/// Checks whether the first `String` ends with the second one. +/// +/// ## Examples +/// +/// ```gleam +/// > ends_with("theory", "ory") +/// True +/// ``` +/// +pub fn ends_with(string: String, suffix: String) -> Bool { + do_ends_with(string, suffix) +} + +@external(erlang, "gleam_stdlib", "string_ends_with") +@external(javascript, "../gleam_stdlib.mjs", "ends_with") +fn do_ends_with(a: String, b: String) -> Bool + +/// Creates a list of `String`s by splitting a given string on a given substring. +/// +/// ## Examples +/// +/// ```gleam +/// > split("home/gleam/desktop/", on: "/") +/// ["home", "gleam", "desktop", ""] +/// ``` +/// +pub fn split(x: String, on substring: String) -> List(String) { + case substring { + "" -> to_graphemes(x) + _ -> + x + |> string_builder.from_string + |> string_builder.split(on: substring) + |> list.map(with: string_builder.to_string) + } +} + +/// Splits a `String` a single time on the given substring. +/// +/// Returns an `Error` if substring not present. +/// +/// ## Examples +/// +/// ```gleam +/// > split_once("home/gleam/desktop/", on: "/") +/// Ok(#("home", "gleam/desktop/")) +/// ``` +/// +/// ```gleam +/// > split_once("home/gleam/desktop/", on: "?") +/// Error(Nil) +/// ``` +/// +pub fn split_once( + x: String, + on substring: String, +) -> Result(#(String, String), Nil) { + do_split_once(x, substring) +} + +@target(erlang) +@external(erlang, "string", "split") +fn erl_split(a: String, b: String) -> List(String) + +@target(erlang) +fn do_split_once(x: String, substring: String) -> Result(#(String, String), Nil) { + case erl_split(x, substring) { + [first, rest] -> Ok(#(first, rest)) + _ -> Error(Nil) + } +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "split_once") +fn do_split_once( + x x: String, + substring substring: String, +) -> Result(#(String, String), Nil) + +/// Creates a new `String` by joining two `String`s together. +/// +/// This function copies both `String`s and runs in linear time. If you find +/// yourself joining `String`s frequently consider using the [`string_builder`](../gleam/string_builder.html) +/// module as it can append `String`s much faster! +/// +/// ## Examples +/// +/// ```gleam +/// > append(to: "butter", suffix: "fly") +/// "butterfly" +/// ``` +/// +pub fn append(to first: String, suffix second: String) -> String { + first + |> string_builder.from_string + |> string_builder.append(second) + |> string_builder.to_string +} + +/// Creates a new `String` by joining many `String`s together. +/// +/// This function copies both `String`s and runs in linear time. If you find +/// yourself joining `String`s frequently consider using the [`string_builder`](../gleam/string_builder.html) +/// module as it can append `String`s much faster! +/// +/// ## Examples +/// +/// ```gleam +/// > concat(["never", "the", "less"]) +/// "nevertheless" +/// ``` +/// +pub fn concat(strings: List(String)) -> String { + strings + |> string_builder.from_strings + |> string_builder.to_string +} + +/// Creates a new `String` by repeating a `String` a given number of times. +/// +/// This function runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > repeat("ha", times: 3) +/// "hahaha" +/// ``` +/// +pub fn repeat(string: String, times times: Int) -> String { + iterator.repeat(string) + |> iterator.take(times) + |> iterator.to_list + |> concat +} + +/// Joins many `String`s together with a given separator. +/// +/// This function runs in linear time. +/// +/// ## Examples +/// +/// ```gleam +/// > join(["home","evan","Desktop"], with: "/") +/// "home/evan/Desktop" +/// ``` +/// +pub fn join(strings: List(String), with separator: String) -> String { + do_join(strings, separator) +} + +@external(javascript, "../gleam_stdlib.mjs", "join") +fn do_join(strings: List(String), separator: String) -> String { + strings + |> list.intersperse(with: separator) + |> concat +} + +/// Pads a `String` on the left until it has at least given number of graphemes. +/// +/// ## Examples +/// +/// ```gleam +/// > pad_left("121", to: 5, with: ".") +/// "..121" +/// ``` +/// +/// ```gleam +/// > pad_left("121", to: 3, with: ".") +/// "121" +/// ``` +/// +/// ```gleam +/// > pad_left("121", to: 2, with: ".") +/// "121" +/// ``` +/// +pub fn pad_left(string: String, to desired_length: Int, with pad_string: String) { + let current_length = length(string) + let to_pad_length = desired_length - current_length + padding(to_pad_length, pad_string) + |> iterator.append(iterator.single(string)) + |> iterator.to_list + |> concat +} + +/// Pads a `String` on the right until it has a given length. +/// +/// ## Examples +/// +/// ```gleam +/// > pad_right("123", to: 5, with: ".") +/// "123.." +/// ``` +/// +/// ```gleam +/// > pad_right("123", to: 3, with: ".") +/// "123" +/// ``` +/// +/// ```gleam +/// > pad_right("123", to: 2, with: ".") +/// "123" +/// ``` +/// +pub fn pad_right( + string: String, + to desired_length: Int, + with pad_string: String, +) { + let current_length = length(string) + let to_pad_length = desired_length - current_length + iterator.single(string) + |> iterator.append(padding(to_pad_length, pad_string)) + |> iterator.to_list + |> concat +} + +fn padding(size: Int, pad_string: String) -> Iterator(String) { + let pad_length = length(pad_string) + let num_pads = size / pad_length + let extra = size % pad_length + iterator.repeat(pad_string) + |> iterator.take(num_pads) + |> iterator.append(iterator.single(slice(pad_string, 0, extra))) +} + +/// Removes whitespace on both sides of a `String`. +/// +/// ## Examples +/// +/// ```gleam +/// > trim(" hats \n") +/// "hats" +/// ``` +/// +pub fn trim(string: String) -> String { + do_trim(string) +} + +@target(erlang) +fn do_trim(string: String) -> String { + erl_trim(string, Both) +} + +@target(erlang) +type Direction { + Leading + Trailing + Both +} + +@target(erlang) +@external(erlang, "string", "trim") +fn erl_trim(a: String, b: Direction) -> String + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "trim") +fn do_trim(string string: String) -> String + +/// Removes whitespace on the left of a `String`. +/// +/// ## Examples +/// +/// ```gleam +/// > trim_left(" hats \n") +/// "hats \n" +/// ``` +/// +pub fn trim_left(string: String) -> String { + do_trim_left(string) +} + +@target(erlang) +fn do_trim_left(string: String) -> String { + erl_trim(string, Leading) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "trim_left") +fn do_trim_left(string string: String) -> String + +/// Removes whitespace on the right of a `String`. +/// +/// ## Examples +/// +/// ```gleam +/// > trim_right(" hats \n") +/// " hats" +/// ``` +/// +pub fn trim_right(string: String) -> String { + do_trim_right(string) +} + +@target(erlang) +fn do_trim_right(string: String) -> String { + erl_trim(string, Trailing) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "trim_right") +fn do_trim_right(string string: String) -> String + +/// Splits a non-empty `String` into its first element (head) and rest (tail). +/// This lets you pattern match on `String`s exactly as you would with lists. +/// +/// Note on JavaScript using the function to iterate over a string will likely +/// be slower than using `to_graphemes` due to string slicing being more +/// expensive on JavaScript than Erlang. +/// +/// ## Examples +/// +/// ```gleam +/// > pop_grapheme("gleam") +/// Ok(#("g", "leam")) +/// ``` +/// +/// ```gleam +/// > pop_grapheme("") +/// Error(Nil) +/// ``` +/// +pub fn pop_grapheme(string: String) -> Result(#(String, String), Nil) { + do_pop_grapheme(string) +} + +@external(erlang, "gleam_stdlib", "string_pop_grapheme") +@external(javascript, "../gleam_stdlib.mjs", "pop_grapheme") +fn do_pop_grapheme(string string: String) -> Result(#(String, String), Nil) + +/// Converts a `String` to a list of +/// [graphemes](https://en.wikipedia.org/wiki/Grapheme). +/// +/// ```gleam +/// > to_graphemes("abc") +/// ["a", "b", "c"] +/// ``` +/// +@external(javascript, "../gleam_stdlib.mjs", "graphemes") +pub fn to_graphemes(string: String) -> List(String) { + do_to_graphemes(string, []) + |> list.reverse +} + +fn do_to_graphemes(string: String, acc: List(String)) -> List(String) { + case pop_grapheme(string) { + Ok(#(grapheme, rest)) -> do_to_graphemes(rest, [grapheme, ..acc]) + _ -> acc + } +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "codepoint") +fn unsafe_int_to_utf_codepoint(a: Int) -> UtfCodepoint + +/// Converts a `String` to a `List` of `UtfCodepoint`. +/// +/// See <https://en.wikipedia.org/wiki/Code_point> and +/// <https://en.wikipedia.org/wiki/Unicode#Codespace_and_Code_Points> for an +/// explanation on code points. +/// +/// ## Examples +/// +/// ```gleam +/// > "a" |> to_utf_codepoints +/// [UtfCodepoint(97)] +/// ``` +/// +/// ```gleam +/// // Semantically the same as: +/// // ["🏳", "️", "", "🌈"] or: +/// // [waving_white_flag, variant_selector_16, zero_width_joiner, rainbow] +/// > "🏳️🌈" |> to_utf_codepoints +/// [UtfCodepoint(127987), UtfCodepoint(65039), UtfCodepoint(8205), UtfCodepoint(127752)] +/// ``` +/// +pub fn to_utf_codepoints(string: String) -> List(UtfCodepoint) { + do_to_utf_codepoints(string) +} + +@target(erlang) +fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) { + do_to_utf_codepoints_impl(<<string:utf8>>, []) + |> list.reverse +} + +@target(erlang) +fn do_to_utf_codepoints_impl( + bit_array: BitArray, + acc: List(UtfCodepoint), +) -> List(UtfCodepoint) { + case bit_array { + <<first:utf8_codepoint, rest:bytes>> -> + do_to_utf_codepoints_impl(rest, [first, ..acc]) + _ -> acc + } +} + +@target(javascript) +fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) { + string + |> string_to_codepoint_integer_list + |> list.map(unsafe_int_to_utf_codepoint) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "string_to_codepoint_integer_list") +fn string_to_codepoint_integer_list(a: String) -> List(Int) + +/// Converts a `List` of `UtfCodepoint`s to a `String`. +/// +/// See <https://en.wikipedia.org/wiki/Code_point> and +/// <https://en.wikipedia.org/wiki/Unicode#Codespace_and_Code_Points> for an +/// explanation on code points. +/// +/// ## Examples +/// +/// ```gleam +/// > { +/// > let assert #(Ok(a), Ok(b), Ok(c)) = #( +/// > utf_codepoint(97), +/// > utf_codepoint(98), +/// > utf_codepoint(99), +/// > ) +/// > [a, b, c] +/// > } +/// > |> from_utf_codepoints +/// "abc" +/// ``` +/// +@external(erlang, "gleam_stdlib", "utf_codepoint_list_to_string") +@external(javascript, "../gleam_stdlib.mjs", "utf_codepoint_list_to_string") +pub fn from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String + +/// Converts an integer to a `UtfCodepoint`. +/// +/// Returns an `Error` if the integer does not represent a valid UTF codepoint. +/// +pub fn utf_codepoint(value: Int) -> Result(UtfCodepoint, Nil) { + case value { + i if i > 1_114_111 -> Error(Nil) + 65_534 | 65_535 -> Error(Nil) + i if i >= 55_296 && i <= 57_343 -> Error(Nil) + i -> Ok(unsafe_int_to_utf_codepoint(i)) + } +} + +/// Converts an UtfCodepoint to its ordinal code point value. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert [utf_codepoint, ..] = to_utf_codepoints("💜") +/// > utf_codepoint_to_int(utf_codepoint) +/// 128156 +/// ``` +/// +pub fn utf_codepoint_to_int(cp: UtfCodepoint) -> Int { + do_utf_codepoint_to_int(cp) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "utf_codepoint_to_int") +fn do_utf_codepoint_to_int(cp cp: UtfCodepoint) -> Int + +/// Converts a `String` into `Option(String)` where an empty `String` becomes +/// `None`. +/// +/// ## Examples +/// +/// ```gleam +/// > to_option("") +/// None +/// ``` +/// +/// ```gleam +/// > to_option("hats") +/// Some("hats") +/// ``` +/// +pub fn to_option(s: String) -> Option(String) { + case s { + "" -> None + _ -> Some(s) + } +} + +/// Returns the first grapheme cluster in a given `String` and wraps it in a +/// `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`. +/// Otherwise, it returns `Ok(String)`. +/// +/// ## Examples +/// +/// ```gleam +/// > first("") +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > first("icecream") +/// Ok("i") +/// ``` +/// +pub fn first(s: String) -> Result(String, Nil) { + case pop_grapheme(s) { + Ok(#(first, _)) -> Ok(first) + Error(e) -> Error(e) + } +} + +/// Returns the last grapheme cluster in a given `String` and wraps it in a +/// `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`. +/// Otherwise, it returns `Ok(String)`. +/// +/// ## Examples +/// +/// ```gleam +/// > last("") +/// Error(Nil) +/// ``` +/// +/// ```gleam +/// > last("icecream") +/// Ok("m") +/// ``` +/// +pub fn last(s: String) -> Result(String, Nil) { + case pop_grapheme(s) { + Ok(#(first, "")) -> Ok(first) + Ok(#(_, rest)) -> Ok(slice(rest, -1, 1)) + Error(e) -> Error(e) + } +} + +/// Creates a new `String` with the first grapheme in the input `String` +/// converted to uppercase and the remaining graphemes to lowercase. +/// +/// ## Examples +/// +/// ```gleam +/// > capitalise("mamouna") +/// "Mamouna" +/// ``` +/// +pub fn capitalise(s: String) -> String { + case pop_grapheme(s) { + Ok(#(first, rest)) -> append(to: uppercase(first), suffix: lowercase(rest)) + _ -> "" + } +} + +/// Returns a `String` representation of a term in Gleam syntax. +/// +pub fn inspect(term: anything) -> String { + do_inspect(term) + |> string_builder.to_string +} + +@external(erlang, "gleam_stdlib", "inspect") +@external(javascript, "../gleam_stdlib.mjs", "inspect") +fn do_inspect(term term: anything) -> StringBuilder + +/// Returns the number of bytes in a `String`. +/// +/// This function runs in constant time on Erlang and in linear time on +/// JavaScript. +/// +/// ## Examples +/// +/// ```gleam +/// > byte_size("🏳️⚧️🏳️🌈👩🏾❤️👨🏻") +/// 58 +/// ``` +/// +@external(erlang, "erlang", "byte_size") +@external(javascript, "../gleam_stdlib.mjs", "byte_size") +pub fn byte_size(string: String) -> Int diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/string_builder.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/string_builder.gleam new file mode 100644 index 0000000..5792ca8 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/string_builder.gleam @@ -0,0 +1,298 @@ +import gleam/list + +/// `StringBuilder` is a type used for efficiently building strings. +/// +/// When we append one string to another the strings must be copied to a +/// new location in memory so that they can sit together. This behaviour +/// enables efficient reading of the string but copying can be expensive, +/// especially if we want to join many strings together. +/// +/// `StringBuilder` is different in that it can be joined together in constant time +/// using minimal memory, and then can be efficiently converted to a string +/// using the `to_string` function. +/// +/// On Erlang this type is compatible with Erlang's iodata. On JavaScript this +/// type is compatible with normal strings. +/// +pub type StringBuilder + +/// Create an empty `StringBuilder`. Useful as the start of a pipe chaining many +/// builders together. +/// +pub fn new() -> StringBuilder { + do_from_strings([]) +} + +/// Prepends a `String` onto the start of some `StringBuilder`. +/// +/// Runs in constant time. +/// +pub fn prepend( + to builder: StringBuilder, + prefix prefix: String, +) -> StringBuilder { + append_builder(from_string(prefix), builder) +} + +/// Appends a `String` onto the end of some `StringBuilder`. +/// +/// Runs in constant time. +/// +pub fn append(to builder: StringBuilder, suffix second: String) -> StringBuilder { + append_builder(builder, from_string(second)) +} + +/// Prepends some `StringBuilder` onto the start of another. +/// +/// Runs in constant time. +/// +pub fn prepend_builder( + to builder: StringBuilder, + prefix prefix: StringBuilder, +) -> StringBuilder { + do_append(prefix, builder) +} + +/// Appends some `StringBuilder` onto the end of another. +/// +/// Runs in constant time. +/// +pub fn append_builder( + to builder: StringBuilder, + suffix suffix: StringBuilder, +) -> StringBuilder { + do_append(builder, suffix) +} + +@external(erlang, "gleam_stdlib", "iodata_append") +@external(javascript, "../gleam_stdlib.mjs", "add") +fn do_append(a: StringBuilder, b: StringBuilder) -> StringBuilder + +/// Converts a list of strings into a builder. +/// +/// Runs in constant time. +/// +pub fn from_strings(strings: List(String)) -> StringBuilder { + do_from_strings(strings) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "concat") +fn do_from_strings(a: List(String)) -> StringBuilder + +/// Joins a list of builders into a single builder. +/// +/// Runs in constant time. +/// +pub fn concat(builders: List(StringBuilder)) -> StringBuilder { + do_concat(builders) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "concat") +fn do_concat(a: List(StringBuilder)) -> StringBuilder + +/// Converts a string into a builder. +/// +/// Runs in constant time. +/// +pub fn from_string(string: String) -> StringBuilder { + do_from_string(string) +} + +@external(erlang, "gleam_stdlib", "identity") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_from_string(a: String) -> StringBuilder + +/// Turns an `StringBuilder` into a `String` +/// +/// This function is implemented natively by the virtual machine and is highly +/// optimised. +/// +pub fn to_string(builder: StringBuilder) -> String { + do_to_string(builder) +} + +@external(erlang, "unicode", "characters_to_binary") +@external(javascript, "../gleam_stdlib.mjs", "identity") +fn do_to_string(a: StringBuilder) -> String + +/// Returns the size of the `StringBuilder` in bytes. +/// +pub fn byte_size(builder: StringBuilder) -> Int { + do_byte_size(builder) +} + +@external(erlang, "erlang", "iolist_size") +@external(javascript, "../gleam_stdlib.mjs", "length") +fn do_byte_size(a: StringBuilder) -> Int + +/// Joins the given builders into a new builder separated with the given string +/// +pub fn join(builders: List(StringBuilder), with sep: String) -> StringBuilder { + builders + |> list.intersperse(from_string(sep)) + |> concat +} + +/// Converts a builder to a new builder where the contents have been +/// lowercased. +/// +pub fn lowercase(builder: StringBuilder) -> StringBuilder { + do_lowercase(builder) +} + +@external(erlang, "string", "lowercase") +@external(javascript, "../gleam_stdlib.mjs", "lowercase") +fn do_lowercase(a: StringBuilder) -> StringBuilder + +/// Converts a builder to a new builder where the contents have been +/// uppercased. +/// +pub fn uppercase(builder: StringBuilder) -> StringBuilder { + do_uppercase(builder) +} + +@external(erlang, "string", "uppercase") +@external(javascript, "../gleam_stdlib.mjs", "uppercase") +fn do_uppercase(a: StringBuilder) -> StringBuilder + +/// Converts a builder to a new builder with the contents reversed. +/// +pub fn reverse(builder: StringBuilder) -> StringBuilder { + do_reverse(builder) +} + +@target(erlang) +@external(erlang, "string", "reverse") +fn do_reverse(a: StringBuilder) -> StringBuilder + +@target(javascript) +fn do_reverse(builder: StringBuilder) -> StringBuilder { + builder + |> to_string + |> do_to_graphemes + |> list.reverse + |> from_strings +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "graphemes") +fn do_to_graphemes(string string: String) -> List(String) + +/// Splits a builder on a given pattern into a list of builders. +/// +pub fn split(iodata: StringBuilder, on pattern: String) -> List(StringBuilder) { + do_split(iodata, pattern) +} + +@target(erlang) +type Direction { + All +} + +@target(erlang) +@external(erlang, "string", "split") +fn erl_split(a: StringBuilder, b: String, c: Direction) -> List(StringBuilder) + +@target(erlang) +fn do_split(iodata: StringBuilder, pattern: String) -> List(StringBuilder) { + erl_split(iodata, pattern, All) +} + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "split") +fn do_split( + builder builder: StringBuilder, + pattern pattern: String, +) -> List(StringBuilder) + +/// Replaces all instances of a pattern with a given string substitute. +/// +pub fn replace( + in builder: StringBuilder, + each pattern: String, + with substitute: String, +) -> StringBuilder { + do_replace(builder, pattern, substitute) +} + +@target(erlang) +fn do_replace( + iodata: StringBuilder, + pattern: String, + substitute: String, +) -> StringBuilder { + erl_replace(iodata, pattern, substitute, All) +} + +@target(erlang) +@external(erlang, "string", "replace") +fn erl_replace( + a: StringBuilder, + b: String, + c: String, + d: Direction, +) -> StringBuilder + +@target(javascript) +@external(javascript, "../gleam_stdlib.mjs", "string_replace") +fn do_replace(a: StringBuilder, b: String, c: String) -> StringBuilder + +/// Compares two builders to determine if they have the same textual content. +/// +/// Comparing two iodata using the `==` operator may return `False` even if they +/// have the same content as they may have been build in different ways, so +/// using this function is often preferred. +/// +/// ## Examples +/// +/// ```gleam +/// > from_strings(["a", "b"]) == from_string("ab") +/// False +/// ``` +/// +/// ```gleam +/// > is_equal(from_strings(["a", "b"]), from_string("ab")) +/// True +/// ``` +/// +pub fn is_equal(a: StringBuilder, b: StringBuilder) -> Bool { + do_is_equal(a, b) +} + +@external(erlang, "string", "equal") +@external(javascript, "../gleam_stdlib.mjs", "equal") +fn do_is_equal(a: StringBuilder, b: StringBuilder) -> Bool + +/// Inspects a builder to determine if it is equivalent to an empty string. +/// +/// ## Examples +/// +/// ```gleam +/// > from_string("ok") |> is_empty +/// False +/// ``` +/// +/// ```gleam +/// > from_string("") |> is_empty +/// True +/// ``` +/// +/// ```gleam +/// > from_strings([]) |> is_empty +/// True +/// ``` +/// +pub fn is_empty(builder: StringBuilder) -> Bool { + do_is_empty(builder) +} + +@target(erlang) +@external(erlang, "string", "is_empty") +fn do_is_empty(a: StringBuilder) -> Bool + +@target(javascript) +fn do_is_empty(builder: StringBuilder) -> Bool { + from_string("") == builder +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/uri.gleam b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/uri.gleam new file mode 100644 index 0000000..11f6ea6 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/uri.gleam @@ -0,0 +1,462 @@ +//// Utilities for working with URIs +//// +//// This module provides functions for working with URIs (for example, parsing +//// URIs or encoding query strings). The functions in this module are implemented +//// according to [RFC 3986](https://tools.ietf.org/html/rfc3986). +//// +//// Query encoding (Form encoding) is defined in the +//// [W3C specification](https://www.w3.org/TR/html52/sec-forms.html#urlencoded-form-data). + +import gleam/int +import gleam/list +import gleam/option.{type Option, None, Some} +import gleam/string +import gleam/string_builder.{type StringBuilder} +@target(javascript) +import gleam/pair +@target(javascript) +import gleam/regex +@target(javascript) +import gleam/result + +/// Type representing holding the parsed components of an URI. +/// All components of a URI are optional, except the path. +/// +pub type Uri { + Uri( + scheme: Option(String), + userinfo: Option(String), + host: Option(String), + port: Option(Int), + path: String, + query: Option(String), + fragment: Option(String), + ) +} + +/// Parses a compliant URI string into the `Uri` Type. +/// If the string is not a valid URI string then an error is returned. +/// +/// The opposite operation is `uri.to_string`. +/// +/// ## Examples +/// +/// ```gleam +/// > parse("https://example.com:1234/a/b?query=true#fragment") +/// Ok( +/// Uri( +/// scheme: Some("https"), +/// userinfo: None, +/// host: Some("example.com"), +/// port: Some(1234), +/// path: "/a/b", +/// query: Some("query=true"), +/// fragment: Some("fragment") +/// ) +/// ) +/// ``` +/// +pub fn parse(uri_string: String) -> Result(Uri, Nil) { + do_parse(uri_string) +} + +@target(erlang) +@external(erlang, "gleam_stdlib", "uri_parse") +fn do_parse(a: String) -> Result(Uri, Nil) + +@target(javascript) +fn do_parse(uri_string: String) -> Result(Uri, Nil) { + // From https://tools.ietf.org/html/rfc3986#appendix-B + let pattern = + // 12 3 4 5 6 7 8 + "^(([a-z][a-z0-9\\+\\-\\.]*):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#.*)?" + let matches = + pattern + |> regex_submatches(uri_string) + |> pad_list(8) + + let #(scheme, authority, path, query, fragment) = case matches { + [ + _scheme_with_colon, + scheme, + authority_with_slashes, + _authority, + path, + query_with_question_mark, + _query, + fragment, + ] -> #( + scheme, + authority_with_slashes, + path, + query_with_question_mark, + fragment, + ) + _ -> #(None, None, None, None, None) + } + + let scheme = noneify_empty_string(scheme) + let path = option.unwrap(path, "") + let query = noneify_query(query) + let #(userinfo, host, port) = split_authority(authority) + let fragment = + fragment + |> option.to_result(Nil) + |> result.try(string.pop_grapheme) + |> result.map(pair.second) + |> option.from_result + let scheme = + scheme + |> noneify_empty_string + |> option.map(string.lowercase) + Ok(Uri( + scheme: scheme, + userinfo: userinfo, + host: host, + port: port, + path: path, + query: query, + fragment: fragment, + )) +} + +@target(javascript) +fn regex_submatches(pattern: String, string: String) -> List(Option(String)) { + pattern + |> regex.compile(regex.Options(case_insensitive: True, multi_line: False)) + |> result.nil_error + |> result.map(regex.scan(_, string)) + |> result.try(list.first) + |> result.map(fn(m: regex.Match) { m.submatches }) + |> result.unwrap([]) +} + +@target(javascript) +fn noneify_query(x: Option(String)) -> Option(String) { + case x { + None -> None + Some(x) -> + case string.pop_grapheme(x) { + Ok(#("?", query)) -> Some(query) + _ -> None + } + } +} + +@target(javascript) +fn noneify_empty_string(x: Option(String)) -> Option(String) { + case x { + Some("") | None -> None + Some(_) -> x + } +} + +// Split an authority into its userinfo, host and port parts. +@target(javascript) +fn split_authority( + authority: Option(String), +) -> #(Option(String), Option(String), Option(Int)) { + case option.unwrap(authority, "") { + "" -> #(None, None, None) + "//" -> #(None, Some(""), None) + authority -> { + let matches = + "^(//)?((.*)@)?(\\[[a-zA-Z0-9:.]*\\]|[^:]*)(:(\\d*))?" + |> regex_submatches(authority) + |> pad_list(6) + case matches { + [_, _, userinfo, host, _, port] -> { + let userinfo = noneify_empty_string(userinfo) + let host = noneify_empty_string(host) + let port = + port + |> option.unwrap("") + |> int.parse + |> option.from_result + #(userinfo, host, port) + } + _ -> #(None, None, None) + } + } + } +} + +@target(javascript) +fn pad_list(list: List(Option(a)), size: Int) -> List(Option(a)) { + list + |> list.append(list.repeat(None, extra_required(list, size))) +} + +@target(javascript) +fn extra_required(list: List(a), remaining: Int) -> Int { + case list { + _ if remaining == 0 -> 0 + [] -> remaining + [_, ..xs] -> extra_required(xs, remaining - 1) + } +} + +/// Parses an urlencoded query string into a list of key value pairs. +/// Returns an error for invalid encoding. +/// +/// The opposite operation is `uri.query_to_string`. +/// +/// ## Examples +/// +/// ```gleam +/// > parse_query("a=1&b=2") +/// Ok([#("a", "1"), #("b", "2")]) +/// ``` +/// +pub fn parse_query(query: String) -> Result(List(#(String, String)), Nil) { + do_parse_query(query) +} + +@external(erlang, "gleam_stdlib", "parse_query") +@external(javascript, "../gleam_stdlib.mjs", "parse_query") +fn do_parse_query(a: String) -> Result(List(#(String, String)), Nil) + +/// Encodes a list of key value pairs as a URI query string. +/// +/// The opposite operation is `uri.parse_query`. +/// +/// ## Examples +/// +/// ```gleam +/// > query_to_string([#("a", "1"), #("b", "2")]) +/// "a=1&b=2" +/// ``` +/// +pub fn query_to_string(query: List(#(String, String))) -> String { + query + |> list.map(query_pair) + |> list.intersperse(string_builder.from_string("&")) + |> string_builder.concat + |> string_builder.to_string +} + +fn query_pair(pair: #(String, String)) -> StringBuilder { + string_builder.from_strings([ + percent_encode(pair.0), + "=", + percent_encode(pair.1), + ]) +} + +/// Encodes a string into a percent encoded representation. +/// +/// ## Examples +/// +/// ```gleam +/// > percent_encode("100% great") +/// "100%25%20great" +/// ``` +/// +pub fn percent_encode(value: String) -> String { + do_percent_encode(value) +} + +@external(erlang, "gleam_stdlib", "percent_encode") +@external(javascript, "../gleam_stdlib.mjs", "percent_encode") +fn do_percent_encode(a: String) -> String + +/// Decodes a percent encoded string. +/// +/// ## Examples +/// +/// ```gleam +/// > percent_decode("100%25+great") +/// Ok("100% great") +/// ``` +/// +pub fn percent_decode(value: String) -> Result(String, Nil) { + do_percent_decode(value) +} + +@external(erlang, "gleam_stdlib", "percent_decode") +@external(javascript, "../gleam_stdlib.mjs", "percent_decode") +fn do_percent_decode(a: String) -> Result(String, Nil) + +fn do_remove_dot_segments( + input: List(String), + accumulator: List(String), +) -> List(String) { + case input { + [] -> list.reverse(accumulator) + [segment, ..rest] -> { + let accumulator = case segment, accumulator { + "", accumulator -> accumulator + ".", accumulator -> accumulator + "..", [] -> [] + "..", [_, ..accumulator] -> accumulator + segment, accumulator -> [segment, ..accumulator] + } + do_remove_dot_segments(rest, accumulator) + } + } +} + +fn remove_dot_segments(input: List(String)) -> List(String) { + do_remove_dot_segments(input, []) +} + +/// Splits the path section of a URI into it's constituent segments. +/// +/// Removes empty segments and resolves dot-segments as specified in +/// [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC. +/// +/// ## Examples +/// +/// ```gleam +/// > path_segments("/users/1") +/// ["users" ,"1"] +/// ``` +/// +pub fn path_segments(path: String) -> List(String) { + remove_dot_segments(string.split(path, "/")) +} + +/// Encodes a `Uri` value as a URI string. +/// +/// The opposite operation is `uri.parse`. +/// +/// ## Examples +/// +/// ```gleam +/// > let uri = Uri(Some("http"), None, Some("example.com"), ...) +/// > to_string(uri) +/// "http://example.com" +/// ``` +/// +pub fn to_string(uri: Uri) -> String { + let parts = case uri.fragment { + Some(fragment) -> ["#", fragment] + _ -> [] + } + let parts = case uri.query { + Some(query) -> ["?", query, ..parts] + _ -> parts + } + let parts = [uri.path, ..parts] + let parts = case uri.host, string.starts_with(uri.path, "/") { + Some(host), False if host != "" -> ["/", ..parts] + _, _ -> parts + } + let parts = case uri.host, uri.port { + Some(_), Some(port) -> [":", int.to_string(port), ..parts] + _, _ -> parts + } + let parts = case uri.scheme, uri.userinfo, uri.host { + Some(s), Some(u), Some(h) -> [s, "://", u, "@", h, ..parts] + Some(s), None, Some(h) -> [s, "://", h, ..parts] + Some(s), Some(_), None | Some(s), None, None -> [s, ":", ..parts] + None, None, Some(h) -> ["//", h, ..parts] + _, _, _ -> parts + } + string.concat(parts) +} + +/// Fetches the origin of a URI. +/// +/// Returns the origin of a uri as defined in +/// [RFC 6454](https://tools.ietf.org/html/rfc6454) +/// +/// The supported URI schemes are `http` and `https`. +/// URLs without a scheme will return `Error`. +/// +/// ## Examples +/// +/// ```gleam +/// > let assert Ok(uri) = parse("http://example.com/path?foo#bar") +/// > origin(uri) +/// Ok("http://example.com") +/// ``` +/// +pub fn origin(uri: Uri) -> Result(String, Nil) { + let Uri(scheme: scheme, host: host, port: port, ..) = uri + case scheme { + Some("https") if port == Some(443) -> { + let origin = Uri(scheme, None, host, None, "", None, None) + Ok(to_string(origin)) + } + Some("http") if port == Some(80) -> { + let origin = Uri(scheme, None, host, None, "", None, None) + Ok(to_string(origin)) + } + Some(s) if s == "http" || s == "https" -> { + let origin = Uri(scheme, None, host, port, "", None, None) + Ok(to_string(origin)) + } + _ -> Error(Nil) + } +} + +fn drop_last(elements: List(a)) -> List(a) { + list.take(from: elements, up_to: list.length(elements) - 1) +} + +fn join_segments(segments: List(String)) -> String { + string.join(["", ..segments], "/") +} + +/// Resolves a URI with respect to the given base URI. +/// +/// The base URI must be an absolute URI or this function will return an error. +/// The algorithm for merging uris is described in +/// [RFC 3986](https://tools.ietf.org/html/rfc3986#section-5.2). +/// +pub fn merge(base: Uri, relative: Uri) -> Result(Uri, Nil) { + case base { + Uri(scheme: Some(_), host: Some(_), ..) -> + case relative { + Uri(host: Some(_), ..) -> { + let path = + string.split(relative.path, "/") + |> remove_dot_segments() + |> join_segments() + let resolved = + Uri( + option.or(relative.scheme, base.scheme), + None, + relative.host, + option.or(relative.port, base.port), + path, + relative.query, + relative.fragment, + ) + Ok(resolved) + } + _ -> { + let #(new_path, new_query) = case relative.path { + "" -> #(base.path, option.or(relative.query, base.query)) + _ -> { + let path_segments = case string.starts_with(relative.path, "/") { + True -> string.split(relative.path, "/") + False -> + string.split(base.path, "/") + |> drop_last() + |> list.append(string.split(relative.path, "/")) + } + let path = + path_segments + |> remove_dot_segments() + |> join_segments() + #(path, relative.query) + } + } + let resolved = + Uri( + base.scheme, + None, + base.host, + base.port, + new_path, + new_query, + relative.fragment, + ) + Ok(resolved) + } + } + _ -> Error(Nil) + } +} diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@base.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@base.erl new file mode 100644 index 0000000..d8d44c3 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@base.erl @@ -0,0 +1,20 @@ +-module(gleam@base). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([encode64/2, decode64/1, url_encode64/2, url_decode64/1]). + +-spec encode64(bitstring(), boolean()) -> binary(). +encode64(Input, Padding) -> + gleam@bit_array:base64_encode(Input, Padding). + +-spec decode64(binary()) -> {ok, bitstring()} | {error, nil}. +decode64(Encoded) -> + gleam@bit_array:base64_decode(Encoded). + +-spec url_encode64(bitstring(), boolean()) -> binary(). +url_encode64(Input, Padding) -> + gleam@bit_array:base64_url_encode(Input, Padding). + +-spec url_decode64(binary()) -> {ok, bitstring()} | {error, nil}. +url_decode64(Encoded) -> + gleam@bit_array:base64_url_decode(Encoded). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_array.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_array.erl new file mode 100644 index 0000000..ae8e5ff --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_array.erl @@ -0,0 +1,102 @@ +-module(gleam@bit_array). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([from_string/1, byte_size/1, slice/3, is_utf8/1, to_string/1, concat/1, append/2, base64_encode/2, base64_decode/1, base64_url_encode/2, base64_url_decode/1, base16_encode/1, base16_decode/1]). + +-spec from_string(binary()) -> bitstring(). +from_string(X) -> + gleam_stdlib:identity(X). + +-spec byte_size(bitstring()) -> integer(). +byte_size(X) -> + erlang:byte_size(X). + +-spec slice(bitstring(), integer(), integer()) -> {ok, bitstring()} | + {error, nil}. +slice(String, Position, Length) -> + gleam_stdlib:bit_array_slice(String, Position, Length). + +-spec do_is_utf8(bitstring()) -> boolean(). +do_is_utf8(Bits) -> + case Bits of + <<>> -> + true; + + <<_/utf8, Rest/binary>> -> + do_is_utf8(Rest); + + _ -> + false + end. + +-spec is_utf8(bitstring()) -> boolean(). +is_utf8(Bits) -> + do_is_utf8(Bits). + +-spec do_to_string(bitstring()) -> {ok, binary()} | {error, nil}. +do_to_string(Bits) -> + case is_utf8(Bits) of + true -> + {ok, gleam_stdlib:identity(Bits)}; + + false -> + {error, nil} + end. + +-spec to_string(bitstring()) -> {ok, binary()} | {error, nil}. +to_string(Bits) -> + do_to_string(Bits). + +-spec concat(list(bitstring())) -> bitstring(). +concat(Bit_arrays) -> + gleam_stdlib:bit_array_concat(Bit_arrays). + +-spec append(bitstring(), bitstring()) -> bitstring(). +append(First, Second) -> + gleam_stdlib:bit_array_concat([First, Second]). + +-spec base64_encode(bitstring(), boolean()) -> binary(). +base64_encode(Input, Padding) -> + Encoded = base64:encode(Input), + case Padding of + true -> + Encoded; + + false -> + gleam@string:replace(Encoded, <<"="/utf8>>, <<""/utf8>>) + end. + +-spec base64_decode(binary()) -> {ok, bitstring()} | {error, nil}. +base64_decode(Encoded) -> + Padded = case erlang:byte_size(gleam_stdlib:identity(Encoded)) rem 4 of + 0 -> + Encoded; + + N -> + gleam@string:append( + Encoded, + gleam@string:repeat(<<"="/utf8>>, 4 - N) + ) + end, + gleam_stdlib:base_decode64(Padded). + +-spec base64_url_encode(bitstring(), boolean()) -> binary(). +base64_url_encode(Input, Padding) -> + _pipe = base64_encode(Input, Padding), + _pipe@1 = gleam@string:replace(_pipe, <<"+"/utf8>>, <<"-"/utf8>>), + gleam@string:replace(_pipe@1, <<"/"/utf8>>, <<"_"/utf8>>). + +-spec base64_url_decode(binary()) -> {ok, bitstring()} | {error, nil}. +base64_url_decode(Encoded) -> + _pipe = Encoded, + _pipe@1 = gleam@string:replace(_pipe, <<"-"/utf8>>, <<"+"/utf8>>), + _pipe@2 = gleam@string:replace(_pipe@1, <<"_"/utf8>>, <<"/"/utf8>>), + base64_decode(_pipe@2). + +-spec base16_encode(bitstring()) -> binary(). +base16_encode(Input) -> + binary:encode_hex(Input). + +-spec base16_decode(binary()) -> {ok, bitstring()} | {error, nil}. +base16_decode(Input) -> + gleam_stdlib:base16_decode(Input). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_builder.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_builder.erl new file mode 100644 index 0000000..648605f --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_builder.erl @@ -0,0 +1,66 @@ +-module(gleam@bit_builder). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([new/0, prepend/2, append/2, prepend_builder/2, append_builder/2, prepend_string/2, append_string/2, concat/1, concat_bit_strings/1, from_string/1, from_string_builder/1, from_bit_string/1, to_bit_string/1, byte_size/1]). + +-spec new() -> gleam@bytes_builder:bytes_builder(). +new() -> + gleam@bytes_builder:new(). + +-spec prepend(gleam@bytes_builder:bytes_builder(), bitstring()) -> gleam@bytes_builder:bytes_builder(). +prepend(To, Prefix) -> + gleam@bytes_builder:prepend(To, Prefix). + +-spec append(gleam@bytes_builder:bytes_builder(), bitstring()) -> gleam@bytes_builder:bytes_builder(). +append(To, Suffix) -> + gleam@bytes_builder:append(To, Suffix). + +-spec prepend_builder( + gleam@bytes_builder:bytes_builder(), + gleam@bytes_builder:bytes_builder() +) -> gleam@bytes_builder:bytes_builder(). +prepend_builder(To, Prefix) -> + gleam@bytes_builder:prepend_builder(To, Prefix). + +-spec append_builder( + gleam@bytes_builder:bytes_builder(), + gleam@bytes_builder:bytes_builder() +) -> gleam@bytes_builder:bytes_builder(). +append_builder(First, Second) -> + gleam_stdlib:iodata_append(First, Second). + +-spec prepend_string(gleam@bytes_builder:bytes_builder(), binary()) -> gleam@bytes_builder:bytes_builder(). +prepend_string(To, Prefix) -> + gleam@bytes_builder:prepend_string(To, Prefix). + +-spec append_string(gleam@bytes_builder:bytes_builder(), binary()) -> gleam@bytes_builder:bytes_builder(). +append_string(To, Suffix) -> + gleam@bytes_builder:append_string(To, Suffix). + +-spec concat(list(gleam@bytes_builder:bytes_builder())) -> gleam@bytes_builder:bytes_builder(). +concat(Builders) -> + gleam_stdlib:identity(Builders). + +-spec concat_bit_strings(list(bitstring())) -> gleam@bytes_builder:bytes_builder(). +concat_bit_strings(Bits) -> + gleam_stdlib:identity(Bits). + +-spec from_string(binary()) -> gleam@bytes_builder:bytes_builder(). +from_string(String) -> + gleam_stdlib:wrap_list(String). + +-spec from_string_builder(gleam@string_builder:string_builder()) -> gleam@bytes_builder:bytes_builder(). +from_string_builder(Builder) -> + gleam_stdlib:wrap_list(Builder). + +-spec from_bit_string(bitstring()) -> gleam@bytes_builder:bytes_builder(). +from_bit_string(Bits) -> + gleam_stdlib:wrap_list(Bits). + +-spec to_bit_string(gleam@bytes_builder:bytes_builder()) -> bitstring(). +to_bit_string(Builder) -> + erlang:list_to_bitstring(Builder). + +-spec byte_size(gleam@bytes_builder:bytes_builder()) -> integer(). +byte_size(Builder) -> + erlang:iolist_size(Builder). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_string.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_string.erl new file mode 100644 index 0000000..d1eea04 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_string.erl @@ -0,0 +1,33 @@ +-module(gleam@bit_string). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([from_string/1, byte_size/1, append/2, slice/3, is_utf8/1, to_string/1, concat/1]). + +-spec from_string(binary()) -> bitstring(). +from_string(X) -> + gleam_stdlib:identity(X). + +-spec byte_size(bitstring()) -> integer(). +byte_size(X) -> + erlang:byte_size(X). + +-spec append(bitstring(), bitstring()) -> bitstring(). +append(First, Second) -> + gleam@bit_array:append(First, Second). + +-spec slice(bitstring(), integer(), integer()) -> {ok, bitstring()} | + {error, nil}. +slice(String, Position, Length) -> + gleam_stdlib:bit_array_slice(String, Position, Length). + +-spec is_utf8(bitstring()) -> boolean(). +is_utf8(Bits) -> + gleam@bit_array:is_utf8(Bits). + +-spec to_string(bitstring()) -> {ok, binary()} | {error, nil}. +to_string(Bits) -> + gleam@bit_array:to_string(Bits). + +-spec concat(list(bitstring())) -> bitstring(). +concat(Bit_strings) -> + gleam_stdlib:bit_array_concat(Bit_strings). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bool.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bool.erl new file mode 100644 index 0000000..4881f2b --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bool.erl @@ -0,0 +1,162 @@ +-module(gleam@bool). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export(['and'/2, 'or'/2, negate/1, nor/2, nand/2, exclusive_or/2, exclusive_nor/2, compare/2, max/2, min/2, to_int/1, to_string/1, guard/3, lazy_guard/3]). + +-spec 'and'(boolean(), boolean()) -> boolean(). +'and'(A, B) -> + A andalso B. + +-spec 'or'(boolean(), boolean()) -> boolean(). +'or'(A, B) -> + A orelse B. + +-spec negate(boolean()) -> boolean(). +negate(Bool) -> + case Bool of + true -> + false; + + false -> + true + end. + +-spec nor(boolean(), boolean()) -> boolean(). +nor(A, B) -> + case {A, B} of + {false, false} -> + true; + + {false, true} -> + false; + + {true, false} -> + false; + + {true, true} -> + false + end. + +-spec nand(boolean(), boolean()) -> boolean(). +nand(A, B) -> + case {A, B} of + {false, false} -> + true; + + {false, true} -> + true; + + {true, false} -> + true; + + {true, true} -> + false + end. + +-spec exclusive_or(boolean(), boolean()) -> boolean(). +exclusive_or(A, B) -> + case {A, B} of + {false, false} -> + false; + + {false, true} -> + true; + + {true, false} -> + true; + + {true, true} -> + false + end. + +-spec exclusive_nor(boolean(), boolean()) -> boolean(). +exclusive_nor(A, B) -> + case {A, B} of + {false, false} -> + true; + + {false, true} -> + false; + + {true, false} -> + false; + + {true, true} -> + true + end. + +-spec compare(boolean(), boolean()) -> gleam@order:order(). +compare(A, B) -> + case {A, B} of + {true, true} -> + eq; + + {true, false} -> + gt; + + {false, false} -> + eq; + + {false, true} -> + lt + end. + +-spec max(boolean(), boolean()) -> boolean(). +max(A, B) -> + case A of + true -> + true; + + false -> + B + end. + +-spec min(boolean(), boolean()) -> boolean(). +min(A, B) -> + case A of + false -> + false; + + true -> + B + end. + +-spec to_int(boolean()) -> integer(). +to_int(Bool) -> + case Bool of + false -> + 0; + + true -> + 1 + end. + +-spec to_string(boolean()) -> binary(). +to_string(Bool) -> + case Bool of + false -> + <<"False"/utf8>>; + + true -> + <<"True"/utf8>> + end. + +-spec guard(boolean(), DCG, fun(() -> DCG)) -> DCG. +guard(Requirement, Consequence, Alternative) -> + case Requirement of + true -> + Consequence; + + false -> + Alternative() + end. + +-spec lazy_guard(boolean(), fun(() -> DCH), fun(() -> DCH)) -> DCH. +lazy_guard(Requirement, Consequence, Alternative) -> + case Requirement of + true -> + Consequence(); + + false -> + Alternative() + end. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bytes_builder.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bytes_builder.erl new file mode 100644 index 0000000..61851fc --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bytes_builder.erl @@ -0,0 +1,87 @@ +-module(gleam@bytes_builder). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([append_builder/2, prepend_builder/2, concat/1, new/0, from_string/1, prepend_string/2, append_string/2, from_string_builder/1, from_bit_array/1, prepend/2, append/2, concat_bit_arrays/1, to_bit_array/1, byte_size/1]). +-export_type([bytes_builder/0]). + +-opaque bytes_builder() :: {bytes, bitstring()} | + {text, gleam@string_builder:string_builder()} | + {many, list(bytes_builder())}. + +-spec append_builder(bytes_builder(), bytes_builder()) -> bytes_builder(). +append_builder(First, Second) -> + gleam_stdlib:iodata_append(First, Second). + +-spec prepend_builder(bytes_builder(), bytes_builder()) -> bytes_builder(). +prepend_builder(Second, First) -> + gleam_stdlib:iodata_append(First, Second). + +-spec concat(list(bytes_builder())) -> bytes_builder(). +concat(Builders) -> + gleam_stdlib:identity(Builders). + +-spec new() -> bytes_builder(). +new() -> + gleam_stdlib:identity([]). + +-spec from_string(binary()) -> bytes_builder(). +from_string(String) -> + gleam_stdlib:wrap_list(String). + +-spec prepend_string(bytes_builder(), binary()) -> bytes_builder(). +prepend_string(Second, First) -> + gleam_stdlib:iodata_append(gleam_stdlib:wrap_list(First), Second). + +-spec append_string(bytes_builder(), binary()) -> bytes_builder(). +append_string(First, Second) -> + gleam_stdlib:iodata_append(First, gleam_stdlib:wrap_list(Second)). + +-spec from_string_builder(gleam@string_builder:string_builder()) -> bytes_builder(). +from_string_builder(Builder) -> + gleam_stdlib:wrap_list(Builder). + +-spec from_bit_array(bitstring()) -> bytes_builder(). +from_bit_array(Bits) -> + gleam_stdlib:wrap_list(Bits). + +-spec prepend(bytes_builder(), bitstring()) -> bytes_builder(). +prepend(Second, First) -> + gleam_stdlib:iodata_append(gleam_stdlib:wrap_list(First), Second). + +-spec append(bytes_builder(), bitstring()) -> bytes_builder(). +append(First, Second) -> + gleam_stdlib:iodata_append(First, gleam_stdlib:wrap_list(Second)). + +-spec concat_bit_arrays(list(bitstring())) -> bytes_builder(). +concat_bit_arrays(Bits) -> + gleam_stdlib:identity(Bits). + +-spec to_list(list(list(bytes_builder())), list(bitstring())) -> list(bitstring()). +to_list(Stack, Acc) -> + case Stack of + [] -> + Acc; + + [[] | Remaining_stack] -> + to_list(Remaining_stack, Acc); + + [[{bytes, Bits} | Rest] | Remaining_stack@1] -> + to_list([Rest | Remaining_stack@1], [Bits | Acc]); + + [[{text, Builder} | Rest@1] | Remaining_stack@2] -> + Bits@1 = gleam_stdlib:identity( + gleam@string_builder:to_string(Builder) + ), + to_list([Rest@1 | Remaining_stack@2], [Bits@1 | Acc]); + + [[{many, Builders} | Rest@2] | Remaining_stack@3] -> + to_list([Builders, Rest@2 | Remaining_stack@3], Acc) + end. + +-spec to_bit_array(bytes_builder()) -> bitstring(). +to_bit_array(Builder) -> + erlang:list_to_bitstring(Builder). + +-spec byte_size(bytes_builder()) -> integer(). +byte_size(Builder) -> + erlang:iolist_size(Builder). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@dict.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@dict.erl new file mode 100644 index 0000000..250f5b8 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@dict.erl @@ -0,0 +1,171 @@ +-module(gleam@dict). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([size/1, to_list/1, new/0, get/2, has_key/2, insert/3, from_list/1, keys/1, values/1, take/2, merge/2, delete/2, drop/2, update/3, fold/3, map_values/2, filter/2]). +-export_type([dict/2]). + +-type dict(KS, KT) :: any() | {gleam_phantom, KS, KT}. + +-spec size(dict(any(), any())) -> integer(). +size(Dict) -> + maps:size(Dict). + +-spec to_list(dict(KY, KZ)) -> list({KY, KZ}). +to_list(Dict) -> + maps:to_list(Dict). + +-spec new() -> dict(any(), any()). +new() -> + maps:new(). + +-spec get(dict(MF, MG), MF) -> {ok, MG} | {error, nil}. +get(From, Get) -> + gleam_stdlib:map_get(From, Get). + +-spec has_key(dict(LP, any()), LP) -> boolean(). +has_key(Dict, Key) -> + maps:is_key(Key, Dict). + +-spec insert(dict(MR, MS), MR, MS) -> dict(MR, MS). +insert(Dict, Key, Value) -> + maps:put(Key, Value, Dict). + +-spec fold_list_of_pair(list({LI, LJ}), dict(LI, LJ)) -> dict(LI, LJ). +fold_list_of_pair(List, Initial) -> + case List of + [] -> + Initial; + + [X | Rest] -> + fold_list_of_pair( + Rest, + insert(Initial, erlang:element(1, X), erlang:element(2, X)) + ) + end. + +-spec from_list(list({LD, LE})) -> dict(LD, LE). +from_list(List) -> + maps:from_list(List). + +-spec reverse_and_concat(list(TS), list(TS)) -> list(TS). +reverse_and_concat(Remaining, Accumulator) -> + case Remaining of + [] -> + Accumulator; + + [Item | Rest] -> + reverse_and_concat(Rest, [Item | Accumulator]) + end. + +-spec do_keys_acc(list({OE, any()}), list(OE)) -> list(OE). +do_keys_acc(List, Acc) -> + case List of + [] -> + reverse_and_concat(Acc, []); + + [X | Xs] -> + do_keys_acc(Xs, [erlang:element(1, X) | Acc]) + end. + +-spec keys(dict(NR, any())) -> list(NR). +keys(Dict) -> + maps:keys(Dict). + +-spec do_values_acc(list({any(), OU}), list(OU)) -> list(OU). +do_values_acc(List, Acc) -> + case List of + [] -> + reverse_and_concat(Acc, []); + + [X | Xs] -> + do_values_acc(Xs, [erlang:element(2, X) | Acc]) + end. + +-spec values(dict(any(), OK)) -> list(OK). +values(Dict) -> + maps:values(Dict). + +-spec insert_taken(dict(PY, PZ), list(PY), dict(PY, PZ)) -> dict(PY, PZ). +insert_taken(Dict, Desired_keys, Acc) -> + Insert = fun(Taken, Key) -> case get(Dict, Key) of + {ok, Value} -> + insert(Taken, Key, Value); + + _ -> + Taken + end end, + case Desired_keys of + [] -> + Acc; + + [X | Xs] -> + insert_taken(Dict, Xs, Insert(Acc, X)) + end. + +-spec take(dict(PK, PL), list(PK)) -> dict(PK, PL). +take(Dict, Desired_keys) -> + maps:with(Desired_keys, Dict). + +-spec insert_pair(dict(QX, QY), {QX, QY}) -> dict(QX, QY). +insert_pair(Dict, Pair) -> + insert(Dict, erlang:element(1, Pair), erlang:element(2, Pair)). + +-spec fold_inserts(list({RD, RE}), dict(RD, RE)) -> dict(RD, RE). +fold_inserts(New_entries, Dict) -> + case New_entries of + [] -> + Dict; + + [X | Xs] -> + fold_inserts(Xs, insert_pair(Dict, X)) + end. + +-spec merge(dict(QH, QI), dict(QH, QI)) -> dict(QH, QI). +merge(Dict, New_entries) -> + maps:merge(Dict, New_entries). + +-spec delete(dict(RK, RL), RK) -> dict(RK, RL). +delete(Dict, Key) -> + maps:remove(Key, Dict). + +-spec drop(dict(RW, RX), list(RW)) -> dict(RW, RX). +drop(Dict, Disallowed_keys) -> + case Disallowed_keys of + [] -> + Dict; + + [X | Xs] -> + drop(delete(Dict, X), Xs) + end. + +-spec update(dict(SD, SE), SD, fun((gleam@option:option(SE)) -> SE)) -> dict(SD, SE). +update(Dict, Key, Fun) -> + _pipe = Dict, + _pipe@1 = get(_pipe, Key), + _pipe@2 = gleam@option:from_result(_pipe@1), + _pipe@3 = Fun(_pipe@2), + insert(Dict, Key, _pipe@3). + +-spec do_fold(list({SK, SL}), SN, fun((SN, SK, SL) -> SN)) -> SN. +do_fold(List, Initial, Fun) -> + case List of + [] -> + Initial; + + [{K, V} | Rest] -> + do_fold(Rest, Fun(Initial, K, V), Fun) + end. + +-spec fold(dict(SO, SP), SS, fun((SS, SO, SP) -> SS)) -> SS. +fold(Dict, Initial, Fun) -> + _pipe = Dict, + _pipe@1 = maps:to_list(_pipe), + do_fold(_pipe@1, Initial, Fun). + +-spec map_values(dict(ND, NE), fun((ND, NE) -> NH)) -> dict(ND, NH). +map_values(Dict, Fun) -> + maps:map(Fun, Dict). + +-spec filter(dict(OY, OZ), fun((OY, OZ) -> boolean())) -> dict(OY, OZ). +filter(Dict, Predicate) -> + maps:filter(Predicate, Dict). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@dynamic.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@dynamic.erl new file mode 100644 index 0000000..f7ebb42 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@dynamic.erl @@ -0,0 +1,808 @@ +-module(gleam@dynamic). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([from/1, unsafe_coerce/1, dynamic/1, bit_array/1, bit_string/1, classify/1, int/1, float/1, bool/1, shallow_list/1, optional/1, any/1, decode1/2, result/2, list/1, string/1, field/2, optional_field/2, element/2, tuple2/2, tuple3/3, tuple4/4, tuple5/5, tuple6/6, dict/2, map/2, decode2/3, decode3/4, decode4/5, decode5/6, decode6/7, decode7/8, decode8/9, decode9/10]). +-export_type([dynamic_/0, decode_error/0, unknown_tuple/0]). + +-type dynamic_() :: any(). + +-type decode_error() :: {decode_error, binary(), binary(), list(binary())}. + +-type unknown_tuple() :: any(). + +-spec from(any()) -> dynamic_(). +from(A) -> + gleam_stdlib:identity(A). + +-spec unsafe_coerce(dynamic_()) -> any(). +unsafe_coerce(A) -> + gleam_stdlib:identity(A). + +-spec dynamic(dynamic_()) -> {ok, dynamic_()} | {error, list(decode_error())}. +dynamic(Value) -> + {ok, Value}. + +-spec bit_array(dynamic_()) -> {ok, bitstring()} | {error, list(decode_error())}. +bit_array(Data) -> + gleam_stdlib:decode_bit_array(Data). + +-spec bit_string(dynamic_()) -> {ok, bitstring()} | + {error, list(decode_error())}. +bit_string(Data) -> + bit_array(Data). + +-spec put_expected(decode_error(), binary()) -> decode_error(). +put_expected(Error, Expected) -> + erlang:setelement(2, Error, Expected). + +-spec classify(dynamic_()) -> binary(). +classify(Data) -> + gleam_stdlib:classify_dynamic(Data). + +-spec int(dynamic_()) -> {ok, integer()} | {error, list(decode_error())}. +int(Data) -> + gleam_stdlib:decode_int(Data). + +-spec float(dynamic_()) -> {ok, float()} | {error, list(decode_error())}. +float(Data) -> + gleam_stdlib:decode_float(Data). + +-spec bool(dynamic_()) -> {ok, boolean()} | {error, list(decode_error())}. +bool(Data) -> + gleam_stdlib:decode_bool(Data). + +-spec shallow_list(dynamic_()) -> {ok, list(dynamic_())} | + {error, list(decode_error())}. +shallow_list(Value) -> + gleam_stdlib:decode_list(Value). + +-spec optional(fun((dynamic_()) -> {ok, DPG} | {error, list(decode_error())})) -> fun((dynamic_()) -> {ok, + gleam@option:option(DPG)} | + {error, list(decode_error())}). +optional(Decode) -> + fun(Value) -> gleam_stdlib:decode_option(Value, Decode) end. + +-spec at_least_decode_tuple_error(integer(), dynamic_()) -> {ok, any()} | + {error, list(decode_error())}. +at_least_decode_tuple_error(Size, Data) -> + S = case Size of + 1 -> + <<""/utf8>>; + + _ -> + <<"s"/utf8>> + end, + Error = begin + _pipe = [<<"Tuple of at least "/utf8>>, + gleam@int:to_string(Size), + <<" element"/utf8>>, + S], + _pipe@1 = gleam@string_builder:from_strings(_pipe), + _pipe@2 = gleam@string_builder:to_string(_pipe@1), + {decode_error, _pipe@2, classify(Data), []} + end, + {error, [Error]}. + +-spec any(list(fun((dynamic_()) -> {ok, DTN} | {error, list(decode_error())}))) -> fun((dynamic_()) -> {ok, + DTN} | + {error, list(decode_error())}). +any(Decoders) -> + fun(Data) -> case Decoders of + [] -> + {error, + [{decode_error, <<"another type"/utf8>>, classify(Data), []}]}; + + [Decoder | Decoders@1] -> + case Decoder(Data) of + {ok, Decoded} -> + {ok, Decoded}; + + {error, _} -> + (any(Decoders@1))(Data) + end + end end. + +-spec all_errors({ok, any()} | {error, list(decode_error())}) -> list(decode_error()). +all_errors(Result) -> + case Result of + {ok, _} -> + []; + + {error, Errors} -> + Errors + end. + +-spec decode1( + fun((DTR) -> DTS), + fun((dynamic_()) -> {ok, DTR} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DTS} | {error, list(decode_error())}). +decode1(Constructor, T1) -> + fun(Value) -> case T1(Value) of + {ok, A} -> + {ok, Constructor(A)}; + + A@1 -> + {error, all_errors(A@1)} + end end. + +-spec push_path(decode_error(), any()) -> decode_error(). +push_path(Error, Name) -> + Name@1 = from(Name), + Decoder = any( + [fun string/1, + fun(X) -> gleam@result:map(int(X), fun gleam@int:to_string/1) end] + ), + Name@3 = case Decoder(Name@1) of + {ok, Name@2} -> + Name@2; + + {error, _} -> + _pipe = [<<"<"/utf8>>, classify(Name@1), <<">"/utf8>>], + _pipe@1 = gleam@string_builder:from_strings(_pipe), + gleam@string_builder:to_string(_pipe@1) + end, + erlang:setelement(4, Error, [Name@3 | erlang:element(4, Error)]). + +-spec result( + fun((dynamic_()) -> {ok, DOU} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DOW} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {ok, DOU} | {error, DOW}} | + {error, list(decode_error())}). +result(Decode_ok, Decode_error) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_result(Value), + fun(Inner_result) -> case Inner_result of + {ok, Raw} -> + gleam@result:'try'( + begin + _pipe = Decode_ok(Raw), + map_errors( + _pipe, + fun(_capture) -> + push_path(_capture, <<"ok"/utf8>>) + end + ) + end, + fun(Value@1) -> {ok, {ok, Value@1}} end + ); + + {error, Raw@1} -> + gleam@result:'try'( + begin + _pipe@1 = Decode_error(Raw@1), + map_errors( + _pipe@1, + fun(_capture@1) -> + push_path(_capture@1, <<"error"/utf8>>) + end + ) + end, + fun(Value@2) -> {ok, {error, Value@2}} end + ) + end end + ) + end. + +-spec list(fun((dynamic_()) -> {ok, DPB} | {error, list(decode_error())})) -> fun((dynamic_()) -> {ok, + list(DPB)} | + {error, list(decode_error())}). +list(Decoder_type) -> + fun(Dynamic) -> + gleam@result:'try'(shallow_list(Dynamic), fun(List) -> _pipe = List, + _pipe@1 = gleam@list:try_map(_pipe, Decoder_type), + map_errors( + _pipe@1, + fun(_capture) -> push_path(_capture, <<"*"/utf8>>) end + ) end) + end. + +-spec map_errors( + {ok, DNP} | {error, list(decode_error())}, + fun((decode_error()) -> decode_error()) +) -> {ok, DNP} | {error, list(decode_error())}. +map_errors(Result, F) -> + gleam@result:map_error( + Result, + fun(_capture) -> gleam@list:map(_capture, F) end + ). + +-spec decode_string(dynamic_()) -> {ok, binary()} | + {error, list(decode_error())}. +decode_string(Data) -> + _pipe = bit_array(Data), + _pipe@1 = map_errors( + _pipe, + fun(_capture) -> put_expected(_capture, <<"String"/utf8>>) end + ), + gleam@result:'try'( + _pipe@1, + fun(Raw) -> case gleam@bit_array:to_string(Raw) of + {ok, String} -> + {ok, String}; + + {error, nil} -> + {error, + [{decode_error, + <<"String"/utf8>>, + <<"BitArray"/utf8>>, + []}]} + end end + ). + +-spec string(dynamic_()) -> {ok, binary()} | {error, list(decode_error())}. +string(Data) -> + decode_string(Data). + +-spec field( + any(), + fun((dynamic_()) -> {ok, DPQ} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DPQ} | {error, list(decode_error())}). +field(Name, Inner_type) -> + fun(Value) -> + Missing_field_error = {decode_error, + <<"field"/utf8>>, + <<"nothing"/utf8>>, + []}, + gleam@result:'try'( + gleam_stdlib:decode_field(Value, Name), + fun(Maybe_inner) -> _pipe = Maybe_inner, + _pipe@1 = gleam@option:to_result(_pipe, [Missing_field_error]), + _pipe@2 = gleam@result:'try'(_pipe@1, Inner_type), + map_errors( + _pipe@2, + fun(_capture) -> push_path(_capture, Name) end + ) end + ) + end. + +-spec optional_field( + any(), + fun((dynamic_()) -> {ok, DPU} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, gleam@option:option(DPU)} | + {error, list(decode_error())}). +optional_field(Name, Inner_type) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_field(Value, Name), + fun(Maybe_inner) -> case Maybe_inner of + none -> + {ok, none}; + + {some, Dynamic_inner} -> + _pipe = Dynamic_inner, + _pipe@1 = gleam_stdlib:decode_option(_pipe, Inner_type), + map_errors( + _pipe@1, + fun(_capture) -> push_path(_capture, Name) end + ) + end end + ) + end. + +-spec element( + integer(), + fun((dynamic_()) -> {ok, DQC} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DQC} | {error, list(decode_error())}). +element(Index, Inner_type) -> + fun(Data) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple(Data), + fun(Tuple) -> + Size = gleam_stdlib:size_of_tuple(Tuple), + gleam@result:'try'(case Index >= 0 of + true -> + case Index < Size of + true -> + gleam_stdlib:tuple_get(Tuple, Index); + + false -> + at_least_decode_tuple_error(Index + 1, Data) + end; + + false -> + case gleam@int:absolute_value(Index) =< Size of + true -> + gleam_stdlib:tuple_get(Tuple, Size + Index); + + false -> + at_least_decode_tuple_error( + gleam@int:absolute_value(Index), + Data + ) + end + end, fun(Data@1) -> _pipe = Inner_type(Data@1), + map_errors( + _pipe, + fun(_capture) -> push_path(_capture, Index) end + ) end) + end + ) + end. + +-spec tuple_errors({ok, any()} | {error, list(decode_error())}, binary()) -> list(decode_error()). +tuple_errors(Result, Name) -> + case Result of + {ok, _} -> + []; + + {error, Errors} -> + gleam@list:map( + Errors, + fun(_capture) -> push_path(_capture, Name) end + ) + end. + +-spec tuple2( + fun((dynamic_()) -> {ok, DRC} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DRE} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {DRC, DRE}} | {error, list(decode_error())}). +tuple2(Decode1, Decode2) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple2(Value), + fun(_use0) -> + {A, B} = _use0, + case {Decode1(A), Decode2(B)} of + {{ok, A@1}, {ok, B@1}} -> + {ok, {A@1, B@1}}; + + {A@2, B@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + {error, _pipe@1} + end + end + ) + end. + +-spec tuple3( + fun((dynamic_()) -> {ok, DRH} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DRJ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DRL} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {DRH, DRJ, DRL}} | {error, list(decode_error())}). +tuple3(Decode1, Decode2, Decode3) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple3(Value), + fun(_use0) -> + {A, B, C} = _use0, + case {Decode1(A), Decode2(B), Decode3(C)} of + {{ok, A@1}, {ok, B@1}, {ok, C@1}} -> + {ok, {A@1, B@1, C@1}}; + + {A@2, B@2, C@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + {error, _pipe@2} + end + end + ) + end. + +-spec tuple4( + fun((dynamic_()) -> {ok, DRO} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DRQ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DRS} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DRU} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {DRO, DRQ, DRS, DRU}} | + {error, list(decode_error())}). +tuple4(Decode1, Decode2, Decode3, Decode4) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple4(Value), + fun(_use0) -> + {A, B, C, D} = _use0, + case {Decode1(A), Decode2(B), Decode3(C), Decode4(D)} of + {{ok, A@1}, {ok, B@1}, {ok, C@1}, {ok, D@1}} -> + {ok, {A@1, B@1, C@1, D@1}}; + + {A@2, B@2, C@2, D@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + _pipe@3 = gleam@list:append( + _pipe@2, + tuple_errors(D@2, <<"3"/utf8>>) + ), + {error, _pipe@3} + end + end + ) + end. + +-spec tuple5( + fun((dynamic_()) -> {ok, DRX} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DRZ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DSB} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DSD} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DSF} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {DRX, DRZ, DSB, DSD, DSF}} | + {error, list(decode_error())}). +tuple5(Decode1, Decode2, Decode3, Decode4, Decode5) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple5(Value), + fun(_use0) -> + {A, B, C, D, E} = _use0, + case {Decode1(A), + Decode2(B), + Decode3(C), + Decode4(D), + Decode5(E)} of + {{ok, A@1}, {ok, B@1}, {ok, C@1}, {ok, D@1}, {ok, E@1}} -> + {ok, {A@1, B@1, C@1, D@1, E@1}}; + + {A@2, B@2, C@2, D@2, E@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + _pipe@3 = gleam@list:append( + _pipe@2, + tuple_errors(D@2, <<"3"/utf8>>) + ), + _pipe@4 = gleam@list:append( + _pipe@3, + tuple_errors(E@2, <<"4"/utf8>>) + ), + {error, _pipe@4} + end + end + ) + end. + +-spec tuple6( + fun((dynamic_()) -> {ok, DSI} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DSK} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DSM} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DSO} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DSQ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DSS} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, {DSI, DSK, DSM, DSO, DSQ, DSS}} | + {error, list(decode_error())}). +tuple6(Decode1, Decode2, Decode3, Decode4, Decode5, Decode6) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_tuple6(Value), + fun(_use0) -> + {A, B, C, D, E, F} = _use0, + case {Decode1(A), + Decode2(B), + Decode3(C), + Decode4(D), + Decode5(E), + Decode6(F)} of + {{ok, A@1}, + {ok, B@1}, + {ok, C@1}, + {ok, D@1}, + {ok, E@1}, + {ok, F@1}} -> + {ok, {A@1, B@1, C@1, D@1, E@1, F@1}}; + + {A@2, B@2, C@2, D@2, E@2, F@2} -> + _pipe = tuple_errors(A@2, <<"0"/utf8>>), + _pipe@1 = gleam@list:append( + _pipe, + tuple_errors(B@2, <<"1"/utf8>>) + ), + _pipe@2 = gleam@list:append( + _pipe@1, + tuple_errors(C@2, <<"2"/utf8>>) + ), + _pipe@3 = gleam@list:append( + _pipe@2, + tuple_errors(D@2, <<"3"/utf8>>) + ), + _pipe@4 = gleam@list:append( + _pipe@3, + tuple_errors(E@2, <<"4"/utf8>>) + ), + _pipe@5 = gleam@list:append( + _pipe@4, + tuple_errors(F@2, <<"5"/utf8>>) + ), + {error, _pipe@5} + end + end + ) + end. + +-spec dict( + fun((dynamic_()) -> {ok, DSV} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DSX} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, gleam@dict:dict(DSV, DSX)} | + {error, list(decode_error())}). +dict(Key_type, Value_type) -> + fun(Value) -> + gleam@result:'try'( + gleam_stdlib:decode_map(Value), + fun(Map) -> + gleam@result:'try'( + begin + _pipe = Map, + _pipe@1 = maps:to_list(_pipe), + gleam@list:try_map( + _pipe@1, + fun(Pair) -> + {K, V} = Pair, + gleam@result:'try'( + begin + _pipe@2 = Key_type(K), + map_errors( + _pipe@2, + fun(_capture) -> + push_path( + _capture, + <<"keys"/utf8>> + ) + end + ) + end, + fun(K@1) -> + gleam@result:'try'( + begin + _pipe@3 = Value_type(V), + map_errors( + _pipe@3, + fun(_capture@1) -> + push_path( + _capture@1, + <<"values"/utf8>> + ) + end + ) + end, + fun(V@1) -> {ok, {K@1, V@1}} end + ) + end + ) + end + ) + end, + fun(Pairs) -> {ok, maps:from_list(Pairs)} end + ) + end + ) + end. + +-spec map( + fun((dynamic_()) -> {ok, DTC} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DTE} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, gleam@dict:dict(DTC, DTE)} | + {error, list(decode_error())}). +map(Key_type, Value_type) -> + dict(Key_type, Value_type). + +-spec decode2( + fun((DTV, DTW) -> DTX), + fun((dynamic_()) -> {ok, DTV} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DTW} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DTX} | {error, list(decode_error())}). +decode2(Constructor, T1, T2) -> + fun(Value) -> case {T1(Value), T2(Value)} of + {{ok, A}, {ok, B}} -> + {ok, Constructor(A, B)}; + + {A@1, B@1} -> + {error, gleam@list:concat([all_errors(A@1), all_errors(B@1)])} + end end. + +-spec decode3( + fun((DUB, DUC, DUD) -> DUE), + fun((dynamic_()) -> {ok, DUB} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DUC} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DUD} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DUE} | {error, list(decode_error())}). +decode3(Constructor, T1, T2, T3) -> + fun(Value) -> case {T1(Value), T2(Value), T3(Value)} of + {{ok, A}, {ok, B}, {ok, C}} -> + {ok, Constructor(A, B, C)}; + + {A@1, B@1, C@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), all_errors(B@1), all_errors(C@1)] + )} + end end. + +-spec decode4( + fun((DUJ, DUK, DUL, DUM) -> DUN), + fun((dynamic_()) -> {ok, DUJ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DUK} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DUL} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DUM} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DUN} | {error, list(decode_error())}). +decode4(Constructor, T1, T2, T3, T4) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}} -> + {ok, Constructor(A, B, C, D)}; + + {A@1, B@1, C@1, D@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1)] + )} + end end. + +-spec decode5( + fun((DUT, DUU, DUV, DUW, DUX) -> DUY), + fun((dynamic_()) -> {ok, DUT} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DUU} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DUV} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DUW} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DUX} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DUY} | {error, list(decode_error())}). +decode5(Constructor, T1, T2, T3, T4, T5) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}, {ok, E}} -> + {ok, Constructor(A, B, C, D, E)}; + + {A@1, B@1, C@1, D@1, E@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1)] + )} + end end. + +-spec decode6( + fun((DVF, DVG, DVH, DVI, DVJ, DVK) -> DVL), + fun((dynamic_()) -> {ok, DVF} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DVG} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DVH} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DVI} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DVJ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DVK} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DVL} | {error, list(decode_error())}). +decode6(Constructor, T1, T2, T3, T4, T5, T6) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}, {ok, E}, {ok, F}} -> + {ok, Constructor(A, B, C, D, E, F)}; + + {A@1, B@1, C@1, D@1, E@1, F@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1)] + )} + end end. + +-spec decode7( + fun((DVT, DVU, DVV, DVW, DVX, DVY, DVZ) -> DWA), + fun((dynamic_()) -> {ok, DVT} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DVU} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DVV} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DVW} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DVX} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DVY} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DVZ} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DWA} | {error, list(decode_error())}). +decode7(Constructor, T1, T2, T3, T4, T5, T6, T7) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X), T7(X)} of + {{ok, A}, {ok, B}, {ok, C}, {ok, D}, {ok, E}, {ok, F}, {ok, G}} -> + {ok, Constructor(A, B, C, D, E, F, G)}; + + {A@1, B@1, C@1, D@1, E@1, F@1, G@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1), + all_errors(G@1)] + )} + end end. + +-spec decode8( + fun((DWJ, DWK, DWL, DWM, DWN, DWO, DWP, DWQ) -> DWR), + fun((dynamic_()) -> {ok, DWJ} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DWK} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DWL} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DWM} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DWN} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DWO} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DWP} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DWQ} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DWR} | {error, list(decode_error())}). +decode8(Constructor, T1, T2, T3, T4, T5, T6, T7, T8) -> + fun(X) -> case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X), T7(X), T8(X)} of + {{ok, A}, + {ok, B}, + {ok, C}, + {ok, D}, + {ok, E}, + {ok, F}, + {ok, G}, + {ok, H}} -> + {ok, Constructor(A, B, C, D, E, F, G, H)}; + + {A@1, B@1, C@1, D@1, E@1, F@1, G@1, H@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1), + all_errors(G@1), + all_errors(H@1)] + )} + end end. + +-spec decode9( + fun((DXB, DXC, DXD, DXE, DXF, DXG, DXH, DXI, DXJ) -> DXK), + fun((dynamic_()) -> {ok, DXB} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXC} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXD} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXE} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXF} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXG} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXH} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXI} | {error, list(decode_error())}), + fun((dynamic_()) -> {ok, DXJ} | {error, list(decode_error())}) +) -> fun((dynamic_()) -> {ok, DXK} | {error, list(decode_error())}). +decode9(Constructor, T1, T2, T3, T4, T5, T6, T7, T8, T9) -> + fun(X) -> + case {T1(X), T2(X), T3(X), T4(X), T5(X), T6(X), T7(X), T8(X), T9(X)} of + {{ok, A}, + {ok, B}, + {ok, C}, + {ok, D}, + {ok, E}, + {ok, F}, + {ok, G}, + {ok, H}, + {ok, I}} -> + {ok, Constructor(A, B, C, D, E, F, G, H, I)}; + + {A@1, B@1, C@1, D@1, E@1, F@1, G@1, H@1, I@1} -> + {error, + gleam@list:concat( + [all_errors(A@1), + all_errors(B@1), + all_errors(C@1), + all_errors(D@1), + all_errors(E@1), + all_errors(F@1), + all_errors(G@1), + all_errors(H@1), + all_errors(I@1)] + )} + end + end. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@float.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@float.erl new file mode 100644 index 0000000..b428ee8 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@float.erl @@ -0,0 +1,181 @@ +-module(gleam@float). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([parse/1, to_string/1, compare/2, min/2, max/2, clamp/3, ceiling/1, floor/1, round/1, truncate/1, absolute_value/1, loosely_compare/3, loosely_equals/3, power/2, square_root/1, negate/1, sum/1, product/1, random/0, divide/2, add/2, multiply/2, subtract/2]). + +-spec parse(binary()) -> {ok, float()} | {error, nil}. +parse(String) -> + gleam_stdlib:parse_float(String). + +-spec to_string(float()) -> binary(). +to_string(X) -> + gleam_stdlib:float_to_string(X). + +-spec compare(float(), float()) -> gleam@order:order(). +compare(A, B) -> + case A =:= B of + true -> + eq; + + false -> + case A < B of + true -> + lt; + + false -> + gt + end + end. + +-spec min(float(), float()) -> float(). +min(A, B) -> + case A < B of + true -> + A; + + false -> + B + end. + +-spec max(float(), float()) -> float(). +max(A, B) -> + case A > B of + true -> + A; + + false -> + B + end. + +-spec clamp(float(), float(), float()) -> float(). +clamp(X, Min_bound, Max_bound) -> + _pipe = X, + _pipe@1 = min(_pipe, Max_bound), + max(_pipe@1, Min_bound). + +-spec ceiling(float()) -> float(). +ceiling(X) -> + math:ceil(X). + +-spec floor(float()) -> float(). +floor(X) -> + math:floor(X). + +-spec round(float()) -> integer(). +round(X) -> + erlang:round(X). + +-spec truncate(float()) -> integer(). +truncate(X) -> + erlang:trunc(X). + +-spec absolute_value(float()) -> float(). +absolute_value(X) -> + case X >= +0.0 of + true -> + X; + + _ -> + +0.0 - X + end. + +-spec loosely_compare(float(), float(), float()) -> gleam@order:order(). +loosely_compare(A, B, Tolerance) -> + Difference = absolute_value(A - B), + case Difference =< Tolerance of + true -> + eq; + + false -> + compare(A, B) + end. + +-spec loosely_equals(float(), float(), float()) -> boolean(). +loosely_equals(A, B, Tolerance) -> + Difference = absolute_value(A - B), + Difference =< Tolerance. + +-spec power(float(), float()) -> {ok, float()} | {error, nil}. +power(Base, Exponent) -> + Fractional = (ceiling(Exponent) - Exponent) > +0.0, + case ((Base < +0.0) andalso Fractional) orelse ((Base =:= +0.0) andalso (Exponent + < +0.0)) of + true -> + {error, nil}; + + false -> + {ok, math:pow(Base, Exponent)} + end. + +-spec square_root(float()) -> {ok, float()} | {error, nil}. +square_root(X) -> + power(X, 0.5). + +-spec negate(float()) -> float(). +negate(X) -> + -1.0 * X. + +-spec do_sum(list(float()), float()) -> float(). +do_sum(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_sum(Rest, X + Initial) + end. + +-spec sum(list(float())) -> float(). +sum(Numbers) -> + _pipe = Numbers, + do_sum(_pipe, +0.0). + +-spec do_product(list(float()), float()) -> float(). +do_product(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_product(Rest, X * Initial) + end. + +-spec product(list(float())) -> float(). +product(Numbers) -> + case Numbers of + [] -> + 1.0; + + _ -> + do_product(Numbers, 1.0) + end. + +-spec random() -> float(). +random() -> + rand:uniform(). + +-spec divide(float(), float()) -> {ok, float()} | {error, nil}. +divide(A, B) -> + case B of + +0.0 -> + {error, nil}; + + B@1 -> + {ok, case B@1 of + +0.0 -> +0.0; + -0.0 -> -0.0; + Gleam@denominator -> A / Gleam@denominator + end} + end. + +-spec add(float(), float()) -> float(). +add(A, B) -> + A + B. + +-spec multiply(float(), float()) -> float(). +multiply(A, B) -> + A * B. + +-spec subtract(float(), float()) -> float(). +subtract(A, B) -> + A - B. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@function.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@function.erl new file mode 100644 index 0000000..ed29603 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@function.erl @@ -0,0 +1,67 @@ +-module(gleam@function). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([compose/2, curry2/1, curry3/1, curry4/1, curry5/1, curry6/1, flip/1, identity/1, constant/1, tap/2, apply1/2, apply2/3, apply3/4]). + +-spec compose(fun((DJZ) -> DKA), fun((DKA) -> DKB)) -> fun((DJZ) -> DKB). +compose(Fun1, Fun2) -> + fun(A) -> Fun2(Fun1(A)) end. + +-spec curry2(fun((DKC, DKD) -> DKE)) -> fun((DKC) -> fun((DKD) -> DKE)). +curry2(Fun) -> + fun(A) -> fun(B) -> Fun(A, B) end end. + +-spec curry3(fun((DKG, DKH, DKI) -> DKJ)) -> fun((DKG) -> fun((DKH) -> fun((DKI) -> DKJ))). +curry3(Fun) -> + fun(A) -> fun(B) -> fun(C) -> Fun(A, B, C) end end end. + +-spec curry4(fun((DKL, DKM, DKN, DKO) -> DKP)) -> fun((DKL) -> fun((DKM) -> fun((DKN) -> fun((DKO) -> DKP)))). +curry4(Fun) -> + fun(A) -> fun(B) -> fun(C) -> fun(D) -> Fun(A, B, C, D) end end end end. + +-spec curry5(fun((DKR, DKS, DKT, DKU, DKV) -> DKW)) -> fun((DKR) -> fun((DKS) -> fun((DKT) -> fun((DKU) -> fun((DKV) -> DKW))))). +curry5(Fun) -> + fun(A) -> + fun(B) -> + fun(C) -> fun(D) -> fun(E) -> Fun(A, B, C, D, E) end end end + end + end. + +-spec curry6(fun((DKY, DKZ, DLA, DLB, DLC, DLD) -> DLE)) -> fun((DKY) -> fun((DKZ) -> fun((DLA) -> fun((DLB) -> fun((DLC) -> fun((DLD) -> DLE)))))). +curry6(Fun) -> + fun(A) -> + fun(B) -> + fun(C) -> + fun(D) -> fun(E) -> fun(F) -> Fun(A, B, C, D, E, F) end end end + end + end + end. + +-spec flip(fun((DLG, DLH) -> DLI)) -> fun((DLH, DLG) -> DLI). +flip(Fun) -> + fun(B, A) -> Fun(A, B) end. + +-spec identity(DLJ) -> DLJ. +identity(X) -> + X. + +-spec constant(DLK) -> fun((any()) -> DLK). +constant(Value) -> + fun(_) -> Value end. + +-spec tap(DLM, fun((DLM) -> any())) -> DLM. +tap(Arg, Effect) -> + Effect(Arg), + Arg. + +-spec apply1(fun((DLO) -> DLP), DLO) -> DLP. +apply1(Fun, Arg1) -> + Fun(Arg1). + +-spec apply2(fun((DLQ, DLR) -> DLS), DLQ, DLR) -> DLS. +apply2(Fun, Arg1, Arg2) -> + Fun(Arg1, Arg2). + +-spec apply3(fun((DLT, DLU, DLV) -> DLW), DLT, DLU, DLV) -> DLW. +apply3(Fun, Arg1, Arg2, Arg3) -> + Fun(Arg1, Arg2, Arg3). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@int.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@int.erl new file mode 100644 index 0000000..7f4e576 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@int.erl @@ -0,0 +1,332 @@ +-module(gleam@int). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([absolute_value/1, parse/1, base_parse/2, to_string/1, to_base_string/2, to_base2/1, to_base8/1, to_base16/1, to_base36/1, to_float/1, power/2, square_root/1, compare/2, min/2, max/2, clamp/3, is_even/1, is_odd/1, negate/1, sum/1, product/1, digits/2, undigits/2, random/1, divide/2, remainder/2, modulo/2, floor_divide/2, add/2, multiply/2, subtract/2, bitwise_and/2, bitwise_not/1, bitwise_or/2, bitwise_exclusive_or/2, bitwise_shift_left/2, bitwise_shift_right/2]). +-export_type([invalid_base/0]). + +-type invalid_base() :: invalid_base. + +-spec absolute_value(integer()) -> integer(). +absolute_value(X) -> + case X >= 0 of + true -> + X; + + false -> + X * -1 + end. + +-spec parse(binary()) -> {ok, integer()} | {error, nil}. +parse(String) -> + gleam_stdlib:parse_int(String). + +-spec base_parse(binary(), integer()) -> {ok, integer()} | {error, nil}. +base_parse(String, Base) -> + case (Base >= 2) andalso (Base =< 36) of + true -> + gleam_stdlib:int_from_base_string(String, Base); + + false -> + {error, nil} + end. + +-spec to_string(integer()) -> binary(). +to_string(X) -> + erlang:integer_to_binary(X). + +-spec to_base_string(integer(), integer()) -> {ok, binary()} | + {error, invalid_base()}. +to_base_string(X, Base) -> + case (Base >= 2) andalso (Base =< 36) of + true -> + {ok, erlang:integer_to_binary(X, Base)}; + + false -> + {error, invalid_base} + end. + +-spec to_base2(integer()) -> binary(). +to_base2(X) -> + erlang:integer_to_binary(X, 2). + +-spec to_base8(integer()) -> binary(). +to_base8(X) -> + erlang:integer_to_binary(X, 8). + +-spec to_base16(integer()) -> binary(). +to_base16(X) -> + erlang:integer_to_binary(X, 16). + +-spec to_base36(integer()) -> binary(). +to_base36(X) -> + erlang:integer_to_binary(X, 36). + +-spec to_float(integer()) -> float(). +to_float(X) -> + erlang:float(X). + +-spec power(integer(), float()) -> {ok, float()} | {error, nil}. +power(Base, Exponent) -> + _pipe = Base, + _pipe@1 = to_float(_pipe), + gleam@float:power(_pipe@1, Exponent). + +-spec square_root(integer()) -> {ok, float()} | {error, nil}. +square_root(X) -> + _pipe = X, + _pipe@1 = to_float(_pipe), + gleam@float:square_root(_pipe@1). + +-spec compare(integer(), integer()) -> gleam@order:order(). +compare(A, B) -> + case A =:= B of + true -> + eq; + + false -> + case A < B of + true -> + lt; + + false -> + gt + end + end. + +-spec min(integer(), integer()) -> integer(). +min(A, B) -> + case A < B of + true -> + A; + + false -> + B + end. + +-spec max(integer(), integer()) -> integer(). +max(A, B) -> + case A > B of + true -> + A; + + false -> + B + end. + +-spec clamp(integer(), integer(), integer()) -> integer(). +clamp(X, Min_bound, Max_bound) -> + _pipe = X, + _pipe@1 = min(_pipe, Max_bound), + max(_pipe@1, Min_bound). + +-spec is_even(integer()) -> boolean(). +is_even(X) -> + (X rem 2) =:= 0. + +-spec is_odd(integer()) -> boolean(). +is_odd(X) -> + (X rem 2) /= 0. + +-spec negate(integer()) -> integer(). +negate(X) -> + -1 * X. + +-spec do_sum(list(integer()), integer()) -> integer(). +do_sum(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_sum(Rest, X + Initial) + end. + +-spec sum(list(integer())) -> integer(). +sum(Numbers) -> + _pipe = Numbers, + do_sum(_pipe, 0). + +-spec do_product(list(integer()), integer()) -> integer(). +do_product(Numbers, Initial) -> + case Numbers of + [] -> + Initial; + + [X | Rest] -> + do_product(Rest, X * Initial) + end. + +-spec product(list(integer())) -> integer(). +product(Numbers) -> + case Numbers of + [] -> + 1; + + _ -> + do_product(Numbers, 1) + end. + +-spec do_digits(integer(), integer(), list(integer())) -> list(integer()). +do_digits(X, Base, Acc) -> + case absolute_value(X) < Base of + true -> + [X | Acc]; + + false -> + do_digits(case Base of + 0 -> 0; + Gleam@denominator -> X div Gleam@denominator + end, Base, [case Base of + 0 -> 0; + Gleam@denominator@1 -> X rem Gleam@denominator@1 + end | Acc]) + end. + +-spec digits(integer(), integer()) -> {ok, list(integer())} | + {error, invalid_base()}. +digits(X, Base) -> + case Base < 2 of + true -> + {error, invalid_base}; + + false -> + {ok, do_digits(X, Base, [])} + end. + +-spec do_undigits(list(integer()), integer(), integer()) -> {ok, integer()} | + {error, invalid_base()}. +do_undigits(Numbers, Base, Acc) -> + case Numbers of + [] -> + {ok, Acc}; + + [Digit | _] when Digit >= Base -> + {error, invalid_base}; + + [Digit@1 | Rest] -> + do_undigits(Rest, Base, (Acc * Base) + Digit@1) + end. + +-spec undigits(list(integer()), integer()) -> {ok, integer()} | + {error, invalid_base()}. +undigits(Numbers, Base) -> + case Base < 2 of + true -> + {error, invalid_base}; + + false -> + do_undigits(Numbers, Base, 0) + end. + +-spec random(integer()) -> integer(). +random(Max) -> + _pipe = (rand:uniform() * to_float(Max)), + _pipe@1 = gleam@float:floor(_pipe), + gleam@float:round(_pipe@1). + +-spec divide(integer(), integer()) -> {ok, integer()} | {error, nil}. +divide(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + Divisor@1 -> + {ok, case Divisor@1 of + 0 -> 0; + Gleam@denominator -> Dividend div Gleam@denominator + end} + end. + +-spec remainder(integer(), integer()) -> {ok, integer()} | {error, nil}. +remainder(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + Divisor@1 -> + {ok, case Divisor@1 of + 0 -> 0; + Gleam@denominator -> Dividend rem Gleam@denominator + end} + end. + +-spec modulo(integer(), integer()) -> {ok, integer()} | {error, nil}. +modulo(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + _ -> + Remainder = case Divisor of + 0 -> 0; + Gleam@denominator -> Dividend rem Gleam@denominator + end, + case (Remainder * Divisor) < 0 of + true -> + {ok, Remainder + Divisor}; + + false -> + {ok, Remainder} + end + end. + +-spec floor_divide(integer(), integer()) -> {ok, integer()} | {error, nil}. +floor_divide(Dividend, Divisor) -> + case Divisor of + 0 -> + {error, nil}; + + Divisor@1 -> + case ((Dividend * Divisor@1) < 0) andalso ((case Divisor@1 of + 0 -> 0; + Gleam@denominator -> Dividend rem Gleam@denominator + end) /= 0) of + true -> + {ok, (case Divisor@1 of + 0 -> 0; + Gleam@denominator@1 -> Dividend div Gleam@denominator@1 + end) - 1}; + + false -> + {ok, case Divisor@1 of + 0 -> 0; + Gleam@denominator@2 -> Dividend div Gleam@denominator@2 + end} + end + end. + +-spec add(integer(), integer()) -> integer(). +add(A, B) -> + A + B. + +-spec multiply(integer(), integer()) -> integer(). +multiply(A, B) -> + A * B. + +-spec subtract(integer(), integer()) -> integer(). +subtract(A, B) -> + A - B. + +-spec bitwise_and(integer(), integer()) -> integer(). +bitwise_and(X, Y) -> + erlang:'band'(X, Y). + +-spec bitwise_not(integer()) -> integer(). +bitwise_not(X) -> + erlang:'bnot'(X). + +-spec bitwise_or(integer(), integer()) -> integer(). +bitwise_or(X, Y) -> + erlang:'bor'(X, Y). + +-spec bitwise_exclusive_or(integer(), integer()) -> integer(). +bitwise_exclusive_or(X, Y) -> + erlang:'bxor'(X, Y). + +-spec bitwise_shift_left(integer(), integer()) -> integer(). +bitwise_shift_left(X, Y) -> + erlang:'bsl'(X, Y). + +-spec bitwise_shift_right(integer(), integer()) -> integer(). +bitwise_shift_right(X, Y) -> + erlang:'bsr'(X, Y). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@io.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@io.erl new file mode 100644 index 0000000..cd01cbc --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@io.erl @@ -0,0 +1,27 @@ +-module(gleam@io). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([print/1, print_error/1, println/1, println_error/1, debug/1]). + +-spec print(binary()) -> nil. +print(String) -> + gleam_stdlib:print(String). + +-spec print_error(binary()) -> nil. +print_error(String) -> + gleam_stdlib:print_error(String). + +-spec println(binary()) -> nil. +println(String) -> + gleam_stdlib:println(String). + +-spec println_error(binary()) -> nil. +println_error(String) -> + gleam_stdlib:println_error(String). + +-spec debug(DBW) -> DBW. +debug(Term) -> + _pipe = Term, + _pipe@1 = gleam@string:inspect(_pipe), + gleam_stdlib:println_error(_pipe@1), + Term. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@iterator.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@iterator.erl new file mode 100644 index 0000000..3d293ba --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@iterator.erl @@ -0,0 +1,744 @@ +-module(gleam@iterator). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([unfold/2, repeatedly/1, repeat/1, from_list/1, transform/3, fold/3, run/1, to_list/1, step/1, take/2, drop/2, map/2, map2/3, append/2, flatten/1, concat/1, flat_map/2, filter/2, cycle/1, find/2, index/1, iterate/2, take_while/2, drop_while/2, scan/3, zip/2, chunk/2, sized_chunk/2, intersperse/2, any/2, all/2, group/2, reduce/2, last/1, empty/0, once/1, range/2, single/1, interleave/2, fold_until/3, try_fold/3, first/1, at/2, length/1, each/2, yield/2]). +-export_type([action/1, iterator/1, step/2, chunk/2, sized_chunk/1]). + +-type action(BSS) :: stop | {continue, BSS, fun(() -> action(BSS))}. + +-opaque iterator(BST) :: {iterator, fun(() -> action(BST))}. + +-type step(BSU, BSV) :: {next, BSU, BSV} | done. + +-type chunk(BSW, BSX) :: {another_by, + list(BSW), + BSX, + BSW, + fun(() -> action(BSW))} | + {last_by, list(BSW)}. + +-type sized_chunk(BSY) :: {another, list(BSY), fun(() -> action(BSY))} | + {last, list(BSY)} | + no_more. + +-spec stop() -> action(any()). +stop() -> + stop. + +-spec do_unfold(BTB, fun((BTB) -> step(BTC, BTB))) -> fun(() -> action(BTC)). +do_unfold(Initial, F) -> + fun() -> case F(Initial) of + {next, X, Acc} -> + {continue, X, do_unfold(Acc, F)}; + + done -> + stop + end end. + +-spec unfold(BTG, fun((BTG) -> step(BTH, BTG))) -> iterator(BTH). +unfold(Initial, F) -> + _pipe = Initial, + _pipe@1 = do_unfold(_pipe, F), + {iterator, _pipe@1}. + +-spec repeatedly(fun(() -> BTL)) -> iterator(BTL). +repeatedly(F) -> + unfold(nil, fun(_) -> {next, F(), nil} end). + +-spec repeat(BTN) -> iterator(BTN). +repeat(X) -> + repeatedly(fun() -> X end). + +-spec from_list(list(BTP)) -> iterator(BTP). +from_list(List) -> + Yield = fun(Acc) -> case Acc of + [] -> + done; + + [Head | Tail] -> + {next, Head, Tail} + end end, + unfold(List, Yield). + +-spec do_transform( + fun(() -> action(BTS)), + BTU, + fun((BTU, BTS) -> step(BTV, BTU)) +) -> fun(() -> action(BTV)). +do_transform(Continuation, State, F) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, El, Next} -> + case F(State, El) of + done -> + stop; + + {next, Yield, Next_state} -> + {continue, Yield, do_transform(Next, Next_state, F)} + end + end end. + +-spec transform(iterator(BTZ), BUB, fun((BUB, BTZ) -> step(BUC, BUB))) -> iterator(BUC). +transform(Iterator, Initial, F) -> + _pipe = do_transform(erlang:element(2, Iterator), Initial, F), + {iterator, _pipe}. + +-spec do_fold(fun(() -> action(BUG)), fun((BUI, BUG) -> BUI), BUI) -> BUI. +do_fold(Continuation, F, Accumulator) -> + case Continuation() of + {continue, Elem, Next} -> + do_fold(Next, F, F(Accumulator, Elem)); + + stop -> + Accumulator + end. + +-spec fold(iterator(BUJ), BUL, fun((BUL, BUJ) -> BUL)) -> BUL. +fold(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + do_fold(_pipe, F, Initial). + +-spec run(iterator(any())) -> nil. +run(Iterator) -> + fold(Iterator, nil, fun(_, _) -> nil end). + +-spec to_list(iterator(BUO)) -> list(BUO). +to_list(Iterator) -> + _pipe = Iterator, + _pipe@1 = fold(_pipe, [], fun(Acc, E) -> [E | Acc] end), + gleam@list:reverse(_pipe@1). + +-spec step(iterator(BUR)) -> step(BUR, iterator(BUR)). +step(Iterator) -> + case (erlang:element(2, Iterator))() of + stop -> + done; + + {continue, E, A} -> + {next, E, {iterator, A}} + end. + +-spec do_take(fun(() -> action(BUW)), integer()) -> fun(() -> action(BUW)). +do_take(Continuation, Desired) -> + fun() -> case Desired > 0 of + false -> + stop; + + true -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + {continue, E, do_take(Next, Desired - 1)} + end + end end. + +-spec take(iterator(BUZ), integer()) -> iterator(BUZ). +take(Iterator, Desired) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_take(_pipe, Desired), + {iterator, _pipe@1}. + +-spec do_drop(fun(() -> action(BVC)), integer()) -> action(BVC). +do_drop(Continuation, Desired) -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + case Desired > 0 of + true -> + do_drop(Next, Desired - 1); + + false -> + {continue, E, Next} + end + end. + +-spec drop(iterator(BVF), integer()) -> iterator(BVF). +drop(Iterator, Desired) -> + _pipe = fun() -> do_drop(erlang:element(2, Iterator), Desired) end, + {iterator, _pipe}. + +-spec do_map(fun(() -> action(BVI)), fun((BVI) -> BVK)) -> fun(() -> action(BVK)). +do_map(Continuation, F) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, E, Continuation@1} -> + {continue, F(E), do_map(Continuation@1, F)} + end end. + +-spec map(iterator(BVM), fun((BVM) -> BVO)) -> iterator(BVO). +map(Iterator, F) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_map(_pipe, F), + {iterator, _pipe@1}. + +-spec do_map2( + fun(() -> action(BVQ)), + fun(() -> action(BVS)), + fun((BVQ, BVS) -> BVU) +) -> fun(() -> action(BVU)). +do_map2(Continuation1, Continuation2, Fun) -> + fun() -> case Continuation1() of + stop -> + stop; + + {continue, A, Next_a} -> + case Continuation2() of + stop -> + stop; + + {continue, B, Next_b} -> + {continue, Fun(A, B), do_map2(Next_a, Next_b, Fun)} + end + end end. + +-spec map2(iterator(BVW), iterator(BVY), fun((BVW, BVY) -> BWA)) -> iterator(BWA). +map2(Iterator1, Iterator2, Fun) -> + _pipe = do_map2( + erlang:element(2, Iterator1), + erlang:element(2, Iterator2), + Fun + ), + {iterator, _pipe}. + +-spec do_append(fun(() -> action(BWC)), fun(() -> action(BWC))) -> action(BWC). +do_append(First, Second) -> + case First() of + {continue, E, First@1} -> + {continue, E, fun() -> do_append(First@1, Second) end}; + + stop -> + Second() + end. + +-spec append(iterator(BWG), iterator(BWG)) -> iterator(BWG). +append(First, Second) -> + _pipe = fun() -> + do_append(erlang:element(2, First), erlang:element(2, Second)) + end, + {iterator, _pipe}. + +-spec do_flatten(fun(() -> action(iterator(BWK)))) -> action(BWK). +do_flatten(Flattened) -> + case Flattened() of + stop -> + stop; + + {continue, It, Next_iterator} -> + do_append( + erlang:element(2, It), + fun() -> do_flatten(Next_iterator) end + ) + end. + +-spec flatten(iterator(iterator(BWO))) -> iterator(BWO). +flatten(Iterator) -> + _pipe = fun() -> do_flatten(erlang:element(2, Iterator)) end, + {iterator, _pipe}. + +-spec concat(list(iterator(BWS))) -> iterator(BWS). +concat(Iterators) -> + flatten(from_list(Iterators)). + +-spec flat_map(iterator(BWW), fun((BWW) -> iterator(BWY))) -> iterator(BWY). +flat_map(Iterator, F) -> + _pipe = Iterator, + _pipe@1 = map(_pipe, F), + flatten(_pipe@1). + +-spec do_filter(fun(() -> action(BXB)), fun((BXB) -> boolean())) -> action(BXB). +do_filter(Continuation, Predicate) -> + case Continuation() of + stop -> + stop; + + {continue, E, Iterator} -> + case Predicate(E) of + true -> + {continue, E, fun() -> do_filter(Iterator, Predicate) end}; + + false -> + do_filter(Iterator, Predicate) + end + end. + +-spec filter(iterator(BXE), fun((BXE) -> boolean())) -> iterator(BXE). +filter(Iterator, Predicate) -> + _pipe = fun() -> do_filter(erlang:element(2, Iterator), Predicate) end, + {iterator, _pipe}. + +-spec cycle(iterator(BXH)) -> iterator(BXH). +cycle(Iterator) -> + _pipe = repeat(Iterator), + flatten(_pipe). + +-spec do_find(fun(() -> action(BXL)), fun((BXL) -> boolean())) -> {ok, BXL} | + {error, nil}. +do_find(Continuation, F) -> + case Continuation() of + stop -> + {error, nil}; + + {continue, E, Next} -> + case F(E) of + true -> + {ok, E}; + + false -> + do_find(Next, F) + end + end. + +-spec find(iterator(BXP), fun((BXP) -> boolean())) -> {ok, BXP} | {error, nil}. +find(Haystack, Is_desired) -> + _pipe = erlang:element(2, Haystack), + do_find(_pipe, Is_desired). + +-spec do_index(fun(() -> action(BXT)), integer()) -> fun(() -> action({BXT, + integer()})). +do_index(Continuation, Next) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, E, Continuation@1} -> + {continue, {E, Next}, do_index(Continuation@1, Next + 1)} + end end. + +-spec index(iterator(BXW)) -> iterator({BXW, integer()}). +index(Iterator) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_index(_pipe, 0), + {iterator, _pipe@1}. + +-spec iterate(BXZ, fun((BXZ) -> BXZ)) -> iterator(BXZ). +iterate(Initial, F) -> + unfold(Initial, fun(Element) -> {next, Element, F(Element)} end). + +-spec do_take_while(fun(() -> action(BYB)), fun((BYB) -> boolean())) -> fun(() -> action(BYB)). +do_take_while(Continuation, Predicate) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + case Predicate(E) of + false -> + stop; + + true -> + {continue, E, do_take_while(Next, Predicate)} + end + end end. + +-spec take_while(iterator(BYE), fun((BYE) -> boolean())) -> iterator(BYE). +take_while(Iterator, Predicate) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_take_while(_pipe, Predicate), + {iterator, _pipe@1}. + +-spec do_drop_while(fun(() -> action(BYH)), fun((BYH) -> boolean())) -> action(BYH). +do_drop_while(Continuation, Predicate) -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + case Predicate(E) of + false -> + {continue, E, Next}; + + true -> + do_drop_while(Next, Predicate) + end + end. + +-spec drop_while(iterator(BYK), fun((BYK) -> boolean())) -> iterator(BYK). +drop_while(Iterator, Predicate) -> + _pipe = fun() -> do_drop_while(erlang:element(2, Iterator), Predicate) end, + {iterator, _pipe}. + +-spec do_scan(fun(() -> action(BYN)), fun((BYP, BYN) -> BYP), BYP) -> fun(() -> action(BYP)). +do_scan(Continuation, F, Accumulator) -> + fun() -> case Continuation() of + stop -> + stop; + + {continue, El, Next} -> + Accumulated = F(Accumulator, El), + {continue, Accumulated, do_scan(Next, F, Accumulated)} + end end. + +-spec scan(iterator(BYR), BYT, fun((BYT, BYR) -> BYT)) -> iterator(BYT). +scan(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_scan(_pipe, F, Initial), + {iterator, _pipe@1}. + +-spec do_zip(fun(() -> action(BYV)), fun(() -> action(BYX))) -> fun(() -> action({BYV, + BYX})). +do_zip(Left, Right) -> + fun() -> case Left() of + stop -> + stop; + + {continue, El_left, Next_left} -> + case Right() of + stop -> + stop; + + {continue, El_right, Next_right} -> + {continue, + {El_left, El_right}, + do_zip(Next_left, Next_right)} + end + end end. + +-spec zip(iterator(BZA), iterator(BZC)) -> iterator({BZA, BZC}). +zip(Left, Right) -> + _pipe = do_zip(erlang:element(2, Left), erlang:element(2, Right)), + {iterator, _pipe}. + +-spec next_chunk(fun(() -> action(BZF)), fun((BZF) -> BZH), BZH, list(BZF)) -> chunk(BZF, BZH). +next_chunk(Continuation, F, Previous_key, Current_chunk) -> + case Continuation() of + stop -> + {last_by, gleam@list:reverse(Current_chunk)}; + + {continue, E, Next} -> + Key = F(E), + case Key =:= Previous_key of + true -> + next_chunk(Next, F, Key, [E | Current_chunk]); + + false -> + {another_by, + gleam@list:reverse(Current_chunk), + Key, + E, + Next} + end + end. + +-spec do_chunk(fun(() -> action(BZL)), fun((BZL) -> BZN), BZN, BZL) -> action(list(BZL)). +do_chunk(Continuation, F, Previous_key, Previous_element) -> + case next_chunk(Continuation, F, Previous_key, [Previous_element]) of + {last_by, Chunk} -> + {continue, Chunk, fun stop/0}; + + {another_by, Chunk@1, Key, El, Next} -> + {continue, Chunk@1, fun() -> do_chunk(Next, F, Key, El) end} + end. + +-spec chunk(iterator(BZQ), fun((BZQ) -> any())) -> iterator(list(BZQ)). +chunk(Iterator, F) -> + _pipe = fun() -> case (erlang:element(2, Iterator))() of + stop -> + stop; + + {continue, E, Next} -> + do_chunk(Next, F, F(E), E) + end end, + {iterator, _pipe}. + +-spec next_sized_chunk(fun(() -> action(BZV)), integer(), list(BZV)) -> sized_chunk(BZV). +next_sized_chunk(Continuation, Left, Current_chunk) -> + case Continuation() of + stop -> + case Current_chunk of + [] -> + no_more; + + Remaining -> + {last, gleam@list:reverse(Remaining)} + end; + + {continue, E, Next} -> + Chunk = [E | Current_chunk], + case Left > 1 of + false -> + {another, gleam@list:reverse(Chunk), Next}; + + true -> + next_sized_chunk(Next, Left - 1, Chunk) + end + end. + +-spec do_sized_chunk(fun(() -> action(BZZ)), integer()) -> fun(() -> action(list(BZZ))). +do_sized_chunk(Continuation, Count) -> + fun() -> case next_sized_chunk(Continuation, Count, []) of + no_more -> + stop; + + {last, Chunk} -> + {continue, Chunk, fun stop/0}; + + {another, Chunk@1, Next_element} -> + {continue, Chunk@1, do_sized_chunk(Next_element, Count)} + end end. + +-spec sized_chunk(iterator(CAD), integer()) -> iterator(list(CAD)). +sized_chunk(Iterator, Count) -> + _pipe = erlang:element(2, Iterator), + _pipe@1 = do_sized_chunk(_pipe, Count), + {iterator, _pipe@1}. + +-spec do_intersperse(fun(() -> action(CAH)), CAH) -> action(CAH). +do_intersperse(Continuation, Separator) -> + case Continuation() of + stop -> + stop; + + {continue, E, Next} -> + Next_interspersed = fun() -> do_intersperse(Next, Separator) end, + {continue, Separator, fun() -> {continue, E, Next_interspersed} end} + end. + +-spec intersperse(iterator(CAK), CAK) -> iterator(CAK). +intersperse(Iterator, Elem) -> + _pipe = fun() -> case (erlang:element(2, Iterator))() of + stop -> + stop; + + {continue, E, Next} -> + {continue, E, fun() -> do_intersperse(Next, Elem) end} + end end, + {iterator, _pipe}. + +-spec do_any(fun(() -> action(CAN)), fun((CAN) -> boolean())) -> boolean(). +do_any(Continuation, Predicate) -> + case Continuation() of + stop -> + false; + + {continue, E, Next} -> + case Predicate(E) of + true -> + true; + + false -> + do_any(Next, Predicate) + end + end. + +-spec any(iterator(CAP), fun((CAP) -> boolean())) -> boolean(). +any(Iterator, Predicate) -> + _pipe = erlang:element(2, Iterator), + do_any(_pipe, Predicate). + +-spec do_all(fun(() -> action(CAR)), fun((CAR) -> boolean())) -> boolean(). +do_all(Continuation, Predicate) -> + case Continuation() of + stop -> + true; + + {continue, E, Next} -> + case Predicate(E) of + true -> + do_all(Next, Predicate); + + false -> + false + end + end. + +-spec all(iterator(CAT), fun((CAT) -> boolean())) -> boolean(). +all(Iterator, Predicate) -> + _pipe = erlang:element(2, Iterator), + do_all(_pipe, Predicate). + +-spec update_group_with(CAV) -> fun((gleam@option:option(list(CAV))) -> list(CAV)). +update_group_with(El) -> + fun(Maybe_group) -> case Maybe_group of + {some, Group} -> + [El | Group]; + + none -> + [El] + end end. + +-spec group_updater(fun((CAZ) -> CBA)) -> fun((gleam@dict:dict(CBA, list(CAZ)), CAZ) -> gleam@dict:dict(CBA, list(CAZ))). +group_updater(F) -> + fun(Groups, Elem) -> _pipe = Groups, + gleam@dict:update(_pipe, F(Elem), update_group_with(Elem)) end. + +-spec group(iterator(CBH), fun((CBH) -> CBJ)) -> gleam@dict:dict(CBJ, list(CBH)). +group(Iterator, Key) -> + _pipe = Iterator, + _pipe@1 = fold(_pipe, gleam@dict:new(), group_updater(Key)), + gleam@dict:map_values( + _pipe@1, + fun(_, Group) -> gleam@list:reverse(Group) end + ). + +-spec reduce(iterator(CBN), fun((CBN, CBN) -> CBN)) -> {ok, CBN} | {error, nil}. +reduce(Iterator, F) -> + case (erlang:element(2, Iterator))() of + stop -> + {error, nil}; + + {continue, E, Next} -> + _pipe = do_fold(Next, F, E), + {ok, _pipe} + end. + +-spec last(iterator(CBR)) -> {ok, CBR} | {error, nil}. +last(Iterator) -> + _pipe = Iterator, + reduce(_pipe, fun(_, Elem) -> Elem end). + +-spec empty() -> iterator(any()). +empty() -> + {iterator, fun stop/0}. + +-spec once(fun(() -> CBX)) -> iterator(CBX). +once(F) -> + _pipe = fun() -> {continue, F(), fun stop/0} end, + {iterator, _pipe}. + +-spec range(integer(), integer()) -> iterator(integer()). +range(Start, Stop) -> + case gleam@int:compare(Start, Stop) of + eq -> + once(fun() -> Start end); + + gt -> + unfold(Start, fun(Current) -> case Current < Stop of + false -> + {next, Current, Current - 1}; + + true -> + done + end end); + + lt -> + unfold(Start, fun(Current@1) -> case Current@1 > Stop of + false -> + {next, Current@1, Current@1 + 1}; + + true -> + done + end end) + end. + +-spec single(CBZ) -> iterator(CBZ). +single(Elem) -> + once(fun() -> Elem end). + +-spec do_interleave(fun(() -> action(CCB)), fun(() -> action(CCB))) -> action(CCB). +do_interleave(Current, Next) -> + case Current() of + stop -> + Next(); + + {continue, E, Next_other} -> + {continue, E, fun() -> do_interleave(Next, Next_other) end} + end. + +-spec interleave(iterator(CCF), iterator(CCF)) -> iterator(CCF). +interleave(Left, Right) -> + _pipe = fun() -> + do_interleave(erlang:element(2, Left), erlang:element(2, Right)) + end, + {iterator, _pipe}. + +-spec do_fold_until( + fun(() -> action(CCJ)), + fun((CCL, CCJ) -> gleam@list:continue_or_stop(CCL)), + CCL +) -> CCL. +do_fold_until(Continuation, F, Accumulator) -> + case Continuation() of + stop -> + Accumulator; + + {continue, Elem, Next} -> + case F(Accumulator, Elem) of + {continue, Accumulator@1} -> + do_fold_until(Next, F, Accumulator@1); + + {stop, Accumulator@2} -> + Accumulator@2 + end + end. + +-spec fold_until( + iterator(CCN), + CCP, + fun((CCP, CCN) -> gleam@list:continue_or_stop(CCP)) +) -> CCP. +fold_until(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + do_fold_until(_pipe, F, Initial). + +-spec do_try_fold( + fun(() -> action(CCR)), + fun((CCT, CCR) -> {ok, CCT} | {error, CCU}), + CCT +) -> {ok, CCT} | {error, CCU}. +do_try_fold(Continuation, F, Accumulator) -> + case Continuation() of + stop -> + {ok, Accumulator}; + + {continue, Elem, Next} -> + gleam@result:'try'( + F(Accumulator, Elem), + fun(Accumulator@1) -> do_try_fold(Next, F, Accumulator@1) end + ) + end. + +-spec try_fold(iterator(CCZ), CDB, fun((CDB, CCZ) -> {ok, CDB} | {error, CDC})) -> {ok, + CDB} | + {error, CDC}. +try_fold(Iterator, Initial, F) -> + _pipe = erlang:element(2, Iterator), + do_try_fold(_pipe, F, Initial). + +-spec first(iterator(CDH)) -> {ok, CDH} | {error, nil}. +first(Iterator) -> + case (erlang:element(2, Iterator))() of + stop -> + {error, nil}; + + {continue, E, _} -> + {ok, E} + end. + +-spec at(iterator(CDL), integer()) -> {ok, CDL} | {error, nil}. +at(Iterator, Index) -> + _pipe = Iterator, + _pipe@1 = drop(_pipe, Index), + first(_pipe@1). + +-spec do_length(fun(() -> action(any())), integer()) -> integer(). +do_length(Continuation, Length) -> + case Continuation() of + stop -> + Length; + + {continue, _, Next} -> + do_length(Next, Length + 1) + end. + +-spec length(iterator(any())) -> integer(). +length(Iterator) -> + _pipe = erlang:element(2, Iterator), + do_length(_pipe, 0). + +-spec each(iterator(CDT), fun((CDT) -> any())) -> nil. +each(Iterator, F) -> + _pipe = Iterator, + _pipe@1 = map(_pipe, F), + run(_pipe@1). + +-spec yield(CDW, fun(() -> iterator(CDW))) -> iterator(CDW). +yield(Element, Next) -> + {iterator, fun() -> {continue, Element, erlang:element(2, Next())} end}. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@list.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@list.erl new file mode 100644 index 0000000..21f87e5 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@list.erl @@ -0,0 +1,1136 @@ +-module(gleam@list). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([length/1, reverse/1, is_empty/1, contains/2, first/1, rest/1, filter/2, filter_map/2, map/2, map2/3, index_map/2, try_map/2, drop/2, take/2, new/0, append/2, prepend/2, concat/1, flatten/1, flat_map/2, fold/3, group/2, map_fold/3, fold_right/3, index_fold/3, try_fold/3, fold_until/3, find/2, find_map/2, all/2, any/2, zip/2, strict_zip/2, unzip/1, intersperse/2, at/2, unique/1, sort/2, range/2, repeat/2, split/2, split_while/2, key_find/2, key_filter/2, pop/2, pop_map/2, key_pop/2, key_set/3, each/2, try_each/2, partition/2, permutations/1, window/2, window_by_2/1, drop_while/2, take_while/2, chunk/2, sized_chunk/2, reduce/2, scan/3, last/1, combinations/2, combination_pairs/1, transpose/1, interleave/1, shuffle/1]). +-export_type([length_mismatch/0, continue_or_stop/1]). + +-type length_mismatch() :: length_mismatch. + +-type continue_or_stop(XQ) :: {continue, XQ} | {stop, XQ}. + +-spec length(list(any())) -> integer(). +length(List) -> + erlang:length(List). + +-spec reverse(list(XV)) -> list(XV). +reverse(Xs) -> + lists:reverse(Xs). + +-spec is_empty(list(any())) -> boolean(). +is_empty(List) -> + List =:= []. + +-spec contains(list(YD), YD) -> boolean(). +contains(List, Elem) -> + case List of + [] -> + false; + + [First | _] when First =:= Elem -> + true; + + [_ | Rest] -> + contains(Rest, Elem) + end. + +-spec first(list(YF)) -> {ok, YF} | {error, nil}. +first(List) -> + case List of + [] -> + {error, nil}; + + [X | _] -> + {ok, X} + end. + +-spec rest(list(YJ)) -> {ok, list(YJ)} | {error, nil}. +rest(List) -> + case List of + [] -> + {error, nil}; + + [_ | Xs] -> + {ok, Xs} + end. + +-spec update_group(fun((YO) -> YP)) -> fun((gleam@dict:dict(YP, list(YO)), YO) -> gleam@dict:dict(YP, list(YO))). +update_group(F) -> + fun(Groups, Elem) -> case gleam@dict:get(Groups, F(Elem)) of + {ok, Existing} -> + gleam@dict:insert(Groups, F(Elem), [Elem | Existing]); + + {error, _} -> + gleam@dict:insert(Groups, F(Elem), [Elem]) + end end. + +-spec do_filter(list(AAC), fun((AAC) -> boolean()), list(AAC)) -> list(AAC). +do_filter(List, Fun, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + New_acc = case Fun(X) of + true -> + [X | Acc]; + + false -> + Acc + end, + do_filter(Xs, Fun, New_acc) + end. + +-spec filter(list(AAG), fun((AAG) -> boolean())) -> list(AAG). +filter(List, Predicate) -> + do_filter(List, Predicate, []). + +-spec do_filter_map( + list(AAJ), + fun((AAJ) -> {ok, AAL} | {error, any()}), + list(AAL) +) -> list(AAL). +do_filter_map(List, Fun, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + New_acc = case Fun(X) of + {ok, X@1} -> + [X@1 | Acc]; + + {error, _} -> + Acc + end, + do_filter_map(Xs, Fun, New_acc) + end. + +-spec filter_map(list(AAR), fun((AAR) -> {ok, AAT} | {error, any()})) -> list(AAT). +filter_map(List, Fun) -> + do_filter_map(List, Fun, []). + +-spec do_map(list(AAY), fun((AAY) -> ABA), list(ABA)) -> list(ABA). +do_map(List, Fun, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + do_map(Xs, Fun, [Fun(X) | Acc]) + end. + +-spec map(list(ABD), fun((ABD) -> ABF)) -> list(ABF). +map(List, Fun) -> + do_map(List, Fun, []). + +-spec do_map2(list(ABN), list(ABP), fun((ABN, ABP) -> ABR), list(ABR)) -> list(ABR). +do_map2(List1, List2, Fun, Acc) -> + case {List1, List2} of + {[], _} -> + reverse(Acc); + + {_, []} -> + reverse(Acc); + + {[A | As_], [B | Bs]} -> + do_map2(As_, Bs, Fun, [Fun(A, B) | Acc]) + end. + +-spec map2(list(ABH), list(ABJ), fun((ABH, ABJ) -> ABL)) -> list(ABL). +map2(List1, List2, Fun) -> + do_map2(List1, List2, Fun, []). + +-spec do_index_map( + list(ABZ), + fun((ABZ, integer()) -> ACB), + integer(), + list(ACB) +) -> list(ACB). +do_index_map(List, Fun, Index, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + Acc@1 = [Fun(X, Index) | Acc], + do_index_map(Xs, Fun, Index + 1, Acc@1) + end. + +-spec index_map(list(ACE), fun((ACE, integer()) -> ACG)) -> list(ACG). +index_map(List, Fun) -> + do_index_map(List, Fun, 0, []). + +-spec do_try_map(list(ACI), fun((ACI) -> {ok, ACK} | {error, ACL}), list(ACK)) -> {ok, + list(ACK)} | + {error, ACL}. +do_try_map(List, Fun, Acc) -> + case List of + [] -> + {ok, reverse(Acc)}; + + [X | Xs] -> + case Fun(X) of + {ok, Y} -> + do_try_map(Xs, Fun, [Y | Acc]); + + {error, Error} -> + {error, Error} + end + end. + +-spec try_map(list(ACS), fun((ACS) -> {ok, ACU} | {error, ACV})) -> {ok, + list(ACU)} | + {error, ACV}. +try_map(List, Fun) -> + do_try_map(List, Fun, []). + +-spec drop(list(ADB), integer()) -> list(ADB). +drop(List, N) -> + case N =< 0 of + true -> + List; + + false -> + case List of + [] -> + []; + + [_ | Xs] -> + drop(Xs, N - 1) + end + end. + +-spec do_take(list(ADE), integer(), list(ADE)) -> list(ADE). +do_take(List, N, Acc) -> + case N =< 0 of + true -> + reverse(Acc); + + false -> + case List of + [] -> + reverse(Acc); + + [X | Xs] -> + do_take(Xs, N - 1, [X | Acc]) + end + end. + +-spec take(list(ADI), integer()) -> list(ADI). +take(List, N) -> + do_take(List, N, []). + +-spec new() -> list(any()). +new() -> + []. + +-spec append(list(ADN), list(ADN)) -> list(ADN). +append(First, Second) -> + lists:append(First, Second). + +-spec prepend(list(ADV), ADV) -> list(ADV). +prepend(List, Item) -> + [Item | List]. + +-spec reverse_and_prepend(list(ADY), list(ADY)) -> list(ADY). +reverse_and_prepend(Prefix, Suffix) -> + case Prefix of + [] -> + Suffix; + + [First | Rest] -> + reverse_and_prepend(Rest, [First | Suffix]) + end. + +-spec do_concat(list(list(AEC)), list(AEC)) -> list(AEC). +do_concat(Lists, Acc) -> + case Lists of + [] -> + reverse(Acc); + + [List | Further_lists] -> + do_concat(Further_lists, reverse_and_prepend(List, Acc)) + end. + +-spec concat(list(list(AEH))) -> list(AEH). +concat(Lists) -> + do_concat(Lists, []). + +-spec flatten(list(list(AEL))) -> list(AEL). +flatten(Lists) -> + do_concat(Lists, []). + +-spec flat_map(list(AEP), fun((AEP) -> list(AER))) -> list(AER). +flat_map(List, Fun) -> + _pipe = map(List, Fun), + concat(_pipe). + +-spec fold(list(AEU), AEW, fun((AEW, AEU) -> AEW)) -> AEW. +fold(List, Initial, Fun) -> + case List of + [] -> + Initial; + + [X | Rest] -> + fold(Rest, Fun(Initial, X), Fun) + end. + +-spec group(list(YW), fun((YW) -> YY)) -> gleam@dict:dict(YY, list(YW)). +group(List, Key) -> + fold(List, gleam@dict:new(), update_group(Key)). + +-spec map_fold(list(ABU), ABW, fun((ABW, ABU) -> {ABW, ABX})) -> {ABW, + list(ABX)}. +map_fold(List, Acc, Fun) -> + _pipe = fold( + List, + {Acc, []}, + fun(Acc@1, Item) -> + {Current_acc, Items} = Acc@1, + {Next_acc, Next_item} = Fun(Current_acc, Item), + {Next_acc, [Next_item | Items]} + end + ), + gleam@pair:map_second(_pipe, fun reverse/1). + +-spec fold_right(list(AEX), AEZ, fun((AEZ, AEX) -> AEZ)) -> AEZ. +fold_right(List, Initial, Fun) -> + case List of + [] -> + Initial; + + [X | Rest] -> + Fun(fold_right(Rest, Initial, Fun), X) + end. + +-spec do_index_fold( + list(AFA), + AFC, + fun((AFC, AFA, integer()) -> AFC), + integer() +) -> AFC. +do_index_fold(Over, Acc, With, Index) -> + case Over of + [] -> + Acc; + + [First | Rest] -> + do_index_fold(Rest, With(Acc, First, Index), With, Index + 1) + end. + +-spec index_fold(list(AFD), AFF, fun((AFF, AFD, integer()) -> AFF)) -> AFF. +index_fold(Over, Initial, Fun) -> + do_index_fold(Over, Initial, Fun, 0). + +-spec try_fold(list(AFG), AFI, fun((AFI, AFG) -> {ok, AFI} | {error, AFJ})) -> {ok, + AFI} | + {error, AFJ}. +try_fold(Collection, Accumulator, Fun) -> + case Collection of + [] -> + {ok, Accumulator}; + + [First | Rest] -> + case Fun(Accumulator, First) of + {ok, Result} -> + try_fold(Rest, Result, Fun); + + {error, _} = Error -> + Error + end + end. + +-spec fold_until(list(AFO), AFQ, fun((AFQ, AFO) -> continue_or_stop(AFQ))) -> AFQ. +fold_until(Collection, Accumulator, Fun) -> + case Collection of + [] -> + Accumulator; + + [First | Rest] -> + case Fun(Accumulator, First) of + {continue, Next_accumulator} -> + fold_until(Rest, Next_accumulator, Fun); + + {stop, B} -> + B + end + end. + +-spec find(list(AFS), fun((AFS) -> boolean())) -> {ok, AFS} | {error, nil}. +find(Haystack, Is_desired) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Is_desired(X) of + true -> + {ok, X}; + + _ -> + find(Rest, Is_desired) + end + end. + +-spec find_map(list(AFW), fun((AFW) -> {ok, AFY} | {error, any()})) -> {ok, AFY} | + {error, nil}. +find_map(Haystack, Fun) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Fun(X) of + {ok, X@1} -> + {ok, X@1}; + + _ -> + find_map(Rest, Fun) + end + end. + +-spec all(list(AGE), fun((AGE) -> boolean())) -> boolean(). +all(List, Predicate) -> + case List of + [] -> + true; + + [First | Rest] -> + case Predicate(First) of + true -> + all(Rest, Predicate); + + false -> + false + end + end. + +-spec any(list(AGG), fun((AGG) -> boolean())) -> boolean(). +any(List, Predicate) -> + case List of + [] -> + false; + + [First | Rest] -> + case Predicate(First) of + true -> + true; + + false -> + any(Rest, Predicate) + end + end. + +-spec do_zip(list(AGI), list(AGK), list({AGI, AGK})) -> list({AGI, AGK}). +do_zip(Xs, Ys, Acc) -> + case {Xs, Ys} of + {[X | Xs@1], [Y | Ys@1]} -> + do_zip(Xs@1, Ys@1, [{X, Y} | Acc]); + + {_, _} -> + reverse(Acc) + end. + +-spec zip(list(AGO), list(AGQ)) -> list({AGO, AGQ}). +zip(List, Other) -> + do_zip(List, Other, []). + +-spec strict_zip(list(AGT), list(AGV)) -> {ok, list({AGT, AGV})} | + {error, length_mismatch()}. +strict_zip(List, Other) -> + case length(List) =:= length(Other) of + true -> + {ok, zip(List, Other)}; + + false -> + {error, length_mismatch} + end. + +-spec do_unzip(list({AWN, AWO}), list(AWN), list(AWO)) -> {list(AWN), list(AWO)}. +do_unzip(Input, Xs, Ys) -> + case Input of + [] -> + {reverse(Xs), reverse(Ys)}; + + [{X, Y} | Rest] -> + do_unzip(Rest, [X | Xs], [Y | Ys]) + end. + +-spec unzip(list({AHE, AHF})) -> {list(AHE), list(AHF)}. +unzip(Input) -> + do_unzip(Input, [], []). + +-spec do_intersperse(list(AHJ), AHJ, list(AHJ)) -> list(AHJ). +do_intersperse(List, Separator, Acc) -> + case List of + [] -> + reverse(Acc); + + [X | Rest] -> + do_intersperse(Rest, Separator, [X, Separator | Acc]) + end. + +-spec intersperse(list(AHN), AHN) -> list(AHN). +intersperse(List, Elem) -> + case List of + [] -> + List; + + [_] -> + List; + + [X | Rest] -> + do_intersperse(Rest, Elem, [X]) + end. + +-spec at(list(AHQ), integer()) -> {ok, AHQ} | {error, nil}. +at(List, Index) -> + case Index >= 0 of + true -> + _pipe = List, + _pipe@1 = drop(_pipe, Index), + first(_pipe@1); + + false -> + {error, nil} + end. + +-spec unique(list(AHU)) -> list(AHU). +unique(List) -> + case List of + [] -> + []; + + [X | Rest] -> + [X | unique(filter(Rest, fun(Y) -> Y /= X end))] + end. + +-spec merge_up( + integer(), + integer(), + list(AHX), + list(AHX), + list(AHX), + fun((AHX, AHX) -> gleam@order:order()) +) -> list(AHX). +merge_up(Na, Nb, A, B, Acc, Compare) -> + case {Na, Nb, A, B} of + {0, 0, _, _} -> + Acc; + + {_, 0, [Ax | Ar], _} -> + merge_up(Na - 1, Nb, Ar, B, [Ax | Acc], Compare); + + {0, _, _, [Bx | Br]} -> + merge_up(Na, Nb - 1, A, Br, [Bx | Acc], Compare); + + {_, _, [Ax@1 | Ar@1], [Bx@1 | Br@1]} -> + case Compare(Ax@1, Bx@1) of + gt -> + merge_up(Na, Nb - 1, A, Br@1, [Bx@1 | Acc], Compare); + + _ -> + merge_up(Na - 1, Nb, Ar@1, B, [Ax@1 | Acc], Compare) + end; + + {_, _, _, _} -> + Acc + end. + +-spec merge_down( + integer(), + integer(), + list(AIC), + list(AIC), + list(AIC), + fun((AIC, AIC) -> gleam@order:order()) +) -> list(AIC). +merge_down(Na, Nb, A, B, Acc, Compare) -> + case {Na, Nb, A, B} of + {0, 0, _, _} -> + Acc; + + {_, 0, [Ax | Ar], _} -> + merge_down(Na - 1, Nb, Ar, B, [Ax | Acc], Compare); + + {0, _, _, [Bx | Br]} -> + merge_down(Na, Nb - 1, A, Br, [Bx | Acc], Compare); + + {_, _, [Ax@1 | Ar@1], [Bx@1 | Br@1]} -> + case Compare(Bx@1, Ax@1) of + lt -> + merge_down(Na - 1, Nb, Ar@1, B, [Ax@1 | Acc], Compare); + + _ -> + merge_down(Na, Nb - 1, A, Br@1, [Bx@1 | Acc], Compare) + end; + + {_, _, _, _} -> + Acc + end. + +-spec merge_sort( + list(AIH), + integer(), + fun((AIH, AIH) -> gleam@order:order()), + boolean() +) -> list(AIH). +merge_sort(L, Ln, Compare, Down) -> + N = Ln div 2, + A = L, + B = drop(L, N), + case Ln < 3 of + true -> + case Down of + true -> + merge_down(N, Ln - N, A, B, [], Compare); + + false -> + merge_up(N, Ln - N, A, B, [], Compare) + end; + + false -> + case Down of + true -> + merge_down( + N, + Ln - N, + merge_sort(A, N, Compare, false), + merge_sort(B, Ln - N, Compare, false), + [], + Compare + ); + + false -> + merge_up( + N, + Ln - N, + merge_sort(A, N, Compare, true), + merge_sort(B, Ln - N, Compare, true), + [], + Compare + ) + end + end. + +-spec sort(list(AIK), fun((AIK, AIK) -> gleam@order:order())) -> list(AIK). +sort(List, Compare) -> + merge_sort(List, length(List), Compare, true). + +-spec tail_recursive_range(integer(), integer(), list(integer())) -> list(integer()). +tail_recursive_range(Start, Stop, Acc) -> + case gleam@int:compare(Start, Stop) of + eq -> + [Stop | Acc]; + + gt -> + tail_recursive_range(Start, Stop + 1, [Stop | Acc]); + + lt -> + tail_recursive_range(Start, Stop - 1, [Stop | Acc]) + end. + +-spec range(integer(), integer()) -> list(integer()). +range(Start, Stop) -> + tail_recursive_range(Start, Stop, []). + +-spec do_repeat(AIQ, integer(), list(AIQ)) -> list(AIQ). +do_repeat(A, Times, Acc) -> + case Times =< 0 of + true -> + Acc; + + false -> + do_repeat(A, Times - 1, [A | Acc]) + end. + +-spec repeat(AIT, integer()) -> list(AIT). +repeat(A, Times) -> + do_repeat(A, Times, []). + +-spec do_split(list(AIV), integer(), list(AIV)) -> {list(AIV), list(AIV)}. +do_split(List, N, Taken) -> + case N =< 0 of + true -> + {reverse(Taken), List}; + + false -> + case List of + [] -> + {reverse(Taken), []}; + + [X | Xs] -> + do_split(Xs, N - 1, [X | Taken]) + end + end. + +-spec split(list(AJA), integer()) -> {list(AJA), list(AJA)}. +split(List, Index) -> + do_split(List, Index, []). + +-spec do_split_while(list(AJE), fun((AJE) -> boolean()), list(AJE)) -> {list(AJE), + list(AJE)}. +do_split_while(List, F, Acc) -> + case List of + [] -> + {reverse(Acc), []}; + + [X | Xs] -> + case F(X) of + false -> + {reverse(Acc), List}; + + _ -> + do_split_while(Xs, F, [X | Acc]) + end + end. + +-spec split_while(list(AJJ), fun((AJJ) -> boolean())) -> {list(AJJ), list(AJJ)}. +split_while(List, Predicate) -> + do_split_while(List, Predicate, []). + +-spec key_find(list({AJN, AJO}), AJN) -> {ok, AJO} | {error, nil}. +key_find(Keyword_list, Desired_key) -> + find_map( + Keyword_list, + fun(Keyword) -> + {Key, Value} = Keyword, + case Key =:= Desired_key of + true -> + {ok, Value}; + + false -> + {error, nil} + end + end + ). + +-spec key_filter(list({AJS, AJT}), AJS) -> list(AJT). +key_filter(Keyword_list, Desired_key) -> + filter_map( + Keyword_list, + fun(Keyword) -> + {Key, Value} = Keyword, + case Key =:= Desired_key of + true -> + {ok, Value}; + + false -> + {error, nil} + end + end + ). + +-spec do_pop(list(BAG), fun((BAG) -> boolean()), list(BAG)) -> {ok, + {BAG, list(BAG)}} | + {error, nil}. +do_pop(Haystack, Predicate, Checked) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Predicate(X) of + true -> + {ok, {X, append(reverse(Checked), Rest)}}; + + false -> + do_pop(Rest, Predicate, [X | Checked]) + end + end. + +-spec pop(list(AKA), fun((AKA) -> boolean())) -> {ok, {AKA, list(AKA)}} | + {error, nil}. +pop(Haystack, Is_desired) -> + do_pop(Haystack, Is_desired, []). + +-spec do_pop_map(list(BAU), fun((BAU) -> {ok, BBH} | {error, any()}), list(BAU)) -> {ok, + {BBH, list(BAU)}} | + {error, nil}. +do_pop_map(Haystack, Mapper, Checked) -> + case Haystack of + [] -> + {error, nil}; + + [X | Rest] -> + case Mapper(X) of + {ok, Y} -> + {ok, {Y, append(reverse(Checked), Rest)}}; + + {error, _} -> + do_pop_map(Rest, Mapper, [X | Checked]) + end + end. + +-spec pop_map(list(AKJ), fun((AKJ) -> {ok, AKL} | {error, any()})) -> {ok, + {AKL, list(AKJ)}} | + {error, nil}. +pop_map(Haystack, Is_desired) -> + do_pop_map(Haystack, Is_desired, []). + +-spec key_pop(list({AKS, AKT}), AKS) -> {ok, {AKT, list({AKS, AKT})}} | + {error, nil}. +key_pop(Haystack, Key) -> + pop_map( + Haystack, + fun(Entry) -> + {K, V} = Entry, + case K of + K@1 when K@1 =:= Key -> + {ok, V}; + + _ -> + {error, nil} + end + end + ). + +-spec key_set(list({AKY, AKZ}), AKY, AKZ) -> list({AKY, AKZ}). +key_set(List, Key, Value) -> + case List of + [] -> + [{Key, Value}]; + + [{K, _} | Rest] when K =:= Key -> + [{Key, Value} | Rest]; + + [First | Rest@1] -> + [First | key_set(Rest@1, Key, Value)] + end. + +-spec each(list(ALC), fun((ALC) -> any())) -> nil. +each(List, F) -> + case List of + [] -> + nil; + + [X | Xs] -> + F(X), + each(Xs, F) + end. + +-spec try_each(list(ALF), fun((ALF) -> {ok, any()} | {error, ALI})) -> {ok, nil} | + {error, ALI}. +try_each(List, Fun) -> + case List of + [] -> + {ok, nil}; + + [X | Xs] -> + case Fun(X) of + {ok, _} -> + try_each(Xs, Fun); + + {error, E} -> + {error, E} + end + end. + +-spec do_partition(list(BCO), fun((BCO) -> boolean()), list(BCO), list(BCO)) -> {list(BCO), + list(BCO)}. +do_partition(List, Categorise, Trues, Falses) -> + case List of + [] -> + {reverse(Trues), reverse(Falses)}; + + [X | Xs] -> + case Categorise(X) of + true -> + do_partition(Xs, Categorise, [X | Trues], Falses); + + false -> + do_partition(Xs, Categorise, Trues, [X | Falses]) + end + end. + +-spec partition(list(ALS), fun((ALS) -> boolean())) -> {list(ALS), list(ALS)}. +partition(List, Categorise) -> + do_partition(List, Categorise, [], []). + +-spec permutations(list(ALW)) -> list(list(ALW)). +permutations(L) -> + case L of + [] -> + [[]]; + + _ -> + _pipe = L, + _pipe@5 = index_map(_pipe, fun(I, I_idx) -> _pipe@1 = L, + _pipe@2 = index_fold( + _pipe@1, + [], + fun(Acc, J, J_idx) -> case I_idx =:= J_idx of + true -> + Acc; + + false -> + [J | Acc] + end end + ), + _pipe@3 = reverse(_pipe@2), + _pipe@4 = permutations(_pipe@3), + map(_pipe@4, fun(Permutation) -> [I | Permutation] end) end), + concat(_pipe@5) + end. + +-spec do_window(list(list(AMA)), list(AMA), integer()) -> list(list(AMA)). +do_window(Acc, L, N) -> + Window = take(L, N), + case length(Window) =:= N of + true -> + do_window([Window | Acc], drop(L, 1), N); + + false -> + Acc + end. + +-spec window(list(AMG), integer()) -> list(list(AMG)). +window(L, N) -> + _pipe = do_window([], L, N), + reverse(_pipe). + +-spec window_by_2(list(AMK)) -> list({AMK, AMK}). +window_by_2(L) -> + zip(L, drop(L, 1)). + +-spec drop_while(list(AMN), fun((AMN) -> boolean())) -> list(AMN). +drop_while(List, Predicate) -> + case List of + [] -> + []; + + [X | Xs] -> + case Predicate(X) of + true -> + drop_while(Xs, Predicate); + + false -> + [X | Xs] + end + end. + +-spec do_take_while(list(AMQ), fun((AMQ) -> boolean()), list(AMQ)) -> list(AMQ). +do_take_while(List, Predicate, Acc) -> + case List of + [] -> + reverse(Acc); + + [First | Rest] -> + case Predicate(First) of + true -> + do_take_while(Rest, Predicate, [First | Acc]); + + false -> + reverse(Acc) + end + end. + +-spec take_while(list(AMU), fun((AMU) -> boolean())) -> list(AMU). +take_while(List, Predicate) -> + do_take_while(List, Predicate, []). + +-spec do_chunk(list(AMX), fun((AMX) -> AMZ), AMZ, list(AMX), list(list(AMX))) -> list(list(AMX)). +do_chunk(List, F, Previous_key, Current_chunk, Acc) -> + case List of + [First | Rest] -> + Key = F(First), + case Key =:= Previous_key of + false -> + New_acc = [reverse(Current_chunk) | Acc], + do_chunk(Rest, F, Key, [First], New_acc); + + _ -> + do_chunk(Rest, F, Key, [First | Current_chunk], Acc) + end; + + _ -> + reverse([reverse(Current_chunk) | Acc]) + end. + +-spec chunk(list(ANF), fun((ANF) -> any())) -> list(list(ANF)). +chunk(List, F) -> + case List of + [] -> + []; + + [First | Rest] -> + do_chunk(Rest, F, F(First), [First], []) + end. + +-spec do_sized_chunk( + list(ANK), + integer(), + integer(), + list(ANK), + list(list(ANK)) +) -> list(list(ANK)). +do_sized_chunk(List, Count, Left, Current_chunk, Acc) -> + case List of + [] -> + case Current_chunk of + [] -> + reverse(Acc); + + Remaining -> + reverse([reverse(Remaining) | Acc]) + end; + + [First | Rest] -> + Chunk = [First | Current_chunk], + case Left > 1 of + false -> + do_sized_chunk( + Rest, + Count, + Count, + [], + [reverse(Chunk) | Acc] + ); + + true -> + do_sized_chunk(Rest, Count, Left - 1, Chunk, Acc) + end + end. + +-spec sized_chunk(list(ANR), integer()) -> list(list(ANR)). +sized_chunk(List, Count) -> + do_sized_chunk(List, Count, Count, [], []). + +-spec reduce(list(ANV), fun((ANV, ANV) -> ANV)) -> {ok, ANV} | {error, nil}. +reduce(List, Fun) -> + case List of + [] -> + {error, nil}; + + [First | Rest] -> + {ok, fold(Rest, First, Fun)} + end. + +-spec do_scan(list(ANZ), AOB, list(AOB), fun((AOB, ANZ) -> AOB)) -> list(AOB). +do_scan(List, Accumulator, Accumulated, Fun) -> + case List of + [] -> + reverse(Accumulated); + + [X | Xs] -> + Next = Fun(Accumulator, X), + do_scan(Xs, Next, [Next | Accumulated], Fun) + end. + +-spec scan(list(AOE), AOG, fun((AOG, AOE) -> AOG)) -> list(AOG). +scan(List, Initial, Fun) -> + do_scan(List, Initial, [], Fun). + +-spec last(list(AOI)) -> {ok, AOI} | {error, nil}. +last(List) -> + _pipe = List, + reduce(_pipe, fun(_, Elem) -> Elem end). + +-spec combinations(list(AOM), integer()) -> list(list(AOM)). +combinations(Items, N) -> + case N of + 0 -> + [[]]; + + _ -> + case Items of + [] -> + []; + + [X | Xs] -> + First_combinations = begin + _pipe = map( + combinations(Xs, N - 1), + fun(Com) -> [X | Com] end + ), + reverse(_pipe) + end, + fold( + First_combinations, + combinations(Xs, N), + fun(Acc, C) -> [C | Acc] end + ) + end + end. + +-spec do_combination_pairs(list(AOQ)) -> list(list({AOQ, AOQ})). +do_combination_pairs(Items) -> + case Items of + [] -> + []; + + [X | Xs] -> + First_combinations = map(Xs, fun(Other) -> {X, Other} end), + [First_combinations | do_combination_pairs(Xs)] + end. + +-spec combination_pairs(list(AOU)) -> list({AOU, AOU}). +combination_pairs(Items) -> + _pipe = do_combination_pairs(Items), + concat(_pipe). + +-spec transpose(list(list(APB))) -> list(list(APB)). +transpose(List_of_list) -> + Take_first = fun(List) -> case List of + [] -> + []; + + [F] -> + [F]; + + [F@1 | _] -> + [F@1] + end end, + case List_of_list of + [] -> + []; + + [[] | Xss] -> + transpose(Xss); + + Rows -> + Firsts = begin + _pipe = Rows, + _pipe@1 = map(_pipe, Take_first), + concat(_pipe@1) + end, + Rest = transpose(map(Rows, fun(_capture) -> drop(_capture, 1) end)), + [Firsts | Rest] + end. + +-spec interleave(list(list(AOX))) -> list(AOX). +interleave(List) -> + _pipe = transpose(List), + concat(_pipe). + +-spec do_shuffle_pair_unwrap(list({float(), APG}), list(APG)) -> list(APG). +do_shuffle_pair_unwrap(List, Acc) -> + case List of + [] -> + Acc; + + [Elem_pair | Enumerable] -> + do_shuffle_pair_unwrap( + Enumerable, + [erlang:element(2, Elem_pair) | Acc] + ) + end. + +-spec do_shuffle_by_pair_indexes(list({float(), APK})) -> list({float(), APK}). +do_shuffle_by_pair_indexes(List_of_pairs) -> + sort( + List_of_pairs, + fun(A_pair, B_pair) -> + gleam@float:compare( + erlang:element(1, A_pair), + erlang:element(1, B_pair) + ) + end + ). + +-spec shuffle(list(APN)) -> list(APN). +shuffle(List) -> + _pipe = List, + _pipe@1 = fold(_pipe, [], fun(Acc, A) -> [{rand:uniform(), A} | Acc] end), + _pipe@2 = do_shuffle_by_pair_indexes(_pipe@1), + do_shuffle_pair_unwrap(_pipe@2, []). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@map.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@map.erl new file mode 100644 index 0000000..a1ed3fd --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@map.erl @@ -0,0 +1,76 @@ +-module(gleam@map). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([size/1, to_list/1, from_list/1, has_key/2, new/0, get/2, insert/3, map_values/2, keys/1, values/1, filter/2, take/2, merge/2, delete/2, drop/2, update/3, fold/3]). + +-spec size(gleam@dict:dict(any(), any())) -> integer(). +size(Map) -> + maps:size(Map). + +-spec to_list(gleam@dict:dict(EWQ, EWR)) -> list({EWQ, EWR}). +to_list(Map) -> + maps:to_list(Map). + +-spec from_list(list({EWT, EWU})) -> gleam@dict:dict(EWT, EWU). +from_list(List) -> + maps:from_list(List). + +-spec has_key(gleam@dict:dict(EWY, any()), EWY) -> boolean(). +has_key(Map, Key) -> + gleam@dict:has_key(Map, Key). + +-spec new() -> gleam@dict:dict(any(), any()). +new() -> + gleam@dict:new(). + +-spec get(gleam@dict:dict(EXB, EXC), EXB) -> {ok, EXC} | {error, nil}. +get(From, Get) -> + gleam@dict:get(From, Get). + +-spec insert(gleam@dict:dict(EXG, EXH), EXG, EXH) -> gleam@dict:dict(EXG, EXH). +insert(Map, Key, Value) -> + gleam@dict:insert(Map, Key, Value). + +-spec map_values(gleam@dict:dict(EXK, EXL), fun((EXK, EXL) -> EXM)) -> gleam@dict:dict(EXK, EXM). +map_values(Map, Fun) -> + gleam@dict:map_values(Map, Fun). + +-spec keys(gleam@dict:dict(EXP, any())) -> list(EXP). +keys(Map) -> + gleam@dict:keys(Map). + +-spec values(gleam@dict:dict(any(), EXS)) -> list(EXS). +values(Map) -> + gleam@dict:values(Map). + +-spec filter(gleam@dict:dict(EXV, EXW), fun((EXV, EXW) -> boolean())) -> gleam@dict:dict(EXV, EXW). +filter(Map, Predicate) -> + gleam@dict:filter(Map, Predicate). + +-spec take(gleam@dict:dict(EXZ, EZT), list(EXZ)) -> gleam@dict:dict(EXZ, EZT). +take(Map, Desired_keys) -> + gleam@dict:take(Map, Desired_keys). + +-spec merge(gleam@dict:dict(EZU, EZV), gleam@dict:dict(EZU, EZV)) -> gleam@dict:dict(EZU, EZV). +merge(Map, New_entries) -> + gleam@dict:merge(Map, New_entries). + +-spec delete(gleam@dict:dict(EYG, EZX), EYG) -> gleam@dict:dict(EYG, EZX). +delete(Map, Key) -> + gleam@dict:delete(Map, Key). + +-spec drop(gleam@dict:dict(EYJ, EZZ), list(EYJ)) -> gleam@dict:dict(EYJ, EZZ). +drop(Map, Disallowed_keys) -> + gleam@dict:drop(Map, Disallowed_keys). + +-spec update( + gleam@dict:dict(EYN, EYO), + EYN, + fun((gleam@option:option(EYO)) -> EYO) +) -> gleam@dict:dict(EYN, EYO). +update(Map, Key, Fun) -> + gleam@dict:update(Map, Key, Fun). + +-spec fold(gleam@dict:dict(EYT, EYU), EYS, fun((EYS, EYT, EYU) -> EYS)) -> EYS. +fold(Map, Initial, Fun) -> + gleam@dict:fold(Map, Initial, Fun). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@option.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@option.erl new file mode 100644 index 0000000..6c9768c --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@option.erl @@ -0,0 +1,147 @@ +-module(gleam@option). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([all/1, is_some/1, is_none/1, to_result/2, from_result/1, unwrap/2, lazy_unwrap/2, map/2, flatten/1, then/2, 'or'/2, lazy_or/2, values/1]). +-export_type([option/1]). + +-type option(GB) :: {some, GB} | none. + +-spec do_all(list(option(GC)), list(GC)) -> option(list(GC)). +do_all(List, Acc) -> + case List of + [] -> + {some, Acc}; + + [X | Rest] -> + Accumulate = fun(Acc@1, Item) -> case {Acc@1, Item} of + {{some, Values}, {some, Value}} -> + {some, [Value | Values]}; + + {_, _} -> + none + end end, + Accumulate(do_all(Rest, Acc), X) + end. + +-spec all(list(option(GI))) -> option(list(GI)). +all(List) -> + do_all(List, []). + +-spec is_some(option(any())) -> boolean(). +is_some(Option) -> + Option /= none. + +-spec is_none(option(any())) -> boolean(). +is_none(Option) -> + Option =:= none. + +-spec to_result(option(GR), GU) -> {ok, GR} | {error, GU}. +to_result(Option, E) -> + case Option of + {some, A} -> + {ok, A}; + + _ -> + {error, E} + end. + +-spec from_result({ok, GX} | {error, any()}) -> option(GX). +from_result(Result) -> + case Result of + {ok, A} -> + {some, A}; + + _ -> + none + end. + +-spec unwrap(option(HC), HC) -> HC. +unwrap(Option, Default) -> + case Option of + {some, X} -> + X; + + none -> + Default + end. + +-spec lazy_unwrap(option(HE), fun(() -> HE)) -> HE. +lazy_unwrap(Option, Default) -> + case Option of + {some, X} -> + X; + + none -> + Default() + end. + +-spec map(option(HG), fun((HG) -> HI)) -> option(HI). +map(Option, Fun) -> + case Option of + {some, X} -> + {some, Fun(X)}; + + none -> + none + end. + +-spec flatten(option(option(HK))) -> option(HK). +flatten(Option) -> + case Option of + {some, X} -> + X; + + none -> + none + end. + +-spec then(option(HO), fun((HO) -> option(HQ))) -> option(HQ). +then(Option, Fun) -> + case Option of + {some, X} -> + Fun(X); + + none -> + none + end. + +-spec 'or'(option(HT), option(HT)) -> option(HT). +'or'(First, Second) -> + case First of + {some, _} -> + First; + + none -> + Second + end. + +-spec lazy_or(option(HX), fun(() -> option(HX))) -> option(HX). +lazy_or(First, Second) -> + case First of + {some, _} -> + First; + + none -> + Second() + end. + +-spec do_values(list(option(IB)), list(IB)) -> list(IB). +do_values(List, Acc) -> + case List of + [] -> + Acc; + + [X | Xs] -> + Accumulate = fun(Acc@1, Item) -> case Item of + {some, Value} -> + [Value | Acc@1]; + + none -> + Acc@1 + end end, + Accumulate(do_values(Xs, Acc), X) + end. + +-spec values(list(option(IG))) -> list(IG). +values(Options) -> + do_values(Options, []). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@order.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@order.erl new file mode 100644 index 0000000..d4b225c --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@order.erl @@ -0,0 +1,79 @@ +-module(gleam@order). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([negate/1, to_int/1, compare/2, max/2, min/2, reverse/1]). +-export_type([order/0]). + +-type order() :: lt | eq | gt. + +-spec negate(order()) -> order(). +negate(Order) -> + case Order of + lt -> + gt; + + eq -> + eq; + + gt -> + lt + end. + +-spec to_int(order()) -> integer(). +to_int(Order) -> + case Order of + lt -> + -1; + + eq -> + 0; + + gt -> + 1 + end. + +-spec compare(order(), order()) -> order(). +compare(A, B) -> + case {A, B} of + {X, Y} when X =:= Y -> + eq; + + {lt, _} -> + lt; + + {eq, gt} -> + lt; + + {_, _} -> + gt + end. + +-spec max(order(), order()) -> order(). +max(A, B) -> + case {A, B} of + {gt, _} -> + gt; + + {eq, lt} -> + eq; + + {_, _} -> + B + end. + +-spec min(order(), order()) -> order(). +min(A, B) -> + case {A, B} of + {lt, _} -> + lt; + + {eq, gt} -> + eq; + + {_, _} -> + B + end. + +-spec reverse(fun((I, I) -> order())) -> fun((I, I) -> order()). +reverse(Orderer) -> + fun(A, B) -> Orderer(B, A) end. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@pair.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@pair.erl new file mode 100644 index 0000000..8e5d10f --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@pair.erl @@ -0,0 +1,33 @@ +-module(gleam@pair). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([first/1, second/1, swap/1, map_first/2, map_second/2, new/2]). + +-spec first({FM, any()}) -> FM. +first(Pair) -> + {A, _} = Pair, + A. + +-spec second({any(), FP}) -> FP. +second(Pair) -> + {_, A} = Pair, + A. + +-spec swap({FQ, FR}) -> {FR, FQ}. +swap(Pair) -> + {A, B} = Pair, + {B, A}. + +-spec map_first({FS, FT}, fun((FS) -> FU)) -> {FU, FT}. +map_first(Pair, Fun) -> + {A, B} = Pair, + {Fun(A), B}. + +-spec map_second({FV, FW}, fun((FW) -> FX)) -> {FV, FX}. +map_second(Pair, Fun) -> + {A, B} = Pair, + {A, Fun(B)}. + +-spec new(FY, FZ) -> {FY, FZ}. +new(First, Second) -> + {First, Second}. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@queue.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@queue.erl new file mode 100644 index 0000000..7c4fd02 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@queue.erl @@ -0,0 +1,121 @@ +-module(gleam@queue). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-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]). +-export_type([queue/1]). + +-opaque queue(DFL) :: {queue, list(DFL), list(DFL)}. + +-spec new() -> queue(any()). +new() -> + {queue, [], []}. + +-spec from_list(list(DFO)) -> queue(DFO). +from_list(List) -> + {queue, [], List}. + +-spec to_list(queue(DFR)) -> list(DFR). +to_list(Queue) -> + _pipe = erlang:element(3, Queue), + gleam@list:append(_pipe, gleam@list:reverse(erlang:element(2, Queue))). + +-spec is_empty(queue(any())) -> boolean(). +is_empty(Queue) -> + (erlang:element(2, Queue) =:= []) andalso (erlang:element(3, Queue) =:= []). + +-spec length(queue(any())) -> integer(). +length(Queue) -> + gleam@list:length(erlang:element(2, Queue)) + gleam@list:length( + erlang:element(3, Queue) + ). + +-spec push_back(queue(DFY), DFY) -> queue(DFY). +push_back(Queue, Item) -> + {queue, [Item | erlang:element(2, Queue)], erlang:element(3, Queue)}. + +-spec push_front(queue(DGB), DGB) -> queue(DGB). +push_front(Queue, Item) -> + {queue, erlang:element(2, Queue), [Item | erlang:element(3, Queue)]}. + +-spec pop_back(queue(DGE)) -> {ok, {DGE, queue(DGE)}} | {error, nil}. +pop_back(Queue) -> + case Queue of + {queue, [], []} -> + {error, nil}; + + {queue, [], Out} -> + pop_back({queue, gleam@list:reverse(Out), []}); + + {queue, [First | Rest], Out@1} -> + Queue@1 = {queue, Rest, Out@1}, + {ok, {First, Queue@1}} + end. + +-spec pop_front(queue(DGJ)) -> {ok, {DGJ, queue(DGJ)}} | {error, nil}. +pop_front(Queue) -> + case Queue of + {queue, [], []} -> + {error, nil}; + + {queue, In, []} -> + pop_front({queue, [], gleam@list:reverse(In)}); + + {queue, In@1, [First | Rest]} -> + Queue@1 = {queue, In@1, Rest}, + {ok, {First, Queue@1}} + end. + +-spec reverse(queue(DGO)) -> queue(DGO). +reverse(Queue) -> + {queue, erlang:element(3, Queue), erlang:element(2, Queue)}. + +-spec check_equal( + list(DGR), + list(DGR), + list(DGR), + list(DGR), + fun((DGR, DGR) -> boolean()) +) -> boolean(). +check_equal(Xs, X_tail, Ys, Y_tail, Eq) -> + case {Xs, X_tail, Ys, Y_tail} of + {[], [], [], []} -> + true; + + {[X | Xs@1], _, [Y | Ys@1], _} -> + case Eq(X, Y) of + false -> + false; + + true -> + check_equal(Xs@1, X_tail, Ys@1, Y_tail, Eq) + end; + + {[], [_ | _], _, _} -> + check_equal(gleam@list:reverse(X_tail), [], Ys, Y_tail, Eq); + + {_, _, [], [_ | _]} -> + check_equal(Xs, X_tail, gleam@list:reverse(Y_tail), [], Eq); + + {_, _, _, _} -> + false + end. + +-spec is_logically_equal(queue(DGW), queue(DGW), fun((DGW, DGW) -> boolean())) -> boolean(). +is_logically_equal(A, B, Element_is_equal) -> + check_equal( + erlang:element(3, A), + erlang:element(2, A), + erlang:element(3, B), + erlang:element(2, B), + Element_is_equal + ). + +-spec is_equal(queue(DGZ), queue(DGZ)) -> boolean(). +is_equal(A, B) -> + check_equal( + erlang:element(3, A), + erlang:element(2, A), + erlang:element(3, B), + erlang:element(2, B), + fun(A@1, B@1) -> A@1 =:= B@1 end + ). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@regex.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@regex.erl new file mode 100644 index 0000000..f49cc28 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@regex.erl @@ -0,0 +1,33 @@ +-module(gleam@regex). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([compile/2, from_string/1, check/2, split/2, scan/2]). +-export_type([regex/0, match/0, compile_error/0, options/0]). + +-type regex() :: any(). + +-type match() :: {match, binary(), list(gleam@option:option(binary()))}. + +-type compile_error() :: {compile_error, binary(), integer()}. + +-type options() :: {options, boolean(), boolean()}. + +-spec compile(binary(), options()) -> {ok, regex()} | {error, compile_error()}. +compile(Pattern, Options) -> + gleam_stdlib:compile_regex(Pattern, Options). + +-spec from_string(binary()) -> {ok, regex()} | {error, compile_error()}. +from_string(Pattern) -> + compile(Pattern, {options, false, false}). + +-spec check(regex(), binary()) -> boolean(). +check(Regex, Content) -> + gleam_stdlib:regex_check(Regex, Content). + +-spec split(regex(), binary()) -> list(binary()). +split(Regex, String) -> + gleam_stdlib:regex_split(Regex, String). + +-spec scan(regex(), binary()) -> list(match()). +scan(Regex, String) -> + gleam_stdlib:regex_scan(Regex, String). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@result.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@result.erl new file mode 100644 index 0000000..62dbca1 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@result.erl @@ -0,0 +1,201 @@ +-module(gleam@result). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([is_ok/1, is_error/1, map/2, map_error/2, flatten/1, 'try'/2, then/2, unwrap/2, lazy_unwrap/2, unwrap_error/2, unwrap_both/1, nil_error/1, 'or'/2, lazy_or/2, all/1, partition/1, replace/2, replace_error/2, values/1, try_recover/2]). + +-spec is_ok({ok, any()} | {error, any()}) -> boolean(). +is_ok(Result) -> + case Result of + {error, _} -> + false; + + {ok, _} -> + true + end. + +-spec is_error({ok, any()} | {error, any()}) -> boolean(). +is_error(Result) -> + case Result of + {ok, _} -> + false; + + {error, _} -> + true + end. + +-spec map({ok, BIZ} | {error, BJA}, fun((BIZ) -> BJD)) -> {ok, BJD} | + {error, BJA}. +map(Result, Fun) -> + case Result of + {ok, X} -> + {ok, Fun(X)}; + + {error, E} -> + {error, E} + end. + +-spec map_error({ok, BJG} | {error, BJH}, fun((BJH) -> BJK)) -> {ok, BJG} | + {error, BJK}. +map_error(Result, Fun) -> + case Result of + {ok, X} -> + {ok, X}; + + {error, Error} -> + {error, Fun(Error)} + end. + +-spec flatten({ok, {ok, BJN} | {error, BJO}} | {error, BJO}) -> {ok, BJN} | + {error, BJO}. +flatten(Result) -> + case Result of + {ok, X} -> + X; + + {error, Error} -> + {error, Error} + end. + +-spec 'try'({ok, BJV} | {error, BJW}, fun((BJV) -> {ok, BJZ} | {error, BJW})) -> {ok, + BJZ} | + {error, BJW}. +'try'(Result, Fun) -> + case Result of + {ok, X} -> + Fun(X); + + {error, E} -> + {error, E} + end. + +-spec then({ok, BKE} | {error, BKF}, fun((BKE) -> {ok, BKI} | {error, BKF})) -> {ok, + BKI} | + {error, BKF}. +then(Result, Fun) -> + 'try'(Result, Fun). + +-spec unwrap({ok, BKN} | {error, any()}, BKN) -> BKN. +unwrap(Result, Default) -> + case Result of + {ok, V} -> + V; + + {error, _} -> + Default + end. + +-spec lazy_unwrap({ok, BKR} | {error, any()}, fun(() -> BKR)) -> BKR. +lazy_unwrap(Result, Default) -> + case Result of + {ok, V} -> + V; + + {error, _} -> + Default() + end. + +-spec unwrap_error({ok, any()} | {error, BKW}, BKW) -> BKW. +unwrap_error(Result, Default) -> + case Result of + {ok, _} -> + Default; + + {error, E} -> + E + end. + +-spec unwrap_both({ok, BKZ} | {error, BKZ}) -> BKZ. +unwrap_both(Result) -> + case Result of + {ok, A} -> + A; + + {error, A@1} -> + A@1 + end. + +-spec nil_error({ok, BLC} | {error, any()}) -> {ok, BLC} | {error, nil}. +nil_error(Result) -> + map_error(Result, fun(_) -> nil end). + +-spec 'or'({ok, BLI} | {error, BLJ}, {ok, BLI} | {error, BLJ}) -> {ok, BLI} | + {error, BLJ}. +'or'(First, Second) -> + case First of + {ok, _} -> + First; + + {error, _} -> + Second + end. + +-spec lazy_or({ok, BLQ} | {error, BLR}, fun(() -> {ok, BLQ} | {error, BLR})) -> {ok, + BLQ} | + {error, BLR}. +lazy_or(First, Second) -> + case First of + {ok, _} -> + First; + + {error, _} -> + Second() + end. + +-spec all(list({ok, BLY} | {error, BLZ})) -> {ok, list(BLY)} | {error, BLZ}. +all(Results) -> + gleam@list:try_map(Results, fun(X) -> X end). + +-spec do_partition(list({ok, BMN} | {error, BMO}), list(BMN), list(BMO)) -> {list(BMN), + list(BMO)}. +do_partition(Results, Oks, Errors) -> + case Results of + [] -> + {Oks, Errors}; + + [{ok, A} | Rest] -> + do_partition(Rest, [A | Oks], Errors); + + [{error, E} | Rest@1] -> + do_partition(Rest@1, Oks, [E | Errors]) + end. + +-spec partition(list({ok, BMG} | {error, BMH})) -> {list(BMG), list(BMH)}. +partition(Results) -> + do_partition(Results, [], []). + +-spec replace({ok, any()} | {error, BMW}, BMZ) -> {ok, BMZ} | {error, BMW}. +replace(Result, Value) -> + case Result of + {ok, _} -> + {ok, Value}; + + {error, Error} -> + {error, Error} + end. + +-spec replace_error({ok, BNC} | {error, any()}, BNG) -> {ok, BNC} | {error, BNG}. +replace_error(Result, Error) -> + case Result of + {ok, X} -> + {ok, X}; + + {error, _} -> + {error, Error} + end. + +-spec values(list({ok, BNJ} | {error, any()})) -> list(BNJ). +values(Results) -> + gleam@list:filter_map(Results, fun(R) -> R end). + +-spec try_recover( + {ok, BNP} | {error, BNQ}, + fun((BNQ) -> {ok, BNP} | {error, BNT}) +) -> {ok, BNP} | {error, BNT}. +try_recover(Result, Fun) -> + case Result of + {ok, Value} -> + {ok, Value}; + + {error, Error} -> + Fun(Error) + end. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@set.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@set.erl new file mode 100644 index 0000000..035386c --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@set.erl @@ -0,0 +1,85 @@ +-module(gleam@set). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([new/0, size/1, insert/2, contains/2, delete/2, to_list/1, from_list/1, fold/3, filter/2, drop/2, take/2, union/2, intersection/2]). +-export_type([set/1]). + +-opaque set(FAG) :: {set, gleam@dict:dict(FAG, list(nil))}. + +-spec new() -> set(any()). +new() -> + {set, gleam@dict:new()}. + +-spec size(set(any())) -> integer(). +size(Set) -> + maps:size(erlang:element(2, Set)). + +-spec insert(set(FAM), FAM) -> set(FAM). +insert(Set, Member) -> + {set, gleam@dict:insert(erlang:element(2, Set), Member, [])}. + +-spec contains(set(FAP), FAP) -> boolean(). +contains(Set, Member) -> + _pipe = erlang:element(2, Set), + _pipe@1 = gleam@dict:get(_pipe, Member), + gleam@result:is_ok(_pipe@1). + +-spec delete(set(FAR), FAR) -> set(FAR). +delete(Set, Member) -> + {set, gleam@dict:delete(erlang:element(2, Set), Member)}. + +-spec to_list(set(FAU)) -> list(FAU). +to_list(Set) -> + gleam@dict:keys(erlang:element(2, Set)). + +-spec from_list(list(FAX)) -> set(FAX). +from_list(Members) -> + Map = gleam@list:fold( + Members, + gleam@dict:new(), + fun(M, K) -> gleam@dict:insert(M, K, []) end + ), + {set, Map}. + +-spec fold(set(FBA), FBC, fun((FBC, FBA) -> FBC)) -> FBC. +fold(Set, Initial, Reducer) -> + gleam@dict:fold( + erlang:element(2, Set), + Initial, + fun(A, K, _) -> Reducer(A, K) end + ). + +-spec filter(set(FBD), fun((FBD) -> boolean())) -> set(FBD). +filter(Set, Predicate) -> + {set, + gleam@dict:filter(erlang:element(2, Set), fun(M, _) -> Predicate(M) end)}. + +-spec drop(set(FBG), list(FBG)) -> set(FBG). +drop(Set, Disallowed) -> + gleam@list:fold(Disallowed, Set, fun delete/2). + +-spec take(set(FBK), list(FBK)) -> set(FBK). +take(Set, Desired) -> + {set, gleam@dict:take(erlang:element(2, Set), Desired)}. + +-spec order(set(FBO), set(FBO)) -> {set(FBO), set(FBO)}. +order(First, Second) -> + case maps:size(erlang:element(2, First)) > maps:size( + erlang:element(2, Second) + ) of + true -> + {First, Second}; + + false -> + {Second, First} + end. + +-spec union(set(FBT), set(FBT)) -> set(FBT). +union(First, Second) -> + {Larger, Smaller} = order(First, Second), + fold(Smaller, Larger, fun insert/2). + +-spec intersection(set(FBX), set(FBX)) -> set(FBX). +intersection(First, Second) -> + {Larger, Smaller} = order(First, Second), + take(Larger, to_list(Smaller)). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@string.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@string.erl new file mode 100644 index 0000000..5f000af --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@string.erl @@ -0,0 +1,352 @@ +-module(gleam@string). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([is_empty/1, length/1, reverse/1, replace/3, lowercase/1, uppercase/1, compare/2, crop/2, contains/2, starts_with/2, ends_with/2, split_once/2, append/2, concat/1, repeat/2, join/2, trim/1, trim_left/1, trim_right/1, pop_grapheme/1, to_graphemes/1, slice/3, drop_left/2, drop_right/2, split/2, pad_left/3, pad_right/3, to_utf_codepoints/1, from_utf_codepoints/1, utf_codepoint/1, utf_codepoint_to_int/1, to_option/1, first/1, last/1, capitalise/1, inspect/1, byte_size/1]). +-export_type([direction/0]). + +-type direction() :: leading | trailing | both. + +-spec is_empty(binary()) -> boolean(). +is_empty(Str) -> + Str =:= <<""/utf8>>. + +-spec length(binary()) -> integer(). +length(String) -> + string:length(String). + +-spec do_reverse(binary()) -> binary(). +do_reverse(String) -> + _pipe = String, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:reverse(_pipe@1), + gleam@string_builder:to_string(_pipe@2). + +-spec reverse(binary()) -> binary(). +reverse(String) -> + do_reverse(String). + +-spec replace(binary(), binary(), binary()) -> binary(). +replace(String, Pattern, Substitute) -> + _pipe = String, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:replace(_pipe@1, Pattern, Substitute), + gleam@string_builder:to_string(_pipe@2). + +-spec lowercase(binary()) -> binary(). +lowercase(String) -> + string:lowercase(String). + +-spec uppercase(binary()) -> binary(). +uppercase(String) -> + string:uppercase(String). + +-spec compare(binary(), binary()) -> gleam@order:order(). +compare(A, B) -> + case A =:= B of + true -> + eq; + + _ -> + case gleam_stdlib:less_than(A, B) of + true -> + lt; + + _ -> + gt + end + end. + +-spec crop(binary(), binary()) -> binary(). +crop(String, Substring) -> + gleam_stdlib:crop_string(String, Substring). + +-spec contains(binary(), binary()) -> boolean(). +contains(Haystack, Needle) -> + gleam_stdlib:contains_string(Haystack, Needle). + +-spec starts_with(binary(), binary()) -> boolean(). +starts_with(String, Prefix) -> + gleam_stdlib:string_starts_with(String, Prefix). + +-spec ends_with(binary(), binary()) -> boolean(). +ends_with(String, Suffix) -> + gleam_stdlib:string_ends_with(String, Suffix). + +-spec do_split_once(binary(), binary()) -> {ok, {binary(), binary()}} | + {error, nil}. +do_split_once(X, Substring) -> + case string:split(X, Substring) of + [First, Rest] -> + {ok, {First, Rest}}; + + _ -> + {error, nil} + end. + +-spec split_once(binary(), binary()) -> {ok, {binary(), binary()}} | + {error, nil}. +split_once(X, Substring) -> + do_split_once(X, Substring). + +-spec append(binary(), binary()) -> binary(). +append(First, Second) -> + _pipe = First, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:append(_pipe@1, Second), + gleam@string_builder:to_string(_pipe@2). + +-spec concat(list(binary())) -> binary(). +concat(Strings) -> + _pipe = Strings, + _pipe@1 = gleam@string_builder:from_strings(_pipe), + gleam@string_builder:to_string(_pipe@1). + +-spec repeat(binary(), integer()) -> binary(). +repeat(String, Times) -> + _pipe = gleam@iterator:repeat(String), + _pipe@1 = gleam@iterator:take(_pipe, Times), + _pipe@2 = gleam@iterator:to_list(_pipe@1), + concat(_pipe@2). + +-spec do_join(list(binary()), binary()) -> binary(). +do_join(Strings, Separator) -> + _pipe = Strings, + _pipe@1 = gleam@list:intersperse(_pipe, Separator), + concat(_pipe@1). + +-spec join(list(binary()), binary()) -> binary(). +join(Strings, Separator) -> + do_join(Strings, Separator). + +-spec do_trim(binary()) -> binary(). +do_trim(String) -> + string:trim(String, both). + +-spec trim(binary()) -> binary(). +trim(String) -> + do_trim(String). + +-spec do_trim_left(binary()) -> binary(). +do_trim_left(String) -> + string:trim(String, leading). + +-spec trim_left(binary()) -> binary(). +trim_left(String) -> + do_trim_left(String). + +-spec do_trim_right(binary()) -> binary(). +do_trim_right(String) -> + string:trim(String, trailing). + +-spec trim_right(binary()) -> binary(). +trim_right(String) -> + do_trim_right(String). + +-spec pop_grapheme(binary()) -> {ok, {binary(), binary()}} | {error, nil}. +pop_grapheme(String) -> + gleam_stdlib:string_pop_grapheme(String). + +-spec do_to_graphemes(binary(), list(binary())) -> list(binary()). +do_to_graphemes(String, Acc) -> + case pop_grapheme(String) of + {ok, {Grapheme, Rest}} -> + do_to_graphemes(Rest, [Grapheme | Acc]); + + _ -> + Acc + end. + +-spec to_graphemes(binary()) -> list(binary()). +to_graphemes(String) -> + _pipe = do_to_graphemes(String, []), + gleam@list:reverse(_pipe). + +-spec slice(binary(), integer(), integer()) -> binary(). +slice(String, Idx, Len) -> + case Len < 0 of + true -> + <<""/utf8>>; + + false -> + case Idx < 0 of + true -> + Translated_idx = length(String) + Idx, + case Translated_idx < 0 of + true -> + <<""/utf8>>; + + false -> + string:slice(String, Translated_idx, Len) + end; + + false -> + string:slice(String, Idx, Len) + end + end. + +-spec drop_left(binary(), integer()) -> binary(). +drop_left(String, Num_graphemes) -> + case Num_graphemes < 0 of + true -> + String; + + false -> + slice(String, Num_graphemes, length(String) - Num_graphemes) + end. + +-spec drop_right(binary(), integer()) -> binary(). +drop_right(String, Num_graphemes) -> + case Num_graphemes < 0 of + true -> + String; + + false -> + slice(String, 0, length(String) - Num_graphemes) + end. + +-spec split(binary(), binary()) -> list(binary()). +split(X, Substring) -> + case Substring of + <<""/utf8>> -> + to_graphemes(X); + + _ -> + _pipe = X, + _pipe@1 = gleam@string_builder:from_string(_pipe), + _pipe@2 = gleam@string_builder:split(_pipe@1, Substring), + gleam@list:map(_pipe@2, fun gleam@string_builder:to_string/1) + end. + +-spec padding(integer(), binary()) -> gleam@iterator:iterator(binary()). +padding(Size, Pad_string) -> + Pad_length = length(Pad_string), + Num_pads = case Pad_length of + 0 -> 0; + Gleam@denominator -> Size div Gleam@denominator + end, + Extra = case Pad_length of + 0 -> 0; + Gleam@denominator@1 -> Size rem Gleam@denominator@1 + end, + _pipe = gleam@iterator:repeat(Pad_string), + _pipe@1 = gleam@iterator:take(_pipe, Num_pads), + gleam@iterator:append( + _pipe@1, + gleam@iterator:single(slice(Pad_string, 0, Extra)) + ). + +-spec pad_left(binary(), integer(), binary()) -> binary(). +pad_left(String, Desired_length, Pad_string) -> + Current_length = length(String), + To_pad_length = Desired_length - Current_length, + _pipe = padding(To_pad_length, Pad_string), + _pipe@1 = gleam@iterator:append(_pipe, gleam@iterator:single(String)), + _pipe@2 = gleam@iterator:to_list(_pipe@1), + concat(_pipe@2). + +-spec pad_right(binary(), integer(), binary()) -> binary(). +pad_right(String, Desired_length, Pad_string) -> + Current_length = length(String), + To_pad_length = Desired_length - Current_length, + _pipe = gleam@iterator:single(String), + _pipe@1 = gleam@iterator:append(_pipe, padding(To_pad_length, Pad_string)), + _pipe@2 = gleam@iterator:to_list(_pipe@1), + concat(_pipe@2). + +-spec do_to_utf_codepoints_impl(bitstring(), list(integer())) -> list(integer()). +do_to_utf_codepoints_impl(Bit_array, Acc) -> + case Bit_array of + <<First/utf8, Rest/binary>> -> + do_to_utf_codepoints_impl(Rest, [First | Acc]); + + _ -> + Acc + end. + +-spec do_to_utf_codepoints(binary()) -> list(integer()). +do_to_utf_codepoints(String) -> + _pipe = do_to_utf_codepoints_impl(<<String/binary>>, []), + gleam@list:reverse(_pipe). + +-spec to_utf_codepoints(binary()) -> list(integer()). +to_utf_codepoints(String) -> + do_to_utf_codepoints(String). + +-spec from_utf_codepoints(list(integer())) -> binary(). +from_utf_codepoints(Utf_codepoints) -> + gleam_stdlib:utf_codepoint_list_to_string(Utf_codepoints). + +-spec utf_codepoint(integer()) -> {ok, integer()} | {error, nil}. +utf_codepoint(Value) -> + case Value of + I when I > 1114111 -> + {error, nil}; + + 65534 -> + {error, nil}; + + 65535 -> + {error, nil}; + + I@1 when (I@1 >= 55296) andalso (I@1 =< 57343) -> + {error, nil}; + + I@2 -> + {ok, gleam_stdlib:identity(I@2)} + end. + +-spec utf_codepoint_to_int(integer()) -> integer(). +utf_codepoint_to_int(Cp) -> + gleam_stdlib:identity(Cp). + +-spec to_option(binary()) -> gleam@option:option(binary()). +to_option(S) -> + case S of + <<""/utf8>> -> + none; + + _ -> + {some, S} + end. + +-spec first(binary()) -> {ok, binary()} | {error, nil}. +first(S) -> + case pop_grapheme(S) of + {ok, {First, _}} -> + {ok, First}; + + {error, E} -> + {error, E} + end. + +-spec last(binary()) -> {ok, binary()} | {error, nil}. +last(S) -> + case pop_grapheme(S) of + {ok, {First, <<""/utf8>>}} -> + {ok, First}; + + {ok, {_, Rest}} -> + {ok, slice(Rest, -1, 1)}; + + {error, E} -> + {error, E} + end. + +-spec capitalise(binary()) -> binary(). +capitalise(S) -> + case pop_grapheme(S) of + {ok, {First, Rest}} -> + append(uppercase(First), lowercase(Rest)); + + _ -> + <<""/utf8>> + end. + +-spec inspect(any()) -> binary(). +inspect(Term) -> + _pipe = gleam_stdlib:inspect(Term), + gleam@string_builder:to_string(_pipe). + +-spec byte_size(binary()) -> integer(). +byte_size(String) -> + erlang:byte_size(String). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@string_builder.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@string_builder.erl new file mode 100644 index 0000000..068bcc1 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@string_builder.erl @@ -0,0 +1,91 @@ +-module(gleam@string_builder). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([prepend_builder/2, append_builder/2, new/0, from_strings/1, concat/1, from_string/1, prepend/2, append/2, to_string/1, byte_size/1, join/2, lowercase/1, uppercase/1, reverse/1, split/2, replace/3, is_equal/2, is_empty/1]). +-export_type([string_builder/0, direction/0]). + +-type string_builder() :: any(). + +-type direction() :: all. + +-spec prepend_builder(string_builder(), string_builder()) -> string_builder(). +prepend_builder(Builder, Prefix) -> + gleam_stdlib:iodata_append(Prefix, Builder). + +-spec append_builder(string_builder(), string_builder()) -> string_builder(). +append_builder(Builder, Suffix) -> + gleam_stdlib:iodata_append(Builder, Suffix). + +-spec new() -> string_builder(). +new() -> + gleam_stdlib:identity([]). + +-spec from_strings(list(binary())) -> string_builder(). +from_strings(Strings) -> + gleam_stdlib:identity(Strings). + +-spec concat(list(string_builder())) -> string_builder(). +concat(Builders) -> + gleam_stdlib:identity(Builders). + +-spec from_string(binary()) -> string_builder(). +from_string(String) -> + gleam_stdlib:identity(String). + +-spec prepend(string_builder(), binary()) -> string_builder(). +prepend(Builder, Prefix) -> + append_builder(from_string(Prefix), Builder). + +-spec append(string_builder(), binary()) -> string_builder(). +append(Builder, Second) -> + append_builder(Builder, from_string(Second)). + +-spec to_string(string_builder()) -> binary(). +to_string(Builder) -> + unicode:characters_to_binary(Builder). + +-spec byte_size(string_builder()) -> integer(). +byte_size(Builder) -> + erlang:iolist_size(Builder). + +-spec join(list(string_builder()), binary()) -> string_builder(). +join(Builders, Sep) -> + _pipe = Builders, + _pipe@1 = gleam@list:intersperse(_pipe, from_string(Sep)), + concat(_pipe@1). + +-spec lowercase(string_builder()) -> string_builder(). +lowercase(Builder) -> + string:lowercase(Builder). + +-spec uppercase(string_builder()) -> string_builder(). +uppercase(Builder) -> + string:uppercase(Builder). + +-spec reverse(string_builder()) -> string_builder(). +reverse(Builder) -> + string:reverse(Builder). + +-spec do_split(string_builder(), binary()) -> list(string_builder()). +do_split(Iodata, Pattern) -> + string:split(Iodata, Pattern, all). + +-spec split(string_builder(), binary()) -> list(string_builder()). +split(Iodata, Pattern) -> + do_split(Iodata, Pattern). + +-spec do_replace(string_builder(), binary(), binary()) -> string_builder(). +do_replace(Iodata, Pattern, Substitute) -> + string:replace(Iodata, Pattern, Substitute, all). + +-spec replace(string_builder(), binary(), binary()) -> string_builder(). +replace(Builder, Pattern, Substitute) -> + do_replace(Builder, Pattern, Substitute). + +-spec is_equal(string_builder(), string_builder()) -> boolean(). +is_equal(A, B) -> + string:equal(A, B). + +-spec is_empty(string_builder()) -> boolean(). +is_empty(Builder) -> + string:is_empty(Builder). diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@uri.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@uri.erl new file mode 100644 index 0000000..3a067d6 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@uri.erl @@ -0,0 +1,252 @@ +-module(gleam@uri). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([parse/1, parse_query/1, percent_encode/1, query_to_string/1, percent_decode/1, path_segments/1, to_string/1, origin/1, merge/2]). +-export_type([uri/0]). + +-type uri() :: {uri, + gleam@option:option(binary()), + gleam@option:option(binary()), + gleam@option:option(binary()), + gleam@option:option(integer()), + binary(), + gleam@option:option(binary()), + gleam@option:option(binary())}. + +-spec parse(binary()) -> {ok, uri()} | {error, nil}. +parse(Uri_string) -> + gleam_stdlib:uri_parse(Uri_string). + +-spec parse_query(binary()) -> {ok, list({binary(), binary()})} | {error, nil}. +parse_query(Query) -> + gleam_stdlib:parse_query(Query). + +-spec percent_encode(binary()) -> binary(). +percent_encode(Value) -> + gleam_stdlib:percent_encode(Value). + +-spec query_pair({binary(), binary()}) -> gleam@string_builder:string_builder(). +query_pair(Pair) -> + gleam@string_builder:from_strings( + [percent_encode(erlang:element(1, Pair)), + <<"="/utf8>>, + percent_encode(erlang:element(2, Pair))] + ). + +-spec query_to_string(list({binary(), binary()})) -> binary(). +query_to_string(Query) -> + _pipe = Query, + _pipe@1 = gleam@list:map(_pipe, fun query_pair/1), + _pipe@2 = gleam@list:intersperse( + _pipe@1, + gleam@string_builder:from_string(<<"&"/utf8>>) + ), + _pipe@3 = gleam@string_builder:concat(_pipe@2), + gleam@string_builder:to_string(_pipe@3). + +-spec percent_decode(binary()) -> {ok, binary()} | {error, nil}. +percent_decode(Value) -> + gleam_stdlib:percent_decode(Value). + +-spec do_remove_dot_segments(list(binary()), list(binary())) -> list(binary()). +do_remove_dot_segments(Input, Accumulator) -> + case Input of + [] -> + gleam@list:reverse(Accumulator); + + [Segment | Rest] -> + Accumulator@5 = case {Segment, Accumulator} of + {<<""/utf8>>, Accumulator@1} -> + Accumulator@1; + + {<<"."/utf8>>, Accumulator@2} -> + Accumulator@2; + + {<<".."/utf8>>, []} -> + []; + + {<<".."/utf8>>, [_ | Accumulator@3]} -> + Accumulator@3; + + {Segment@1, Accumulator@4} -> + [Segment@1 | Accumulator@4] + end, + do_remove_dot_segments(Rest, Accumulator@5) + end. + +-spec remove_dot_segments(list(binary())) -> list(binary()). +remove_dot_segments(Input) -> + do_remove_dot_segments(Input, []). + +-spec path_segments(binary()) -> list(binary()). +path_segments(Path) -> + remove_dot_segments(gleam@string:split(Path, <<"/"/utf8>>)). + +-spec to_string(uri()) -> binary(). +to_string(Uri) -> + Parts = case erlang:element(8, Uri) of + {some, Fragment} -> + [<<"#"/utf8>>, Fragment]; + + _ -> + [] + end, + Parts@1 = case erlang:element(7, Uri) of + {some, Query} -> + [<<"?"/utf8>>, Query | Parts]; + + _ -> + Parts + end, + Parts@2 = [erlang:element(6, Uri) | Parts@1], + Parts@3 = case {erlang:element(4, Uri), + gleam@string:starts_with(erlang:element(6, Uri), <<"/"/utf8>>)} of + {{some, Host}, false} when Host =/= <<""/utf8>> -> + [<<"/"/utf8>> | Parts@2]; + + {_, _} -> + Parts@2 + end, + Parts@4 = case {erlang:element(4, Uri), erlang:element(5, Uri)} of + {{some, _}, {some, Port}} -> + [<<":"/utf8>>, gleam@int:to_string(Port) | Parts@3]; + + {_, _} -> + Parts@3 + end, + Parts@5 = case {erlang:element(2, Uri), + erlang:element(3, Uri), + erlang:element(4, Uri)} of + {{some, S}, {some, U}, {some, H}} -> + [S, <<"://"/utf8>>, U, <<"@"/utf8>>, H | Parts@4]; + + {{some, S@1}, none, {some, H@1}} -> + [S@1, <<"://"/utf8>>, H@1 | Parts@4]; + + {{some, S@2}, {some, _}, none} -> + [S@2, <<":"/utf8>> | Parts@4]; + + {{some, S@2}, none, none} -> + [S@2, <<":"/utf8>> | Parts@4]; + + {none, none, {some, H@2}} -> + [<<"//"/utf8>>, H@2 | Parts@4]; + + {_, _, _} -> + Parts@4 + end, + gleam@string:concat(Parts@5). + +-spec origin(uri()) -> {ok, binary()} | {error, nil}. +origin(Uri) -> + {uri, Scheme, _, Host, Port, _, _, _} = Uri, + case Scheme of + {some, <<"https"/utf8>>} when Port =:= {some, 443} -> + Origin = {uri, Scheme, none, Host, none, <<""/utf8>>, none, none}, + {ok, to_string(Origin)}; + + {some, <<"http"/utf8>>} when Port =:= {some, 80} -> + Origin@1 = {uri, Scheme, none, Host, none, <<""/utf8>>, none, none}, + {ok, to_string(Origin@1)}; + + {some, S} when (S =:= <<"http"/utf8>>) orelse (S =:= <<"https"/utf8>>) -> + Origin@2 = {uri, Scheme, none, Host, Port, <<""/utf8>>, none, none}, + {ok, to_string(Origin@2)}; + + _ -> + {error, nil} + end. + +-spec drop_last(list(FFS)) -> list(FFS). +drop_last(Elements) -> + gleam@list:take(Elements, gleam@list:length(Elements) - 1). + +-spec join_segments(list(binary())) -> binary(). +join_segments(Segments) -> + gleam@string:join([<<""/utf8>> | Segments], <<"/"/utf8>>). + +-spec merge(uri(), uri()) -> {ok, uri()} | {error, nil}. +merge(Base, Relative) -> + case Base of + {uri, {some, _}, _, {some, _}, _, _, _, _} -> + case Relative of + {uri, _, _, {some, _}, _, _, _, _} -> + Path = begin + _pipe = gleam@string:split( + erlang:element(6, Relative), + <<"/"/utf8>> + ), + _pipe@1 = remove_dot_segments(_pipe), + join_segments(_pipe@1) + end, + Resolved = {uri, + gleam@option:'or'( + erlang:element(2, Relative), + erlang:element(2, Base) + ), + none, + erlang:element(4, Relative), + gleam@option:'or'( + erlang:element(5, Relative), + erlang:element(5, Base) + ), + Path, + erlang:element(7, Relative), + erlang:element(8, Relative)}, + {ok, Resolved}; + + _ -> + {New_path, New_query} = case erlang:element(6, Relative) of + <<""/utf8>> -> + {erlang:element(6, Base), + gleam@option:'or'( + erlang:element(7, Relative), + erlang:element(7, Base) + )}; + + _ -> + Path_segments = case gleam@string:starts_with( + erlang:element(6, Relative), + <<"/"/utf8>> + ) of + true -> + gleam@string:split( + erlang:element(6, Relative), + <<"/"/utf8>> + ); + + false -> + _pipe@2 = gleam@string:split( + erlang:element(6, Base), + <<"/"/utf8>> + ), + _pipe@3 = drop_last(_pipe@2), + gleam@list:append( + _pipe@3, + gleam@string:split( + erlang:element(6, Relative), + <<"/"/utf8>> + ) + ) + end, + Path@1 = begin + _pipe@4 = Path_segments, + _pipe@5 = remove_dot_segments(_pipe@4), + join_segments(_pipe@5) + end, + {Path@1, erlang:element(7, Relative)} + end, + Resolved@1 = {uri, + erlang:element(2, Base), + none, + erlang:element(4, Base), + erlang:element(5, Base), + New_path, + New_query, + erlang:element(8, Relative)}, + {ok, Resolved@1} + end; + + _ -> + {error, nil} + end. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.app.src b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.app.src new file mode 100644 index 0000000..ddec67a --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.app.src @@ -0,0 +1,31 @@ +{application, gleam_stdlib, [ + {vsn, "0.34.0"}, + {applications, []}, + {description, "A standard library for the Gleam programming language"}, + {modules, [gleam@base, + gleam@bit_array, + gleam@bit_builder, + gleam@bit_string, + gleam@bool, + gleam@bytes_builder, + gleam@dict, + gleam@dynamic, + gleam@float, + gleam@function, + gleam@int, + gleam@io, + gleam@iterator, + gleam@list, + gleam@map, + gleam@option, + gleam@order, + gleam@pair, + gleam@queue, + gleam@regex, + gleam@result, + gleam@set, + gleam@string, + gleam@string_builder, + gleam@uri]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.erl b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.erl new file mode 100644 index 0000000..c6ea125 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.erl @@ -0,0 +1,529 @@ +-module(gleam_stdlib). + +-export([ + map_get/2, iodata_append/2, identity/1, decode_int/1, decode_bool/1, + decode_float/1, decode_list/1, decode_option/2, decode_field/2, parse_int/1, + parse_float/1, less_than/2, string_pop_grapheme/1, string_starts_with/2, + wrap_list/1, string_ends_with/2, string_pad/4, decode_map/1, uri_parse/1, + bit_array_int_to_u32/1, bit_array_int_from_u32/1, decode_result/1, + bit_array_slice/3, decode_bit_array/1, compile_regex/2, regex_scan/2, + percent_encode/1, percent_decode/1, regex_check/2, regex_split/2, + base_decode64/1, parse_query/1, bit_array_concat/1, size_of_tuple/1, + decode_tuple/1, decode_tuple2/1, decode_tuple3/1, decode_tuple4/1, + decode_tuple5/1, decode_tuple6/1, tuple_get/2, classify_dynamic/1, print/1, + println/1, print_error/1, println_error/1, inspect/1, float_to_string/1, + int_from_base_string/2, utf_codepoint_list_to_string/1, contains_string/2, + crop_string/2, base16_decode/1 +]). + +%% Taken from OTP's uri_string module +-define(DEC2HEX(X), + if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0; + ((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10 + end). + +%% Taken from OTP's uri_string module +-define(HEX2DEC(X), + if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0; + ((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10; + ((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10 + end). + +-define(is_lowercase_char(X), (X > 96 andalso X < 123)). +-define(is_underscore_char(X), (X == 95)). +-define(is_digit_char(X), (X > 47 andalso X < 58)). + +uppercase(X) -> X - 32. + +map_get(Map, Key) -> + case maps:find(Key, Map) of + error -> {error, nil}; + OkFound -> OkFound + end. + +iodata_append(Iodata, String) -> [Iodata, String]. + +identity(X) -> X. + +decode_error_msg(Expected, Data) when is_binary(Expected) -> + decode_error(Expected, classify_dynamic(Data)). +decode_error(Expected, Got) when is_binary(Expected) andalso is_binary(Got) -> + {error, [{decode_error, Expected, Got, []}]}. + +classify_dynamic(nil) -> <<"Nil">>; +classify_dynamic(X) when is_atom(X) -> <<"Atom">>; +classify_dynamic(X) when is_binary(X) -> <<"String">>; +classify_dynamic(X) when is_bitstring(X) -> <<"BitArray">>; +classify_dynamic(X) when is_integer(X) -> <<"Int">>; +classify_dynamic(X) when is_float(X) -> <<"Float">>; +classify_dynamic(X) when is_list(X) -> <<"List">>; +classify_dynamic(X) when is_boolean(X) -> <<"Bool">>; +classify_dynamic(X) when is_map(X) -> <<"Map">>; +classify_dynamic(X) when is_tuple(X) -> + iolist_to_binary(["Tuple of ", integer_to_list(tuple_size(X)), " elements"]); +classify_dynamic(X) when + is_function(X, 0) orelse is_function(X, 1) orelse is_function(X, 2) orelse + is_function(X, 3) orelse is_function(X, 4) orelse is_function(X, 5) orelse + is_function(X, 6) orelse is_function(X, 7) orelse is_function(X, 8) orelse + is_function(X, 9) orelse is_function(X, 10) orelse is_function(X, 11) orelse + is_function(X, 12) -> <<"Function">>; +classify_dynamic(_) -> <<"Some other type">>. + +decode_map(Data) when is_map(Data) -> {ok, Data}; +decode_map(Data) -> decode_error_msg(<<"Map">>, Data). + +decode_bit_array(Data) when is_bitstring(Data) -> {ok, Data}; +decode_bit_array(Data) -> decode_error_msg(<<"BitArray">>, Data). + +decode_int(Data) when is_integer(Data) -> {ok, Data}; +decode_int(Data) -> decode_error_msg(<<"Int">>, Data). + +decode_float(Data) when is_float(Data) -> {ok, Data}; +decode_float(Data) -> decode_error_msg(<<"Float">>, Data). + +decode_bool(Data) when is_boolean(Data) -> {ok, Data}; +decode_bool(Data) -> decode_error_msg(<<"Bool">>, Data). + +decode_list(Data) when is_list(Data) -> {ok, Data}; +decode_list(Data) -> decode_error_msg(<<"List">>, Data). + +decode_field(Data, Key) when is_map(Data) -> + case Data of + #{Key := Value} -> {ok, {some, Value}}; + _ -> + {ok, none} + end; +decode_field(Data, _) -> + decode_error_msg(<<"Map">>, Data). + +size_of_tuple(Data) -> tuple_size(Data). + +tuple_get(_tup, Index) when Index < 0 -> {error, nil}; +tuple_get(Data, Index) when Index >= tuple_size(Data) -> {error, nil}; +tuple_get(Data, Index) -> {ok, element(Index + 1, Data)}. + +decode_tuple(Data) when is_tuple(Data) -> {ok, Data}; +decode_tuple(Data) -> decode_error_msg(<<"Tuple">>, Data). + +decode_tuple2({_,_} = A) -> {ok, A}; +decode_tuple2([A,B]) -> {ok, {A,B}}; +decode_tuple2(Data) -> decode_error_msg(<<"Tuple of 2 elements">>, Data). + +decode_tuple3({_,_,_} = A) -> {ok, A}; +decode_tuple3([A,B,C]) -> {ok, {A,B,C}}; +decode_tuple3(Data) -> decode_error_msg(<<"Tuple of 3 elements">>, Data). + +decode_tuple4({_,_,_,_} = A) -> {ok, A}; +decode_tuple4([A,B,C,D]) -> {ok, {A,B,C,D}}; +decode_tuple4(Data) -> decode_error_msg(<<"Tuple of 4 elements">>, Data). + +decode_tuple5({_,_,_,_,_} = A) -> {ok, A}; +decode_tuple5([A,B,C,D,E]) -> {ok, {A,B,C,D,E}}; +decode_tuple5(Data) -> decode_error_msg(<<"Tuple of 5 elements">>, Data). + +decode_tuple6({_,_,_,_,_,_} = A) -> {ok, A}; +decode_tuple6([A,B,C,D,E,F]) -> {ok, {A,B,C,D,E,F}}; +decode_tuple6(Data) -> decode_error_msg(<<"Tuple of 6 elements">>, Data). + +decode_option(Term, F) -> + Decode = fun(Inner) -> + case F(Inner) of + {ok, Decoded} -> {ok, {some, Decoded}}; + Error -> Error + end + end, + case Term of + undefined -> {ok, none}; + error -> {ok, none}; + null -> {ok, none}; + none -> {ok, none}; + nil -> {ok, none}; + {some, Inner} -> Decode(Inner); + _ -> Decode(Term) + end. + +decode_result(Term) -> + case Term of + {ok, Inner} -> {ok, {ok, Inner}}; + ok -> {ok, {ok, nil}}; + {error, Inner} -> {ok, {error, Inner}}; + error -> {ok, {error, nil}}; + _ -> decode_error_msg(<<"Result">>, Term) + end. + +int_from_base_string(String, Base) -> + case catch binary_to_integer(String, Base) of + Int when is_integer(Int) -> {ok, Int}; + _ -> {error, nil} + end. + +parse_int(String) -> + case catch binary_to_integer(String) of + Int when is_integer(Int) -> {ok, Int}; + _ -> {error, nil} + end. + +parse_float(String) -> + case catch binary_to_float(String) of + Float when is_float(Float) -> {ok, Float}; + _ -> {error, nil} + end. + +less_than(Lhs, Rhs) -> + Lhs < Rhs. + +string_starts_with(_, <<>>) -> true; +string_starts_with(String, Prefix) when byte_size(Prefix) > byte_size(String) -> false; +string_starts_with(String, Prefix) -> + PrefixSize = byte_size(Prefix), + Prefix == binary_part(String, 0, PrefixSize). + +string_ends_with(_, <<>>) -> true; +string_ends_with(String, Suffix) when byte_size(Suffix) > byte_size(String) -> false; +string_ends_with(String, Suffix) -> + SuffixSize = byte_size(Suffix), + Suffix == binary_part(String, byte_size(String) - SuffixSize, SuffixSize). + +string_pad(String, Length, Dir, PadString) -> + Chars = string:pad(String, Length, Dir, binary_to_list(PadString)), + case unicode:characters_to_binary(Chars) of + Bin when is_binary(Bin) -> Bin; + Error -> erlang:error({gleam_error, {string_invalid_utf8, Error}}) + end. + +string_pop_grapheme(String) -> + case string:next_grapheme(String) of + [ Next | Rest ] -> + {ok, {unicode:characters_to_binary([Next]), unicode:characters_to_binary(Rest)}}; + _ -> {error, nil} + end. + +bit_array_concat(BitArrays) -> + list_to_bitstring(BitArrays). + +bit_array_slice(Bin, Pos, Len) -> + try {ok, binary:part(Bin, Pos, Len)} + catch error:badarg -> {error, nil} + end. + +bit_array_int_to_u32(I) when 0 =< I, I < 4294967296 -> + {ok, <<I:32>>}; +bit_array_int_to_u32(_) -> + {error, nil}. + +bit_array_int_from_u32(<<I:32>>) -> + {ok, I}; +bit_array_int_from_u32(_) -> + {error, nil}. + +compile_regex(String, Options) -> + {options, Caseless, Multiline} = Options, + OptionsList = [ + unicode, + ucp, + Caseless andalso caseless, + Multiline andalso multiline + ], + FilteredOptions = [Option || Option <- OptionsList, Option /= false], + case re:compile(String, FilteredOptions) of + {ok, MP} -> {ok, MP}; + {error, {Str, Pos}} -> + {error, {compile_error, unicode:characters_to_binary(Str), Pos}} + end. + +regex_check(Regex, String) -> + re:run(String, Regex) /= nomatch. + +regex_split(Regex, String) -> + re:split(String, Regex). + +regex_submatches(_, {-1, 0}) -> none; +regex_submatches(String, {Start, Length}) -> + BinarySlice = binary:part(String, {Start, Length}), + case string:is_empty(binary_to_list(BinarySlice)) of + true -> none; + false -> {some, BinarySlice} + end. + +regex_matches(String, [{Start, Length} | Submatches]) -> + Submatches1 = lists:map(fun(X) -> regex_submatches(String, X) end, Submatches), + {match, binary:part(String, Start, Length), Submatches1}. + +regex_scan(Regex, String) -> + case re:run(String, Regex, [global]) of + {match, Captured} -> lists:map(fun(X) -> regex_matches(String, X) end, Captured); + nomatch -> [] + end. + +base_decode64(S) -> + try {ok, base64:decode(S)} + catch error:_ -> {error, nil} + end. + +wrap_list(X) when is_list(X) -> X; +wrap_list(X) -> [X]. + +parse_query(Query) -> + case uri_string:dissect_query(Query) of + {error, _, _} -> {error, nil}; + Pairs -> + Pairs1 = lists:map(fun + ({K, true}) -> {K, <<"">>}; + (Pair) -> Pair + end, Pairs), + {ok, Pairs1} + end. + +percent_encode(B) -> percent_encode(B, <<>>). +percent_encode(<<>>, Acc) -> + Acc; +percent_encode(<<H,T/binary>>, Acc) -> + case percent_ok(H) of + true -> + percent_encode(T, <<Acc/binary,H>>); + false -> + <<A:4,B:4>> = <<H>>, + percent_encode(T, <<Acc/binary,$%,(?DEC2HEX(A)),(?DEC2HEX(B))>>) + end. + +percent_decode(Cs) -> percent_decode(Cs, <<>>). +percent_decode(<<$%, C0, C1, Cs/binary>>, Acc) -> + case is_hex_digit(C0) andalso is_hex_digit(C1) of + true -> + B = ?HEX2DEC(C0)*16+?HEX2DEC(C1), + percent_decode(Cs, <<Acc/binary, B>>); + false -> + {error, nil} + end; +percent_decode(<<C,Cs/binary>>, Acc) -> + percent_decode(Cs, <<Acc/binary, C>>); +percent_decode(<<>>, Acc) -> + check_utf8(Acc). + +percent_ok($!) -> true; +percent_ok($$) -> true; +percent_ok($') -> true; +percent_ok($() -> true; +percent_ok($)) -> true; +percent_ok($*) -> true; +percent_ok($+) -> true; +percent_ok($-) -> true; +percent_ok($.) -> true; +percent_ok($_) -> true; +percent_ok($~) -> true; +percent_ok(C) when $0 =< C, C =< $9 -> true; +percent_ok(C) when $A =< C, C =< $Z -> true; +percent_ok(C) when $a =< C, C =< $z -> true; +percent_ok(_) -> false. + +is_hex_digit(C) -> + ($0 =< C andalso C =< $9) orelse ($a =< C andalso C =< $f) orelse ($A =< C andalso C =< $F). + +check_utf8(Cs) -> + case unicode:characters_to_list(Cs) of + {incomplete, _, _} -> {error, nil}; + {error, _, _} -> {error, nil}; + _ -> {ok, Cs} + end. + +uri_parse(String) -> + case uri_string:parse(String) of + {error, _, _} -> {error, nil}; + Uri -> + {ok, {uri, + maps_get_optional(Uri, scheme), + maps_get_optional(Uri, userinfo), + maps_get_optional(Uri, host), + maps_get_optional(Uri, port), + maps_get_or(Uri, path, <<>>), + maps_get_optional(Uri, query), + maps_get_optional(Uri, fragment) + }} + end. + +maps_get_optional(Map, Key) -> + try {some, maps:get(Key, Map)} + catch _:_ -> none + end. + +maps_get_or(Map, Key, Default) -> + try maps:get(Key, Map) + catch _:_ -> Default + end. + +print(String) -> + io:put_chars(String), + nil. + +println(String) -> + io:put_chars([String, $\n]), + nil. + +print_error(String) -> + io:put_chars(standard_error, String), + nil. + +println_error(String) -> + io:put_chars(standard_error, [String, $\n]), + nil. + +inspect(true) -> + "True"; +inspect(false) -> + "False"; +inspect(nil) -> + "Nil"; +inspect(Data) when is_map(Data) -> + Fields = [ + [<<"#(">>, inspect(Key), <<", ">>, inspect(Value), <<")">>] + || {Key, Value} <- maps:to_list(Data) + ], + ["dict.from_list([", lists:join(", ", Fields), "])"]; +inspect(Atom) when is_atom(Atom) -> + Binary = erlang:atom_to_binary(Atom), + case inspect_maybe_gleam_atom(Binary, none, <<>>) of + {ok, Inspected} -> Inspected; + {error, _} -> ["atom.create_from_string(\"", Binary, "\")"] + end; +inspect(Any) when is_integer(Any) -> + erlang:integer_to_list(Any); +inspect(Any) when is_float(Any) -> + io_lib_format:fwrite_g(Any); +inspect(Binary) when is_binary(Binary) -> + case inspect_maybe_utf8_string(Binary, <<>>) of + {ok, InspectedUtf8String} -> InspectedUtf8String; + {error, not_a_utf8_string} -> + Segments = [erlang:integer_to_list(X) || <<X>> <= Binary], + ["<<", lists:join(", ", Segments), ">>"] + end; +inspect(Bits) when is_bitstring(Bits) -> + inspect_bit_array(Bits); +inspect(List) when is_list(List) -> + case inspect_list(List) of + {proper, Elements} -> ["[", Elements, "]"]; + {improper, Elements} -> ["//erl([", Elements, "])"] + end; +inspect(Any) when is_tuple(Any) % Record constructors + andalso is_atom(element(1, Any)) + andalso element(1, Any) =/= false + andalso element(1, Any) =/= true + andalso element(1, Any) =/= nil +-> + [Atom | ArgsList] = erlang:tuple_to_list(Any), + Args = lists:join(<<", ">>, + lists:map(fun inspect/1, ArgsList) + ), + [inspect(Atom), "(", Args, ")"]; +inspect(Tuple) when is_tuple(Tuple) -> + Elements = lists:map(fun inspect/1, erlang:tuple_to_list(Tuple)), + ["#(", lists:join(", ", Elements), ")"]; +inspect(Any) when is_function(Any) -> + {arity, Arity} = erlang:fun_info(Any, arity), + ArgsAsciiCodes = lists:seq($a, $a + Arity - 1), + Args = lists:join(<<", ">>, + lists:map(fun(Arg) -> <<Arg>> end, ArgsAsciiCodes) + ), + ["//fn(", Args, ") { ... }"]; +inspect(Any) -> + ["//erl(", io_lib:format("~p", [Any]), ")"]. + + +inspect_maybe_gleam_atom(<<>>, none, _) -> + {error, nil}; +inspect_maybe_gleam_atom(<<First, _Rest/binary>>, none, _) when ?is_digit_char(First) -> + {error, nil}; +inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, none, _) -> + {error, nil}; +inspect_maybe_gleam_atom(<<"_">>, _PrevChar, _Acc) -> + {error, nil}; +inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, $_, _Acc) -> + {error, nil}; +inspect_maybe_gleam_atom(<<First, _Rest/binary>>, _PrevChar, _Acc) + when not (?is_lowercase_char(First) orelse ?is_underscore_char(First) orelse ?is_digit_char(First)) -> + {error, nil}; +inspect_maybe_gleam_atom(<<First, Rest/binary>>, none, Acc) -> + inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, (uppercase(First))>>); +inspect_maybe_gleam_atom(<<"_", Rest/binary>>, _PrevChar, Acc) -> + inspect_maybe_gleam_atom(Rest, $_, Acc); +inspect_maybe_gleam_atom(<<First, Rest/binary>>, $_, Acc) -> + inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, (uppercase(First))>>); +inspect_maybe_gleam_atom(<<First, Rest/binary>>, _PrevChar, Acc) -> + inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, First>>); +inspect_maybe_gleam_atom(<<>>, _PrevChar, Acc) -> + {ok, Acc}; +inspect_maybe_gleam_atom(A, B, C) -> + erlang:display({A, B, C}), + throw({gleam_error, A, B, C}). + +inspect_list([]) -> + {proper, []}; +inspect_list([First]) -> + {proper, [inspect(First)]}; +inspect_list([First | Rest]) when is_list(Rest) -> + {Kind, Inspected} = inspect_list(Rest), + {Kind, [inspect(First), <<", ">> | Inspected]}; +inspect_list([First | ImproperTail]) -> + {improper, [inspect(First), <<" | ">>, inspect(ImproperTail)]}. + +inspect_bit_array(Bits) -> + Text = inspect_bit_array(Bits, <<"<<">>), + <<Text/binary, ">>">>. + +inspect_bit_array(<<>>, Acc) -> + Acc; +inspect_bit_array(<<X, Rest/bitstring>>, Acc) -> + inspect_bit_array(Rest, append_segment(Acc, erlang:integer_to_binary(X))); +inspect_bit_array(Rest, Acc) -> + Size = bit_size(Rest), + <<X:Size>> = Rest, + X1 = erlang:integer_to_binary(X), + Size1 = erlang:integer_to_binary(Size), + Segment = <<X1/binary, ":size(", Size1/binary, ")">>, + inspect_bit_array(<<>>, append_segment(Acc, Segment)). + +append_segment(<<"<<">>, Segment) -> + <<"<<", Segment/binary>>; +append_segment(Acc, Segment) -> + <<Acc/binary, ", ", Segment/binary>>. + + +inspect_maybe_utf8_string(Binary, Acc) -> + case Binary of + <<>> -> {ok, <<$", Acc/binary, $">>}; + <<First/utf8, Rest/binary>> -> + Escaped = case First of + $" -> <<$\\, $">>; + $\\ -> <<$\\, $\\>>; + $\r -> <<$\\, $r>>; + $\n -> <<$\\, $n>>; + $\t -> <<$\\, $t>>; + Other -> <<Other/utf8>> + end, + inspect_maybe_utf8_string(Rest, <<Acc/binary, Escaped/binary>>); + _ -> {error, not_a_utf8_string} + end. + +float_to_string(Float) when is_float(Float) -> + erlang:iolist_to_binary(io_lib_format:fwrite_g(Float)). + +utf_codepoint_list_to_string(List) -> + case unicode:characters_to_binary(List) of + {error, _} -> erlang:error({gleam_error, {string_invalid_utf8, List}}); + Binary -> Binary + end. + +crop_string(String, Prefix) -> + case string:find(String, Prefix) of + nomatch -> String; + New -> New + end. + +contains_string(String, Substring) -> + is_bitstring(string:find(String, Substring)). + +base16_decode(String) -> + try + {ok, binary:decode_hex(String)} + catch + _:_ -> {error, nil} + end. diff --git a/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.mjs b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.mjs new file mode 100644 index 0000000..45c28cf --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.mjs @@ -0,0 +1,878 @@ +import { + BitArray, + Error, + List, + Ok, + Result, + UtfCodepoint, + stringBits, + toBitArray, + NonEmpty, + CustomType, +} from "./gleam.mjs"; +import { + CompileError as RegexCompileError, + Match as RegexMatch, +} from "./gleam/regex.mjs"; +import { DecodeError } from "./gleam/dynamic.mjs"; +import { Some, None } from "./gleam/option.mjs"; +import Dict from "./dict.mjs"; + +const Nil = undefined; +const NOT_FOUND = {}; + +export function identity(x) { + return x; +} + +export function parse_int(value) { + if (/^[-+]?(\d+)$/.test(value)) { + return new Ok(parseInt(value)); + } else { + return new Error(Nil); + } +} + +export function parse_float(value) { + if (/^[-+]?(\d+)\.(\d+)$/.test(value)) { + return new Ok(parseFloat(value)); + } else { + return new Error(Nil); + } +} + +export function to_string(term) { + return term.toString(); +} + +export function float_to_string(float) { + const string = float.toString(); + if (string.indexOf(".") >= 0) { + return string; + } else { + return string + ".0"; + } +} + +export function int_to_base_string(int, base) { + return int.toString(base).toUpperCase(); +} + +const int_base_patterns = { + 2: /[^0-1]/, + 3: /[^0-2]/, + 4: /[^0-3]/, + 5: /[^0-4]/, + 6: /[^0-5]/, + 7: /[^0-6]/, + 8: /[^0-7]/, + 9: /[^0-8]/, + 10: /[^0-9]/, + 11: /[^0-9a]/, + 12: /[^0-9a-b]/, + 13: /[^0-9a-c]/, + 14: /[^0-9a-d]/, + 15: /[^0-9a-e]/, + 16: /[^0-9a-f]/, + 17: /[^0-9a-g]/, + 18: /[^0-9a-h]/, + 19: /[^0-9a-i]/, + 20: /[^0-9a-j]/, + 21: /[^0-9a-k]/, + 22: /[^0-9a-l]/, + 23: /[^0-9a-m]/, + 24: /[^0-9a-n]/, + 25: /[^0-9a-o]/, + 26: /[^0-9a-p]/, + 27: /[^0-9a-q]/, + 28: /[^0-9a-r]/, + 29: /[^0-9a-s]/, + 30: /[^0-9a-t]/, + 31: /[^0-9a-u]/, + 32: /[^0-9a-v]/, + 33: /[^0-9a-w]/, + 34: /[^0-9a-x]/, + 35: /[^0-9a-y]/, + 36: /[^0-9a-z]/, +}; + +export function int_from_base_string(string, base) { + if (int_base_patterns[base].test(string.replace(/^-/, "").toLowerCase())) { + return new Error(Nil); + } + + const result = parseInt(string, base); + + if (isNaN(result)) { + return new Error(Nil); + } + + return new Ok(result); +} + +export function string_replace(string, target, substitute) { + if (typeof string.replaceAll !== "undefined") { + return string.replaceAll(target, substitute); + } + // Fallback for older Node.js versions: + // 1. <https://stackoverflow.com/a/1144788> + // 2. <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping> + // TODO: This fallback could be remove once Node.js 14 is EOL + // aka <https://nodejs.org/en/about/releases/> on or after 2024-04-30 + return string.replace( + // $& means the whole matched string + new RegExp(target.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), + substitute + ); +} + +export function string_reverse(string) { + return [...string].reverse().join(""); +} + +export function string_length(string) { + if (string === "") { + return 0; + } + const iterator = graphemes_iterator(string); + if (iterator) { + let i = 0; + for (const _ of iterator) { + i++; + } + return i; + } else { + return string.match(/./gsu).length; + } +} + +export function graphemes(string) { + const iterator = graphemes_iterator(string); + if (iterator) { + return List.fromArray(Array.from(iterator).map((item) => item.segment)); + } else { + return List.fromArray(string.match(/./gsu)); + } +} + +function graphemes_iterator(string) { + if (Intl && Intl.Segmenter) { + return new Intl.Segmenter().segment(string)[Symbol.iterator](); + } +} + +export function pop_grapheme(string) { + let first; + const iterator = graphemes_iterator(string); + if (iterator) { + first = iterator.next().value?.segment; + } else { + first = string.match(/./su)?.[0]; + } + if (first) { + return new Ok([first, string.slice(first.length)]); + } else { + return new Error(Nil); + } +} + +export function lowercase(string) { + return string.toLowerCase(); +} + +export function uppercase(string) { + return string.toUpperCase(); +} + +export function less_than(a, b) { + return a < b; +} + +export function add(a, b) { + return a + b; +} + +export function equal(a, b) { + return a === b; +} + +export function split(xs, pattern) { + return List.fromArray(xs.split(pattern)); +} + +export function join(xs, separator) { + const iterator = xs[Symbol.iterator](); + let result = iterator.next().value || ""; + let current = iterator.next(); + while (!current.done) { + result = result + separator + current.value; + current = iterator.next(); + } + return result; +} + +export function concat(xs) { + let result = ""; + for (const x of xs) { + result = result + x; + } + return result; +} + +export function length(data) { + return data.length; +} + +export function crop_string(string, substring) { + return string.substring(string.indexOf(substring)); +} + +export function contains_string(haystack, needle) { + return haystack.indexOf(needle) >= 0; +} + +export function starts_with(haystack, needle) { + return haystack.startsWith(needle); +} + +export function ends_with(haystack, needle) { + return haystack.endsWith(needle); +} + +export function split_once(haystack, needle) { + const index = haystack.indexOf(needle); + if (index >= 0) { + const before = haystack.slice(0, index); + const after = haystack.slice(index + needle.length); + return new Ok([before, after]); + } else { + return new Error(Nil); + } +} + +export function trim(string) { + return string.trim(); +} + +export function trim_left(string) { + return string.trimLeft(); +} + +export function trim_right(string) { + return string.trimRight(); +} + +export function bit_array_from_string(string) { + return toBitArray([stringBits(string)]); +} + +export function bit_array_concat(bit_arrays) { + return toBitArray(bit_arrays.toArray().map((b) => b.buffer)); +} + +export function console_log(term) { + console.log(term); +} + +export function console_error(term) { + console.error(term); +} + +export function crash(message) { + throw new globalThis.Error(message); +} + +export function bit_array_to_string(bit_array) { + try { + const decoder = new TextDecoder("utf-8", { fatal: true }); + return new Ok(decoder.decode(bit_array.buffer)); + } catch (_error) { + return new Error(Nil); + } +} + +export function print(string) { + if (typeof process === "object") { + process.stdout.write(string); // We can write without a trailing newline + } else if (typeof Deno === "object") { + Deno.stdout.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline + } else { + console.log(string); // We're in a browser. Newlines are mandated + } +} + +export function print_error(string) { + if (typeof process === "object" && process.stderr?.write) { + process.stderr.write(string); // We can write without a trailing newline + } else if (typeof Deno === "object") { + Deno.stderr.writeSync(new TextEncoder().encode(string)); // We can write without a trailing newline + } else { + console.error(string); // We're in a browser. Newlines are mandated + } +} + +export function print_debug(string) { + if (typeof process === "object" && process.stderr?.write) { + process.stderr.write(string + "\n"); // If we're in Node.js, use `stderr` + } else if (typeof Deno === "object") { + Deno.stderr.writeSync(new TextEncoder().encode(string + "\n")); // If we're in Deno, use `stderr` + } else { + console.log(string); // Otherwise, use `console.log` (so that it doesn't look like an error) + } +} + +export function ceiling(float) { + return Math.ceil(float); +} + +export function floor(float) { + return Math.floor(float); +} + +export function round(float) { + return Math.round(float); +} + +export function truncate(float) { + return Math.trunc(float); +} + +export function power(base, exponent) { + // It is checked in Gleam that: + // - The base is non-negative and that the exponent is not fractional. + // - The base is non-zero and the exponent is non-negative (otherwise + // the result will essentially be division by zero). + // It can thus be assumed that valid input is passed to the Math.pow + // function and a NaN or Infinity value will not be produced. + return Math.pow(base, exponent); +} + +export function random_uniform() { + const random_uniform_result = Math.random(); + // With round-to-nearest-even behavior, the ranges claimed for the functions below + // (excluding the one for Math.random() itself) aren't exact. + // If extremely large bounds are chosen (2^53 or higher), + // it's possible in extremely rare cases to calculate the usually-excluded upper bound. + // Note that as numbers in JavaScript are IEEE 754 floating point numbers + // See: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random> + // Because of this, we just loop 'until' we get a valid result where 0.0 <= x < 1.0: + if (random_uniform_result === 1.0) { + return random_uniform(); + } + return random_uniform_result; +} + +export function bit_array_slice(bits, position, length) { + const start = Math.min(position, position + length); + const end = Math.max(position, position + length); + if (start < 0 || end > bits.length) return new Error(Nil); + const buffer = new Uint8Array(bits.buffer.buffer, start, Math.abs(length)); + return new Ok(new BitArray(buffer)); +} + +export function codepoint(int) { + return new UtfCodepoint(int); +} + +export function string_to_codepoint_integer_list(string) { + return List.fromArray(Array.from(string).map((item) => item.codePointAt(0))); +} + +export function utf_codepoint_list_to_string(utf_codepoint_integer_list) { + return utf_codepoint_integer_list + .toArray() + .map((x) => String.fromCodePoint(x.value)) + .join(""); +} + +export function utf_codepoint_to_int(utf_codepoint) { + return utf_codepoint.value; +} + +export function regex_check(regex, string) { + regex.lastIndex = 0; + return regex.test(string); +} + +export function compile_regex(pattern, options) { + try { + let flags = "gu"; + if (options.case_insensitive) flags += "i"; + if (options.multi_line) flags += "m"; + return new Ok(new RegExp(pattern, flags)); + } catch (error) { + const number = (error.columnNumber || 0) | 0; + return new Error(new RegexCompileError(error.message, number)); + } +} + +export function regex_scan(regex, string) { + const matches = Array.from(string.matchAll(regex)).map((match) => { + const content = match[0]; + const submatches = []; + for (let n = match.length - 1; n > 0; n--) { + if (match[n]) { + submatches[n - 1] = new Some(match[n]); + continue; + } + if (submatches.length > 0) { + submatches[n - 1] = new None(); + } + } + return new RegexMatch(content, List.fromArray(submatches)); + }); + return List.fromArray(matches); +} + +export function new_map() { + return Dict.new(); +} + +export function map_size(map) { + return map.size; +} + +export function map_to_list(map) { + return List.fromArray(map.entries()); +} + +export function map_remove(key, map) { + return map.delete(key); +} + +export function map_get(map, key) { + const value = map.get(key, NOT_FOUND); + if (value === NOT_FOUND) { + return new Error(Nil); + } + return new Ok(value); +} + +export function map_insert(key, value, map) { + return map.set(key, value); +} + +function unsafe_percent_decode(string) { + return decodeURIComponent((string || "").replace("+", " ")); +} + +export function percent_decode(string) { + try { + return new Ok(unsafe_percent_decode(string)); + } catch (_error) { + return new Error(Nil); + } +} + +export function percent_encode(string) { + return encodeURIComponent(string); +} + +export function parse_query(query) { + try { + const pairs = []; + for (const section of query.split("&")) { + const [key, value] = section.split("="); + if (!key) continue; + pairs.push([unsafe_percent_decode(key), unsafe_percent_decode(value)]); + } + return new Ok(List.fromArray(pairs)); + } catch (_error) { + return new Error(Nil); + } +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +export function encode64(bit_array) { + const aBytes = bit_array.buffer; + let nMod3 = 2; + let sB64Enc = ""; + + for (let nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) { + nMod3 = nIdx % 3; + if (nIdx > 0 && ((nIdx * 4) / 3) % 76 === 0) { + sB64Enc += "\r\n"; + } + nUint24 |= aBytes[nIdx] << ((16 >>> nMod3) & 24); + if (nMod3 === 2 || aBytes.length - nIdx === 1) { + sB64Enc += String.fromCharCode( + uint6ToB64((nUint24 >>> 18) & 63), + uint6ToB64((nUint24 >>> 12) & 63), + uint6ToB64((nUint24 >>> 6) & 63), + uint6ToB64(nUint24 & 63) + ); + nUint24 = 0; + } + } + + return ( + sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + + (nMod3 === 2 ? "" : nMod3 === 1 ? "=" : "==") + ); +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function uint6ToB64(nUint6) { + return nUint6 < 26 + ? nUint6 + 65 + : nUint6 < 52 + ? nUint6 + 71 + : nUint6 < 62 + ? nUint6 - 4 + : nUint6 === 62 + ? 43 + : nUint6 === 63 + ? 47 + : 65; +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function b64ToUint6(nChr) { + return nChr > 64 && nChr < 91 + ? nChr - 65 + : nChr > 96 && nChr < 123 + ? nChr - 71 + : nChr > 47 && nChr < 58 + ? nChr + 4 + : nChr === 43 + ? 62 + : nChr === 47 + ? 63 + : 0; +} + +// From https://developer.mozilla.org/en-US/docs/Glossary/Base64#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +export function decode64(sBase64) { + if (sBase64.match(/[^A-Za-z0-9\+\/=]/g)) return new Error(Nil); + const sB64Enc = sBase64.replace(/=/g, ""); + const nInLen = sB64Enc.length; + const nOutLen = (nInLen * 3 + 1) >> 2; + const taBytes = new Uint8Array(nOutLen); + + for ( + let nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; + nInIdx < nInLen; + nInIdx++ + ) { + nMod4 = nInIdx & 3; + nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << (6 * (3 - nMod4)); + if (nMod4 === 3 || nInLen - nInIdx === 1) { + for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) { + taBytes[nOutIdx] = (nUint24 >>> ((16 >>> nMod3) & 24)) & 255; + } + nUint24 = 0; + } + } + + return new Ok(new BitArray(taBytes)); +} + +export function classify_dynamic(data) { + if (typeof data === "string") { + return "String"; + } else if (data instanceof Result) { + return "Result"; + } else if (data instanceof List) { + return "List"; + } else if (data instanceof BitArray) { + return "BitArray"; + } else if (data instanceof Dict) { + return "Map"; + } else if (Number.isInteger(data)) { + return "Int"; + } else if (Array.isArray(data)) { + return `Tuple of ${data.length} elements`; + } else if (typeof data === "number") { + return "Float"; + } else if (data === null) { + return "Null"; + } else if (data === undefined) { + return "Nil"; + } else { + const type = typeof data; + return type.charAt(0).toUpperCase() + type.slice(1); + } +} + +function decoder_error(expected, got) { + return decoder_error_no_classify(expected, classify_dynamic(got)); +} + +function decoder_error_no_classify(expected, got) { + return new Error( + List.fromArray([new DecodeError(expected, got, List.fromArray([]))]) + ); +} + +export function decode_string(data) { + return typeof data === "string" + ? new Ok(data) + : decoder_error("String", data); +} + +export function decode_int(data) { + return Number.isInteger(data) ? new Ok(data) : decoder_error("Int", data); +} + +export function decode_float(data) { + return typeof data === "number" ? new Ok(data) : decoder_error("Float", data); +} + +export function decode_bool(data) { + return typeof data === "boolean" ? new Ok(data) : decoder_error("Bool", data); +} + +export function decode_bit_array(data) { + if (data instanceof BitArray) { + return new Ok(data); + } + if (data instanceof Uint8Array) { + return new Ok(new BitArray(data)); + } + return decoder_error("BitArray", data); +} + +export function decode_tuple(data) { + return Array.isArray(data) ? new Ok(data) : decoder_error("Tuple", data); +} + +export function decode_tuple2(data) { + return decode_tupleN(data, 2); +} + +export function decode_tuple3(data) { + return decode_tupleN(data, 3); +} + +export function decode_tuple4(data) { + return decode_tupleN(data, 4); +} + +export function decode_tuple5(data) { + return decode_tupleN(data, 5); +} + +export function decode_tuple6(data) { + return decode_tupleN(data, 6); +} + +function decode_tupleN(data, n) { + if (Array.isArray(data) && data.length == n) { + return new Ok(data); + } + + const list = decode_exact_length_list(data, n); + if (list) return new Ok(list); + + return decoder_error(`Tuple of ${n} elements`, data); +} + +function decode_exact_length_list(data, n) { + if (!(data instanceof List)) return; + + const elements = []; + let current = data; + + for (let i = 0; i < n; i++) { + if (!(current instanceof NonEmpty)) break; + elements.push(current.head); + current = current.tail; + } + + if (elements.length === n && !(current instanceof NonEmpty)) return elements; +} + +export function tuple_get(data, index) { + return index >= 0 && data.length > index + ? new Ok(data[index]) + : new Error(Nil); +} + +export function decode_list(data) { + if (Array.isArray(data)) { + return new Ok(List.fromArray(data)); + } + return data instanceof List ? new Ok(data) : decoder_error("List", data); +} + +export function decode_result(data) { + return data instanceof Result ? new Ok(data) : decoder_error("Result", data); +} + +export function decode_map(data) { + if (data instanceof Dict) { + return new Ok(Dict.fromMap(data)); + } + if (data == null) { + return decoder_error("Map", data); + } + if (typeof data !== "object") { + return decoder_error("Map", data); + } + const proto = Object.getPrototypeOf(data); + if (proto === Object.prototype || proto === null) { + return new Ok(Dict.fromObject(data)); + } + return decoder_error("Map", data); +} + +export function decode_option(data, decoder) { + if (data === null || data === undefined || data instanceof None) + return new Ok(new None()); + if (data instanceof Some) data = data[0]; + const result = decoder(data); + if (result.isOk()) { + return new Ok(new Some(result[0])); + } else { + return result; + } +} + +export function decode_field(value, name) { + const not_a_map_error = () => decoder_error("Map", value); + + if ( + value instanceof Dict || + value instanceof WeakMap || + value instanceof Map + ) { + const entry = map_get(value, name); + return new Ok(entry.isOk() ? new Some(entry[0]) : new None()); + } else if (Object.getPrototypeOf(value) == Object.prototype) { + return try_get_field(value, name, () => new Ok(new None())); + } else { + return try_get_field(value, name, not_a_map_error); + } +} + +function try_get_field(value, field, or_else) { + try { + return field in value ? new Ok(new Some(value[field])) : or_else(); + } catch { + return or_else(); + } +} + +export function byte_size(string) { + return new TextEncoder().encode(string).length; +} + +// In Javascript bitwise operations convert numbers to a sequence of 32 bits +// while Erlang uses arbitrary precision. +// To get around this problem and get consistent results use BigInt and then +// downcast the value back to a Number value. + +export function bitwise_and(x, y) { + return Number(BigInt(x) & BigInt(y)); +} + +export function bitwise_not(x) { + return Number(~BigInt(x)); +} + +export function bitwise_or(x, y) { + return Number(BigInt(x) | BigInt(y)); +} + +export function bitwise_exclusive_or(x, y) { + return Number(BigInt(x) ^ BigInt(y)); +} + +export function bitwise_shift_left(x, y) { + return Number(BigInt(x) << BigInt(y)); +} + +export function bitwise_shift_right(x, y) { + return Number(BigInt(x) >> BigInt(y)); +} + +export function inspect(v) { + const t = typeof v; + if (v === true) return "True"; + if (v === false) return "False"; + if (v === null) return "//js(null)"; + if (v === undefined) return "Nil"; + if (t === "string") return JSON.stringify(v); + if (t === "bigint" || t === "number") return v.toString(); + if (Array.isArray(v)) return `#(${v.map(inspect).join(", ")})`; + if (v instanceof List) return inspectList(v); + if (v instanceof UtfCodepoint) return inspectUtfCodepoint(v); + if (v instanceof BitArray) return inspectBitArray(v); + if (v instanceof CustomType) return inspectCustomType(v); + if (v instanceof Dict) return inspectDict(v); + if (v instanceof Set) return `//js(Set(${[...v].map(inspect).join(", ")}))`; + if (v instanceof RegExp) return `//js(${v})`; + if (v instanceof Date) return `//js(Date("${v.toISOString()}"))`; + if (v instanceof Function) { + const args = []; + for (const i of Array(v.length).keys()) + args.push(String.fromCharCode(i + 97)); + return `//fn(${args.join(", ")}) { ... }`; + } + return inspectObject(v); +} + +function inspectDict(map) { + let body = "dict.from_list(["; + let first = true; + map.forEach((value, key) => { + if (!first) body = body + ", "; + body = body + "#(" + inspect(key) + ", " + inspect(value) + ")"; + first = false; + }); + return body + "])"; +} + +function inspectObject(v) { + const name = Object.getPrototypeOf(v)?.constructor?.name || "Object"; + const props = []; + for (const k of Object.keys(v)) { + props.push(`${inspect(k)}: ${inspect(v[k])}`); + } + const body = props.length ? " " + props.join(", ") + " " : ""; + const head = name === "Object" ? "" : name + " "; + return `//js(${head}{${body}})`; +} + +function inspectCustomType(record) { + const props = Object.keys(record) + .map((label) => { + const value = inspect(record[label]); + return isNaN(parseInt(label)) ? `${label}: ${value}` : value; + }) + .join(", "); + return props + ? `${record.constructor.name}(${props})` + : record.constructor.name; +} + +export function inspectList(list) { + return `[${list.toArray().map(inspect).join(", ")}]`; +} + +export function inspectBitArray(bits) { + return `<<${Array.from(bits.buffer).join(", ")}>>`; +} + +export function inspectUtfCodepoint(codepoint) { + return `//utfcodepoint(${String.fromCodePoint(codepoint.value)})`; +} + +export function base16_encode(bit_array) { + let result = ""; + for (const byte of bit_array.buffer) { + result += byte.toString(16).padStart(2, "0").toUpperCase(); + } + return result; +} + +export function base16_decode(string) { + const bytes = new Uint8Array(string.length / 2); + for (let i = 0; i < string.length; i += 2) { + const a = parseInt(string[i], 16); + const b = parseInt(string[i + 1], 16); + if (isNaN(a) || isNaN(b)) return new Error(Nil); + bytes[i / 2] = a * 16 + b; + } + return new Ok(new BitArray(bytes)); +} diff --git a/aoc2023/build/packages/tom/build/packages/gleeunit/LICENCE b/aoc2023/build/packages/tom/build/packages/gleeunit/LICENCE new file mode 100644 index 0000000..c7967c3 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleeunit/LICENCE @@ -0,0 +1,191 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2021, Louis Pilfold <louis@lpil.uk>. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/aoc2023/build/packages/tom/build/packages/gleeunit/README.md b/aoc2023/build/packages/tom/build/packages/gleeunit/README.md new file mode 100644 index 0000000..3ca1c63 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleeunit/README.md @@ -0,0 +1,52 @@ +# gleeunit + +Gleam bindings to the Erlang EUnit test framework. + +A custom test runner is included for when compiled to JavaScript running on +either NodeJS or Deno. + +Documentation is available on [HexDocs](https://hexdocs.pm/gleeunit/index.html). + +## Usage + +Add this package to your Gleam project. + +```sh +gleam add gleeunit --dev +``` + +And then call the `gleeunit.main` function from your test main function. + +```gleam +// In test/yourapp_test.gleam +import gleeunit + +pub fn main() { + gleeunit.main() +} +``` + +Now any public function with a name ending in `_test` in the `test` directory +will be found and run as a test. + +```gleam +pub fn the_universe_test() { + let assert 1 = 1 +} +``` + +Run the tests by entering `gleam test` in the command line. + +### Deno + +If using the Deno JavaScript runtime, you will need to add the following to your +`gleam.toml`. + +```toml +[javascript.deno] +allow_read = [ + "gleam.toml", + "test", + "build", +] +``` diff --git a/aoc2023/build/packages/tom/build/packages/gleeunit/gleam.toml b/aoc2023/build/packages/tom/build/packages/gleeunit/gleam.toml new file mode 100644 index 0000000..c5be79b --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleeunit/gleam.toml @@ -0,0 +1,17 @@ +name = "gleeunit" +version = "1.0.2" +licences = ["Apache-2.0"] +description = "Gleam bindings to Erlang's EUnit test framework" +gleam = ">= 0.33.0" + +[javascript.deno] +allow_read = [ + "gleam.toml", + "test", + "build", +] + +[dependencies] +gleam_stdlib = "~> 0.32" + +[dev-dependencies] diff --git a/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.app.src b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.app.src new file mode 100644 index 0000000..eb6365f --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.app.src @@ -0,0 +1,8 @@ +{application, gleeunit, [ + {vsn, "1.0.2"}, + {applications, [gleam_stdlib]}, + {description, "Gleam bindings to Erlang's EUnit test framework"}, + {modules, [gleeunit, + gleeunit@should]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.erl b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.erl new file mode 100644 index 0000000..22e1e7f --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.erl @@ -0,0 +1,59 @@ +-module(gleeunit). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([main/0]). +-export_type([atom_/0, encoding/0, report_module_name/0, gleeunit_progress_option/0, eunit_option/0]). + +-type atom_() :: any(). + +-type encoding() :: utf8. + +-type report_module_name() :: gleeunit_progress. + +-type gleeunit_progress_option() :: {colored, boolean()}. + +-type eunit_option() :: verbose | + no_tty | + {report, {report_module_name(), list(gleeunit_progress_option())}}. + +-spec gleam_to_erlang_module_name(binary()) -> binary(). +gleam_to_erlang_module_name(Path) -> + _pipe = Path, + _pipe@1 = gleam@string:replace(_pipe, <<".gleam"/utf8>>, <<""/utf8>>), + _pipe@2 = gleam@string:replace(_pipe@1, <<".erl"/utf8>>, <<""/utf8>>), + gleam@string:replace(_pipe@2, <<"/"/utf8>>, <<"@"/utf8>>). + +-spec do_main() -> nil. +do_main() -> + Options = [verbose, + no_tty, + {report, {gleeunit_progress, [{colored, true}]}}], + Result = begin + _pipe = gleeunit_ffi:find_files( + <<"**/*.{erl,gleam}"/utf8>>, + <<"test"/utf8>> + ), + _pipe@1 = gleam@list:map(_pipe, fun gleam_to_erlang_module_name/1), + _pipe@2 = gleam@list:map( + _pipe@1, + fun(_capture) -> erlang:binary_to_atom(_capture, utf8) end + ), + _pipe@3 = eunit:test(_pipe@2, Options), + _pipe@4 = (gleam@dynamic:result( + fun gleam@dynamic:dynamic/1, + fun gleam@dynamic:dynamic/1 + ))(_pipe@3), + gleam@result:unwrap(_pipe@4, {error, gleam@dynamic:from(nil)}) + end, + Code = case Result of + {ok, _} -> + 0; + + {error, _} -> + 1 + end, + erlang:halt(Code). + +-spec main() -> nil. +main() -> + do_main(). diff --git a/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.gleam b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.gleam new file mode 100644 index 0000000..884c3fa --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.gleam @@ -0,0 +1,92 @@ +/// Find and run all test functions for the current project using Erlang's EUnit +/// test framework. +/// +/// Any Erlang or Gleam function in the `test` directory with a name editing in +/// `_test` is considered a test function and will be run. +/// +/// If running on JavaScript tests will be run with a custom test runner. +/// +pub fn main() -> Nil { + do_main() +} + +@target(javascript) +@external(javascript, "./gleeunit_ffi.mjs", "main") +fn do_main() -> Nil + +@target(erlang) +import gleam/list +@target(erlang) +import gleam/result +@target(erlang) +import gleam/string +@target(erlang) +import gleam/dynamic.{type Dynamic} + +@target(erlang) +fn do_main() -> Nil { + let options = [Verbose, NoTty, Report(#(GleeunitProgress, [Colored(True)]))] + + let result = + find_files(matching: "**/*.{erl,gleam}", in: "test") + |> list.map(gleam_to_erlang_module_name) + |> list.map(dangerously_convert_string_to_atom(_, Utf8)) + |> run_eunit(options) + |> dynamic.result(dynamic.dynamic, dynamic.dynamic) + |> result.unwrap(Error(dynamic.from(Nil))) + + let code = case result { + Ok(_) -> 0 + Error(_) -> 1 + } + halt(code) +} + +@target(erlang) +@external(erlang, "erlang", "halt") +fn halt(a: Int) -> Nil + +@target(erlang) +fn gleam_to_erlang_module_name(path: String) -> String { + path + |> string.replace(".gleam", "") + |> string.replace(".erl", "") + |> string.replace("/", "@") +} + +@target(erlang) +@external(erlang, "gleeunit_ffi", "find_files") +fn find_files(matching matching: String, in in: String) -> List(String) + +@target(erlang) +type Atom + +@target(erlang) +type Encoding { + Utf8 +} + +@target(erlang) +@external(erlang, "erlang", "binary_to_atom") +fn dangerously_convert_string_to_atom(a: String, b: Encoding) -> Atom + +@target(erlang) +type ReportModuleName { + GleeunitProgress +} + +@target(erlang) +type GleeunitProgressOption { + Colored(Bool) +} + +@target(erlang) +type EunitOption { + Verbose + NoTty + Report(#(ReportModuleName, List(GleeunitProgressOption))) +} + +@target(erlang) +@external(erlang, "eunit", "test") +fn run_eunit(a: List(Atom), b: List(EunitOption)) -> Dynamic diff --git a/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit/should.gleam b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit/should.gleam new file mode 100644 index 0000000..da484e3 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit/should.gleam @@ -0,0 +1,65 @@ +//// A module for testing your Gleam code. The functions found here are +//// compatible with the Erlang eunit test framework. +//// +//// More information on running eunit can be found in [the rebar3 +//// documentation](https://rebar3.org/docs/testing/eunit/). + +import gleam/string + +@external(erlang, "gleeunit_ffi", "should_equal") +pub fn equal(a: t, b: t) -> Nil { + case a == b { + True -> Nil + _ -> + panic as string.concat([ + "\n\t", + string.inspect(a), + "\n\tshould equal \n\t", + string.inspect(b), + ]) + } +} + +@external(erlang, "gleeunit_ffi", "should_not_equal") +pub fn not_equal(a: t, b: t) -> Nil { + case a != b { + True -> Nil + _ -> + panic as string.concat([ + "\n", + string.inspect(a), + "\nshould not equal \n", + string.inspect(b), + ]) + } +} + +@external(erlang, "gleeunit_ffi", "should_be_ok") +pub fn be_ok(a: Result(a, e)) -> a { + case a { + Ok(value) -> value + _ -> panic as string.concat(["\n", string.inspect(a), "\nshould be ok"]) + } +} + +@external(erlang, "gleeunit_ffi", "should_be_error") +pub fn be_error(a: Result(a, e)) -> e { + case a { + Error(error) -> error + _ -> panic as string.concat(["\n", string.inspect(a), "\nshould be error"]) + } +} + +pub fn be_true(actual: Bool) -> Nil { + actual + |> equal(True) +} + +pub fn be_false(actual: Bool) -> Nil { + actual + |> equal(False) +} + +pub fn fail() -> Nil { + be_true(False) +} diff --git a/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit@should.erl b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit@should.erl new file mode 100644 index 0000000..bfb45f5 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit@should.erl @@ -0,0 +1,34 @@ +-module(gleeunit@should). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). + +-export([equal/2, not_equal/2, be_ok/1, be_error/1, be_true/1, be_false/1, fail/0]). + +-spec equal(FMN, FMN) -> nil. +equal(A, B) -> + gleeunit_ffi:should_equal(A, B). + +-spec not_equal(FMO, FMO) -> nil. +not_equal(A, B) -> + gleeunit_ffi:should_not_equal(A, B). + +-spec be_ok({ok, FMP} | {error, any()}) -> FMP. +be_ok(A) -> + gleeunit_ffi:should_be_ok(A). + +-spec be_error({ok, any()} | {error, FMU}) -> FMU. +be_error(A) -> + gleeunit_ffi:should_be_error(A). + +-spec be_true(boolean()) -> nil. +be_true(Actual) -> + _pipe = Actual, + gleeunit_ffi:should_equal(_pipe, true). + +-spec be_false(boolean()) -> nil. +be_false(Actual) -> + _pipe = Actual, + gleeunit_ffi:should_equal(_pipe, false). + +-spec fail() -> nil. +fail() -> + be_true(false). diff --git a/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_ffi.erl b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_ffi.erl new file mode 100644 index 0000000..31f9ef9 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_ffi.erl @@ -0,0 +1,24 @@ +-module(gleeunit_ffi). + +-export([find_files/2, should_equal/2, should_not_equal/2, should_be_ok/1, + should_be_error/1]). + +-include_lib("eunit/include/eunit.hrl"). + +find_files(Pattern, In) -> + Results = filelib:wildcard(binary_to_list(Pattern), binary_to_list(In)), + lists:map(fun list_to_binary/1, Results). + + +should_equal(Actual, Expected) -> + ?assertEqual(Expected, Actual), + nil. +should_not_equal(Actual, Expected) -> + ?assertNotEqual(Expected, Actual), + nil. +should_be_ok(A) -> + ?assertMatch({ok, _}, A), + element(2, A). +should_be_error(A) -> + ?assertMatch({error, _}, A), + element(2, A). diff --git a/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_ffi.mjs b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_ffi.mjs new file mode 100644 index 0000000..339a843 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_ffi.mjs @@ -0,0 +1,101 @@ +async function* gleamFiles(directory) { + for (let entry of await read_dir(directory)) { + let path = join_path(directory, entry); + if (path.endsWith(".gleam")) { + yield path; + } else { + try { + yield* gleamFiles(path); + } catch (error) { + // Could not read directory, assume it's a file + } + } + } +} + +async function readRootPackageName() { + let toml = await read_file("gleam.toml", "utf-8"); + for (let line of toml.split("\n")) { + let matches = line.match(/\s*name\s*=\s*"([a-z][a-z0-9_]*)"/); // Match regexp in compiler-cli/src/new.rs in validate_name() + if (matches) return matches[1]; + } + throw new Error("Could not determine package name from gleam.toml"); +} + +export async function main() { + let passes = 0; + let failures = 0; + + let packageName = await readRootPackageName(); + let dist = `../${packageName}/`; + + for await (let path of await gleamFiles("test")) { + let js_path = path.slice("test/".length).replace(".gleam", ".mjs"); + let module = await import(join_path(dist, js_path)); + for (let fnName of Object.keys(module)) { + if (!fnName.endsWith("_test")) continue; + try { + await module[fnName](); + write(`\u001b[32m.\u001b[0m`); + passes++; + } catch (error) { + let moduleName = "\n" + js_path.slice(0, -4); + let line = error.line ? `:${error.line}` : ""; + write(`\n❌ ${moduleName}.${fnName}${line}: ${error}\n`); + failures++; + } + } + } + + console.log(` +${passes + failures} tests, ${failures} failures`); + exit(failures ? 1 : 0); +} + +export function crash(message) { + throw new Error(message); +} + +function write(message) { + if (globalThis.Deno) { + Deno.stdout.writeSync(new TextEncoder().encode(message)); + } else { + process.stdout.write(message); + } +} + +function exit(code) { + if (globalThis.Deno) { + Deno.exit(code); + } else { + process.exit(code); + } +} + +async function read_dir(path) { + if (globalThis.Deno) { + let items = []; + for await (let item of Deno.readDir(path, { withFileTypes: true })) { + items.push(item.name); + } + return items; + } else { + let { readdir } = await import("fs/promises"); + return readdir(path); + } +} + +function join_path(a, b) { + if (a.endsWith("/")) return a + b; + return a + "/" + b; +} + +async function read_file(path) { + if (globalThis.Deno) { + return Deno.readTextFile(path); + } else { + let { readFile } = await import("fs/promises"); + let contents = await readFile(path); + return contents.toString(); + } +} diff --git a/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_progress.erl b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_progress.erl new file mode 100644 index 0000000..1f68eb9 --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_progress.erl @@ -0,0 +1,607 @@ +%% A formatter adapted from Sean Cribb's https://github.com/seancribbs/eunit_formatters + +%% @doc A listener/reporter for eunit that prints '.' for each +%% success, 'F' for each failure, and 'E' for each error. It can also +%% optionally summarize the failures at the end. +-compile({nowarn_unused_function, [insert/2, to_list/1, to_list/2, size/1]}). +-module(gleeunit_progress). +-behaviour(eunit_listener). +-define(NOTEST, true). +-include_lib("eunit/include/eunit.hrl"). + +-define(RED, "\e[0;31m"). +-define(GREEN, "\e[0;32m"). +-define(YELLOW, "\e[0;33m"). +-define(WHITE, "\e[0;37m"). +-define(CYAN, "\e[0;36m"). +-define(RESET, "\e[0m"). + +-record(node,{ + rank = 0 :: non_neg_integer(), + key :: term(), + value :: term(), + children = new() :: binomial_heap() + }). + +-export_type([binomial_heap/0, heap_node/0]). +-type binomial_heap() :: [ heap_node() ]. +-type heap_node() :: #node{}. + +%% eunit_listener callbacks +-export([ + init/1, + handle_begin/3, + handle_end/3, + handle_cancel/3, + terminate/2, + start/0, + start/1 + ]). + +%% -- binomial_heap.erl content start -- + +-record(state, { + status = dict:new() :: euf_dict(), + failures = [] :: [[pos_integer()]], + skips = [] :: [[pos_integer()]], + timings = new() :: binomial_heap(), + colored = true :: boolean(), + profile = false :: boolean() + }). + +-type euf_dict() :: dict:dict(). + +-spec new() -> binomial_heap(). +new() -> + []. + +% Inserts a new pair into the heap (or creates a new heap) +-spec insert(term(), term()) -> binomial_heap(). +insert(Key,Value) -> + insert(Key,Value,[]). + +-spec insert(term(), term(), binomial_heap()) -> binomial_heap(). +insert(Key,Value,Forest) -> + insTree(#node{key=Key,value=Value},Forest). + +% Merges two heaps +-spec merge(binomial_heap(), binomial_heap()) -> binomial_heap(). +merge(TS1,[]) when is_list(TS1) -> TS1; +merge([],TS2) when is_list(TS2) -> TS2; +merge([#node{rank=R1}=T1|TS1]=F1,[#node{rank=R2}=T2|TS2]=F2) -> + if + R1 < R2 -> + [T1 | merge(TS1,F2)]; + R2 < R1 -> + [T2 | merge(F1, TS2)]; + true -> + insTree(link(T1,T2),merge(TS1,TS2)) + end. + +% Deletes the top entry from the heap and returns it +-spec delete(binomial_heap()) -> {{term(), term()}, binomial_heap()}. +delete(TS) -> + {#node{key=Key,value=Value,children=TS1},TS2} = getMin(TS), + {{Key,Value},merge(lists:reverse(TS1),TS2)}. + +% Turns the heap into list in heap order +-spec to_list(binomial_heap()) -> [{term(), term()}]. +to_list([]) -> []; +to_list(List) when is_list(List) -> + to_list([],List). +to_list(Acc, []) -> + lists:reverse(Acc); +to_list(Acc,Forest) -> + {Next, Trees} = delete(Forest), + to_list([Next|Acc], Trees). + +% Take N elements from the top of the heap +-spec take(non_neg_integer(), binomial_heap()) -> [{term(), term()}]. +take(N,Trees) when is_integer(N), is_list(Trees) -> + take(N,Trees,[]). +take(0,_Trees,Acc) -> + lists:reverse(Acc); +take(_N,[],Acc)-> + lists:reverse(Acc); +take(N,Trees,Acc) -> + {Top,T2} = delete(Trees), + take(N-1,T2,[Top|Acc]). + +% Get an estimate of the size based on the binomial property +-spec size(binomial_heap()) -> non_neg_integer(). +size(Forest) -> + erlang:trunc(lists:sum([math:pow(2,R) || #node{rank=R} <- Forest])). + +%% Private API +-spec link(heap_node(), heap_node()) -> heap_node(). +link(#node{rank=R,key=X1,children=C1}=T1,#node{key=X2,children=C2}=T2) -> + case X1 < X2 of + true -> + T1#node{rank=R+1,children=[T2|C1]}; + _ -> + T2#node{rank=R+1,children=[T1|C2]} + end. + +insTree(Tree, []) -> + [Tree]; +insTree(#node{rank=R1}=T1, [#node{rank=R2}=T2|Rest] = TS) -> + case R1 < R2 of + true -> + [T1|TS]; + _ -> + insTree(link(T1,T2),Rest) + end. + +getMin([T]) -> + {T,[]}; +getMin([#node{key=K} = T|TS]) -> + {#node{key=K1} = T1,TS1} = getMin(TS), + case K < K1 of + true -> {T,TS}; + _ -> {T1,[T|TS1]} + end. + +%% -- binomial_heap.erl content end -- + +%% Startup +start() -> + start([]). + +start(Options) -> + eunit_listener:start(?MODULE, Options). + +%%------------------------------------------ +%% eunit_listener callbacks +%%------------------------------------------ +init(Options) -> + #state{colored=proplists:get_bool(colored, Options), + profile=proplists:get_bool(profile, Options)}. + +handle_begin(group, Data, St) -> + GID = proplists:get_value(id, Data), + Dict = St#state.status, + St#state{status=dict:store(GID, orddict:from_list([{type, group}|Data]), Dict)}; +handle_begin(test, Data, St) -> + TID = proplists:get_value(id, Data), + Dict = St#state.status, + St#state{status=dict:store(TID, orddict:from_list([{type, test}|Data]), Dict)}. + +handle_end(group, Data, St) -> + St#state{status=merge_on_end(Data, St#state.status)}; +handle_end(test, Data, St) -> + NewStatus = merge_on_end(Data, St#state.status), + St1 = print_progress(Data, St), + St2 = record_timing(Data, St1), + St2#state{status=NewStatus}. + +handle_cancel(_, Data, #state{status=Status, skips=Skips}=St) -> + Status1 = merge_on_end(Data, Status), + ID = proplists:get_value(id, Data), + St#state{status=Status1, skips=[ID|Skips]}. + +terminate({ok, Data}, St) -> + print_failures(St), + print_pending(St), + print_profile(St), + print_timing(St), + print_results(Data, St); +terminate({error, Reason}, St) -> + io:nl(), io:nl(), + print_colored(io_lib:format("Eunit failed: ~25p~n", [Reason]), ?RED, St), + sync_end(error). + +sync_end(Result) -> + receive + {stop, Reference, ReplyTo} -> + ReplyTo ! {result, Reference, Result}, + ok + end. + +%%------------------------------------------ +%% Print and collect information during run +%%------------------------------------------ +print_progress(Data, St) -> + TID = proplists:get_value(id, Data), + case proplists:get_value(status, Data) of + ok -> + print_progress_success(St), + St; + {skipped, _Reason} -> + print_progress_skipped(St), + St#state{skips=[TID|St#state.skips]}; + {error, Exception} -> + print_progress_failed(Exception, St), + St#state{failures=[TID|St#state.failures]} + end. + +record_timing(Data, State=#state{timings=T, profile=true}) -> + TID = proplists:get_value(id, Data), + case lists:keyfind(time, 1, Data) of + {time, Int} -> + %% It's a min-heap, so we insert negative numbers instead + %% of the actuals and normalize when we report on them. + T1 = insert(-Int, TID, T), + State#state{timings=T1}; + false -> + State + end; +record_timing(_Data, State) -> + State. + +print_progress_success(St) -> + print_colored(".", ?GREEN, St). + +print_progress_skipped(St) -> + print_colored("*", ?YELLOW, St). + +print_progress_failed(_Exc, St) -> + print_colored("F", ?RED, St). + +merge_on_end(Data, Dict) -> + ID = proplists:get_value(id, Data), + dict:update(ID, + fun(Old) -> + orddict:merge(fun merge_data/3, Old, orddict:from_list(Data)) + end, Dict). + +merge_data(_K, undefined, X) -> X; +merge_data(_K, X, undefined) -> X; +merge_data(_K, _, X) -> X. + +%%------------------------------------------ +%% Print information at end of run +%%------------------------------------------ +print_failures(#state{failures=[]}) -> + ok; +print_failures(#state{failures=Fails}=State) -> + io:nl(), + io:fwrite("Failures:~n",[]), + lists:foldr(print_failure_fun(State), 1, Fails), + ok. + +print_failure_fun(#state{status=Status}=State) -> + fun(Key, Count) -> + TestData = dict:fetch(Key, Status), + TestId = format_test_identifier(TestData), + io:fwrite("~n ~p) ~ts~n", [Count, TestId]), + print_failure_reason(proplists:get_value(status, TestData), + proplists:get_value(output, TestData), + State), + io:nl(), + Count + 1 + end. + +print_gleam_location(#{function := Function, line := Line, module := Module }, State) -> + X = indent(5, "location: ~s.~s:~p~n", [Module, Function, Line]), + print_colored(X, ?CYAN, State); +print_gleam_location(_, _) -> + ok. + +inspect(X) -> + gleam@string:inspect(X). + +print_gleam_failure_reason( + #{gleam_error := assert, message := Message, value := Value}, + State +) -> + print_colored(indent(5, "~s~n", [Message]), ?RED, State), + print_colored(indent(5, " value: ", []), ?RED, State), + print_colored(indent(0, "~ts~n", [inspect(Value)]), ?RESET, State); +print_gleam_failure_reason( + #{gleam_error := todo, message := Message}, + State +) -> + print_colored(indent(5, "todo expression run~n", []), ?RED, State), + print_colored(indent(5, " message: ", []), ?RED, State), + print_colored(indent(0, "~s~n", [Message]), ?RESET, State); +print_gleam_failure_reason(Error, State) -> + print_colored(indent(5, "~p~n", [Error]), ?RED, State). + +% New Gleeunit specific formatters +print_failure_reason( + {error, {error, #{gleam_error := _} = Error, Stack}}, Output, State +) when is_list(Stack) -> + print_gleam_failure_reason(Error, State), + print_gleam_location(Error, State), + print_stack(Stack, State), + print_failure_output(5, Output, State); +print_failure_reason({error, {error, {case_clause, Value}, Stack}}, Output, State) when is_list(Stack) -> + print_colored(indent(5, "No case clause matched~n", []), ?RED, State), + print_colored(indent(5, "Value: ", []), ?CYAN, State), + print_colored(indent(0, "~ts~n", [inspect(Value)]), ?RESET, State), + print_stack(Stack, State), + print_failure_output(5, Output, State); +% From the original Erlang version +print_failure_reason({skipped, Reason}, _Output, State) -> + print_colored(io_lib:format(" ~ts~n", [format_pending_reason(Reason)]), + ?RED, State); +print_failure_reason({error, {_Class, Term, _}}, Output, State) when + is_tuple(Term), tuple_size(Term) == 2, is_list(element(2, Term)) -> + print_assertion_failure(Term, State), + print_failure_output(5, Output, State); +print_failure_reason({error, {error, Error, Stack}}, Output, State) when is_list(Stack) -> + print_colored(indent(5, "Failure: ~p~n", [Error]), ?RED, State), + print_stack(Stack, State), + print_failure_output(5, Output, State); +print_failure_reason({error, Reason}, Output, State) -> + print_colored(indent(5, "Failure: ~p~n", [Reason]), ?RED, State), + print_failure_output(5, Output, State). + +gleam_format_module_name(Module) -> + string:replace(atom_to_list(Module), "@", "/", all). + +print_stack(Stack, State) -> + print_colored(indent(5, "stacktrace:~n", []), ?CYAN, State), + print_stackframes(Stack, State). +print_stackframes([{eunit_test, _, _, _} | Stack], State) -> + print_stackframes(Stack, State); +print_stackframes([{eunit_proc, _, _, _} | Stack], State) -> + print_stackframes(Stack, State); +print_stackframes([{Module, Function, _Arity, _Location} | Stack], State) -> + GleamModule = gleam_format_module_name(Module), + print_colored(indent(7, "~s.~p~n", [GleamModule, Function]), ?CYAN, State), + print_stackframes(Stack, State); +print_stackframes([], _State) -> + ok. + + +print_failure_output(_, <<>>, _) -> ok; +print_failure_output(_, undefined, _) -> ok; +print_failure_output(Indent, Output, State) -> + print_colored(indent(Indent, "output: ~ts", [Output]), ?CYAN, State). + +print_assertion_failure({Type, Props}, State) -> + FailureDesc = format_assertion_failure(Type, Props, 5), + print_colored(FailureDesc, ?RED, State), + io:nl(). + +print_pending(#state{skips=[]}) -> + ok; +print_pending(#state{status=Status, skips=Skips}=State) -> + io:nl(), + io:fwrite("Pending:~n", []), + lists:foreach(fun(ID) -> + Info = dict:fetch(ID, Status), + case proplists:get_value(reason, Info) of + undefined -> + ok; + Reason -> + print_pending_reason(Reason, Info, State) + end + end, lists:reverse(Skips)), + io:nl(). + +print_pending_reason(Reason0, Data, State) -> + Text = case proplists:get_value(type, Data) of + group -> + io_lib:format(" ~ts~n", [proplists:get_value(desc, Data)]); + test -> + io_lib:format(" ~ts~n", [format_test_identifier(Data)]) + end, + Reason = io_lib:format(" %% ~ts~n", [format_pending_reason(Reason0)]), + print_colored(Text, ?YELLOW, State), + print_colored(Reason, ?CYAN, State). + +print_profile(#state{timings=T, status=Status, profile=true}=State) -> + TopN = take(10, T), + TopNTime = abs(lists:sum([ Time || {Time, _} <- TopN ])), + TLG = dict:fetch([], Status), + TotalTime = proplists:get_value(time, TLG), + if TotalTime =/= undefined andalso TotalTime > 0 andalso TopN =/= [] -> + TopNPct = (TopNTime / TotalTime) * 100, + io:nl(), io:nl(), + io:fwrite("Top ~p slowest tests (~ts, ~.1f% of total time):", [length(TopN), format_time(TopNTime), TopNPct]), + lists:foreach(print_timing_fun(State), TopN), + io:nl(); + true -> ok + end; +print_profile(#state{profile=false}) -> + ok. + +print_timing(#state{status=Status}) -> + TLG = dict:fetch([], Status), + Time = proplists:get_value(time, TLG), + io:nl(), + io:fwrite("Finished in ~ts~n", [format_time(Time)]), + ok. + +print_results(Data, State) -> + Pass = proplists:get_value(pass, Data, 0), + Fail = proplists:get_value(fail, Data, 0), + Skip = proplists:get_value(skip, Data, 0), + Cancel = proplists:get_value(cancel, Data, 0), + Total = Pass + Fail + Skip + Cancel, + {Color, Result} = if Fail > 0 -> {?RED, error}; + Skip > 0; Cancel > 0 -> {?YELLOW, error}; + Pass =:= 0 -> {?YELLOW, ok}; + true -> {?GREEN, ok} + end, + print_results(Color, Total, Fail, Skip, Cancel, State), + sync_end(Result). + +print_results(Color, 0, _, _, _, State) -> + print_colored(Color, "0 tests\n", State); +print_results(Color, Total, Fail, Skip, Cancel, State) -> + SkipText = format_optional_result(Skip, "skipped"), + CancelText = format_optional_result(Cancel, "cancelled"), + Text = io_lib:format("~p tests, ~p failures~ts~ts~n", [Total, Fail, SkipText, CancelText]), + print_colored(Text, Color, State). + +print_timing_fun(#state{status=Status}=State) -> + fun({Time, Key}) -> + TestData = dict:fetch(Key, Status), + TestId = format_test_identifier(TestData), + io:nl(), + io:fwrite(" ~ts~n", [TestId]), + print_colored([" "|format_time(abs(Time))], ?CYAN, State) + end. + +%%------------------------------------------ +%% Print to the console with the given color +%% if enabled. +%%------------------------------------------ +print_colored(Text, Color, #state{colored=true}) -> + io:fwrite("~s~ts~s", [Color, Text, ?RESET]); +print_colored(Text, _Color, #state{colored=false}) -> + io:fwrite("~ts", [Text]). + +%%------------------------------------------ +%% Generic data formatters +%%------------------------------------------ +format_function_name(M, F) -> + M1 = gleam_format_module_name(M), + io_lib:format("~ts.~ts", [M1, F]). + +format_optional_result(0, _) -> + []; +format_optional_result(Count, Text) -> + io_lib:format(", ~p ~ts", [Count, Text]). + +format_test_identifier(Data) -> + {Mod, Fun, _} = proplists:get_value(source, Data), + Line = case proplists:get_value(line, Data) of + 0 -> ""; + L -> io_lib:format(":~p", [L]) + end, + Desc = case proplists:get_value(desc, Data) of + undefined -> ""; + DescText -> io_lib:format(": ~ts", [DescText]) + end, + io_lib:format("~ts~ts~ts", [format_function_name(Mod, Fun), Line, Desc]). + +format_time(undefined) -> + "? seconds"; +format_time(Time) -> + io_lib:format("~.3f seconds", [Time / 1000]). + +format_pending_reason({module_not_found, M}) -> + M1 = gleam_format_module_name(M), + io_lib:format("Module '~ts' missing", [M1]); +format_pending_reason({no_such_function, {M,F,_}}) -> + M1 = gleam_format_module_name(M), + io_lib:format("Function ~ts undefined", [format_function_name(M1,F)]); +format_pending_reason({exit, Reason}) -> + io_lib:format("Related process exited with reason: ~p", [Reason]); +format_pending_reason(Reason) -> + io_lib:format("Unknown error: ~p", [Reason]). + +%% @doc Formats all the known eunit assertions, you're on your own if +%% you make an assertion yourself. +format_assertion_failure(Type, Props, I) when Type =:= assertion_failed + ; Type =:= assert -> + Keys = proplists:get_keys(Props), + HasEUnitProps = ([expression, value] -- Keys) =:= [], + HasHamcrestProps = ([expected, actual, matcher] -- Keys) =:= [], + if + HasEUnitProps -> + [indent(I, "Failure: ?assert(~ts)~n", [proplists:get_value(expression, Props)]), + indent(I, " expected: true~n", []), + case proplists:get_value(value, Props) of + false -> + indent(I, " got: false", []); + {not_a_boolean, V} -> + indent(I, " got: ~p", [V]) + end]; + HasHamcrestProps -> + [indent(I, "Failure: ?assertThat(~p)~n", [proplists:get_value(matcher, Props)]), + indent(I, " expected: ~ts~n", [inspect(proplists:get_value(expected, Props))]), + indent(I, " got: ~ts", [inspect(proplists:get_value(actual, Props))])]; + true -> + [indent(I, "Failure: unknown assert: ~p", [Props])] + end; + +format_assertion_failure(Type, Props, I) when Type =:= assertMatch_failed + ; Type =:= assertMatch -> + Expr = proplists:get_value(expression, Props), + Pattern = proplists:get_value(pattern, Props), + Value = proplists:get_value(value, Props), + [indent(I, "Failure: ?assertMatch(~ts, ~ts)~n", [Pattern, Expr]), + indent(I, " expected: = ~ts~n", [Pattern]), + indent(I, " got: ~p", [Value])]; + +format_assertion_failure(Type, Props, I) when Type =:= assertNotMatch_failed + ; Type =:= assertNotMatch -> + Expr = proplists:get_value(expression, Props), + Pattern = proplists:get_value(pattern, Props), + Value = proplists:get_value(value, Props), + [indent(I, "Failure: ?assertNotMatch(~ts, ~ts)~n", [Pattern, Expr]), + indent(I, " expected not: = ~ts~n", [Pattern]), + indent(I, " got: ~p", [Value])]; + +format_assertion_failure(Type, Props, I) when Type =:= assertEqual_failed + ; Type =:= assertEqual -> + Expected = inspect(proplists:get_value(expected, Props)), + Value = inspect(proplists:get_value(value, Props)), + [indent(I, "Values were not equal~n", []), + indent(I, "expected: ~ts~n", [Expected]), + indent(I, " got: ~ts", [Value])]; + +format_assertion_failure(Type, Props, I) when Type =:= assertNotEqual_failed + ; Type =:= assertNotEqual -> + Value = inspect(proplists:get_value(value, Props)), + [indent(I, "Values were equal~n", []), + indent(I, "expected: not ~ts~n,", [Value]), + indent(I, " got: ~ts", [Value])]; + +format_assertion_failure(Type, Props, I) when Type =:= assertException_failed + ; Type =:= assertException -> + Expr = proplists:get_value(expression, Props), + Pattern = proplists:get_value(pattern, Props), + {Class, Term} = extract_exception_pattern(Pattern), % I hate that we have to do this, why not just give DATA + [indent(I, "Failure: ?assertException(~ts, ~ts, ~ts)~n", [Class, Term, Expr]), + case proplists:is_defined(unexpected_success, Props) of + true -> + [indent(I, " expected: exception ~ts but nothing was raised~n", [Pattern]), + indent(I, " got: value ~p", [proplists:get_value(unexpected_success, Props)])]; + false -> + Ex = proplists:get_value(unexpected_exception, Props), + [indent(I, " expected: exception ~ts~n", [Pattern]), + indent(I, " got: exception ~p", [Ex])] + end]; + +format_assertion_failure(Type, Props, I) when Type =:= assertNotException_failed + ; Type =:= assertNotException -> + Expr = proplists:get_value(expression, Props), + Pattern = proplists:get_value(pattern, Props), + {Class, Term} = extract_exception_pattern(Pattern), % I hate that we have to do this, why not just give DAT + Ex = proplists:get_value(unexpected_exception, Props), + [indent(I, "Failure: ?assertNotException(~ts, ~ts, ~ts)~n", [Class, Term, Expr]), + indent(I, " expected not: exception ~ts~n", [Pattern]), + indent(I, " got: exception ~p", [Ex])]; + +format_assertion_failure(Type, Props, I) when Type =:= command_failed + ; Type =:= command -> + Cmd = proplists:get_value(command, Props), + Expected = proplists:get_value(expected_status, Props), + Status = proplists:get_value(status, Props), + [indent(I, "Failure: ?cmdStatus(~p, ~p)~n", [Expected, Cmd]), + indent(I, " expected: status ~p~n", [Expected]), + indent(I, " got: status ~p", [Status])]; + +format_assertion_failure(Type, Props, I) when Type =:= assertCmd_failed + ; Type =:= assertCmd -> + Cmd = proplists:get_value(command, Props), + Expected = proplists:get_value(expected_status, Props), + Status = proplists:get_value(status, Props), + [indent(I, "Failure: ?assertCmdStatus(~p, ~p)~n", [Expected, Cmd]), + indent(I, " expected: status ~p~n", [Expected]), + indent(I, " got: status ~p", [Status])]; + +format_assertion_failure(Type, Props, I) when Type =:= assertCmdOutput_failed + ; Type =:= assertCmdOutput -> + Cmd = proplists:get_value(command, Props), + Expected = proplists:get_value(expected_output, Props), + Output = proplists:get_value(output, Props), + [indent(I, "Failure: ?assertCmdOutput(~p, ~p)~n", [Expected, Cmd]), + indent(I, " expected: ~p~n", [Expected]), + indent(I, " got: ~p", [Output])]; + +format_assertion_failure(Type, Props, I) -> + indent(I, "~p", [{Type, Props}]). + +indent(I, Fmt, Args) -> + io_lib:format("~" ++ integer_to_list(I) ++ "s" ++ Fmt, [" "|Args]). + +extract_exception_pattern(Str) -> + ["{", Class, Term|_] = re:split(Str, "[, ]{1,2}", [unicode,{return,list}]), + {Class, Term}. diff --git a/aoc2023/build/packages/tom/build/packages/packages.toml b/aoc2023/build/packages/tom/build/packages/packages.toml new file mode 100644 index 0000000..b7ab86d --- /dev/null +++ b/aoc2023/build/packages/tom/build/packages/packages.toml @@ -0,0 +1,3 @@ +[packages] +gleam_stdlib = "0.34.0" +gleeunit = "1.0.2" diff --git a/aoc2023/build/packages/tom/build/prod/erlang/gleam.lock b/aoc2023/build/packages/tom/build/prod/erlang/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/packages/tom/build/prod/erlang/gleam.lock diff --git a/aoc2023/build/packages/tom/build/prod/javascript/gleam.lock b/aoc2023/build/packages/tom/build/prod/javascript/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/packages/tom/build/prod/javascript/gleam.lock diff --git a/aoc2023/build/packages/tom/gleam.toml b/aoc2023/build/packages/tom/gleam.toml new file mode 100644 index 0000000..f131d09 --- /dev/null +++ b/aoc2023/build/packages/tom/gleam.toml @@ -0,0 +1,13 @@ +name = "tom" +version = "0.2.1" + +description = "A pure Gleam TOML parser!" +licences = ["Apache-2.0"] +repository = { type = "github", user = "lpil", repo = "tom" } +links = [{ title = "TOML website", href = "https://toml.io/en/" }] + +[dependencies] +gleam_stdlib = "~> 0.32" + +[dev-dependencies] +gleeunit = "~> 1.0" diff --git a/aoc2023/build/packages/tom/include/tom_DateTimeValue.hrl b/aoc2023/build/packages/tom/include/tom_DateTimeValue.hrl new file mode 100644 index 0000000..3b1e660 --- /dev/null +++ b/aoc2023/build/packages/tom/include/tom_DateTimeValue.hrl @@ -0,0 +1,5 @@ +-record(date_time_value, { + date :: tom:date(), + time :: tom:time(), + offset :: tom:offset() +}). diff --git a/aoc2023/build/packages/tom/include/tom_DateValue.hrl b/aoc2023/build/packages/tom/include/tom_DateValue.hrl new file mode 100644 index 0000000..c41f901 --- /dev/null +++ b/aoc2023/build/packages/tom/include/tom_DateValue.hrl @@ -0,0 +1 @@ +-record(date_value, {year :: integer(), month :: integer(), day :: integer()}). diff --git a/aoc2023/build/packages/tom/include/tom_KeyAlreadyInUse.hrl b/aoc2023/build/packages/tom/include/tom_KeyAlreadyInUse.hrl new file mode 100644 index 0000000..930df26 --- /dev/null +++ b/aoc2023/build/packages/tom/include/tom_KeyAlreadyInUse.hrl @@ -0,0 +1 @@ +-record(key_already_in_use, {key :: list(binary())}). diff --git a/aoc2023/build/packages/tom/include/tom_NotFound.hrl b/aoc2023/build/packages/tom/include/tom_NotFound.hrl new file mode 100644 index 0000000..19c9a17 --- /dev/null +++ b/aoc2023/build/packages/tom/include/tom_NotFound.hrl @@ -0,0 +1 @@ +-record(not_found, {key :: list(binary())}). diff --git a/aoc2023/build/packages/tom/include/tom_Offset.hrl b/aoc2023/build/packages/tom/include/tom_Offset.hrl new file mode 100644 index 0000000..a58a8e1 --- /dev/null +++ b/aoc2023/build/packages/tom/include/tom_Offset.hrl @@ -0,0 +1,5 @@ +-record(offset, { + direction :: tom:sign(), + hours :: integer(), + minutes :: integer() +}). diff --git a/aoc2023/build/packages/tom/include/tom_TimeValue.hrl b/aoc2023/build/packages/tom/include/tom_TimeValue.hrl new file mode 100644 index 0000000..e1275de --- /dev/null +++ b/aoc2023/build/packages/tom/include/tom_TimeValue.hrl @@ -0,0 +1,6 @@ +-record(time_value, { + hour :: integer(), + minute :: integer(), + second :: integer(), + millisecond :: integer() +}). diff --git a/aoc2023/build/packages/tom/include/tom_Unexpected.hrl b/aoc2023/build/packages/tom/include/tom_Unexpected.hrl new file mode 100644 index 0000000..ab1091c --- /dev/null +++ b/aoc2023/build/packages/tom/include/tom_Unexpected.hrl @@ -0,0 +1 @@ +-record(unexpected, {got :: binary(), expected :: binary()}). diff --git a/aoc2023/build/packages/tom/include/tom_WrongType.hrl b/aoc2023/build/packages/tom/include/tom_WrongType.hrl new file mode 100644 index 0000000..ae57352 --- /dev/null +++ b/aoc2023/build/packages/tom/include/tom_WrongType.hrl @@ -0,0 +1,5 @@ +-record(wrong_type, { + key :: list(binary()), + expected :: binary(), + got :: binary() +}). diff --git a/aoc2023/build/packages/tom/manifest.toml b/aoc2023/build/packages/tom/manifest.toml new file mode 100644 index 0000000..e1aa028 --- /dev/null +++ b/aoc2023/build/packages/tom/manifest.toml @@ -0,0 +1,11 @@ +# This file was generated by Gleam +# You typically do not need to edit this file + +packages = [ + { name = "gleam_stdlib", version = "0.34.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "1FB8454D2991E9B4C0C804544D8A9AD0F6184725E20D63C3155F0AEB4230B016" }, + { name = "gleeunit", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D364C87AFEB26BDB4FB8A5ABDE67D635DC9FA52D6AB68416044C35B096C6882D" }, +] + +[requirements] +gleam_stdlib = { version = "~> 0.32" } +gleeunit = { version = "~> 1.0" } diff --git a/aoc2023/build/packages/tom/src/tom.app.src b/aoc2023/build/packages/tom/src/tom.app.src new file mode 100644 index 0000000..051649c --- /dev/null +++ b/aoc2023/build/packages/tom/src/tom.app.src @@ -0,0 +1,8 @@ +{application, tom, [ + {vsn, "0.2.1"}, + {applications, [gleam_stdlib, + gleeunit]}, + {description, "A pure Gleam TOML parser!"}, + {modules, [tom]}, + {registered, []} +]}. diff --git a/aoc2023/build/packages/tom/src/tom.erl b/aoc2023/build/packages/tom/src/tom.erl new file mode 100644 index 0000000..4f5c071 --- /dev/null +++ b/aoc2023/build/packages/tom/src/tom.erl @@ -0,0 +1,2140 @@ +-module(tom). +-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]). + +-export([get/2, get_int/2, get_float/2, get_bool/2, get_string/2, get_date/2, get_time/2, get_date_time/2, get_array/2, get_table/2, get_number/2, parse/1]). +-export_type([toml/0, date_time/0, date/0, time/0, offset/0, sign/0, parse_error/0, number_/0, get_error/0]). + +-type toml() :: {int, integer()} | + {float, float()} | + {infinity, sign()} | + {nan, sign()} | + {bool, boolean()} | + {string, binary()} | + {date, date()} | + {time, time()} | + {date_time, date_time()} | + {array, list(toml())} | + {array_of_tables, list(gleam@map:map_(binary(), toml()))} | + {table, gleam@map:map_(binary(), toml())} | + {inline_table, gleam@map:map_(binary(), toml())}. + +-type date_time() :: {date_time_value, date(), time(), offset()}. + +-type date() :: {date_value, integer(), integer(), integer()}. + +-type time() :: {time_value, integer(), integer(), integer(), integer()}. + +-type offset() :: local | {offset, sign(), integer(), integer()}. + +-type sign() :: positive | negative. + +-type parse_error() :: {unexpected, binary(), binary()} | + {key_already_in_use, list(binary())}. + +-type number_() :: {number_int, integer()} | + {number_float, float()} | + {number_infinity, sign()} | + {number_nan, sign()}. + +-type get_error() :: {not_found, list(binary())} | + {wrong_type, list(binary()), binary(), binary()}. + +-spec classify(toml()) -> binary(). +classify(Toml) -> + case Toml of + {int, _} -> + <<"Int"/utf8>>; + + {float, _} -> + <<"Float"/utf8>>; + + {nan, positive} -> + <<"NaN"/utf8>>; + + {nan, negative} -> + <<"Negative NaN"/utf8>>; + + {infinity, positive} -> + <<"Infinity"/utf8>>; + + {infinity, negative} -> + <<"Negative Infinity"/utf8>>; + + {bool, _} -> + <<"Bool"/utf8>>; + + {string, _} -> + <<"String"/utf8>>; + + {date, _} -> + <<"Date"/utf8>>; + + {time, _} -> + <<"Time"/utf8>>; + + {date_time, _} -> + <<"DateTime"/utf8>>; + + {array, _} -> + <<"Array"/utf8>>; + + {array_of_tables, _} -> + <<"Array"/utf8>>; + + {table, _} -> + <<"Table"/utf8>>; + + {inline_table, _} -> + <<"Table"/utf8>> + end. + +-spec push_key({ok, FIU} | {error, get_error()}, binary()) -> {ok, FIU} | + {error, get_error()}. +push_key(Result, Key) -> + case Result of + {ok, T} -> + {ok, T}; + + {error, {not_found, Path}} -> + {error, {not_found, [Key | Path]}}; + + {error, {wrong_type, Path@1, Expected, Got}} -> + {error, {wrong_type, [Key | Path@1], Expected, Got}} + end. + +-spec get(gleam@map:map_(binary(), toml()), list(binary())) -> {ok, toml()} | + {error, get_error()}. +get(Toml, Key) -> + case Key of + [] -> + {error, {not_found, []}}; + + [K] -> + gleam@result:replace_error(gleam@map:get(Toml, K), {not_found, [K]}); + + [K@1 | Key@1] -> + case gleam@map:get(Toml, K@1) of + {ok, {table, T}} -> + push_key(get(T, Key@1), K@1); + + {ok, Other} -> + {error, + {wrong_type, [K@1], <<"Table"/utf8>>, classify(Other)}}; + + {error, _} -> + {error, {not_found, [K@1]}} + end + end. + +-spec get_int(gleam@map:map_(binary(), toml()), list(binary())) -> {ok, + integer()} | + {error, get_error()}. +get_int(Toml, Key) -> + case get(Toml, Key) of + {ok, {int, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Int"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_float(gleam@map:map_(binary(), toml()), list(binary())) -> {ok, + float()} | + {error, get_error()}. +get_float(Toml, Key) -> + case get(Toml, Key) of + {ok, {float, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Float"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_bool(gleam@map:map_(binary(), toml()), list(binary())) -> {ok, + boolean()} | + {error, get_error()}. +get_bool(Toml, Key) -> + case get(Toml, Key) of + {ok, {bool, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Bool"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_string(gleam@map:map_(binary(), toml()), list(binary())) -> {ok, + binary()} | + {error, get_error()}. +get_string(Toml, Key) -> + case get(Toml, Key) of + {ok, {string, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"String"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_date(gleam@map:map_(binary(), toml()), list(binary())) -> {ok, date()} | + {error, get_error()}. +get_date(Toml, Key) -> + case get(Toml, Key) of + {ok, {date, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Date"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_time(gleam@map:map_(binary(), toml()), list(binary())) -> {ok, time()} | + {error, get_error()}. +get_time(Toml, Key) -> + case get(Toml, Key) of + {ok, {time, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Time"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_date_time(gleam@map:map_(binary(), toml()), list(binary())) -> {ok, + date_time()} | + {error, get_error()}. +get_date_time(Toml, Key) -> + case get(Toml, Key) of + {ok, {date_time, I}} -> + {ok, I}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"DateTime"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_array(gleam@map:map_(binary(), toml()), list(binary())) -> {ok, + list(toml())} | + {error, get_error()}. +get_array(Toml, Key) -> + case get(Toml, Key) of + {ok, {array, I}} -> + {ok, I}; + + {ok, {array_of_tables, I@1}} -> + {ok, gleam@list:map(I@1, fun(Field@0) -> {table, Field@0} end)}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Array"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_table(gleam@map:map_(binary(), toml()), list(binary())) -> {ok, + gleam@map:map_(binary(), toml())} | + {error, get_error()}. +get_table(Toml, Key) -> + case get(Toml, Key) of + {ok, {table, I}} -> + {ok, I}; + + {ok, {inline_table, I@1}} -> + {ok, I@1}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Table"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec get_number(gleam@map:map_(binary(), toml()), list(binary())) -> {ok, + number_()} | + {error, get_error()}. +get_number(Toml, Key) -> + case get(Toml, Key) of + {ok, {int, X}} -> + {ok, {number_int, X}}; + + {ok, {float, X@1}} -> + {ok, {number_float, X@1}}; + + {ok, {nan, X@2}} -> + {ok, {number_nan, X@2}}; + + {ok, {infinity, X@3}} -> + {ok, {number_infinity, X@3}}; + + {ok, Other} -> + {error, {wrong_type, Key, <<"Number"/utf8>>, classify(Other)}}; + + {error, E} -> + {error, E} + end. + +-spec merge(gleam@map:map_(binary(), toml()), binary(), toml(), toml()) -> {ok, + gleam@map:map_(binary(), toml())} | + {error, list(binary())}. +merge(Table, Key, Old, New) -> + case {Old, New} of + {{array_of_tables, Tables}, {array_of_tables, New@1}} -> + {ok, + gleam@map:insert( + Table, + Key, + {array_of_tables, gleam@list:append(New@1, Tables)} + )}; + + {_, _} -> + {error, [Key]} + end. + +-spec insert_loop(gleam@map:map_(binary(), toml()), list(binary()), toml()) -> {ok, + gleam@map:map_(binary(), toml())} | + {error, list(binary())}. +insert_loop(Table, Key, Value) -> + case Key of + [] -> + erlang:error(#{gleam_error => panic, + message => <<"unreachable"/utf8>>, + module => <<"tom"/utf8>>, + function => <<"insert_loop"/utf8>>, + line => 511}); + + [K] -> + case gleam@map:get(Table, K) of + {error, nil} -> + {ok, gleam@map:insert(Table, K, Value)}; + + {ok, Old} -> + merge(Table, K, Old, Value) + end; + + [K@1 | Key@1] -> + case gleam@map:get(Table, K@1) of + {error, nil} -> + case insert_loop(gleam@map:new(), Key@1, Value) of + {ok, Inner} -> + {ok, gleam@map:insert(Table, K@1, {table, Inner})}; + + {error, Path} -> + {error, [K@1 | Path]} + end; + + {ok, {array_of_tables, [Inner@1 | Rest]}} -> + case insert_loop(Inner@1, Key@1, Value) of + {ok, Inner@2} -> + {ok, + gleam@map:insert( + Table, + K@1, + {array_of_tables, [Inner@2 | Rest]} + )}; + + {error, Path@1} -> + {error, [K@1 | Path@1]} + end; + + {ok, {table, Inner@3}} -> + case insert_loop(Inner@3, Key@1, Value) of + {ok, Inner@4} -> + {ok, gleam@map:insert(Table, K@1, {table, Inner@4})}; + + {error, Path@2} -> + {error, [K@1 | Path@2]} + end; + + {ok, _} -> + {error, [K@1]} + end + end. + +-spec insert(gleam@map:map_(binary(), toml()), list(binary()), toml()) -> {ok, + gleam@map:map_(binary(), toml())} | + {error, parse_error()}. +insert(Table, Key, Value) -> + case insert_loop(Table, Key, Value) of + {ok, Table@1} -> + {ok, Table@1}; + + {error, Path} -> + {error, {key_already_in_use, Path}} + end. + +-spec expect_end_of_line( + list(binary()), + fun((list(binary())) -> {ok, {FKZ, list(binary())}} | {error, parse_error()}) +) -> {ok, {FKZ, list(binary())}} | {error, parse_error()}. +expect_end_of_line(Input, Next) -> + case Input of + [<<"\n"/utf8>> | Input@1] -> + Next(Input@1); + + [<<"\r\n"/utf8>> | Input@2] -> + Next(Input@2); + + [G | _] -> + {error, {unexpected, G, <<"\n"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"\n"/utf8>>}} + end. + +-spec parse_key_quoted(list(binary()), binary(), binary()) -> {ok, + {binary(), list(binary())}} | + {error, parse_error()}. +parse_key_quoted(Input, Close, Name) -> + case Input of + [G | Input@1] when G =:= Close -> + {ok, {Name, Input@1}}; + + [G@1 | Input@2] -> + parse_key_quoted(Input@2, Close, <<Name/binary, G@1/binary>>); + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, Close}} + end. + +-spec parse_key_bare(list(binary()), binary()) -> {ok, + {binary(), list(binary())}} | + {error, parse_error()}. +parse_key_bare(Input, Name) -> + case Input of + [<<" "/utf8>> | Input@1] when Name =/= <<""/utf8>> -> + {ok, {Name, Input@1}}; + + [<<"="/utf8>> | _] when Name =/= <<""/utf8>> -> + {ok, {Name, Input}}; + + [<<"."/utf8>> | _] when Name =/= <<""/utf8>> -> + {ok, {Name, Input}}; + + [<<"]"/utf8>> | _] when Name =/= <<""/utf8>> -> + {ok, {Name, Input}}; + + [<<","/utf8>> | _] when Name =/= <<""/utf8>> -> + {error, {unexpected, <<","/utf8>>, <<"="/utf8>>}}; + + [<<"\n"/utf8>> | _] when Name =/= <<""/utf8>> -> + {error, {unexpected, <<"\n"/utf8>>, <<"="/utf8>>}}; + + [<<"\r\n"/utf8>> | _] when Name =/= <<""/utf8>> -> + {error, {unexpected, <<"\r\n"/utf8>>, <<"="/utf8>>}}; + + [<<"\n"/utf8>> | _] -> + {error, {unexpected, <<"\n"/utf8>>, <<"key"/utf8>>}}; + + [<<"\r\n"/utf8>> | _] -> + {error, {unexpected, <<"\r\n"/utf8>>, <<"key"/utf8>>}}; + + [<<"]"/utf8>> | _] -> + {error, {unexpected, <<"]"/utf8>>, <<"key"/utf8>>}}; + + [<<","/utf8>> | _] -> + {error, {unexpected, <<","/utf8>>, <<"key"/utf8>>}}; + + [G | Input@2] -> + parse_key_bare(Input@2, <<Name/binary, G/binary>>); + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"key"/utf8>>}} + end. + +-spec skip_line_whitespace(list(binary())) -> list(binary()). +skip_line_whitespace(Input) -> + gleam@list:drop_while( + Input, + fun(G) -> (G =:= <<" "/utf8>>) orelse (G =:= <<"\t"/utf8>>) end + ). + +-spec parse_key_segment(list(binary())) -> {ok, {binary(), list(binary())}} | + {error, parse_error()}. +parse_key_segment(Input) -> + Input@1 = skip_line_whitespace(Input), + case Input@1 of + [<<"="/utf8>> | _] -> + {error, {unexpected, <<"="/utf8>>, <<"Key"/utf8>>}}; + + [<<"\n"/utf8>> | _] -> + {error, {unexpected, <<"\n"/utf8>>, <<"Key"/utf8>>}}; + + [<<"\r\n"/utf8>> | _] -> + {error, {unexpected, <<"\r\n"/utf8>>, <<"Key"/utf8>>}}; + + [<<"["/utf8>> | _] -> + {error, {unexpected, <<"["/utf8>>, <<"Key"/utf8>>}}; + + [<<"\""/utf8>> | Input@2] -> + parse_key_quoted(Input@2, <<"\""/utf8>>, <<""/utf8>>); + + [<<"'"/utf8>> | Input@3] -> + parse_key_quoted(Input@3, <<"'"/utf8>>, <<""/utf8>>); + + _ -> + parse_key_bare(Input@1, <<""/utf8>>) + end. + +-spec skip_whitespace(list(binary())) -> list(binary()). +skip_whitespace(Input) -> + case Input of + [<<" "/utf8>> | Input@1] -> + skip_whitespace(Input@1); + + [<<"\t"/utf8>> | Input@2] -> + skip_whitespace(Input@2); + + [<<"\n"/utf8>> | Input@3] -> + skip_whitespace(Input@3); + + [<<"\r\n"/utf8>> | Input@4] -> + skip_whitespace(Input@4); + + Input@5 -> + Input@5 + end. + +-spec drop_comments(list(binary()), list(binary())) -> list(binary()). +drop_comments(Input, Acc) -> + case Input of + [<<"#"/utf8>> | Input@1] -> + _pipe = Input@1, + _pipe@1 = gleam@list:drop_while( + _pipe, + fun(G) -> G /= <<"\n"/utf8>> end + ), + drop_comments(_pipe@1, Acc); + + [G@1 | Input@2] -> + drop_comments(Input@2, [G@1 | Acc]); + + [] -> + gleam@list:reverse(Acc) + end. + +-spec do( + {ok, {FLK, list(binary())}} | {error, parse_error()}, + fun((FLK, list(binary())) -> {ok, FLN} | {error, parse_error()}) +) -> {ok, FLN} | {error, parse_error()}. +do(Result, Next) -> + case Result of + {ok, {A, Input}} -> + Next(A, Input); + + {error, E} -> + {error, E} + end. + +-spec parse_key(list(binary()), list(binary())) -> {ok, + {list(binary()), list(binary())}} | + {error, parse_error()}. +parse_key(Input, Segments) -> + do( + parse_key_segment(Input), + fun(Segment, Input@1) -> + Segments@1 = [Segment | Segments], + Input@2 = skip_line_whitespace(Input@1), + case Input@2 of + [<<"."/utf8>> | Input@3] -> + parse_key(Input@3, Segments@1); + + _ -> + {ok, {gleam@list:reverse(Segments@1), Input@2}} + end + end + ). + +-spec expect( + list(binary()), + binary(), + fun((list(binary())) -> {ok, {FLS, list(binary())}} | {error, parse_error()}) +) -> {ok, {FLS, list(binary())}} | {error, parse_error()}. +expect(Input, Expected, Next) -> + case Input of + [G | Input@1] when G =:= Expected -> + Next(Input@1); + + [G@1 | _] -> + {error, {unexpected, G@1, Expected}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, Expected}} + end. + +-spec parse_table_header(list(binary())) -> {ok, + {list(binary()), list(binary())}} | + {error, parse_error()}. +parse_table_header(Input) -> + Input@1 = skip_line_whitespace(Input), + do( + parse_key(Input@1, []), + fun(Key, Input@2) -> + expect( + Input@2, + <<"]"/utf8>>, + fun(Input@3) -> + Input@4 = skip_line_whitespace(Input@3), + expect_end_of_line( + Input@4, + fun(Input@5) -> {ok, {Key, Input@5}} end + ) + end + ) + end + ). + +-spec parse_hex(list(binary()), integer(), sign()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_hex(Input, Number, Sign) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_hex(Input@1, Number, Sign); + + [<<"0"/utf8>> | Input@2] -> + parse_hex(Input@2, (Number * 16) + 0, Sign); + + [<<"1"/utf8>> | Input@3] -> + parse_hex(Input@3, (Number * 16) + 1, Sign); + + [<<"2"/utf8>> | Input@4] -> + parse_hex(Input@4, (Number * 16) + 2, Sign); + + [<<"3"/utf8>> | Input@5] -> + parse_hex(Input@5, (Number * 16) + 3, Sign); + + [<<"4"/utf8>> | Input@6] -> + parse_hex(Input@6, (Number * 16) + 4, Sign); + + [<<"5"/utf8>> | Input@7] -> + parse_hex(Input@7, (Number * 16) + 5, Sign); + + [<<"6"/utf8>> | Input@8] -> + parse_hex(Input@8, (Number * 16) + 6, Sign); + + [<<"7"/utf8>> | Input@9] -> + parse_hex(Input@9, (Number * 16) + 7, Sign); + + [<<"8"/utf8>> | Input@10] -> + parse_hex(Input@10, (Number * 16) + 8, Sign); + + [<<"9"/utf8>> | Input@11] -> + parse_hex(Input@11, (Number * 16) + 9, Sign); + + [<<"a"/utf8>> | Input@12] -> + parse_hex(Input@12, (Number * 16) + 10, Sign); + + [<<"b"/utf8>> | Input@13] -> + parse_hex(Input@13, (Number * 16) + 11, Sign); + + [<<"c"/utf8>> | Input@14] -> + parse_hex(Input@14, (Number * 16) + 12, Sign); + + [<<"d"/utf8>> | Input@15] -> + parse_hex(Input@15, (Number * 16) + 13, Sign); + + [<<"e"/utf8>> | Input@16] -> + parse_hex(Input@16, (Number * 16) + 14, Sign); + + [<<"f"/utf8>> | Input@17] -> + parse_hex(Input@17, (Number * 16) + 15, Sign); + + [<<"A"/utf8>> | Input@18] -> + parse_hex(Input@18, (Number * 16) + 10, Sign); + + [<<"B"/utf8>> | Input@19] -> + parse_hex(Input@19, (Number * 16) + 11, Sign); + + [<<"C"/utf8>> | Input@20] -> + parse_hex(Input@20, (Number * 16) + 12, Sign); + + [<<"D"/utf8>> | Input@21] -> + parse_hex(Input@21, (Number * 16) + 13, Sign); + + [<<"E"/utf8>> | Input@22] -> + parse_hex(Input@22, (Number * 16) + 14, Sign); + + [<<"F"/utf8>> | Input@23] -> + parse_hex(Input@23, (Number * 16) + 15, Sign); + + Input@24 -> + Number@1 = case Sign of + positive -> + Number; + + negative -> + - Number + end, + {ok, {{int, Number@1}, Input@24}} + end. + +-spec parse_octal(list(binary()), integer(), sign()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_octal(Input, Number, Sign) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_octal(Input@1, Number, Sign); + + [<<"0"/utf8>> | Input@2] -> + parse_octal(Input@2, (Number * 8) + 0, Sign); + + [<<"1"/utf8>> | Input@3] -> + parse_octal(Input@3, (Number * 8) + 1, Sign); + + [<<"2"/utf8>> | Input@4] -> + parse_octal(Input@4, (Number * 8) + 2, Sign); + + [<<"3"/utf8>> | Input@5] -> + parse_octal(Input@5, (Number * 8) + 3, Sign); + + [<<"4"/utf8>> | Input@6] -> + parse_octal(Input@6, (Number * 8) + 4, Sign); + + [<<"5"/utf8>> | Input@7] -> + parse_octal(Input@7, (Number * 8) + 5, Sign); + + [<<"6"/utf8>> | Input@8] -> + parse_octal(Input@8, (Number * 8) + 6, Sign); + + [<<"7"/utf8>> | Input@9] -> + parse_octal(Input@9, (Number * 8) + 7, Sign); + + Input@10 -> + Number@1 = case Sign of + positive -> + Number; + + negative -> + - Number + end, + {ok, {{int, Number@1}, Input@10}} + end. + +-spec parse_binary(list(binary()), integer(), sign()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_binary(Input, Number, Sign) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_binary(Input@1, Number, Sign); + + [<<"0"/utf8>> | Input@2] -> + parse_binary(Input@2, (Number * 2) + 0, Sign); + + [<<"1"/utf8>> | Input@3] -> + parse_binary(Input@3, (Number * 2) + 1, Sign); + + Input@4 -> + Number@1 = case Sign of + positive -> + Number; + + negative -> + - Number + end, + {ok, {{int, Number@1}, Input@4}} + end. + +-spec parse_exponent(list(binary()), float(), sign(), integer(), sign()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_exponent(Input, N, N_sign, Ex, Ex_sign) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_exponent(Input@1, N, N_sign, Ex, Ex_sign); + + [<<"0"/utf8>> | Input@2] -> + parse_exponent(Input@2, N, N_sign, Ex * 10, Ex_sign); + + [<<"1"/utf8>> | Input@3] -> + parse_exponent(Input@3, N, N_sign, (Ex * 10) + 1, Ex_sign); + + [<<"2"/utf8>> | Input@4] -> + parse_exponent(Input@4, N, N_sign, (Ex * 10) + 2, Ex_sign); + + [<<"3"/utf8>> | Input@5] -> + parse_exponent(Input@5, N, N_sign, (Ex * 10) + 3, Ex_sign); + + [<<"4"/utf8>> | Input@6] -> + parse_exponent(Input@6, N, N_sign, (Ex * 10) + 4, Ex_sign); + + [<<"5"/utf8>> | Input@7] -> + parse_exponent(Input@7, N, N_sign, (Ex * 10) + 5, Ex_sign); + + [<<"6"/utf8>> | Input@8] -> + parse_exponent(Input@8, N, N_sign, (Ex * 10) + 6, Ex_sign); + + [<<"7"/utf8>> | Input@9] -> + parse_exponent(Input@9, N, N_sign, (Ex * 10) + 7, Ex_sign); + + [<<"8"/utf8>> | Input@10] -> + parse_exponent(Input@10, N, N_sign, (Ex * 10) + 8, Ex_sign); + + [<<"9"/utf8>> | Input@11] -> + parse_exponent(Input@11, N, N_sign, (Ex * 10) + 9, Ex_sign); + + Input@12 -> + Number = case N_sign of + positive -> + N; + + negative -> + N * -1.0 + end, + Exponent = gleam@int:to_float(case Ex_sign of + positive -> + Ex; + + negative -> + - Ex + end), + Multiplier@1 = case gleam@float:power(10.0, Exponent) of + {ok, Multiplier} -> + Multiplier; + + {error, _} -> + 1.0 + end, + {ok, {{float, Number * Multiplier@1}, Input@12}} + end. + +-spec parse_float(list(binary()), float(), sign(), float()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_float(Input, Number, Sign, Unit) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_float(Input@1, Number, Sign, Unit); + + [<<"0"/utf8>> | Input@2] -> + parse_float(Input@2, Number, Sign, Unit * 0.1); + + [<<"1"/utf8>> | Input@3] -> + parse_float(Input@3, Number + (1.0 * Unit), Sign, Unit * 0.1); + + [<<"2"/utf8>> | Input@4] -> + parse_float(Input@4, Number + (2.0 * Unit), Sign, Unit * 0.1); + + [<<"3"/utf8>> | Input@5] -> + parse_float(Input@5, Number + (3.0 * Unit), Sign, Unit * 0.1); + + [<<"4"/utf8>> | Input@6] -> + parse_float(Input@6, Number + (4.0 * Unit), Sign, Unit * 0.1); + + [<<"5"/utf8>> | Input@7] -> + parse_float(Input@7, Number + (5.0 * Unit), Sign, Unit * 0.1); + + [<<"6"/utf8>> | Input@8] -> + parse_float(Input@8, Number + (6.0 * Unit), Sign, Unit * 0.1); + + [<<"7"/utf8>> | Input@9] -> + parse_float(Input@9, Number + (7.0 * Unit), Sign, Unit * 0.1); + + [<<"8"/utf8>> | Input@10] -> + parse_float(Input@10, Number + (8.0 * Unit), Sign, Unit * 0.1); + + [<<"9"/utf8>> | Input@11] -> + parse_float(Input@11, Number + (9.0 * Unit), Sign, Unit * 0.1); + + [<<"e"/utf8>>, <<"+"/utf8>> | Input@12] -> + parse_exponent(Input@12, Number, Sign, 0, positive); + + [<<"e"/utf8>>, <<"-"/utf8>> | Input@13] -> + parse_exponent(Input@13, Number, Sign, 0, negative); + + [<<"e"/utf8>> | Input@14] -> + parse_exponent(Input@14, Number, Sign, 0, positive); + + [<<"E"/utf8>>, <<"+"/utf8>> | Input@15] -> + parse_exponent(Input@15, Number, Sign, 0, positive); + + [<<"E"/utf8>>, <<"-"/utf8>> | Input@16] -> + parse_exponent(Input@16, Number, Sign, 0, negative); + + [<<"E"/utf8>> | Input@17] -> + parse_exponent(Input@17, Number, Sign, 0, positive); + + Input@18 -> + Number@1 = case Sign of + positive -> + Number; + + negative -> + Number * -1.0 + end, + {ok, {{float, Number@1}, Input@18}} + end. + +-spec parse_string(list(binary()), binary()) -> {ok, {toml(), list(binary())}} | + {error, parse_error()}. +parse_string(Input, String) -> + case Input of + [<<"\""/utf8>> | Input@1] -> + {ok, {{string, String}, Input@1}}; + + [<<"\\"/utf8>>, <<"t"/utf8>> | Input@2] -> + parse_string(Input@2, <<String/binary, "\t"/utf8>>); + + [<<"\\"/utf8>>, <<"n"/utf8>> | Input@3] -> + parse_string(Input@3, <<String/binary, "\n"/utf8>>); + + [<<"\\"/utf8>>, <<"r"/utf8>> | Input@4] -> + parse_string(Input@4, <<String/binary, "\r"/utf8>>); + + [<<"\\"/utf8>>, <<"\""/utf8>> | Input@5] -> + parse_string(Input@5, <<String/binary, "\""/utf8>>); + + [<<"\\"/utf8>>, <<"\\"/utf8>> | Input@6] -> + parse_string(Input@6, <<String/binary, "\\"/utf8>>); + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"\""/utf8>>}}; + + [<<"\n"/utf8>> | _] -> + {error, {unexpected, <<"\n"/utf8>>, <<"\""/utf8>>}}; + + [<<"\r\n"/utf8>> | _] -> + {error, {unexpected, <<"\r\n"/utf8>>, <<"\""/utf8>>}}; + + [G | Input@7] -> + parse_string(Input@7, <<String/binary, G/binary>>) + end. + +-spec parse_multi_line_string(list(binary()), binary()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_multi_line_string(Input, String) -> + case Input of + [<<"\""/utf8>>, <<"\""/utf8>>, <<"\""/utf8>> | Input@1] -> + {ok, {{string, String}, Input@1}}; + + [<<"\\"/utf8>>, <<"\n"/utf8>> | Input@2] -> + parse_multi_line_string(skip_whitespace(Input@2), String); + + [<<"\\"/utf8>>, <<"\r\n"/utf8>> | Input@3] -> + parse_multi_line_string(skip_whitespace(Input@3), String); + + [<<"\r\n"/utf8>> | Input@4] when String =:= <<""/utf8>> -> + parse_multi_line_string(Input@4, String); + + [<<"\n"/utf8>> | Input@5] when String =:= <<""/utf8>> -> + parse_multi_line_string(Input@5, String); + + [<<"\r\n"/utf8>> | Input@6] when String =:= <<""/utf8>> -> + parse_multi_line_string(Input@6, String); + + [<<"\\"/utf8>>, <<"t"/utf8>> | Input@7] -> + parse_multi_line_string(Input@7, <<String/binary, "\t"/utf8>>); + + [<<"\\"/utf8>>, <<"n"/utf8>> | Input@8] -> + parse_multi_line_string(Input@8, <<String/binary, "\n"/utf8>>); + + [<<"\\"/utf8>>, <<"r"/utf8>> | Input@9] -> + parse_multi_line_string(Input@9, <<String/binary, "\r"/utf8>>); + + [<<"\\"/utf8>>, <<"\""/utf8>> | Input@10] -> + parse_multi_line_string(Input@10, <<String/binary, "\""/utf8>>); + + [<<"\\"/utf8>>, <<"\\"/utf8>> | Input@11] -> + parse_multi_line_string(Input@11, <<String/binary, "\\"/utf8>>); + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"\""/utf8>>}}; + + [G | Input@12] -> + parse_multi_line_string(Input@12, <<String/binary, G/binary>>) + end. + +-spec parse_multi_line_literal_string(list(binary()), binary()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_multi_line_literal_string(Input, String) -> + case Input of + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"\""/utf8>>}}; + + [<<"'"/utf8>>, <<"'"/utf8>>, <<"'"/utf8>>, <<"'"/utf8>> | _] -> + {error, {unexpected, <<"''''"/utf8>>, <<"'''"/utf8>>}}; + + [<<"'"/utf8>>, <<"'"/utf8>>, <<"'"/utf8>> | Input@1] -> + {ok, {{string, String}, Input@1}}; + + [<<"\n"/utf8>> | Input@2] when String =:= <<""/utf8>> -> + parse_multi_line_literal_string(Input@2, String); + + [<<"\r\n"/utf8>> | Input@3] when String =:= <<""/utf8>> -> + parse_multi_line_literal_string(Input@3, String); + + [G | Input@4] -> + parse_multi_line_literal_string( + Input@4, + <<String/binary, G/binary>> + ) + end. + +-spec parse_literal_string(list(binary()), binary()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_literal_string(Input, String) -> + case Input of + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"\""/utf8>>}}; + + [<<"\n"/utf8>> | _] -> + {error, {unexpected, <<"\n"/utf8>>, <<"'"/utf8>>}}; + + [<<"\r\n"/utf8>> | _] -> + {error, {unexpected, <<"\r\n"/utf8>>, <<"'"/utf8>>}}; + + [<<"'"/utf8>> | Input@1] -> + {ok, {{string, String}, Input@1}}; + + [G | Input@2] -> + parse_literal_string(Input@2, <<String/binary, G/binary>>) + end. + +-spec parse_time_ms(list(binary()), integer(), integer()) -> {ok, + {{integer(), integer()}, list(binary())}} | + {error, parse_error()}. +parse_time_ms(Input, Seconds, Ms) -> + case Input of + [<<"0"/utf8>> | Input@1] when Ms < 100000 -> + parse_time_ms(Input@1, Seconds, (Ms * 10) + 0); + + [<<"1"/utf8>> | Input@2] when Ms < 100000 -> + parse_time_ms(Input@2, Seconds, (Ms * 10) + 1); + + [<<"2"/utf8>> | Input@3] when Ms < 100000 -> + parse_time_ms(Input@3, Seconds, (Ms * 10) + 2); + + [<<"3"/utf8>> | Input@4] when Ms < 100000 -> + parse_time_ms(Input@4, Seconds, (Ms * 10) + 3); + + [<<"4"/utf8>> | Input@5] when Ms < 100000 -> + parse_time_ms(Input@5, Seconds, (Ms * 10) + 4); + + [<<"5"/utf8>> | Input@6] when Ms < 100000 -> + parse_time_ms(Input@6, Seconds, (Ms * 10) + 5); + + [<<"6"/utf8>> | Input@7] when Ms < 100000 -> + parse_time_ms(Input@7, Seconds, (Ms * 10) + 6); + + [<<"7"/utf8>> | Input@8] when Ms < 100000 -> + parse_time_ms(Input@8, Seconds, (Ms * 10) + 7); + + [<<"8"/utf8>> | Input@9] when Ms < 100000 -> + parse_time_ms(Input@9, Seconds, (Ms * 10) + 8); + + [<<"9"/utf8>> | Input@10] when Ms < 100000 -> + parse_time_ms(Input@10, Seconds, (Ms * 10) + 9); + + _ -> + {ok, {{Seconds, Ms}, Input}} + end. + +-spec parse_number_under_60(list(binary()), binary()) -> {ok, + {integer(), list(binary())}} | + {error, parse_error()}. +parse_number_under_60(Input, Expected) -> + case Input of + [<<"0"/utf8>>, <<"0"/utf8>> | Input@1] -> + {ok, {0, Input@1}}; + + [<<"0"/utf8>>, <<"1"/utf8>> | Input@2] -> + {ok, {1, Input@2}}; + + [<<"0"/utf8>>, <<"2"/utf8>> | Input@3] -> + {ok, {2, Input@3}}; + + [<<"0"/utf8>>, <<"3"/utf8>> | Input@4] -> + {ok, {3, Input@4}}; + + [<<"0"/utf8>>, <<"4"/utf8>> | Input@5] -> + {ok, {4, Input@5}}; + + [<<"0"/utf8>>, <<"5"/utf8>> | Input@6] -> + {ok, {5, Input@6}}; + + [<<"0"/utf8>>, <<"6"/utf8>> | Input@7] -> + {ok, {6, Input@7}}; + + [<<"0"/utf8>>, <<"7"/utf8>> | Input@8] -> + {ok, {7, Input@8}}; + + [<<"0"/utf8>>, <<"8"/utf8>> | Input@9] -> + {ok, {8, Input@9}}; + + [<<"0"/utf8>>, <<"9"/utf8>> | Input@10] -> + {ok, {9, Input@10}}; + + [<<"1"/utf8>>, <<"0"/utf8>> | Input@11] -> + {ok, {10, Input@11}}; + + [<<"1"/utf8>>, <<"1"/utf8>> | Input@12] -> + {ok, {11, Input@12}}; + + [<<"1"/utf8>>, <<"2"/utf8>> | Input@13] -> + {ok, {12, Input@13}}; + + [<<"1"/utf8>>, <<"3"/utf8>> | Input@14] -> + {ok, {13, Input@14}}; + + [<<"1"/utf8>>, <<"4"/utf8>> | Input@15] -> + {ok, {14, Input@15}}; + + [<<"1"/utf8>>, <<"5"/utf8>> | Input@16] -> + {ok, {15, Input@16}}; + + [<<"1"/utf8>>, <<"6"/utf8>> | Input@17] -> + {ok, {16, Input@17}}; + + [<<"1"/utf8>>, <<"7"/utf8>> | Input@18] -> + {ok, {17, Input@18}}; + + [<<"1"/utf8>>, <<"8"/utf8>> | Input@19] -> + {ok, {18, Input@19}}; + + [<<"1"/utf8>>, <<"9"/utf8>> | Input@20] -> + {ok, {19, Input@20}}; + + [<<"2"/utf8>>, <<"0"/utf8>> | Input@21] -> + {ok, {20, Input@21}}; + + [<<"2"/utf8>>, <<"1"/utf8>> | Input@22] -> + {ok, {21, Input@22}}; + + [<<"2"/utf8>>, <<"2"/utf8>> | Input@23] -> + {ok, {22, Input@23}}; + + [<<"2"/utf8>>, <<"3"/utf8>> | Input@24] -> + {ok, {23, Input@24}}; + + [<<"2"/utf8>>, <<"4"/utf8>> | Input@25] -> + {ok, {24, Input@25}}; + + [<<"2"/utf8>>, <<"5"/utf8>> | Input@26] -> + {ok, {25, Input@26}}; + + [<<"2"/utf8>>, <<"6"/utf8>> | Input@27] -> + {ok, {26, Input@27}}; + + [<<"2"/utf8>>, <<"7"/utf8>> | Input@28] -> + {ok, {27, Input@28}}; + + [<<"2"/utf8>>, <<"8"/utf8>> | Input@29] -> + {ok, {28, Input@29}}; + + [<<"2"/utf8>>, <<"9"/utf8>> | Input@30] -> + {ok, {29, Input@30}}; + + [<<"3"/utf8>>, <<"0"/utf8>> | Input@31] -> + {ok, {30, Input@31}}; + + [<<"3"/utf8>>, <<"1"/utf8>> | Input@32] -> + {ok, {31, Input@32}}; + + [<<"3"/utf8>>, <<"2"/utf8>> | Input@33] -> + {ok, {32, Input@33}}; + + [<<"3"/utf8>>, <<"3"/utf8>> | Input@34] -> + {ok, {33, Input@34}}; + + [<<"3"/utf8>>, <<"4"/utf8>> | Input@35] -> + {ok, {34, Input@35}}; + + [<<"3"/utf8>>, <<"5"/utf8>> | Input@36] -> + {ok, {35, Input@36}}; + + [<<"3"/utf8>>, <<"6"/utf8>> | Input@37] -> + {ok, {36, Input@37}}; + + [<<"3"/utf8>>, <<"7"/utf8>> | Input@38] -> + {ok, {37, Input@38}}; + + [<<"3"/utf8>>, <<"8"/utf8>> | Input@39] -> + {ok, {38, Input@39}}; + + [<<"3"/utf8>>, <<"9"/utf8>> | Input@40] -> + {ok, {39, Input@40}}; + + [<<"4"/utf8>>, <<"0"/utf8>> | Input@41] -> + {ok, {40, Input@41}}; + + [<<"4"/utf8>>, <<"1"/utf8>> | Input@42] -> + {ok, {41, Input@42}}; + + [<<"4"/utf8>>, <<"2"/utf8>> | Input@43] -> + {ok, {42, Input@43}}; + + [<<"4"/utf8>>, <<"3"/utf8>> | Input@44] -> + {ok, {43, Input@44}}; + + [<<"4"/utf8>>, <<"4"/utf8>> | Input@45] -> + {ok, {44, Input@45}}; + + [<<"4"/utf8>>, <<"5"/utf8>> | Input@46] -> + {ok, {45, Input@46}}; + + [<<"4"/utf8>>, <<"6"/utf8>> | Input@47] -> + {ok, {46, Input@47}}; + + [<<"4"/utf8>>, <<"7"/utf8>> | Input@48] -> + {ok, {47, Input@48}}; + + [<<"4"/utf8>>, <<"8"/utf8>> | Input@49] -> + {ok, {48, Input@49}}; + + [<<"4"/utf8>>, <<"9"/utf8>> | Input@50] -> + {ok, {49, Input@50}}; + + [<<"5"/utf8>>, <<"0"/utf8>> | Input@51] -> + {ok, {50, Input@51}}; + + [<<"5"/utf8>>, <<"1"/utf8>> | Input@52] -> + {ok, {51, Input@52}}; + + [<<"5"/utf8>>, <<"2"/utf8>> | Input@53] -> + {ok, {52, Input@53}}; + + [<<"5"/utf8>>, <<"3"/utf8>> | Input@54] -> + {ok, {53, Input@54}}; + + [<<"5"/utf8>>, <<"4"/utf8>> | Input@55] -> + {ok, {54, Input@55}}; + + [<<"5"/utf8>>, <<"5"/utf8>> | Input@56] -> + {ok, {55, Input@56}}; + + [<<"5"/utf8>>, <<"6"/utf8>> | Input@57] -> + {ok, {56, Input@57}}; + + [<<"5"/utf8>>, <<"7"/utf8>> | Input@58] -> + {ok, {57, Input@58}}; + + [<<"5"/utf8>>, <<"8"/utf8>> | Input@59] -> + {ok, {58, Input@59}}; + + [<<"5"/utf8>>, <<"9"/utf8>> | Input@60] -> + {ok, {59, Input@60}}; + + [G | _] -> + {error, {unexpected, G, Expected}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, Expected}} + end. + +-spec parse_hour_minute(list(binary())) -> {ok, + {{integer(), integer()}, list(binary())}} | + {error, parse_error()}. +parse_hour_minute(Input) -> + do(case Input of + [<<"0"/utf8>>, <<"0"/utf8>>, <<":"/utf8>> | Input@1] -> + {ok, {0, Input@1}}; + + [<<"0"/utf8>>, <<"1"/utf8>>, <<":"/utf8>> | Input@2] -> + {ok, {1, Input@2}}; + + [<<"0"/utf8>>, <<"2"/utf8>>, <<":"/utf8>> | Input@3] -> + {ok, {2, Input@3}}; + + [<<"0"/utf8>>, <<"3"/utf8>>, <<":"/utf8>> | Input@4] -> + {ok, {3, Input@4}}; + + [<<"0"/utf8>>, <<"4"/utf8>>, <<":"/utf8>> | Input@5] -> + {ok, {4, Input@5}}; + + [<<"0"/utf8>>, <<"5"/utf8>>, <<":"/utf8>> | Input@6] -> + {ok, {5, Input@6}}; + + [<<"0"/utf8>>, <<"6"/utf8>>, <<":"/utf8>> | Input@7] -> + {ok, {6, Input@7}}; + + [<<"0"/utf8>>, <<"7"/utf8>>, <<":"/utf8>> | Input@8] -> + {ok, {7, Input@8}}; + + [<<"0"/utf8>>, <<"8"/utf8>>, <<":"/utf8>> | Input@9] -> + {ok, {8, Input@9}}; + + [<<"0"/utf8>>, <<"9"/utf8>>, <<":"/utf8>> | Input@10] -> + {ok, {9, Input@10}}; + + [<<"1"/utf8>>, <<"0"/utf8>>, <<":"/utf8>> | Input@11] -> + {ok, {10, Input@11}}; + + [<<"1"/utf8>>, <<"1"/utf8>>, <<":"/utf8>> | Input@12] -> + {ok, {11, Input@12}}; + + [<<"1"/utf8>>, <<"2"/utf8>>, <<":"/utf8>> | Input@13] -> + {ok, {12, Input@13}}; + + [<<"1"/utf8>>, <<"3"/utf8>>, <<":"/utf8>> | Input@14] -> + {ok, {13, Input@14}}; + + [<<"1"/utf8>>, <<"4"/utf8>>, <<":"/utf8>> | Input@15] -> + {ok, {14, Input@15}}; + + [<<"1"/utf8>>, <<"5"/utf8>>, <<":"/utf8>> | Input@16] -> + {ok, {15, Input@16}}; + + [<<"1"/utf8>>, <<"6"/utf8>>, <<":"/utf8>> | Input@17] -> + {ok, {16, Input@17}}; + + [<<"1"/utf8>>, <<"7"/utf8>>, <<":"/utf8>> | Input@18] -> + {ok, {17, Input@18}}; + + [<<"1"/utf8>>, <<"8"/utf8>>, <<":"/utf8>> | Input@19] -> + {ok, {18, Input@19}}; + + [<<"1"/utf8>>, <<"9"/utf8>>, <<":"/utf8>> | Input@20] -> + {ok, {19, Input@20}}; + + [<<"2"/utf8>>, <<"0"/utf8>>, <<":"/utf8>> | Input@21] -> + {ok, {20, Input@21}}; + + [<<"2"/utf8>>, <<"1"/utf8>>, <<":"/utf8>> | Input@22] -> + {ok, {21, Input@22}}; + + [<<"2"/utf8>>, <<"2"/utf8>>, <<":"/utf8>> | Input@23] -> + {ok, {22, Input@23}}; + + [<<"2"/utf8>>, <<"3"/utf8>>, <<":"/utf8>> | Input@24] -> + {ok, {23, Input@24}}; + + [G | _] -> + {error, {unexpected, G, <<"time"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"time"/utf8>>}} + end, fun(Hours, Input@25) -> + do( + parse_number_under_60(Input@25, <<"minutes"/utf8>>), + fun(Minutes, Input@26) -> {ok, {{Hours, Minutes}, Input@26}} end + ) + end). + +-spec parse_time_s_ms(list(binary())) -> {ok, + {{integer(), integer()}, list(binary())}} | + {error, parse_error()}. +parse_time_s_ms(Input) -> + case Input of + [<<":"/utf8>> | Input@1] -> + do( + parse_number_under_60(Input@1, <<"seconds"/utf8>>), + fun(Seconds, Input@2) -> case Input@2 of + [<<"."/utf8>> | Input@3] -> + parse_time_ms(Input@3, Seconds, 0); + + _ -> + {ok, {{Seconds, 0}, Input@2}} + end end + ); + + _ -> + {ok, {{0, 0}, Input}} + end. + +-spec parse_time_minute(list(binary()), integer()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_time_minute(Input, Hours) -> + do( + parse_number_under_60(Input, <<"minutes"/utf8>>), + fun(Minutes, Input@1) -> + do( + parse_time_s_ms(Input@1), + fun(_use0, Input@2) -> + {Seconds, Ms} = _use0, + Time = {time_value, Hours, Minutes, Seconds, Ms}, + {ok, {{time, Time}, Input@2}} + end + ) + end + ). + +-spec parse_time_value(list(binary())) -> {ok, {time(), list(binary())}} | + {error, parse_error()}. +parse_time_value(Input) -> + do( + parse_hour_minute(Input), + fun(_use0, Input@1) -> + {Hours, Minutes} = _use0, + do( + parse_time_s_ms(Input@1), + fun(_use0@1, Input@2) -> + {Seconds, Ms} = _use0@1, + Time = {time_value, Hours, Minutes, Seconds, Ms}, + {ok, {Time, Input@2}} + end + ) + end + ). + +-spec parse_offset_hours(list(binary()), sign()) -> {ok, + {offset(), list(binary())}} | + {error, parse_error()}. +parse_offset_hours(Input, Sign) -> + do( + parse_hour_minute(Input), + fun(_use0, Input@1) -> + {Hours, Minutes} = _use0, + {ok, {{offset, Sign, Hours, Minutes}, Input@1}} + end + ). + +-spec parse_offset(list(binary())) -> {ok, {offset(), list(binary())}} | + {error, parse_error()}. +parse_offset(Input) -> + case Input of + [<<"Z"/utf8>> | Input@1] -> + {ok, {{offset, positive, 0, 0}, Input@1}}; + + [<<"+"/utf8>> | Input@2] -> + parse_offset_hours(Input@2, positive); + + [<<"-"/utf8>> | Input@3] -> + parse_offset_hours(Input@3, negative); + + _ -> + {ok, {local, Input}} + end. + +-spec parse_date_end(list(binary()), integer(), integer(), integer()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_date_end(Input, Year, Month, Day) -> + Date = {date_value, Year, Month, Day}, + case Input of + [<<" "/utf8>> | Input@1] -> + do( + parse_time_value(Input@1), + fun(Time, Input@2) -> + do( + parse_offset(Input@2), + fun(Offset, Input@3) -> + {ok, + {{date_time, + {date_time_value, Date, Time, Offset}}, + Input@3}} + end + ) + end + ); + + [<<"T"/utf8>> | Input@1] -> + do( + parse_time_value(Input@1), + fun(Time, Input@2) -> + do( + parse_offset(Input@2), + fun(Offset, Input@3) -> + {ok, + {{date_time, + {date_time_value, Date, Time, Offset}}, + Input@3}} + end + ) + end + ); + + _ -> + {ok, {{date, Date}, Input}} + end. + +-spec parse_date_day(list(binary()), integer(), integer()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_date_day(Input, Year, Month) -> + case Input of + [<<"0"/utf8>>, <<"1"/utf8>> | Input@1] -> + parse_date_end(Input@1, Year, Month, 1); + + [<<"0"/utf8>>, <<"2"/utf8>> | Input@2] -> + parse_date_end(Input@2, Year, Month, 2); + + [<<"0"/utf8>>, <<"3"/utf8>> | Input@3] -> + parse_date_end(Input@3, Year, Month, 3); + + [<<"0"/utf8>>, <<"4"/utf8>> | Input@4] -> + parse_date_end(Input@4, Year, Month, 4); + + [<<"0"/utf8>>, <<"5"/utf8>> | Input@5] -> + parse_date_end(Input@5, Year, Month, 5); + + [<<"0"/utf8>>, <<"6"/utf8>> | Input@6] -> + parse_date_end(Input@6, Year, Month, 6); + + [<<"0"/utf8>>, <<"7"/utf8>> | Input@7] -> + parse_date_end(Input@7, Year, Month, 7); + + [<<"0"/utf8>>, <<"8"/utf8>> | Input@8] -> + parse_date_end(Input@8, Year, Month, 8); + + [<<"0"/utf8>>, <<"9"/utf8>> | Input@9] -> + parse_date_end(Input@9, Year, Month, 9); + + [<<"1"/utf8>>, <<"0"/utf8>> | Input@10] -> + parse_date_end(Input@10, Year, Month, 10); + + [<<"1"/utf8>>, <<"1"/utf8>> | Input@11] -> + parse_date_end(Input@11, Year, Month, 11); + + [<<"1"/utf8>>, <<"2"/utf8>> | Input@12] -> + parse_date_end(Input@12, Year, Month, 12); + + [<<"1"/utf8>>, <<"3"/utf8>> | Input@13] -> + parse_date_end(Input@13, Year, Month, 13); + + [<<"1"/utf8>>, <<"4"/utf8>> | Input@14] -> + parse_date_end(Input@14, Year, Month, 14); + + [<<"1"/utf8>>, <<"5"/utf8>> | Input@15] -> + parse_date_end(Input@15, Year, Month, 15); + + [<<"1"/utf8>>, <<"6"/utf8>> | Input@16] -> + parse_date_end(Input@16, Year, Month, 16); + + [<<"1"/utf8>>, <<"7"/utf8>> | Input@17] -> + parse_date_end(Input@17, Year, Month, 17); + + [<<"1"/utf8>>, <<"8"/utf8>> | Input@18] -> + parse_date_end(Input@18, Year, Month, 18); + + [<<"1"/utf8>>, <<"9"/utf8>> | Input@19] -> + parse_date_end(Input@19, Year, Month, 19); + + [<<"2"/utf8>>, <<"0"/utf8>> | Input@20] -> + parse_date_end(Input@20, Year, Month, 20); + + [<<"2"/utf8>>, <<"1"/utf8>> | Input@21] -> + parse_date_end(Input@21, Year, Month, 21); + + [<<"2"/utf8>>, <<"2"/utf8>> | Input@22] -> + parse_date_end(Input@22, Year, Month, 22); + + [<<"2"/utf8>>, <<"3"/utf8>> | Input@23] -> + parse_date_end(Input@23, Year, Month, 23); + + [<<"2"/utf8>>, <<"4"/utf8>> | Input@24] -> + parse_date_end(Input@24, Year, Month, 24); + + [<<"2"/utf8>>, <<"5"/utf8>> | Input@25] -> + parse_date_end(Input@25, Year, Month, 25); + + [<<"2"/utf8>>, <<"6"/utf8>> | Input@26] -> + parse_date_end(Input@26, Year, Month, 26); + + [<<"2"/utf8>>, <<"7"/utf8>> | Input@27] -> + parse_date_end(Input@27, Year, Month, 27); + + [<<"2"/utf8>>, <<"8"/utf8>> | Input@28] -> + parse_date_end(Input@28, Year, Month, 28); + + [<<"2"/utf8>>, <<"9"/utf8>> | Input@29] -> + parse_date_end(Input@29, Year, Month, 29); + + [<<"3"/utf8>>, <<"0"/utf8>> | Input@30] -> + parse_date_end(Input@30, Year, Month, 30); + + [<<"3"/utf8>>, <<"1"/utf8>> | Input@31] -> + parse_date_end(Input@31, Year, Month, 31); + + [G | _] -> + {error, {unexpected, G, <<"date day"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"date day"/utf8>>}} + end. + +-spec parse_date(list(binary()), integer()) -> {ok, {toml(), list(binary())}} | + {error, parse_error()}. +parse_date(Input, Year) -> + case Input of + [<<"0"/utf8>>, <<"1"/utf8>>, <<"-"/utf8>> | Input@1] -> + parse_date_day(Input@1, Year, 1); + + [<<"0"/utf8>>, <<"2"/utf8>>, <<"-"/utf8>> | Input@2] -> + parse_date_day(Input@2, Year, 2); + + [<<"0"/utf8>>, <<"3"/utf8>>, <<"-"/utf8>> | Input@3] -> + parse_date_day(Input@3, Year, 3); + + [<<"0"/utf8>>, <<"4"/utf8>>, <<"-"/utf8>> | Input@4] -> + parse_date_day(Input@4, Year, 4); + + [<<"0"/utf8>>, <<"5"/utf8>>, <<"-"/utf8>> | Input@5] -> + parse_date_day(Input@5, Year, 5); + + [<<"0"/utf8>>, <<"6"/utf8>>, <<"-"/utf8>> | Input@6] -> + parse_date_day(Input@6, Year, 6); + + [<<"0"/utf8>>, <<"7"/utf8>>, <<"-"/utf8>> | Input@7] -> + parse_date_day(Input@7, Year, 7); + + [<<"0"/utf8>>, <<"8"/utf8>>, <<"-"/utf8>> | Input@8] -> + parse_date_day(Input@8, Year, 8); + + [<<"0"/utf8>>, <<"9"/utf8>>, <<"-"/utf8>> | Input@9] -> + parse_date_day(Input@9, Year, 9); + + [<<"1"/utf8>>, <<"0"/utf8>>, <<"-"/utf8>> | Input@10] -> + parse_date_day(Input@10, Year, 10); + + [<<"1"/utf8>>, <<"1"/utf8>>, <<"-"/utf8>> | Input@11] -> + parse_date_day(Input@11, Year, 11); + + [<<"1"/utf8>>, <<"2"/utf8>>, <<"-"/utf8>> | Input@12] -> + parse_date_day(Input@12, Year, 12); + + [G | _] -> + {error, {unexpected, G, <<"date month"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"date month"/utf8>>}} + end. + +-spec parse_number(list(binary()), integer(), sign()) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_number(Input, Number, Sign) -> + case Input of + [<<"_"/utf8>> | Input@1] -> + parse_number(Input@1, Number, Sign); + + [<<"0"/utf8>> | Input@2] -> + parse_number(Input@2, (Number * 10) + 0, Sign); + + [<<"1"/utf8>> | Input@3] -> + parse_number(Input@3, (Number * 10) + 1, Sign); + + [<<"2"/utf8>> | Input@4] -> + parse_number(Input@4, (Number * 10) + 2, Sign); + + [<<"3"/utf8>> | Input@5] -> + parse_number(Input@5, (Number * 10) + 3, Sign); + + [<<"4"/utf8>> | Input@6] -> + parse_number(Input@6, (Number * 10) + 4, Sign); + + [<<"5"/utf8>> | Input@7] -> + parse_number(Input@7, (Number * 10) + 5, Sign); + + [<<"6"/utf8>> | Input@8] -> + parse_number(Input@8, (Number * 10) + 6, Sign); + + [<<"7"/utf8>> | Input@9] -> + parse_number(Input@9, (Number * 10) + 7, Sign); + + [<<"8"/utf8>> | Input@10] -> + parse_number(Input@10, (Number * 10) + 8, Sign); + + [<<"9"/utf8>> | Input@11] -> + parse_number(Input@11, (Number * 10) + 9, Sign); + + [<<"-"/utf8>> | Input@12] -> + parse_date(Input@12, Number); + + [<<":"/utf8>> | Input@13] when Number < 24 -> + parse_time_minute(Input@13, Number); + + [<<"."/utf8>> | Input@14] -> + parse_float(Input@14, gleam@int:to_float(Number), Sign, 0.1); + + [<<"e"/utf8>>, <<"+"/utf8>> | Input@15] -> + parse_exponent( + Input@15, + gleam@int:to_float(Number), + Sign, + 0, + positive + ); + + [<<"e"/utf8>>, <<"-"/utf8>> | Input@16] -> + parse_exponent( + Input@16, + gleam@int:to_float(Number), + Sign, + 0, + negative + ); + + [<<"e"/utf8>> | Input@17] -> + parse_exponent( + Input@17, + gleam@int:to_float(Number), + Sign, + 0, + positive + ); + + [<<"E"/utf8>>, <<"+"/utf8>> | Input@18] -> + parse_exponent( + Input@18, + gleam@int:to_float(Number), + Sign, + 0, + positive + ); + + [<<"E"/utf8>>, <<"-"/utf8>> | Input@19] -> + parse_exponent( + Input@19, + gleam@int:to_float(Number), + Sign, + 0, + negative + ); + + [<<"E"/utf8>> | Input@20] -> + parse_exponent( + Input@20, + gleam@int:to_float(Number), + Sign, + 0, + positive + ); + + Input@21 -> + Number@1 = case Sign of + positive -> + Number; + + negative -> + - Number + end, + {ok, {{int, Number@1}, Input@21}} + end. + +-spec reverse_arrays_of_tables(toml()) -> toml(). +reverse_arrays_of_tables(Toml) -> + case Toml of + {array_of_tables, Tables} -> + {array_of_tables, reverse_arrays_of_tables_array(Tables, [])}; + + {table, Table} -> + {table, reverse_arrays_of_tables_table(Table)}; + + _ -> + Toml + end. + +-spec reverse_arrays_of_tables_table(gleam@map:map_(binary(), toml())) -> gleam@map:map_(binary(), toml()). +reverse_arrays_of_tables_table(Table) -> + gleam@map:map_values(Table, fun(_, V) -> reverse_arrays_of_tables(V) end). + +-spec reverse_arrays_of_tables_array( + list(gleam@map:map_(binary(), toml())), + list(gleam@map:map_(binary(), toml())) +) -> list(gleam@map:map_(binary(), toml())). +reverse_arrays_of_tables_array(Array, Acc) -> + case Array of + [] -> + Acc; + + [First | Rest] -> + First@1 = reverse_arrays_of_tables_table(First), + reverse_arrays_of_tables_array(Rest, [First@1 | Acc]) + end. + +-spec parse_inline_table_property( + list(binary()), + gleam@map:map_(binary(), toml()) +) -> {ok, {gleam@map:map_(binary(), toml()), list(binary())}} | + {error, parse_error()}. +parse_inline_table_property(Input, Properties) -> + Input@1 = skip_whitespace(Input), + do( + parse_key(Input@1, []), + fun(Key, Input@2) -> + Input@3 = skip_line_whitespace(Input@2), + expect( + Input@3, + <<"="/utf8>>, + fun(Input@4) -> + Input@5 = skip_line_whitespace(Input@4), + do( + parse_value(Input@5), + fun(Value, Input@6) -> + case insert(Properties, Key, Value) of + {ok, Properties@1} -> + {ok, {Properties@1, Input@6}}; + + {error, E} -> + {error, E} + end + end + ) + end + ) + end + ). + +-spec parse_value(list(binary())) -> {ok, {toml(), list(binary())}} | + {error, parse_error()}. +parse_value(Input) -> + case Input of + [<<"t"/utf8>>, <<"r"/utf8>>, <<"u"/utf8>>, <<"e"/utf8>> | Input@1] -> + {ok, {{bool, true}, Input@1}}; + + [<<"f"/utf8>>, + <<"a"/utf8>>, + <<"l"/utf8>>, + <<"s"/utf8>>, + <<"e"/utf8>> | + Input@2] -> + {ok, {{bool, false}, Input@2}}; + + [<<"n"/utf8>>, <<"a"/utf8>>, <<"n"/utf8>> | Input@3] -> + {ok, {{nan, positive}, Input@3}}; + + [<<"+"/utf8>>, <<"n"/utf8>>, <<"a"/utf8>>, <<"n"/utf8>> | Input@4] -> + {ok, {{nan, positive}, Input@4}}; + + [<<"-"/utf8>>, <<"n"/utf8>>, <<"a"/utf8>>, <<"n"/utf8>> | Input@5] -> + {ok, {{nan, negative}, Input@5}}; + + [<<"i"/utf8>>, <<"n"/utf8>>, <<"f"/utf8>> | Input@6] -> + {ok, {{infinity, positive}, Input@6}}; + + [<<"+"/utf8>>, <<"i"/utf8>>, <<"n"/utf8>>, <<"f"/utf8>> | Input@7] -> + {ok, {{infinity, positive}, Input@7}}; + + [<<"-"/utf8>>, <<"i"/utf8>>, <<"n"/utf8>>, <<"f"/utf8>> | Input@8] -> + {ok, {{infinity, negative}, Input@8}}; + + [<<"["/utf8>> | Input@9] -> + parse_array(Input@9, []); + + [<<"{"/utf8>> | Input@10] -> + parse_inline_table(Input@10, gleam@map:new()); + + [<<"0"/utf8>>, <<"x"/utf8>> | Input@11] -> + parse_hex(Input@11, 0, positive); + + [<<"+"/utf8>>, <<"0"/utf8>>, <<"x"/utf8>> | Input@12] -> + parse_hex(Input@12, 0, positive); + + [<<"-"/utf8>>, <<"0"/utf8>>, <<"x"/utf8>> | Input@13] -> + parse_hex(Input@13, 0, negative); + + [<<"0"/utf8>>, <<"o"/utf8>> | Input@14] -> + parse_octal(Input@14, 0, positive); + + [<<"+"/utf8>>, <<"0"/utf8>>, <<"o"/utf8>> | Input@15] -> + parse_octal(Input@15, 0, positive); + + [<<"-"/utf8>>, <<"0"/utf8>>, <<"o"/utf8>> | Input@16] -> + parse_octal(Input@16, 0, negative); + + [<<"0"/utf8>>, <<"b"/utf8>> | Input@17] -> + parse_binary(Input@17, 0, positive); + + [<<"+"/utf8>>, <<"0"/utf8>>, <<"b"/utf8>> | Input@18] -> + parse_binary(Input@18, 0, positive); + + [<<"-"/utf8>>, <<"0"/utf8>>, <<"b"/utf8>> | Input@19] -> + parse_binary(Input@19, 0, negative); + + [<<"+"/utf8>> | Input@20] -> + parse_number(Input@20, 0, positive); + + [<<"-"/utf8>> | Input@21] -> + parse_number(Input@21, 0, negative); + + [<<"0"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"1"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"2"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"3"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"4"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"5"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"6"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"7"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"8"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"9"/utf8>> | _] -> + parse_number(Input, 0, positive); + + [<<"\""/utf8>>, <<"\""/utf8>>, <<"\""/utf8>> | Input@22] -> + parse_multi_line_string(Input@22, <<""/utf8>>); + + [<<"\""/utf8>> | Input@23] -> + parse_string(Input@23, <<""/utf8>>); + + [<<"'"/utf8>>, <<"'"/utf8>>, <<"'"/utf8>> | Input@24] -> + parse_multi_line_literal_string(Input@24, <<""/utf8>>); + + [<<"'"/utf8>> | Input@25] -> + parse_literal_string(Input@25, <<""/utf8>>); + + [G | _] -> + {error, {unexpected, G, <<"value"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"value"/utf8>>}} + end. + +-spec parse_inline_table(list(binary()), gleam@map:map_(binary(), toml())) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_inline_table(Input, Properties) -> + Input@1 = skip_whitespace(Input), + case Input@1 of + [<<"}"/utf8>> | Input@2] -> + {ok, {{inline_table, Properties}, Input@2}}; + + _ -> + case parse_inline_table_property(Input@1, Properties) of + {ok, {Properties@1, Input@3}} -> + Input@4 = skip_whitespace(Input@3), + case Input@4 of + [<<"}"/utf8>> | Input@5] -> + {ok, {{inline_table, Properties@1}, Input@5}}; + + [<<","/utf8>> | Input@6] -> + Input@7 = skip_whitespace(Input@6), + parse_inline_table(Input@7, Properties@1); + + [G | _] -> + {error, {unexpected, G, <<"}"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"}"/utf8>>}} + end; + + {error, E} -> + {error, E} + end + end. + +-spec parse_key_value(list(binary()), gleam@map:map_(binary(), toml())) -> {ok, + {gleam@map:map_(binary(), toml()), list(binary())}} | + {error, parse_error()}. +parse_key_value(Input, Toml) -> + do( + parse_key(Input, []), + fun(Key, Input@1) -> + Input@2 = skip_line_whitespace(Input@1), + expect( + Input@2, + <<"="/utf8>>, + fun(Input@3) -> + Input@4 = skip_line_whitespace(Input@3), + do( + parse_value(Input@4), + fun(Value, Input@5) -> case insert(Toml, Key, Value) of + {ok, Toml@1} -> + {ok, {Toml@1, Input@5}}; + + {error, E} -> + {error, E} + end end + ) + end + ) + end + ). + +-spec parse_table(list(binary()), gleam@map:map_(binary(), toml())) -> {ok, + {gleam@map:map_(binary(), toml()), list(binary())}} | + {error, parse_error()}. +parse_table(Input, Toml) -> + Input@1 = skip_whitespace(Input), + case Input@1 of + [<<"["/utf8>> | _] -> + {ok, {Toml, Input@1}}; + + [] -> + {ok, {Toml, Input@1}}; + + _ -> + case parse_key_value(Input@1, Toml) of + {ok, {Toml@1, Input@2}} -> + case skip_line_whitespace(Input@2) of + [] -> + {ok, {Toml@1, []}}; + + [<<"\n"/utf8>> | In] -> + parse_table(In, Toml@1); + + [<<"\r\n"/utf8>> | In] -> + parse_table(In, Toml@1); + + [G | _] -> + {error, {unexpected, G, <<"\n"/utf8>>}} + end; + + E -> + E + end + end. + +-spec parse_array_of_tables(list(binary())) -> {ok, + {{list(binary()), gleam@map:map_(binary(), toml())}, list(binary())}} | + {error, parse_error()}. +parse_array_of_tables(Input) -> + Input@1 = skip_line_whitespace(Input), + do( + parse_key(Input@1, []), + fun(Key, Input@2) -> + expect( + Input@2, + <<"]"/utf8>>, + fun(Input@3) -> + expect( + Input@3, + <<"]"/utf8>>, + fun(Input@4) -> + do( + parse_table(Input@4, gleam@map:new()), + fun(Table, Input@5) -> + {ok, {{Key, Table}, Input@5}} + end + ) + end + ) + end + ) + end + ). + +-spec parse_table_and_header(list(binary())) -> {ok, + {{list(binary()), gleam@map:map_(binary(), toml())}, list(binary())}} | + {error, parse_error()}. +parse_table_and_header(Input) -> + do( + parse_table_header(Input), + fun(Key, Input@1) -> + do( + parse_table(Input@1, gleam@map:new()), + fun(Table, Input@2) -> {ok, {{Key, Table}, Input@2}} end + ) + end + ). + +-spec parse_tables(list(binary()), gleam@map:map_(binary(), toml())) -> {ok, + gleam@map:map_(binary(), toml())} | + {error, parse_error()}. +parse_tables(Input, Toml) -> + case Input of + [<<"["/utf8>>, <<"["/utf8>> | Input@1] -> + case parse_array_of_tables(Input@1) of + {error, E} -> + {error, E}; + + {ok, {{Key, Table}, Input@2}} -> + case insert(Toml, Key, {array_of_tables, [Table]}) of + {ok, Toml@1} -> + parse_tables(Input@2, Toml@1); + + {error, E@1} -> + {error, E@1} + end + end; + + [<<"["/utf8>> | Input@3] -> + case parse_table_and_header(Input@3) of + {error, E@2} -> + {error, E@2}; + + {ok, {{Key@1, Table@1}, Input@4}} -> + case insert(Toml, Key@1, {table, Table@1}) of + {ok, Toml@2} -> + parse_tables(Input@4, Toml@2); + + {error, E@3} -> + {error, E@3} + end + end; + + [G | _] -> + {error, {unexpected, G, <<"["/utf8>>}}; + + [] -> + {ok, Toml} + end. + +-spec parse(binary()) -> {ok, gleam@map:map_(binary(), toml())} | + {error, parse_error()}. +parse(Input) -> + Input@1 = gleam@string:to_graphemes(Input), + Input@2 = drop_comments(Input@1, []), + Input@3 = skip_whitespace(Input@2), + do( + parse_table(Input@3, gleam@map:new()), + fun(Toml, Input@4) -> case parse_tables(Input@4, Toml) of + {ok, Toml@1} -> + {ok, reverse_arrays_of_tables_table(Toml@1)}; + + {error, E} -> + {error, E} + end end + ). + +-spec parse_array(list(binary()), list(toml())) -> {ok, + {toml(), list(binary())}} | + {error, parse_error()}. +parse_array(Input, Elements) -> + Input@1 = skip_whitespace(Input), + case Input@1 of + [<<"]"/utf8>> | Input@2] -> + {ok, {{array, gleam@list:reverse(Elements)}, Input@2}}; + + _ -> + do( + parse_value(Input@1), + fun(Element, Input@3) -> + Elements@1 = [Element | Elements], + Input@4 = skip_whitespace(Input@3), + case Input@4 of + [<<"]"/utf8>> | Input@5] -> + {ok, + {{array, gleam@list:reverse(Elements@1)}, + Input@5}}; + + [<<","/utf8>> | Input@6] -> + Input@7 = skip_whitespace(Input@6), + parse_array(Input@7, Elements@1); + + [G | _] -> + {error, {unexpected, G, <<"]"/utf8>>}}; + + [] -> + {error, {unexpected, <<"EOF"/utf8>>, <<"]"/utf8>>}} + end + end + ) + end. diff --git a/aoc2023/build/packages/tom/src/tom.gleam b/aoc2023/build/packages/tom/src/tom.gleam new file mode 100644 index 0000000..e19ce3e --- /dev/null +++ b/aoc2023/build/packages/tom/src/tom.gleam @@ -0,0 +1,1317 @@ +//// A pure Gleam TOML parser! +//// +//// ```gleam +//// import tom +//// +//// const config = " +//// [person] +//// name = \"Lucy\" +//// is_cool = true +//// " +//// +//// pub fn main() { +//// // Parse a string of TOML +//// let assert Ok(parsed) = tom.parse(config) +//// +//// // Now you can work with the data directly, or you can use the `get_*` +//// // functions to retrieve values. +//// +//// tom.get_string(parsed, ["person", "name"]) +//// // -> Ok("Lucy") +//// +//// let is_cool = tom.get_bool(parsed, ["person", "is_cool"]) +//// // -> Ok(True) +//// } +//// ``` + +import gleam/int +import gleam/list +import gleam/float +import gleam/string +import gleam/result +import gleam/map.{type Map} + +/// A TOML document. +pub type Toml { + Int(Int) + Float(Float) + /// Infinity is a valid number in TOML but Gleam does not support it, so this + /// variant represents the infinity values. + Infinity(Sign) + /// NaN is a valid number in TOML but Gleam does not support it, so this + /// variant represents the NaN values. + Nan(Sign) + Bool(Bool) + String(String) + Date(Date) + Time(Time) + DateTime(DateTime) + Array(List(Toml)) + ArrayOfTables(List(Map(String, Toml))) + Table(Map(String, Toml)) + InlineTable(Map(String, Toml)) +} + +pub type DateTime { + DateTimeValue(date: Date, time: Time, offset: Offset) +} + +pub type Date { + DateValue(year: Int, month: Int, day: Int) +} + +pub type Time { + TimeValue(hour: Int, minute: Int, second: Int, millisecond: Int) +} + +pub type Offset { + Local + Offset(direction: Sign, hours: Int, minutes: Int) +} + +pub type Sign { + Positive + Negative +} + +/// An error that can occur when parsing a TOML document. +pub type ParseError { + /// An unexpected character was encountered when parsing the document. + Unexpected(got: String, expected: String) + /// More than one items have the same key in the document. + KeyAlreadyInUse(key: List(String)) +} + +type Tokens = + List(String) + +type Parsed(a) = + Result(#(a, Tokens), ParseError) + +/// A number of any kind, returned by the `get_number` function. +pub type Number { + NumberInt(Int) + NumberFloat(Float) + NumberInfinity(Sign) + NumberNan(Sign) +} + +/// An error that can occur when retrieving a value from a TOML document with +/// one of the `get_*` functions. +pub type GetError { + /// There was no value at the given key. + NotFound(key: List(String)) + /// The value at the given key was not of the expected type. + WrongType(key: List(String), expected: String, got: String) +} + +// TODO: test +/// Get a value of any type from a TOML document. +/// +/// ## Examples +/// +/// ```gleam +/// let assert Ok(parsed) = parse("a.b.c = 1") +/// get(parsed, ["a", "b", "c"]) +/// // -> Ok(Int(1)) +/// ``` +/// +pub fn get(toml: Map(String, Toml), key: List(String)) -> Result(Toml, GetError) { + case key { + [] -> Error(NotFound([])) + [k] -> result.replace_error(map.get(toml, k), NotFound([k])) + [k, ..key] -> { + case map.get(toml, k) { + Ok(Table(t)) -> push_key(get(t, key), k) + Ok(other) -> Error(WrongType([k], "Table", classify(other))) + Error(_) -> Error(NotFound([k])) + } + } + } +} + +// TODO: test +/// Get an int from a TOML document. +/// +/// ## Examples +/// +/// ```gleam +/// let assert Ok(parsed) = parse("a.b.c = 1") +/// get_int(parsed, ["a", "b", "c"]) +/// // -> Ok(1) +/// ``` +/// +pub fn get_int( + toml: Map(String, Toml), + key: List(String), +) -> Result(Int, GetError) { + case get(toml, key) { + Ok(Int(i)) -> Ok(i) + Ok(other) -> Error(WrongType(key, "Int", classify(other))) + Error(e) -> Error(e) + } +} + +// TODO: test +/// Get a float from a TOML document. +/// +/// ## Examples +/// +/// ```gleam +/// let assert Ok(parsed) = parse("a.b.c = 1.1") +/// get_float(parsed, ["a", "b", "c"]) +/// // -> Ok(1.1) +/// ``` +/// +pub fn get_float( + toml: Map(String, Toml), + key: List(String), +) -> Result(Float, GetError) { + case get(toml, key) { + Ok(Float(i)) -> Ok(i) + Ok(other) -> Error(WrongType(key, "Float", classify(other))) + Error(e) -> Error(e) + } +} + +// TODO: test +/// Get a bool from a TOML document. +/// +/// ## Examples +/// +/// ```gleam +/// let assert Ok(parsed) = parse("a.b.c = true") +/// get_bool(parsed, ["a", "b", "c"]) +/// // -> Ok(True) +/// ``` +/// +pub fn get_bool( + toml: Map(String, Toml), + key: List(String), +) -> Result(Bool, GetError) { + case get(toml, key) { + Ok(Bool(i)) -> Ok(i) + Ok(other) -> Error(WrongType(key, "Bool", classify(other))) + Error(e) -> Error(e) + } +} + +// TODO: test +/// Get a string from a TOML document. +/// +/// ## Examples +/// +/// ```gleam +/// let assert Ok(parsed) = parse("a.b.c = \"ok\"") +/// get_string(parsed, ["a", "b", "c"]) +/// // -> Ok("ok") +/// ``` +/// +pub fn get_string( + toml: Map(String, Toml), + key: List(String), +) -> Result(String, GetError) { + case get(toml, key) { + Ok(String(i)) -> Ok(i) + Ok(other) -> Error(WrongType(key, "String", classify(other))) + Error(e) -> Error(e) + } +} + +// TODO: test +/// Get a date from a TOML document. +/// +/// ## Examples +/// +/// ```gleam +/// let assert Ok(parsed) = parse("a.b.c = 1979-05-27") +/// get_date(parsed, ["a", "b", "c"]) +/// // -> Ok("1979-05-27") +/// ``` +/// +pub fn get_date( + toml: Map(String, Toml), + key: List(String), +) -> Result(Date, GetError) { + case get(toml, key) { + Ok(Date(i)) -> Ok(i) + Ok(other) -> Error(WrongType(key, "Date", classify(other))) + Error(e) -> Error(e) + } +} + +// TODO: test +/// Get a time from a TOML document. +/// +/// ## Examples +/// +/// ```gleam +/// let assert Ok(parsed) = parse("a.b.c = 07:32:00") +/// get_time(parsed, ["a", "b", "c"]) +/// // -> Ok("07:32:00") +/// ``` +/// +pub fn get_time( + toml: Map(String, Toml), + key: List(String), +) -> Result(Time, GetError) { + case get(toml, key) { + Ok(Time(i)) -> Ok(i) + Ok(other) -> Error(WrongType(key, "Time", classify(other))) + Error(e) -> Error(e) + } +} + +// TODO: test +/// Get a date-time from a TOML document. +/// +/// ## Examples +/// +/// ```gleam +/// let assert Ok(parsed) = parse("a.b.c = 1979-05-27T07:32:00") +/// get_date_time(parsed, ["a", "b", "c"]) +/// // -> Ok("1979-05-27T07:32:00") +/// ``` +/// +pub fn get_date_time( + toml: Map(String, Toml), + key: List(String), +) -> Result(DateTime, GetError) { + case get(toml, key) { + Ok(DateTime(i)) -> Ok(i) + Ok(other) -> Error(WrongType(key, "DateTime", classify(other))) + Error(e) -> Error(e) + } +} + +// TODO: test +/// Get an array from a TOML document. +/// +/// ## Examples +/// +/// ```gleam +/// let assert Ok(parsed) = parse("a.b.c = [1, 2]") +/// get_array(parsed, ["a", "b", "c"]) +/// // -> Ok([Int(1), Int(2)]) +/// ``` +/// +pub fn get_array( + toml: Map(String, Toml), + key: List(String), +) -> Result(List(Toml), GetError) { + case get(toml, key) { + Ok(Array(i)) -> Ok(i) + Ok(ArrayOfTables(i)) -> Ok(list.map(i, Table)) + Ok(other) -> Error(WrongType(key, "Array", classify(other))) + Error(e) -> Error(e) + } +} + +// TODO: test +/// Get a table from a TOML document. +/// +/// ## Examples +/// +/// ```gleam +/// let assert Ok(parsed) = parse("a.b.c = { d = 1 }") +/// get_table(parsed, ["a", "b", "c"]) +/// // -> Ok(map.from_list([#("d", Int(1))])) +/// ``` +/// +pub fn get_table( + toml: Map(String, Toml), + key: List(String), +) -> Result(Map(String, Toml), GetError) { + case get(toml, key) { + Ok(Table(i)) -> Ok(i) + Ok(InlineTable(i)) -> Ok(i) + Ok(other) -> Error(WrongType(key, "Table", classify(other))) + Error(e) -> Error(e) + } +} + +// TODO: test +/// Get a number of any kind from a TOML document. +/// This could be an int, a float, a NaN, or an infinity. +/// +/// ## Examples +/// +/// ```gleam +/// let assert Ok(parsed) = parse("a.b.c = { d = inf }") +/// get_number(parsed, ["a", "b", "c"]) +/// // -> Ok(NumberInfinity(Positive))) +/// ``` +/// +pub fn get_number( + toml: Map(String, Toml), + key: List(String), +) -> Result(Number, GetError) { + case get(toml, key) { + Ok(Int(x)) -> Ok(NumberInt(x)) + Ok(Float(x)) -> Ok(NumberFloat(x)) + Ok(Nan(x)) -> Ok(NumberNan(x)) + Ok(Infinity(x)) -> Ok(NumberInfinity(x)) + Ok(other) -> Error(WrongType(key, "Number", classify(other))) + Error(e) -> Error(e) + } +} + +fn classify(toml: Toml) -> String { + case toml { + Int(_) -> "Int" + Float(_) -> "Float" + Nan(Positive) -> "NaN" + Nan(Negative) -> "Negative NaN" + Infinity(Positive) -> "Infinity" + Infinity(Negative) -> "Negative Infinity" + Bool(_) -> "Bool" + String(_) -> "String" + Date(_) -> "Date" + Time(_) -> "Time" + DateTime(_) -> "DateTime" + Array(_) -> "Array" + ArrayOfTables(_) -> "Array" + Table(_) -> "Table" + InlineTable(_) -> "Table" + } +} + +fn push_key(result: Result(t, GetError), key: String) -> Result(t, GetError) { + case result { + Ok(t) -> Ok(t) + Error(NotFound(path)) -> Error(NotFound([key, ..path])) + Error(WrongType(path, expected, got)) -> + Error(WrongType([key, ..path], expected, got)) + } +} + +pub fn parse(input: String) -> Result(Map(String, Toml), ParseError) { + let input = string.to_graphemes(input) + let input = drop_comments(input, []) + let input = skip_whitespace(input) + use toml, input <- do(parse_table(input, map.new())) + case parse_tables(input, toml) { + Ok(toml) -> Ok(reverse_arrays_of_tables_table(toml)) + Error(e) -> Error(e) + } +} + +fn parse_tables( + input: Tokens, + toml: Map(String, Toml), +) -> Result(Map(String, Toml), ParseError) { + case input { + ["[", "[", ..input] -> { + case parse_array_of_tables(input) { + Error(e) -> Error(e) + Ok(#(#(key, table), input)) -> { + case insert(toml, key, ArrayOfTables([table])) { + Ok(toml) -> parse_tables(input, toml) + Error(e) -> Error(e) + } + } + } + } + ["[", ..input] -> { + case parse_table_and_header(input) { + Error(e) -> Error(e) + Ok(#(#(key, table), input)) -> { + case insert(toml, key, Table(table)) { + Ok(toml) -> parse_tables(input, toml) + Error(e) -> Error(e) + } + } + } + } + [g, ..] -> Error(Unexpected(g, "[")) + [] -> Ok(toml) + } +} + +fn parse_array_of_tables( + input: Tokens, +) -> Parsed(#(List(String), Map(String, Toml))) { + let input = skip_line_whitespace(input) + use key, input <- do(parse_key(input, [])) + use input <- expect(input, "]") + use input <- expect(input, "]") + use table, input <- do(parse_table(input, map.new())) + Ok(#(#(key, table), input)) +} + +fn parse_table_header(input: Tokens) -> Parsed(List(String)) { + let input = skip_line_whitespace(input) + use key, input <- do(parse_key(input, [])) + use input <- expect(input, "]") + let input = skip_line_whitespace(input) + use input <- expect_end_of_line(input) + Ok(#(key, input)) +} + +fn parse_table_and_header( + input: Tokens, +) -> Parsed(#(List(String), Map(String, Toml))) { + use key, input <- do(parse_table_header(input)) + use table, input <- do(parse_table(input, map.new())) + Ok(#(#(key, table), input)) +} + +fn parse_table( + input: Tokens, + toml: Map(String, Toml), +) -> Parsed(Map(String, Toml)) { + let input = skip_whitespace(input) + case input { + ["[", ..] | [] -> Ok(#(toml, input)) + _ -> + case parse_key_value(input, toml) { + Ok(#(toml, input)) -> + case skip_line_whitespace(input) { + [] -> Ok(#(toml, [])) + ["\n", ..in] | ["\r\n", ..in] -> parse_table(in, toml) + [g, ..] -> Error(Unexpected(g, "\n")) + } + e -> e + } + } +} + +fn parse_key_value( + input: Tokens, + toml: Map(String, Toml), +) -> Parsed(Map(String, Toml)) { + use key, input <- do(parse_key(input, [])) + let input = skip_line_whitespace(input) + use input <- expect(input, "=") + let input = skip_line_whitespace(input) + use value, input <- do(parse_value(input)) + case insert(toml, key, value) { + Ok(toml) -> Ok(#(toml, input)) + Error(e) -> Error(e) + } +} + +fn insert( + table: Map(String, Toml), + key: List(String), + value: Toml, +) -> Result(Map(String, Toml), ParseError) { + case insert_loop(table, key, value) { + Ok(table) -> Ok(table) + Error(path) -> Error(KeyAlreadyInUse(path)) + } +} + +fn insert_loop( + table: Map(String, Toml), + key: List(String), + value: Toml, +) -> Result(Map(String, Toml), List(String)) { + case key { + [] -> panic as "unreachable" + [k] -> { + case map.get(table, k) { + Error(Nil) -> Ok(map.insert(table, k, value)) + Ok(old) -> merge(table, k, old, value) + } + } + [k, ..key] -> { + case map.get(table, k) { + Error(Nil) -> { + case insert_loop(map.new(), key, value) { + Ok(inner) -> Ok(map.insert(table, k, Table(inner))) + Error(path) -> Error([k, ..path]) + } + } + Ok(ArrayOfTables([inner, ..rest])) -> { + case insert_loop(inner, key, value) { + Ok(inner) -> + Ok(map.insert(table, k, ArrayOfTables([inner, ..rest]))) + Error(path) -> Error([k, ..path]) + } + } + Ok(Table(inner)) -> { + case insert_loop(inner, key, value) { + Ok(inner) -> Ok(map.insert(table, k, Table(inner))) + Error(path) -> Error([k, ..path]) + } + } + Ok(_) -> Error([k]) + } + } + } +} + +fn merge( + table: Map(String, Toml), + key: String, + old: Toml, + new: Toml, +) -> Result(Map(String, Toml), List(String)) { + case old, new { + // When both are arrays of tables then they are merged together + ArrayOfTables(tables), ArrayOfTables(new) -> + Ok(map.insert(table, key, ArrayOfTables(list.append(new, tables)))) + + _, _ -> Error([key]) + } +} + +fn expect_end_of_line(input: Tokens, next: fn(Tokens) -> Parsed(a)) -> Parsed(a) { + case input { + ["\n", ..input] -> next(input) + ["\r\n", ..input] -> next(input) + [g, ..] -> Error(Unexpected(g, "\n")) + [] -> Error(Unexpected("EOF", "\n")) + } +} + +fn parse_value(input) -> Parsed(Toml) { + case input { + ["t", "r", "u", "e", ..input] -> Ok(#(Bool(True), input)) + ["f", "a", "l", "s", "e", ..input] -> Ok(#(Bool(False), input)) + + ["n", "a", "n", ..input] -> Ok(#(Nan(Positive), input)) + ["+", "n", "a", "n", ..input] -> Ok(#(Nan(Positive), input)) + ["-", "n", "a", "n", ..input] -> Ok(#(Nan(Negative), input)) + + ["i", "n", "f", ..input] -> Ok(#(Infinity(Positive), input)) + ["+", "i", "n", "f", ..input] -> Ok(#(Infinity(Positive), input)) + ["-", "i", "n", "f", ..input] -> Ok(#(Infinity(Negative), input)) + + ["[", ..input] -> parse_array(input, []) + ["{", ..input] -> parse_inline_table(input, map.new()) + + ["0", "x", ..input] -> parse_hex(input, 0, Positive) + ["+", "0", "x", ..input] -> parse_hex(input, 0, Positive) + ["-", "0", "x", ..input] -> parse_hex(input, 0, Negative) + + ["0", "o", ..input] -> parse_octal(input, 0, Positive) + ["+", "0", "o", ..input] -> parse_octal(input, 0, Positive) + ["-", "0", "o", ..input] -> parse_octal(input, 0, Negative) + + ["0", "b", ..input] -> parse_binary(input, 0, Positive) + ["+", "0", "b", ..input] -> parse_binary(input, 0, Positive) + ["-", "0", "b", ..input] -> parse_binary(input, 0, Negative) + + ["+", ..input] -> parse_number(input, 0, Positive) + ["-", ..input] -> parse_number(input, 0, Negative) + ["0", ..] + | ["1", ..] + | ["2", ..] + | ["3", ..] + | ["4", ..] + | ["5", ..] + | ["6", ..] + | ["7", ..] + | ["8", ..] + | ["9", ..] -> parse_number(input, 0, Positive) + + ["\"", "\"", "\"", ..input] -> parse_multi_line_string(input, "") + ["\"", ..input] -> parse_string(input, "") + + ["'", "'", "'", ..input] -> parse_multi_line_literal_string(input, "") + ["'", ..input] -> parse_literal_string(input, "") + + [g, ..] -> Error(Unexpected(g, "value")) + [] -> Error(Unexpected("EOF", "value")) + } +} + +fn parse_key(input: Tokens, segments: List(String)) -> Parsed(List(String)) { + use segment, input <- do(parse_key_segment(input)) + let segments = [segment, ..segments] + let input = skip_line_whitespace(input) + + case input { + [".", ..input] -> parse_key(input, segments) + _ -> Ok(#(list.reverse(segments), input)) + } +} + +fn parse_key_segment(input: Tokens) -> Parsed(String) { + let input = skip_line_whitespace(input) + case input { + ["=", ..] -> Error(Unexpected("=", "Key")) + ["\n", ..] -> Error(Unexpected("\n", "Key")) + ["\r\n", ..] -> Error(Unexpected("\r\n", "Key")) + ["[", ..] -> Error(Unexpected("[", "Key")) + ["\"", ..input] -> parse_key_quoted(input, "\"", "") + ["'", ..input] -> parse_key_quoted(input, "'", "") + _ -> parse_key_bare(input, "") + } +} + +fn parse_key_quoted( + input: Tokens, + close: String, + name: String, +) -> Parsed(String) { + case input { + [g, ..input] if g == close -> Ok(#(name, input)) + [g, ..input] -> parse_key_quoted(input, close, name <> g) + [] -> Error(Unexpected("EOF", close)) + } +} + +fn parse_key_bare(input: Tokens, name: String) -> Parsed(String) { + case input { + [" ", ..input] if name != "" -> Ok(#(name, input)) + ["=", ..] if name != "" -> Ok(#(name, input)) + [".", ..] if name != "" -> Ok(#(name, input)) + ["]", ..] if name != "" -> Ok(#(name, input)) + [",", ..] if name != "" -> Error(Unexpected(",", "=")) + ["\n", ..] if name != "" -> Error(Unexpected("\n", "=")) + ["\r\n", ..] if name != "" -> Error(Unexpected("\r\n", "=")) + ["\n", ..] -> Error(Unexpected("\n", "key")) + ["\r\n", ..] -> Error(Unexpected("\r\n", "key")) + ["]", ..] -> Error(Unexpected("]", "key")) + [",", ..] -> Error(Unexpected(",", "key")) + [g, ..input] -> parse_key_bare(input, name <> g) + [] -> Error(Unexpected("EOF", "key")) + } +} + +fn skip_line_whitespace(input: Tokens) -> Tokens { + list.drop_while(input, fn(g) { g == " " || g == "\t" }) +} + +fn skip_whitespace(input: Tokens) -> Tokens { + case input { + [" ", ..input] -> skip_whitespace(input) + ["\t", ..input] -> skip_whitespace(input) + ["\n", ..input] -> skip_whitespace(input) + ["\r\n", ..input] -> skip_whitespace(input) + input -> input + } +} + +fn drop_comments(input: Tokens, acc: Tokens) -> Tokens { + case input { + ["#", ..input] -> + input + |> list.drop_while(fn(g) { g != "\n" }) + |> drop_comments(acc) + [g, ..input] -> drop_comments(input, [g, ..acc]) + [] -> list.reverse(acc) + } +} + +fn do( + result: Result(#(a, Tokens), ParseError), + next: fn(a, Tokens) -> Result(b, ParseError), +) -> Result(b, ParseError) { + case result { + Ok(#(a, input)) -> next(a, input) + Error(e) -> Error(e) + } +} + +fn expect( + input: Tokens, + expected: String, + next: fn(Tokens) -> Parsed(a), +) -> Parsed(a) { + case input { + [g, ..input] if g == expected -> next(input) + [g, ..] -> Error(Unexpected(g, expected)) + [] -> Error(Unexpected("EOF", expected)) + } +} + +fn parse_inline_table( + input: Tokens, + properties: Map(String, Toml), +) -> Parsed(Toml) { + let input = skip_whitespace(input) + case input { + ["}", ..input] -> Ok(#(InlineTable(properties), input)) + _ -> + case parse_inline_table_property(input, properties) { + Ok(#(properties, input)) -> { + let input = skip_whitespace(input) + case input { + ["}", ..input] -> Ok(#(InlineTable(properties), input)) + [",", ..input] -> { + let input = skip_whitespace(input) + parse_inline_table(input, properties) + } + [g, ..] -> Error(Unexpected(g, "}")) + [] -> Error(Unexpected("EOF", "}")) + } + } + Error(e) -> Error(e) + } + } +} + +fn parse_inline_table_property( + input: Tokens, + properties: Map(String, Toml), +) -> Parsed(Map(String, Toml)) { + let input = skip_whitespace(input) + use key, input <- do(parse_key(input, [])) + let input = skip_line_whitespace(input) + use input <- expect(input, "=") + let input = skip_line_whitespace(input) + use value, input <- do(parse_value(input)) + case insert(properties, key, value) { + Ok(properties) -> Ok(#(properties, input)) + Error(e) -> Error(e) + } +} + +fn parse_array(input: Tokens, elements: List(Toml)) -> Parsed(Toml) { + let input = skip_whitespace(input) + case input { + ["]", ..input] -> Ok(#(Array(list.reverse(elements)), input)) + _ -> { + use element, input <- do(parse_value(input)) + let elements = [element, ..elements] + let input = skip_whitespace(input) + case input { + ["]", ..input] -> Ok(#(Array(list.reverse(elements)), input)) + [",", ..input] -> { + let input = skip_whitespace(input) + parse_array(input, elements) + } + [g, ..] -> Error(Unexpected(g, "]")) + [] -> Error(Unexpected("EOF", "]")) + } + } + } +} + +fn parse_hex(input: Tokens, number: Int, sign: Sign) -> Parsed(Toml) { + case input { + ["_", ..input] -> parse_hex(input, number, sign) + ["0", ..input] -> parse_hex(input, number * 16 + 0, sign) + ["1", ..input] -> parse_hex(input, number * 16 + 1, sign) + ["2", ..input] -> parse_hex(input, number * 16 + 2, sign) + ["3", ..input] -> parse_hex(input, number * 16 + 3, sign) + ["4", ..input] -> parse_hex(input, number * 16 + 4, sign) + ["5", ..input] -> parse_hex(input, number * 16 + 5, sign) + ["6", ..input] -> parse_hex(input, number * 16 + 6, sign) + ["7", ..input] -> parse_hex(input, number * 16 + 7, sign) + ["8", ..input] -> parse_hex(input, number * 16 + 8, sign) + ["9", ..input] -> parse_hex(input, number * 16 + 9, sign) + ["a", ..input] -> parse_hex(input, number * 16 + 10, sign) + ["b", ..input] -> parse_hex(input, number * 16 + 11, sign) + ["c", ..input] -> parse_hex(input, number * 16 + 12, sign) + ["d", ..input] -> parse_hex(input, number * 16 + 13, sign) + ["e", ..input] -> parse_hex(input, number * 16 + 14, sign) + ["f", ..input] -> parse_hex(input, number * 16 + 15, sign) + ["A", ..input] -> parse_hex(input, number * 16 + 10, sign) + ["B", ..input] -> parse_hex(input, number * 16 + 11, sign) + ["C", ..input] -> parse_hex(input, number * 16 + 12, sign) + ["D", ..input] -> parse_hex(input, number * 16 + 13, sign) + ["E", ..input] -> parse_hex(input, number * 16 + 14, sign) + ["F", ..input] -> parse_hex(input, number * 16 + 15, sign) + + // Anything else and the number is terminated + input -> { + let number = case sign { + Positive -> number + Negative -> -number + } + Ok(#(Int(number), input)) + } + } +} + +fn parse_octal(input: Tokens, number: Int, sign: Sign) -> Parsed(Toml) { + case input { + ["_", ..input] -> parse_octal(input, number, sign) + ["0", ..input] -> parse_octal(input, number * 8 + 0, sign) + ["1", ..input] -> parse_octal(input, number * 8 + 1, sign) + ["2", ..input] -> parse_octal(input, number * 8 + 2, sign) + ["3", ..input] -> parse_octal(input, number * 8 + 3, sign) + ["4", ..input] -> parse_octal(input, number * 8 + 4, sign) + ["5", ..input] -> parse_octal(input, number * 8 + 5, sign) + ["6", ..input] -> parse_octal(input, number * 8 + 6, sign) + ["7", ..input] -> parse_octal(input, number * 8 + 7, sign) + + // Anything else and the number is terminated + input -> { + let number = case sign { + Positive -> number + Negative -> -number + } + Ok(#(Int(number), input)) + } + } +} + +fn parse_binary(input: Tokens, number: Int, sign: Sign) -> Parsed(Toml) { + case input { + ["_", ..input] -> parse_binary(input, number, sign) + ["0", ..input] -> parse_binary(input, number * 2 + 0, sign) + ["1", ..input] -> parse_binary(input, number * 2 + 1, sign) + + // Anything else and the number is terminated + input -> { + let number = case sign { + Positive -> number + Negative -> -number + } + Ok(#(Int(number), input)) + } + } +} + +fn parse_number(input: Tokens, number: Int, sign: Sign) -> Parsed(Toml) { + case input { + ["_", ..input] -> parse_number(input, number, sign) + ["0", ..input] -> parse_number(input, number * 10 + 0, sign) + ["1", ..input] -> parse_number(input, number * 10 + 1, sign) + ["2", ..input] -> parse_number(input, number * 10 + 2, sign) + ["3", ..input] -> parse_number(input, number * 10 + 3, sign) + ["4", ..input] -> parse_number(input, number * 10 + 4, sign) + ["5", ..input] -> parse_number(input, number * 10 + 5, sign) + ["6", ..input] -> parse_number(input, number * 10 + 6, sign) + ["7", ..input] -> parse_number(input, number * 10 + 7, sign) + ["8", ..input] -> parse_number(input, number * 10 + 8, sign) + ["9", ..input] -> parse_number(input, number * 10 + 9, sign) + + ["-", ..input] -> parse_date(input, number) + [":", ..input] if number < 24 -> parse_time_minute(input, number) + + [".", ..input] -> parse_float(input, int.to_float(number), sign, 0.1) + + ["e", "+", ..input] -> + parse_exponent(input, int.to_float(number), sign, 0, Positive) + ["e", "-", ..input] -> + parse_exponent(input, int.to_float(number), sign, 0, Negative) + ["e", ..input] -> + parse_exponent(input, int.to_float(number), sign, 0, Positive) + ["E", "+", ..input] -> + parse_exponent(input, int.to_float(number), sign, 0, Positive) + ["E", "-", ..input] -> + parse_exponent(input, int.to_float(number), sign, 0, Negative) + ["E", ..input] -> + parse_exponent(input, int.to_float(number), sign, 0, Positive) + + // Anything else and the number is terminated + input -> { + let number = case sign { + Positive -> number + Negative -> -number + } + Ok(#(Int(number), input)) + } + } +} + +fn parse_exponent( + input: Tokens, + n: Float, + n_sign: Sign, + ex: Int, + ex_sign: Sign, +) -> Parsed(Toml) { + case input { + ["_", ..input] -> parse_exponent(input, n, n_sign, ex, ex_sign) + ["0", ..input] -> parse_exponent(input, n, n_sign, ex * 10, ex_sign) + ["1", ..input] -> parse_exponent(input, n, n_sign, ex * 10 + 1, ex_sign) + ["2", ..input] -> parse_exponent(input, n, n_sign, ex * 10 + 2, ex_sign) + ["3", ..input] -> parse_exponent(input, n, n_sign, ex * 10 + 3, ex_sign) + ["4", ..input] -> parse_exponent(input, n, n_sign, ex * 10 + 4, ex_sign) + ["5", ..input] -> parse_exponent(input, n, n_sign, ex * 10 + 5, ex_sign) + ["6", ..input] -> parse_exponent(input, n, n_sign, ex * 10 + 6, ex_sign) + ["7", ..input] -> parse_exponent(input, n, n_sign, ex * 10 + 7, ex_sign) + ["8", ..input] -> parse_exponent(input, n, n_sign, ex * 10 + 8, ex_sign) + ["9", ..input] -> parse_exponent(input, n, n_sign, ex * 10 + 9, ex_sign) + + // Anything else and the number is terminated + input -> { + let number = case n_sign { + Positive -> n + Negative -> n *. -1.0 + } + let exponent = + int.to_float(case ex_sign { + Positive -> ex + Negative -> -ex + }) + let multiplier = case float.power(10.0, exponent) { + Ok(multiplier) -> multiplier + Error(_) -> 1.0 + } + Ok(#(Float(number *. multiplier), input)) + } + } +} + +fn parse_float( + input: Tokens, + number: Float, + sign: Sign, + unit: Float, +) -> Parsed(Toml) { + case input { + ["_", ..input] -> parse_float(input, number, sign, unit) + ["0", ..input] -> parse_float(input, number, sign, unit *. 0.1) + ["1", ..input] -> + parse_float(input, number +. 1.0 *. unit, sign, unit *. 0.1) + ["2", ..input] -> + parse_float(input, number +. 2.0 *. unit, sign, unit *. 0.1) + ["3", ..input] -> + parse_float(input, number +. 3.0 *. unit, sign, unit *. 0.1) + ["4", ..input] -> + parse_float(input, number +. 4.0 *. unit, sign, unit *. 0.1) + ["5", ..input] -> + parse_float(input, number +. 5.0 *. unit, sign, unit *. 0.1) + ["6", ..input] -> + parse_float(input, number +. 6.0 *. unit, sign, unit *. 0.1) + ["7", ..input] -> + parse_float(input, number +. 7.0 *. unit, sign, unit *. 0.1) + ["8", ..input] -> + parse_float(input, number +. 8.0 *. unit, sign, unit *. 0.1) + ["9", ..input] -> + parse_float(input, number +. 9.0 *. unit, sign, unit *. 0.1) + + ["e", "+", ..input] -> parse_exponent(input, number, sign, 0, Positive) + ["e", "-", ..input] -> parse_exponent(input, number, sign, 0, Negative) + ["e", ..input] -> parse_exponent(input, number, sign, 0, Positive) + ["E", "+", ..input] -> parse_exponent(input, number, sign, 0, Positive) + ["E", "-", ..input] -> parse_exponent(input, number, sign, 0, Negative) + ["E", ..input] -> parse_exponent(input, number, sign, 0, Positive) + + // Anything else and the number is terminated + input -> { + let number = case sign { + Positive -> number + Negative -> number *. -1.0 + } + Ok(#(Float(number), input)) + } + } +} + +fn parse_string(input: Tokens, string: String) -> Parsed(Toml) { + case input { + ["\"", ..input] -> Ok(#(String(string), input)) + ["\\", "t", ..input] -> parse_string(input, string <> "\t") + ["\\", "n", ..input] -> parse_string(input, string <> "\n") + ["\\", "r", ..input] -> parse_string(input, string <> "\r") + ["\\", "\"", ..input] -> parse_string(input, string <> "\"") + ["\\", "\\", ..input] -> parse_string(input, string <> "\\") + [] -> Error(Unexpected("EOF", "\"")) + ["\n", ..] -> Error(Unexpected("\n", "\"")) + ["\r\n", ..] -> Error(Unexpected("\r\n", "\"")) + [g, ..input] -> parse_string(input, string <> g) + } +} + +fn parse_multi_line_string(input: Tokens, string: String) -> Parsed(Toml) { + case input { + ["\"", "\"", "\"", ..input] -> Ok(#(String(string), input)) + ["\\", "\n", ..input] -> + parse_multi_line_string(skip_whitespace(input), string) + ["\\", "\r\n", ..input] -> + parse_multi_line_string(skip_whitespace(input), string) + ["\r\n", ..input] if string == "" -> parse_multi_line_string(input, string) + ["\n", ..input] if string == "" -> parse_multi_line_string(input, string) + ["\r\n", ..input] if string == "" -> parse_multi_line_string(input, string) + ["\\", "t", ..input] -> parse_multi_line_string(input, string <> "\t") + ["\\", "n", ..input] -> parse_multi_line_string(input, string <> "\n") + ["\\", "r", ..input] -> parse_multi_line_string(input, string <> "\r") + ["\\", "\"", ..input] -> parse_multi_line_string(input, string <> "\"") + ["\\", "\\", ..input] -> parse_multi_line_string(input, string <> "\\") + [] -> Error(Unexpected("EOF", "\"")) + [g, ..input] -> parse_multi_line_string(input, string <> g) + } +} + +fn parse_multi_line_literal_string( + input: Tokens, + string: String, +) -> Parsed(Toml) { + case input { + [] -> Error(Unexpected("EOF", "\"")) + ["'", "'", "'", "'", ..] -> Error(Unexpected("''''", "'''")) + ["'", "'", "'", ..input] -> Ok(#(String(string), input)) + ["\n", ..input] if string == "" -> + parse_multi_line_literal_string(input, string) + ["\r\n", ..input] if string == "" -> + parse_multi_line_literal_string(input, string) + [g, ..input] -> parse_multi_line_literal_string(input, string <> g) + } +} + +fn parse_literal_string(input: Tokens, string: String) -> Parsed(Toml) { + case input { + [] -> Error(Unexpected("EOF", "\"")) + ["\n", ..] -> Error(Unexpected("\n", "'")) + ["\r\n", ..] -> Error(Unexpected("\r\n", "'")) + ["'", ..input] -> Ok(#(String(string), input)) + [g, ..input] -> parse_literal_string(input, string <> g) + } +} + +fn reverse_arrays_of_tables(toml: Toml) -> Toml { + case toml { + ArrayOfTables(tables) -> + ArrayOfTables(reverse_arrays_of_tables_array(tables, [])) + + Table(table) -> Table(reverse_arrays_of_tables_table(table)) + + _ -> toml + } +} + +fn reverse_arrays_of_tables_table(table: Map(String, Toml)) -> Map(String, Toml) { + map.map_values(table, fn(_, v) { reverse_arrays_of_tables(v) }) +} + +fn reverse_arrays_of_tables_array( + array: List(Map(String, Toml)), + acc: List(Map(String, Toml)), +) -> List(Map(String, Toml)) { + case array { + [] -> acc + [first, ..rest] -> { + let first = reverse_arrays_of_tables_table(first) + reverse_arrays_of_tables_array(rest, [first, ..acc]) + } + } +} + +fn parse_time_minute(input: Tokens, hours: Int) -> Parsed(Toml) { + use minutes, input <- do(parse_number_under_60(input, "minutes")) + use #(seconds, ms), input <- do(parse_time_s_ms(input)) + let time = TimeValue(hours, minutes, seconds, ms) + Ok(#(Time(time), input)) +} + +fn parse_hour_minute(input: Tokens) -> Parsed(#(Int, Int)) { + use hours, input <- do(case input { + ["0", "0", ":", ..input] -> Ok(#(0, input)) + ["0", "1", ":", ..input] -> Ok(#(1, input)) + ["0", "2", ":", ..input] -> Ok(#(2, input)) + ["0", "3", ":", ..input] -> Ok(#(3, input)) + ["0", "4", ":", ..input] -> Ok(#(4, input)) + ["0", "5", ":", ..input] -> Ok(#(5, input)) + ["0", "6", ":", ..input] -> Ok(#(6, input)) + ["0", "7", ":", ..input] -> Ok(#(7, input)) + ["0", "8", ":", ..input] -> Ok(#(8, input)) + ["0", "9", ":", ..input] -> Ok(#(9, input)) + ["1", "0", ":", ..input] -> Ok(#(10, input)) + ["1", "1", ":", ..input] -> Ok(#(11, input)) + ["1", "2", ":", ..input] -> Ok(#(12, input)) + ["1", "3", ":", ..input] -> Ok(#(13, input)) + ["1", "4", ":", ..input] -> Ok(#(14, input)) + ["1", "5", ":", ..input] -> Ok(#(15, input)) + ["1", "6", ":", ..input] -> Ok(#(16, input)) + ["1", "7", ":", ..input] -> Ok(#(17, input)) + ["1", "8", ":", ..input] -> Ok(#(18, input)) + ["1", "9", ":", ..input] -> Ok(#(19, input)) + ["2", "0", ":", ..input] -> Ok(#(20, input)) + ["2", "1", ":", ..input] -> Ok(#(21, input)) + ["2", "2", ":", ..input] -> Ok(#(22, input)) + ["2", "3", ":", ..input] -> Ok(#(23, input)) + [g, ..] -> Error(Unexpected(g, "time")) + [] -> Error(Unexpected("EOF", "time")) + }) + + use minutes, input <- do(parse_number_under_60(input, "minutes")) + Ok(#(#(hours, minutes), input)) +} + +fn parse_time_value(input: Tokens) -> Parsed(Time) { + use #(hours, minutes), input <- do(parse_hour_minute(input)) + use #(seconds, ms), input <- do(parse_time_s_ms(input)) + let time = TimeValue(hours, minutes, seconds, ms) + Ok(#(time, input)) +} + +fn parse_time_s_ms(input: Tokens) -> Parsed(#(Int, Int)) { + case input { + [":", ..input] -> { + use seconds, input <- do(parse_number_under_60(input, "seconds")) + case input { + [".", ..input] -> parse_time_ms(input, seconds, 0) + _ -> Ok(#(#(seconds, 0), input)) + } + } + + _ -> Ok(#(#(0, 0), input)) + } +} + +fn parse_time_ms(input: Tokens, seconds: Int, ms: Int) -> Parsed(#(Int, Int)) { + case input { + ["0", ..input] if ms < 100_000 -> parse_time_ms(input, seconds, ms * 10 + 0) + ["1", ..input] if ms < 100_000 -> parse_time_ms(input, seconds, ms * 10 + 1) + ["2", ..input] if ms < 100_000 -> parse_time_ms(input, seconds, ms * 10 + 2) + ["3", ..input] if ms < 100_000 -> parse_time_ms(input, seconds, ms * 10 + 3) + ["4", ..input] if ms < 100_000 -> parse_time_ms(input, seconds, ms * 10 + 4) + ["5", ..input] if ms < 100_000 -> parse_time_ms(input, seconds, ms * 10 + 5) + ["6", ..input] if ms < 100_000 -> parse_time_ms(input, seconds, ms * 10 + 6) + ["7", ..input] if ms < 100_000 -> parse_time_ms(input, seconds, ms * 10 + 7) + ["8", ..input] if ms < 100_000 -> parse_time_ms(input, seconds, ms * 10 + 8) + ["9", ..input] if ms < 100_000 -> parse_time_ms(input, seconds, ms * 10 + 9) + + // Anything else and the number is terminated + _ -> Ok(#(#(seconds, ms), input)) + } +} + +fn parse_number_under_60(input: Tokens, expected: String) -> Parsed(Int) { + case input { + ["0", "0", ..input] -> Ok(#(0, input)) + ["0", "1", ..input] -> Ok(#(1, input)) + ["0", "2", ..input] -> Ok(#(2, input)) + ["0", "3", ..input] -> Ok(#(3, input)) + ["0", "4", ..input] -> Ok(#(4, input)) + ["0", "5", ..input] -> Ok(#(5, input)) + ["0", "6", ..input] -> Ok(#(6, input)) + ["0", "7", ..input] -> Ok(#(7, input)) + ["0", "8", ..input] -> Ok(#(8, input)) + ["0", "9", ..input] -> Ok(#(9, input)) + ["1", "0", ..input] -> Ok(#(10, input)) + ["1", "1", ..input] -> Ok(#(11, input)) + ["1", "2", ..input] -> Ok(#(12, input)) + ["1", "3", ..input] -> Ok(#(13, input)) + ["1", "4", ..input] -> Ok(#(14, input)) + ["1", "5", ..input] -> Ok(#(15, input)) + ["1", "6", ..input] -> Ok(#(16, input)) + ["1", "7", ..input] -> Ok(#(17, input)) + ["1", "8", ..input] -> Ok(#(18, input)) + ["1", "9", ..input] -> Ok(#(19, input)) + ["2", "0", ..input] -> Ok(#(20, input)) + ["2", "1", ..input] -> Ok(#(21, input)) + ["2", "2", ..input] -> Ok(#(22, input)) + ["2", "3", ..input] -> Ok(#(23, input)) + ["2", "4", ..input] -> Ok(#(24, input)) + ["2", "5", ..input] -> Ok(#(25, input)) + ["2", "6", ..input] -> Ok(#(26, input)) + ["2", "7", ..input] -> Ok(#(27, input)) + ["2", "8", ..input] -> Ok(#(28, input)) + ["2", "9", ..input] -> Ok(#(29, input)) + ["3", "0", ..input] -> Ok(#(30, input)) + ["3", "1", ..input] -> Ok(#(31, input)) + ["3", "2", ..input] -> Ok(#(32, input)) + ["3", "3", ..input] -> Ok(#(33, input)) + ["3", "4", ..input] -> Ok(#(34, input)) + ["3", "5", ..input] -> Ok(#(35, input)) + ["3", "6", ..input] -> Ok(#(36, input)) + ["3", "7", ..input] -> Ok(#(37, input)) + ["3", "8", ..input] -> Ok(#(38, input)) + ["3", "9", ..input] -> Ok(#(39, input)) + ["4", "0", ..input] -> Ok(#(40, input)) + ["4", "1", ..input] -> Ok(#(41, input)) + ["4", "2", ..input] -> Ok(#(42, input)) + ["4", "3", ..input] -> Ok(#(43, input)) + ["4", "4", ..input] -> Ok(#(44, input)) + ["4", "5", ..input] -> Ok(#(45, input)) + ["4", "6", ..input] -> Ok(#(46, input)) + ["4", "7", ..input] -> Ok(#(47, input)) + ["4", "8", ..input] -> Ok(#(48, input)) + ["4", "9", ..input] -> Ok(#(49, input)) + ["5", "0", ..input] -> Ok(#(50, input)) + ["5", "1", ..input] -> Ok(#(51, input)) + ["5", "2", ..input] -> Ok(#(52, input)) + ["5", "3", ..input] -> Ok(#(53, input)) + ["5", "4", ..input] -> Ok(#(54, input)) + ["5", "5", ..input] -> Ok(#(55, input)) + ["5", "6", ..input] -> Ok(#(56, input)) + ["5", "7", ..input] -> Ok(#(57, input)) + ["5", "8", ..input] -> Ok(#(58, input)) + ["5", "9", ..input] -> Ok(#(59, input)) + + [g, ..] -> Error(Unexpected(g, expected)) + [] -> Error(Unexpected("EOF", expected)) + } +} + +fn parse_date(input: Tokens, year: Int) -> Parsed(Toml) { + case input { + ["0", "1", "-", ..input] -> parse_date_day(input, year, 1) + ["0", "2", "-", ..input] -> parse_date_day(input, year, 2) + ["0", "3", "-", ..input] -> parse_date_day(input, year, 3) + ["0", "4", "-", ..input] -> parse_date_day(input, year, 4) + ["0", "5", "-", ..input] -> parse_date_day(input, year, 5) + ["0", "6", "-", ..input] -> parse_date_day(input, year, 6) + ["0", "7", "-", ..input] -> parse_date_day(input, year, 7) + ["0", "8", "-", ..input] -> parse_date_day(input, year, 8) + ["0", "9", "-", ..input] -> parse_date_day(input, year, 9) + ["1", "0", "-", ..input] -> parse_date_day(input, year, 10) + ["1", "1", "-", ..input] -> parse_date_day(input, year, 11) + ["1", "2", "-", ..input] -> parse_date_day(input, year, 12) + + [g, ..] -> Error(Unexpected(g, "date month")) + [] -> Error(Unexpected("EOF", "date month")) + } +} + +fn parse_date_day(input: Tokens, year: Int, month: Int) -> Parsed(Toml) { + case input { + ["0", "1", ..input] -> parse_date_end(input, year, month, 1) + ["0", "2", ..input] -> parse_date_end(input, year, month, 2) + ["0", "3", ..input] -> parse_date_end(input, year, month, 3) + ["0", "4", ..input] -> parse_date_end(input, year, month, 4) + ["0", "5", ..input] -> parse_date_end(input, year, month, 5) + ["0", "6", ..input] -> parse_date_end(input, year, month, 6) + ["0", "7", ..input] -> parse_date_end(input, year, month, 7) + ["0", "8", ..input] -> parse_date_end(input, year, month, 8) + ["0", "9", ..input] -> parse_date_end(input, year, month, 9) + ["1", "0", ..input] -> parse_date_end(input, year, month, 10) + ["1", "1", ..input] -> parse_date_end(input, year, month, 11) + ["1", "2", ..input] -> parse_date_end(input, year, month, 12) + ["1", "3", ..input] -> parse_date_end(input, year, month, 13) + ["1", "4", ..input] -> parse_date_end(input, year, month, 14) + ["1", "5", ..input] -> parse_date_end(input, year, month, 15) + ["1", "6", ..input] -> parse_date_end(input, year, month, 16) + ["1", "7", ..input] -> parse_date_end(input, year, month, 17) + ["1", "8", ..input] -> parse_date_end(input, year, month, 18) + ["1", "9", ..input] -> parse_date_end(input, year, month, 19) + ["2", "0", ..input] -> parse_date_end(input, year, month, 20) + ["2", "1", ..input] -> parse_date_end(input, year, month, 21) + ["2", "2", ..input] -> parse_date_end(input, year, month, 22) + ["2", "3", ..input] -> parse_date_end(input, year, month, 23) + ["2", "4", ..input] -> parse_date_end(input, year, month, 24) + ["2", "5", ..input] -> parse_date_end(input, year, month, 25) + ["2", "6", ..input] -> parse_date_end(input, year, month, 26) + ["2", "7", ..input] -> parse_date_end(input, year, month, 27) + ["2", "8", ..input] -> parse_date_end(input, year, month, 28) + ["2", "9", ..input] -> parse_date_end(input, year, month, 29) + ["3", "0", ..input] -> parse_date_end(input, year, month, 30) + ["3", "1", ..input] -> parse_date_end(input, year, month, 31) + + [g, ..] -> Error(Unexpected(g, "date day")) + [] -> Error(Unexpected("EOF", "date day")) + } +} + +fn parse_date_end( + input: Tokens, + year: Int, + month: Int, + day: Int, +) -> Parsed(Toml) { + let date = DateValue(year, month, day) + case input { + [" ", ..input] | ["T", ..input] -> { + use time, input <- do(parse_time_value(input)) + use offset, input <- do(parse_offset(input)) + Ok(#(DateTime(DateTimeValue(date, time, offset)), input)) + } + + _ -> Ok(#(Date(date), input)) + } +} + +fn parse_offset(input: Tokens) -> Parsed(Offset) { + case input { + ["Z", ..input] -> Ok(#(Offset(Positive, 0, 0), input)) + ["+", ..input] -> parse_offset_hours(input, Positive) + ["-", ..input] -> parse_offset_hours(input, Negative) + _ -> Ok(#(Local, input)) + } +} + +fn parse_offset_hours(input: Tokens, sign: Sign) -> Parsed(Offset) { + use #(hours, minutes), input <- do(parse_hour_minute(input)) + Ok(#(Offset(sign, hours, minutes), input)) +} diff --git a/aoc2023/build/prod/erlang/gleam.lock b/aoc2023/build/prod/erlang/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/prod/erlang/gleam.lock diff --git a/aoc2023/build/prod/javascript/gleam.lock b/aoc2023/build/prod/javascript/gleam.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/aoc2023/build/prod/javascript/gleam.lock diff --git a/aoc2023/src/day1/input.txt b/aoc2023/src/day1/input.txt new file mode 100644 index 0000000..6efe96c --- /dev/null +++ b/aoc2023/src/day1/input.txt @@ -0,0 +1,1000 @@ +9dlvndqbddghpxc +rtkrbtthree8sixfoureight6 +fdxrqmfxdkstpmcj7lmphgsmqqnmjrtwo3tcbc +onetjcsmgk57nvmkvcvkdtqtsksgpchsfsjzkkmb +six8threepvlxttc85two +8five9ttqst2one2vz +hbrmhsnjeight64dgdnvdbspk7ninetzbvjczqrj +fourtwofivesix5 +3gksfourqf48 +7one1tnqxfvhmjvjzfive +sevenmcjs3lmlmxmcgptwobjggfive6four +seven8five3 +5sfknxsn5sevenfour446 +bxc5two67seven2 +jcsfivefive89seven85 +nine296 +seven5twoeight +1eighttwo8jfnhmfivefivezdsxqxqsjkone +foureight48sbkkvc17zbksgvcbb +lnzgspccsn4cxqqdbkj +qlxrxkpeight48xbgqnlkpkoneseven +z7onetwonec +7cns +pnpfninefive79twoone7 +2hrqpjjjbn +4gmlttgdzrhxbxnnine +4sixfiveone76jctmjsxdh5jrkv +3kvjmhpmglrdgmdnine +four63sevensevenone +jmz1eight4threej1 +four21zxksf9jxdvjmtn337 +msnronenine43three1threefrv +rjfhd6eight4 +78blgveightfiveone7bnsfnrmxsmtwonemrb +sixseven6four6 +mdjphcm9 +xsjmgdgqtwolg1nine45eight +five2six85npdqxgrshdjs4 +jbbnine2ttrktc2hxpxfdxgf +fngvqsgmjfmfslrmone2vtpsstpkhr2jmmxk +f683glvfsdvnsghvrzcdmxnx81 +lqblzgj322kqfsjrbxgcgsct +threeldfnrbstbxqdpxpkbztbp84eight +sevensevenmthprqg9six +qldknljthdjthreeklttd6six +7eightcdqxcftbgbfbnvqfive +gxjzhvkbcjhscdxhjdqxnhsevenxrdrjbcl5fvlvlxjjvb +9sixqnine9jk9six +zjtdbzr6njdgflrmpshxn +rktpknvmjknb7threefourhdxhcdtgtkvone +276lzxhone3two2 +82fivelppqzjq +lchslxtwohslsztgps5pdssctclhdkqtwo +2five8three9dnine8 +68jpnqldjgfnpcmvbxnszhz2252 +q32 +2sixtwo87 +hlmdvlrqlrjdshone3five +fivetwo7 +xsdcktrone29 +eightfour9eighttwoxvhdth9lndg4 +two8jgddjhcj67eight +8nrkrcrqhr21stqtvqn +tvbonepzrrklninexmpxrlkcpgg9qgrkcjt +6two5qjmoneclfhzhkxbntmvmdrc +prhmt4xvlg +3mghfgrhzkj5 +lq2lnrcj1pnlh +sixqhfqrmf8fivenkkcqpgf85lone +tlrlcbhdvd5 +three8seven +thfns325threefpvlntfvrf +twoblkldr2mmrsxpqxcms39seven6 +2mpcvttntg31mkznplfkbcgccsix +2sbs +828jnvjnbgrs1 +fhcglnxzss23bxfnpczvthree2 +7fhghprqvrbx1nxml2one32 +5fivethree7qrsixmcdveight6 +five4seven +1cfcfdzfjphsevenmdvnzh +qhmnleightbhbcntwojjfxpvlxt2spponenine +fivelskzvzsix5xtqkfl1 +2jfgpmdncvpjmqcgvnzpqlstzgfdvfxrlscjkzczsf +rzzplmzsfivetxbhcqnzdq4 +mvrvfour9eightseventhree +7smrdqkrh8qlzc +mpf2fivefivefivepgm +1sixpkrdjlszgdnccnllfsevenksdkvqbxbpbblthqpzqf +six91dxxdhrxcbmqpqm +sevenfour8nine7 +one2hnfvh +55jmqkqgvsgqcrzvmzqhone8twopsrtgmqrj +xnfjxqlrsjmgk68kvpptczxhkxcvrpgctddjklrmhzjgtcjh +seveng6two +1threexrzqcrknhc3 +58qtpqqz58888cmhs +pxvbhmczrvpnjnsrcdrnrjvzzpjnbgbxdseven6 +34two565 +four4six +sqtxsjsix54 +four3xrxmrkn4nrcsmljqrninethreeone +3six4bqddfivejnfrhnqqsgqhj +gtbtrtzp8seveneight3seven4xzdnfrvzgn +vggfdfvlrgvqqvjhkmxfsfbdpqfivexs16 +onegkvdhrfninerndk46nine +5fiveeighthnrlzln +threeqctjkpxjx39six89two2 +99ninecbzck +nxqlhpgnine6pvrrpfjpssix6seven +1dbrzjkckthm5sixsix +fivefmfqcsj19nhnzg +five91eightninecn +7ljnl71eight7mzhzfht +84sevenzrqvkxszdhg66 +jskktpm5mphd1 +boneightfournq6ndnqpdbm97five +5twonine +scqpkxrjtwo8foureight11 +3eight7brgqfivezpgclhfj +zkfrsdgbmczlrzchvfql78ftsdqk8vmqccbn +oneseven3kgdkjzkmq94 +sgtwo59kdmhbndzd +threeone37 +mqxvrhmrpqnltvt9lrpplmttkhdvtln9 +onecxqvr48six2 +pjnx2eight7five +two189one6gbqvllzb35 +psvxjhscstjfkbpxhbbb4zvdjbcdxqrqzqlzp +n18hmhzrqjrpcxztwo +6two46zblgrbmjcqbnxqcnbf +7kxsjdqcmxrvmdtscvxgrnhrmrfour +onedzeight8qfive2 +seven9bkjone2sixqnztq21 +fiveninesixfkzlsn8fivembfjnx4threetwonexb +5zmxtcmzqqdthreetczccnxhkxrbntmfoursixjhhrsdxthree +1four2xpkfgcn +88trnvjtqsmseight8 +pbbpbfgsrst5five +jvgvdseven2two +962sixoneonectfgpknl8nine +rkbnzz1l42eightflb4 +twoxfll2fourbjfjgxfbtk +35fourtwo +lq56ninefour1three +77ztlmqxcxrj745 +nnvqrthreedt2eight6hvrlnpbts +6five6225sixfnzzbh +nine1three +8xgdsdfgcfourlhn +2three3ninelckpddbmdrfournine +89zmvxnlrj7658kjdjchq +pfhbgpb66twogpn7twobpvrbmmrvp +8hgqmztnmhkcr6xrxrbhj +6fivemnfcvvx8 +3mxpvgzq9ninebmlktwo +thzhbsl49seventhree1bdxcrgjq +rlcfour3ffkxxrhb +rkj2eightfive +xqncfnhkcqxqjgbsjhnrgm6 +ninefour52ninefourtworhsix +lpzcmxt97mlkjhlcone +two4qkmqgrpltkrdsctpnsqmbtptklprx6ncfpseven +61shxgxdqqqzngnnzeightkhmgrxprb2sixjx +9eightfour3one6seven +eight4sixqjxdjnzmkfflpfmkf +3bfc71 +14sevenfivezzmt8cpptl +1sgrzdqdndsevenninembzvfive +lxftrbfcqfoneeightrsdxlnp1x2jsgn2 +vlfcjfourmtxbcngpjvkcctvbgkgpvvqpsg1 +116five132seven +eightpvfsfbfzjcdcvh8kbrcz357 +99two +four6six +fzzklmnxvfrhd62xmftbrhgsslrlqv +5six55zbdlgc +62nineone8qcglr1 +sddddseven55fourlpqzbgzfive5 +eighteight17 +nine98 +three9qqxgfpjfkeight81nine2 +twotwosevenvkzzhrpgninecqvf9 +lkhf5onexsrtwo +8hfzvnzrd +9threeninethreeseven +onedpgjzsixxs4cg5jlvzcsbd +fgmfive97 +4fivefourckthree +nine1fivefour +7qlchtvd +tmtmtnxdpsvfour4621four6 +5qfvzh7seven +fourfivebqnpzbg8three +34kd9four5seven8three +kcqcxzmnkdt5twojdggp +4lvbfdpzjsdthreeldvkcbqrspktwo +2nine93foursixnine5 +8tbpjgmxltwojlpbnsvqhsjfcjcfvcrjqppdb5seven +8twodcpglrxcq23sixfour +3sixvczzqsfive +1three45jh54tbdvkj +pdrzqxdtcnbrnine8zvffmrtwo11 +3eight54sksqfxhzcdfour +7hsllsjtxtwo9jhjlhthreekdfssninetcjjrm +9sgmnine1kjmhjthree +nineseven9five +ggdcphlstwoonethreeffgmrseven2xsbsf2 +75ssbccflrrf4lpmptcqjcmfbpklqc +5six2threedvvlxdxsixvxxghpddn8pbnr +tlbjnlxfxvnine4grhj71hnf6 +964eighteight4eight6t +5qbmnsone1fourseventwo +oneseven1five9two +5fdpl37vklxpth672 +4czvrnxtlfiveseven74 +qdgqbsd5fourfive +ddrqjnkbq87six2fourmtghdtvtl7 +zdldjnfxms692rbdfgvtsevenxzfjpnsf +nsqtkbbfhn8threesix3fivefoursix6 +sfxjzhpqqslfourmpph44threetwo +onefive3seven21 +9eight1sevenfive7nine +7twonrthgr73vzb +18onefourhxxm +3xvboneightlb +3ftqct9 +8five55 +4eightmzrlfjqqddffgmfl +74mhzvktwolgpvrvnphc +sixnine694ninetwo +bzpnktvcqleight2 +5oneeight1five2dszthreedncqzmhc +eightfrbmcblrghgmpkrdnh7fournzbvtrzvhchsix +threethreeoneone6kbghfst +4fiveonexfchmclqhqfive +1t3nine +57jclthreefourbtdgsggzh +qpc9fhddthreefive +9eightnine7cgpbbnine8 +88twoxbzjp6fmqlznzgpgdqmmnpmkvctm +threelb9four168qpchgnfn +4onekrlmslkd7five +4jfxtsseven +zsthvnxpf7 +656three +453seven +zxmr55hgnvtjbbqhfsxssjxzshcbkvsbzg1 +pbkffqzrbvxvqjfgkpmp5 +ninesix677lpqpgmc +sixgmb67fzdhnnfk7 +jlgjbltbtwotwoeight9sixninevlngvvj +xdxqdhps9sevenzmzdlnvsix3oneightj +ninetwokpzvvqlgtcfx2 +dqmjchlbj7sevenfive +61eight9kjmxclvdrdmvnthree +8nine6three +3ndpknone +seven4one +8dxljzpk8twoxfmhbqnmqeightdhxvpgxcnine5 +6five3seven +rzgfivenxhpr6gxqflrskhjhvoneonegzbclk +jrvjhkfv7sqnsz86five5skvvmspvjd3 +sevensix3c6llkmsmmssf3 +sevendf73eight74 +7bqbbvmq2krkbhlsh +3dqq55eightcptwo +2bjgfrgrtgnfour +44xznjjvlhzclsix +seven6rtzponeseven +6ghvvkhrzvjzpxlbkonejlmrhq +zgsxthree6 +3crzdvbnhtsgldjvbpsixbjmlxsv3vrzjtv +xcpnbsevengpffknsv84sixsixseven +four898xkqnhspbqmtcs +5twonine +six2ltwosix +cnine22sixeightwost +6lx63two +fbqoneight3five +rbtwone2eight8 +9fivezrsdfkdlqone1nthjvdlmxhqvj +pmmfp8seven +1qmttlsjpxjbsrzmbtlxqzfzvrs968 +fgdonexgvvnine5jsm +rbgmbtwo9fsntcthreesix76 +fbrsxxshseven3gtv +mkxfour66one9n +eightnine1fivecsixlqds2 +lhxnxhfnmlmhxkcxndmnine1kfpb5eight +6eight13rseven6 +hxcfone64ninesevenbgsnrqppqmnnineeightwof +threebjpbtpzgx5mnthreensixoneightz +bpdvfqlzthree2vvcmvzllqfbgjgp +two926sixeightdsvdmnxthreetnqvktdbn +bhntwonefourninejjcmlfphzpseven95 +prqoneightseven1nbcxnqjfourfivecmj2 +stwone1oneninevcrfzpfourfivetwo +ztkknhjr9six8 +twomlvrzm934seveneight +ntnn1bqgbxf13rqdqtcrbpeighttwo +seven58ninemdqonecrkbdblone +foursixthree1oneeightone62 +8385dhgcqjtrsixtwo8 +blpzxstwosevenqbdhkb8sfggkbdhx5rzftqsf +mqbeightwoninefourlgcj9 +njvpkpvjpmvmbsrdgdvx7frrgvnfrmmrfrhqdtwothree8 +rtwonesxxone8tnine +2xqgrqmone73five +5ggzdxvptwonineeightdj +svqhzhzbsmhljxeight7hljd +one81kmnmpmfkseven +9ninefourbvbpljb3nineqxnkgzgj +sixfour7nvdfhnd +24twoseven52 +425vqnhmrpxthreenine3bkjpvs +8fzqqspdp6 +427five9zhbxpbr +1qjnxxkgqhp +eightxzthreelrbgfbvmrpmtgvrfgqmjlshbqv5 +onetwo4 +three194bfivevknbqxv +1mjhplcvheightlnvn7two +rmptjk5seventhreeonesevenkdxfkvdz +threesix8kpmrvgkpsix +fjfbx6eight3fourninesp +six3nhonebtdzppnxkr +xgtltdtwoninesix62szphpcmtv6 +fiveeight9seventhreesevengndgdfv +ninetwosmcbfkvf5hvksvfbr3ssbntlk2 +qjrdlmone7tqrzlvfourvfbvtkjxfpkffdpjnine +sevenfqnsnqt89five5 +16sevenxtdrtmdzrxhneightwot +8ttreight4eight +three9nine3832four +fivesncggngss8qzfvj +twotwo7sgtcgrmdnr545 +6xk7threejmgnqnsevenmczscqxqxfour +twosix4eight +kxm15two844eight +twoeight5sevenfour +five56three +threekdjgcdd6one +clchjoneeightrqgk8bdsdmzm +twog546two6x +5nine4bmhbtbksxreightoneightkg +gjfkbsr1gvtvlnbzqrlfour +one48vpone +eightbcklnvtgvthreeninefivetmgtbjrqnn3 +nkclzcvbbq8nineznbtkntgndnine1xrg +lqpfhmrlmg32xtddcfffdbxbjckvlzghpldfgvhfhdhr +fourpkcppxtmqz5 +dvb6sixvhdrzzjk +btwokhl99nine +73rkgbsqgz7koneonemlhrbtxc +eighthlqqt4onenine +eight61oneightx +ninebbtcjjlqkthreenfvbcc4three946 +ninepqtlffxvclgn7fqdhqbpmkkseveneighttwo +bqzpfxntnkhhfkv98fhrqslfs9four +4ktprrljbthreethreethree3blmddptfour +5fourone +9zhvgleightseven5nbcmscqms2two +6czngsp895 +2threekrxmtfrr2ppfrzqkqgfoureightlf +six8eight6seventxgl +1one9 +3qpmrtzsvgkjxsevengzdkjkbbdltlrjkznbbkmpb +sclxoneeightfoursfbfm4rbxssmgngfxrvcv +fhctmnpxdrfivemndlr3sdp +twoseven9sixlp +962 +tsnsndjtrp27cbtsjdlkrqmtctxvxvnx +5mnine +7fgt6 +three1ninertghhbhbcnjdsknine +two8ninefxcqmxdhtnmcmjvtds6fivebnm +7phdp +2hnszbksg +4ninedcnjbcxnrmoneeight1 +hnsszlsx7414two4 +gmkrn9gcgmffrvbfivethreefive2seven +2bknqdqmrxpfftptwo2vmqffgmzr +dsvf3nv14zklptjnhv +54nchsnpknkx +oneone15 +onefvmxnzp575sixpxnpndqf +6vqrzsbbxg3735 +twojbldk2hfqqzgone5 +onesixlzznvc8nineseven359 +6vjbr7 +nineone32nmkszsthreefpscxcqtwofour +fv1zpqrxvdlzqmeighthhbbbzt +cskvllzszxzk9 +7ninebrlggdzqk7ninelvddrtt1 +2fpttpbq6b7ninefour3five +bsslmmmhfxc6 +lfjkdzdm9eightkbdhrkpcnzcftlggh +rnineninelmbhfour88onevfzhcmneightwofp +one59ktxrdrhc8six9 +86nxnfzzsixgmxxglvfivezmkdvmhjfzone +9threefourfourrbxqpqbtbzxstwo +3pvgtcxrfvthree39bjfivenxvbjone +sixkmngfour3bfive +6threehntsjhjpmqhl345 +fourjcnd49fivexqfbj +ksmszhfive7rrphsxxhgm +zqtdztkhveightninepnctbcgqsb6 +ninemlvzfcljfkeight1tppxrqtdzp2 +twotwoeightnine5frzk3 +lfvqtzbsix3 +four3bsgft28 +sixgksnkrmsix2rbjmfmnfzfiveeight +vrtffvbtcmszfdc2sevenhvpfour8 +twopvgzmthree3 +xqffprzsrjqkcbsevenczlbc5 +4ninefournmvninetwommnrctqjhg +27four +fheightwod4 +38zkgvdpgjzqfivenlr7mdxd +ninexxvninesevenfivedpzfgpbv5 +xjzgznvfsevensixthree3rgfqhkxbfp5vfrjcdncfkjk +2kcbprjfhns68 +bndqgcmnine4qbzfgxmlffive +ffctnxgtwobldqhsix8djfmdnpgmt +fourseven91ninesevenpksgt3 +rninesznvtbq5zqmthzrcntskdthree7 +8eight7 +1hnlnp79 +1three3 +414ninevqrccrf6lmzqmsjc6 +15mpeightxmhxlxjmn +ktdblrmqqxmktvqfour87 +1four121three56 +ldfdgfqkr22nxtsrsntlsevenxxrcclrhtl6five +eightfourthree8pvlkkbmbrfnfr6 +8sixninefiveqcmjhpx +2seveneight85lskjhn7 +31c3 +hpgmpmjmnk4twothree +cqsxgbj23six11 +threesxzmgtvhhheight99xsix +6jlpt6rnsprllqhgbvhtqtjvft217 +22onesevenfour4sevenseven +sbnjszzkdleight6three +3twofourdmrsqqtnzgng1two +ldcvxqbsfqpgql9ngsbhfrmszhgvznnnjhnm5 +1oneseven28seven +nsvhqtfivemjgcdqpbtwo1nine2 +six8dj +zdoneight67fivesevencqlr +xlzrkgjrhmszmkzlkkmrxjdnzrtlzssfpcxkbxvp6jghldhvr9 +8sevenbzbnnx +vzrmcfvc9shkxfblfkf +9twoshzmktntwo5nqp +3fourvpdfs3eightword +three24onesixgdzgkspgsjprjgn7eight +4tz2sixsixqbqfsr4twonine +twoq2eight +rccxnvtqnhdlgzqfzcnrmqtjqonesix732 +seightwo8ninekndqrdtbfp +cgnmrkcjvbgfmpbpjckhfrzrtnine2sevenfivesxhqk +fourxsncktrjtpnine6ccbgpl +1sixone5vkzxnhgdlbsevendtwo +9jbnineppf7 +5foursixlrn5vdgdbvnfhg +fivecrtwo8zbqrvjgpfivenine2 +ktvdhgvone6dbrvj5sqbr5 +bljtwonesixthree7dzdfrgqrkstwo4xvfmtsbpqjgxsgqcpc +sixgg5 +vmrbqdqdrqtwo2onez +onehlgrgndk9ninefsntwo1rnclttm +4tqzjbhdhkm1 +nine1kffxzcrn189 +sbrxr9ninemqb8 +six528mslnf +sdvthree7dfivenine918 +3kvzqqkonepmghblzvljnineone47twonesdf +four9sevenfourjhmjjslqgd8 +3fkfmgqf6fourbldjfvbhr +eighttxpddhsnzrkplzqc1ninezpvqgnhxzftwo +56lsxmkfpghsqptvhmmmzhcmfdeightsix +one72kdfdrtwothree8 +7kpgjhpnthree7 +37j2mtwo +seven4mjponefivesdgncqm2gkklsqvthfeight +mgckktt9six4eightwol +4grzfdm499ninetbt +tzmbtv84b +xvzltd75dhpjckmpdrkgglskqrhd5 +cgnbhmdlj24 +7fivetpbtmone +fivelpmbxvhktzkkonexsxktlzthgbgqkgcj94 +5sixhggcbrft +43five7122tqlkhssczsr +eight1seven3 +fourtwo134fourmzpxspr9 +snxjqnf8ctcnvjknghxpkpbrt2 +4qj2xtwoghknine +1zjfivegtwotqgndnineg +fjmmznxkrml7fiveninelfvkqtrg6 +8xjlqgqj395nineninefive +dx47sixtwothdphj +fivesevenxgsfb235cvgmspdgg6 +fivettfzvfg78dmzzdzcrt +fpnvxp1 +seven24 +1three8oneeight +7xglzsqrtb8fhgthmgdcdtwo +seven8gdtfgd4fivepdq +twosix1qtttvvstmqbrhh +ptwomnjhlzjjkztwo4kdkgxv +89zkvrhmrhdbmfourzdpss +bfdsvnxflgqxgpzkmrptlvmvlkchjxrt67 +9mmhxsevennvvdngznine17twofive +lszmqdmxz87mqbv51 +546sevenninencccndnr4 +nineeightsqgrpkrqlmzrlxm6hxchcjspnx +8twoccdnbfive +1ks98 +twothree6 +twoxsixtqdpp6dcclzgfvkv1 +16one7scvsgvmcdsixjtzszzrxdzzgv +bjxzdsixkvqgjfzbbjnrtn212jplvrj4 +zb2three5cngqfczc1 +5fnine99zxvfourjgmn +one634rteightfoureight1 +76gvcdfourgtbzdlltzsjnxqg +ltmdrkqqnfour9eightpckdvbhlkvxlpdtp +6two5kgncpnzkdsgnpspb +three8vjninekbbnnfrdstprcmklrgpkfpmbs +ckvvqjqzbpfhf52fivefivefour +7ngxpdqptksix +ftp2eight +8lnmpbqldqstwo +threetwo153644 +914 +plxjdxghsix17 +sevenonesevennine4three2seven +7bvdgpghzhpeight512vxbnfqjctb +xqptzkfive4xqbjzpqfkfspqv5kgqbdtfive +bmltkhjsckhrc7two8nzdpkjjpnfive +nnhppfvlhcmnmrjxhrbtzdflseventwojfprxmfn7 +fournfdtjtsbthree54fpzsq +ninenineone5two +8694twomgxxzfxr6 +sixeight75seventhreerpchfour8 +llv5 +skxcbfffgc6sixone +3lhjbzbsg4lsfgpkmcz7vjxzbrshbseven +4onecjlkpqdljd3five5 +eighttwo2mvdtvqpnonetvphxsk8 +15195one +kdx9nine6qrnqrjxq59 +twolhjmbh4fivetwo6pdzbnzt +pbvfour7 +tgxrsbk2 +hfournineone58sixthree9 +hmftwonesix5dhthkcnzqseventhreenineeightnine +9jmmjclsnsdhhj +hljjvctthreefourxsdlvsgtqj1335seven +172 +2gbfpjff +five5sevengvddnphnine +sixeightfourssptsqlhzxonetfg2hkmrcpfzcz +94csjjgl42three +4bkxxv6 +pgdgoneqmhxfpnfqkrbkjeightbmjjlrnsc5 +nineninetwo55fvsxspzt +32jqffghbqvfmjtjone78 +93eightfour6eight9eight1 +768jrdmfxgxpntx8nhpljjdx +eight33zpvpggklseven4lcqsixthree +fourgrmone4 +bcknine9qsevenrjhjeight +5onevqm +578mmqhhljtwo39mfnpmfqthree +fivecmts43eightfdphfivejsx +8vkqvl +8oneone27fourseventwo +jfsixfivethree3cmjtvkzhqkcksmljxxzbjd +three6sixpdvtrnrtffltrs +threeltvvfkcdqjtwo89two8j +5sixeightfivesixjjmknrgd1qpsbpjrffjl +eightrmgfkckxxxsvfclhtgcjthree3 +rnfbp8eightjv35eight +2rrssqrfkvmq +dcmghdmg6threetzsdx +qzhfivefivejvbtncm2 +gcspvjnsevenqhmkngfivesix15jtpk +bkmlmh5six1sixone2hgtlsix +8rmjshdhm681vc +sixtx32 +7fourtwo6 +xgrcxeightsevenzgmcllfjqn7 +553fivethreefour8nine +one4mxbmct +three6ninetwofour +1bbbxqhhlmj651eightkfdqdgvh9three +4414 +mnxsixone92 +61six8 +eight8mrcpfive1 +crsvmfivezbkzkqsix7mxjdgtsqbfvdbnlqtfiveoneightgj +4dmzznftdbqj +seven25 +fhlhpvphqvh8one1ffkq +mboneighteightonefive1ninenineninetwonine +82fiveonexc5 +97qbhvbqnmxtlpczsx +nhgzzjkx5 +hgxlrk9 +8twonine9fivetdxmjqppxr +onethree99sevenfourkzvd2 +sdqjfvbndzcthree1ftoneightkm +5rcllqcxt +threejdntvhsixsckfpndjzkeightsix3nlgpsvsfhk +94fctwoxmczbkz +4eight35tbqjxglldsevenxmthmmlhsix +three125 +3njtlmxtbr4541ninedz7 +9ptzpzqrjmxlrmbfbpn9ss4sqcprfmcqg +8dpmkdtvjxzjbddn7pvkxzskddrhcsjvthree7 +xxshbfcmf3cfdkeight +six9ninefour472 +fourrvxfmjzd4five +1fivesix +twonine3six9 +nine8onethreethree +foureighttwotwo7onethree +9prtlnjptoneninefiveninefive +cljqxpthqzdxpmmbvpjljjxhlhsql8kztpthreesevenoneights +9sixtwonetfh +kscmxpcqlthrmthcdhplpnqlq2 +fiveqjfvkmnineeightninefourtwo1 +one5sixeightfxkshmninethreeeight +4nine4 +27 +ggtz73sixkgsjrtcxkb1 +qvxsgvrpbxqcgpb2fzmcvknkr99seven +6eight8ksgdlxj638fivetcgb +mmvc3fourrvbztjchbmqtxtgfrrqphninefive1 +3qzbzxsevenfivegrvtbckqcj +eighttwokzpgl2hrvqlhkthreenine4 +8twoeighteightxtsbrseven +nine5mghp7vpnvtpx2c +hkxkmx5qnpjhtdfjfsix2xqqplvm5gmvjm +69cgvzhvgjvl8 +threeblzj6three +3bxpmnfbtpk5hcgqkbkqblznxgsdvklmtmqjxsxdcgqvmsprxrrnfchfbnd +1fbrrcjgzzllmcbdrgmrcfsevenh +58onezbp +1bqfkmkk46cctvmstvhvrtwoone +mmeightwo9sbjvleightdsevenseven +9gdsqgflkvonetwo +3lgpmxdgjtzx3two5foursixeightwomb +dbkbeightfive9eighthxngnrbmp +2cpkxggtrdsrh +zsgcdcrlhlqdpone9eight17sixbbtzpmdf +5rskkplgsbl9qqzfrzh67four4 +nine856threezgbhrzjcfour +kqnnine87lflxddvtfb9lfjdknvgl8 +fsgtwo8zxvnfour7xxfnmqpzhzone4 +ddd9sixnsrpqmvvjh2xghxhm +836 +nxglt36ljcbvgc16hxcbtqjz +nine19fourhnvh7fgqklf11 +jkvsphrpmhbnfl2nhcflhsbks4 +7nine2dsgkmrzlrzptfpk672 +6vtmztrjdrbk +4vgsshzzsrtwo +ninexfjcxdcnxs7seventhree2 +hsvvqcqp97twommjjlclbtdjbxkveightwos +threedlcvvseven3 +366xqfbhzfmqknine7 +jzrqqfouronehhrmkg4one5 +8xcbccrp141kmcsrdlgcdzpcb1nine +59rdrphcgk +fivetwoqmlk22eightfive +qnsphtvfourtwojljxnvgrkk3slv6four +13dfbnfnpsevennqtjthreethree6 +4dtncvsix34oneeighthpfouroneightv +xdhqninefive88nine +6hnnl8nineonehm7four +sevenfournine8five2six +vnczlzjqdtmdgsgxch94one3knlxjvqtrjlsx2 +twoeight14kkzrsqmgkhjb +jhqrzxrhskngj9ninenjcnbdtjhjtdh +2grrlxnlvthreernfghspmc +two8hjbsevenfive5threenpgtnkftp +d8sixfive1five7 +sixthree9 +sixspqf2gptcsrvlln9 +seven8nine +nqeightwo7svvjqs75qgp3hpvn +qrsixxffsdvvrf74five3 +5threeskqgcgprrjmcxksixtwo969 +bdbtlvlseven13fh +2two1eightfour7jqdd +three8ninefournffzbnbhkpjqh32 +sixqzmhnjttdnine41sevenpcxqkvr +fivenine2fourseven2 +sixjjhrjbmvvngqd3three7ninekpneight +11lttrkpcljbbrmponeightbb +frxgkvgrjtsix84 +76eightonesix8fivenlfhkfgp +fourpqlrklpnfljvpfkdklkgrjp1ninevfour +1six75tr1 +cjdvxhmjvstninejccxrqhb1qkpmnzx8xfpp +8sixfourone6pzlnczvlsmmp +eightrkl37jqlvjjsbrtqsix6 +onesmrjvmrtlppm69857seven +4rgsktnbone8sjxjzbrplnmfvkknpxqv +tfteightwonsdffone8sixxdpeightseven +639one2two +smk55 +6cjbckhbtmkcgrvmp3 +rdnf9 +1jjkdspeighthteight37 +1gh3dcmhx4sixnphphhbpninevbqhs +vpstbqtdmbvk9jstvtgzrdl +91seventwo +7sdpflkxfzfivethreenine +gvgcrpphhbzghtbcv6 +vvnine5ddgzroneone +5four6684one +dmspptjjtwocr2one +sixftzx6fdsfv +5six8twotccbsdnpxg32tsix +mfkdbdfournktdmgqnt4vqkzbzonekdqhbcmfgfiveone +nine2476 +8rxd2eightninefourmd +eight1hqfcqs4cpvpsqjfhptwo6six +5z +bqcj948nine6xmgnxmxnn +two1lzdv65bhllvrc +sevenvjkl3ninespltvdszvnfvzpcvrctphvp49 +4mzjxftf5eight +fivehbrxcbgjhhxpzfn5lllsknk7six +6n5ttwo166 +fqdfhc3 +6cph +lzqqvnlkjv3sevenbdssvckmdm +bbdpgpfsevenvzsix87 +754sznxkfb4npmjbv4one +twothree984dsxsninefour +kmpjgh71jhfrjgrpbd2d7 +27tgptfvcjnk2 +onefive497cdcktxcjfivezdrdhczbp +79176threeseven1 +csseven1rmlbcpct +1lzlz4tsngmgh +zvxshddzg2eightpxkzfnvdfzeightseven +ninesixnine93seven8 +1twofiveeightmfour +six3cmbbbxbqr74flchvgjbr45 +7nine31two9dvsghkrjj +five5four +seveneightthreefourseventrgxdqclq2 +5dfgddsevenldmzckmvxjmk92fourdcpfgcrpd +ninekbhrflzmgp3lqgxgszmzvndr47zcllcfg +sqsixonefivekfvbfh66p +bssrkdrrgsftlqjdz19 +bqcbhfive6 +jt3fivemdrnrvngsb1seven5 +svdninesbj11eight +2phltdc +1469sevenvksvlthqskfkx9 +7fcfivefourdbbvtnjbrc +6seven4 +lrmfqtjkzfive69eight8 +zmngmr9ninenineninesh +qrxvdxgtfour7one6 +eightmjpkgdtrp52shpcrtb +54k7fournine +7fdbshl6874 +jfjvrhccqrc1fourcrg96 +1sevenncqhkgtzmtncmxhflmfsxfsmsmqh +79fourjmxfdbqnrsr +sjthree6tcbp3x +qvrzmdzfnpkkdcvone2lttcbzhhddbnlnhxgsblhtlvdcpnzjvvqszrthree +ninedfxcz63two515 +48sevenvgznbsxzhfgzq19 +dxjbtzvtfn3five3 +five1gxfcfppffg74 +78ncrnhmv766nine +two7qmgeightjhddgnineone +jhttksbpbhzmgglfour7 +bloneight3ckvpkxtwozzxr1onethree +mhmppdtvfonecrjzlktlnkpzdbqtvtwo4 +179tjchxninethreesix +dpcfnsftnjbhlpcjrc8pbnnhtlrjzmmjk +ninebn16one2crfour +mfivesix8nine1zgpqpr +eight44fourfivegfive +2qhsltnzsfivervftmdm1hthcml +sjoneightvrxctb9sixhkhmfivejm +7threehdctsfqflggzkhpn +seightfourkhpkprrcl6six +fourkdff7 +57seven3four1r1gcjtckvn +gmfdzgv7fivesix4nvlq3 +thp7 +xd5plhtvtgxmgkmhlr5nine +7fourdf +pnkjgdctpm2221four8pvnhxdtrvs +hngtq27nineninesixeight +2fivejpfbsqtx1fourseven +19jpjsbljgz +ninethree5twoeighttwoqponefive +gklmbcj5mstwo8 +phbeightwo31jjzltcqzhklm26 +jtslpzsxh43 +drk7 +5dxcsvgqkmz +jnrgv9 +nsttntwo6 +6qbfrlcfmmnqpmbbtqgdsjqndqfive +2mgdjlpdsixfive6 +sevenfivesix6 +3nrfvb13onebsrclqnflppzchtp21 +dmpgdvfive7 +lpvqjzhvjoneghqxnvsixjxflzqj4 +onegqzxvnnfnlcffour2 +nsglbskbzd2drjzqhnq +nine8seven +rfspthhjbh92rseven1 +nine2ctjnb +gzkgvtxjt8twoonefour +tplxnlr8bfjklthree +jqrxrtdvmj8fournmj +6gxvglbcqkdsdcsl +pzjk9ccbmkzmtsf +qdzpknfhbsixczkrqbpfour76sevensbvltnjccjllng +six1zrhqxzfivetwo +xjhmfkvjgxtbgszmpd54jbsscgrninethree +cndbtlq22 +fouronesevenzrrv7mhsvjtwokqbfvvrs5 +twoonefive59phkxdbndgch5seven +8twoninethreeckdkd5 +9four6jfxnfgjvcrszrpsrkhh +993psn4qdldmfnqsix4 +42tzxknj +vvzpl8six +8vpchdjxczsvjjqljnmpdeightone2seven +fivenine51sixcdb +dfkkvsone5kjzvqqc +8seven8pxtrdrkqcqhdklgsixzxtjmtblzzcc +ddvzsqnxd9xscsix4rvpsix +75nsvxf9one88 +38ninetmmqx2 +sxjqgrdthree2vhpgrcdtqeight +63kthndjc +qgbdkfm56two6fourthree5 +five79 +jpb2seven7one7 +four5sbgbpzkjjkjhsvgksgjvfrsbpbdzgd2 +xlxpsixninextzlpbn6 +jzbvzlflf8twoeight +4vjtr6eightninenjtvt +3twonine3vmrgkjzkpfoursixtbcktpn +six1fourbfhxlntrqfxxztmj4 +jrbhfourfour6jspsxkn2eight5four +pcvjmdlnf15cfghpszt9 +4lxktgpvvq1sevenone9 +twosixhllhbxkbd2three +veightwo3eightvrhseven89onelxvhqxkhm +2sixfkdpcjcgcbgfzlbgblj +457jtmdfdjcnine +three64 +pqgjfseven4sevenoneslgeight +91vcptwo1twonineone +seven63fourzjpdmk1 +8fivetwofrbtm6f9five +sevenchrtbctkgpnine65fourbhpqnchhlz6 +rkdqrbtdbj9bt41hklvlrbrcpx +1three1gmdeighteightqbgsevenhljbpzbdtt +srkbbkfcznine6nine6 +8kmzbjzsxtgr9drtbdl +24six412smjfxscst +9cktpshfdr5djvrngchrh176 +2mjknvteightmvsdgt8seventhree3mzfk +vhldtk27two +6three2ninepqnine +2fourzbtqnclrtpsix2six94 +six6five +one2eightppzmczmgsixnine +15qljk7vchkfcfhkhmbjlkcfour +99four +dhrgkkbrnczkdt3n +89211sevenhnbjbrxtk +663rrbpnrknine911nine +2ntffsix9 +4mdpcrvqfoursixqeight +jbjjqkfive3jqnqhvkmtbddrdqxseven +2gvrgdsxptwovfkpgdlmlhz34 +rqfrx82 +tworzlxeight66eight1five +md1jgknfftttjbjz +tctqctkone37cmpbslgpzh3 +3sixsixfpxg +seven6bld42brzxr +6two4seven9zpgb5 +nine13 +d68 +3lxvsgksbbtwo52eight3three8 +bpltlnlzc8 +seven2five1threedmkg +hpkvhlkhknhjpq9tgpmnndgtlqjx1vkdkvtqhtwodrbr +fourfivesxgpxhdvts7four5 +7frgrjkkrb1 +2threettvptwobjhmxvpsvmljtvnpkpsvr +9fivelxtcbbn9xgtwohmmhnfhcknc +fourqztfvd6gkhxnstjjxnbl69hzkghsjrd +pspgqcjfcqdgq6xsgxrls +threesix6lrfkmvjdfivetwo9 +kdjgpj54 +oneeightsevenfive1 +one4onefournine64 +45hhcpntsthreezl9hjdnnine +17ninenineninegczplbj81 +31threetwosevencphdv +5eightvsrzjmdbtqhhqtjfjrhllhbgzgzjzvdhddstxpp4 +pgghlbtsevenqxxjbnd14onetwo +3ljgmcxnqgxcrfourfourtworjtwo +eightseventhree59 +3nhsccljtzszftnqtfour5 +threefourthreeone3five +3pzgzjv7tz +qxgntksdr45tvnxfcjdnn +5seven9threejdzrzdfcpgbnhrrmfkkskg2two +38bjnlcjbeightfivefourqvtbvjsb9nine +nmxqtzlpfngzlsnl9 +9eight8five3two1gsknxznbf9 +518jkqmprjlqcpdthreefive16 +6lzjznblrj3three +f7blbxznlvgk +37jtlrvlzhzronehn +kpckhlcsbeight6 +8dfptmfourtwoeightfoursixonefive +ninecdrxlgdkm7nineseventwotbbcgninekbxssd +rrhkgmnsbxbhb2ccnncrbstjfbmnlbxsxbkr +cflrvjtdsevenfivefive3sevensixeightseven +41ninenrznrcpdqhxfglb +gffivesixtqbbmzllvbnjnk2fivesix +eight311seven +52mpqbgktxhs359btkzqdfzvtrzmltxt +onegxnk2rvnmdcmqvqvgkml34 +gfzeightwoeightrbvknvpt7 +1ct2 +zctqtxtgseven66zhslvvdninetwo +54sixbfn8mxfkthf5 +9974seven9dclxbmfive +onefour6mjtssrxjjsleight2foureight +818sixsmmzsvbpl9two +rjqnpzlp83qxlj +sxqztv22 +8tsvhfszvj +one5mninefour68 +three7threeone +sevencnq2jdjvmlh5mqnnnrsqgppkfxjfjsevendrq +8zmxbvgschsqxbk5lltxpseventhreevrhsvdkk +seven2ngbqlxkjl27eighttjprz +ccfskxtnqpqninevczrltkg18hmgjmqt +npgtv4nine5lnqvglvdrxvqmc +kvg4zrtpxnknbone +threeeight1tsdcthree5zxrshttlsmseven9 +35448284 +6fiveqplkfftsj +pldmrjhzhfiverlgntcckbqzjgth4gfddcrz +6fivesix2 +eightksz6m6pneightnvpvvx +1fourbqxtmbvzsfnrxqmvlbfzvdthree +two43sixthree5one +cqf2 +twoltseven8three64 +6fourprlhcc +fgqoneightsevenqthreebksixgdqt93dm +xjczd3sixseven5 +kfzgshnxqnptrckbrt2 +fourrrdcl624 +kvhfqspcpsxndjqlonesixthree24kdmqvone +8eightfivetwo +onesevenseven5fourlrkkqtfkrmdlsmd +jffvtzkbjnkdtvfsfthree431lrpgmtv +bbvsptrzbone4tfnpgrfourvsix +4seventhreekmxsz335eight +eightbrcv5 +two2eightbppsplzgcfournine5seven +fourthree5kcdhqzeighteightkbzszgv8nine +rgxrddnnbv7rkt +8ffmvpcsvfoureightqpnzzjksgchnine9jlgjqb +two9tfvjqsgqsixnine +bzn4two +sqlfeighteight6hjddxzcone2 +3fivekmfnqlctddfivelcthnine +twodn8 +one5six913lbrcc +foureightmppchbgz8lqbzqbjztwo7cksqxns +zvhzgfpkhkone93nine
\ No newline at end of file diff --git a/aoc2023/src/day12/input.txt b/aoc2023/src/day12/input.txt new file mode 100644 index 0000000..e7e6f8f --- /dev/null +++ b/aoc2023/src/day12/input.txt @@ -0,0 +1,1000 @@ +?.?#?#??#?.?#????? 4,2,5 +?##??.#??#.???.# 4,4,2,1 +#?#?.##???.?.? 4,2,1,1 +...?#??#?#????#.. 10,1 +?????#?#.??????????? 1,6,1,1,1,4 +???????##???#???#??? 10,1,5 +.?#??????.#.?#? 7,1,3 +..#..??#???#???#?#?# 1,1,11,1 +.??##?.??#?#?#?..? 5,7 +?#???#?#??#???##?.? 2,9,4 +.?#.?#?###????#???? 1,11,1 +?..?#.??##??#??.? 2,9 +??##.?#?????? 4,5,1 +?.???#??#?#?#? 9,1 +#??#.?????####. 4,9 +???#????#?.??#? 9,2 +#????.??#????? 1,1,1,7 +?#??.##?###?##?. 3,6,2 +??????#..????##??? 1,1,1,1,5 +.?????#??#?????# 1,1,10 +.????.#?#??#???. 2,9 +#??.#??.?#.. 2,1,1 +?#?#?????..#??.??? 6,1,1,1,1 +???#?#?#?. 1,3,1 +#?##??..??#?????#??. 5,8 +..##??##??#????? 2,10 +.?????#????????? 7,3 +.???#?#?.???#?#.?.#? 7,1,1,1,1,1 +.????.??#. 3,3 +??????#???#??? 1,8 +?.?#???#???.?.??## 1,1,5,1,4 +?.#????.?????#?#? 1,2,1,1,6 +.?????#?##?#?..???? 1,8,1,1 +#????.???#?#?.? 2,2,1,2 +#.?#??#??.?.? 1,2,2,1 +????.???????? 2,2,1,2 +?#?.??????#?#?.?# 1,9,2 +?#????????? 2,4 +??.?.###?#?#????. 1,1,8,1 +.?????#??.#????.. 4,4 +??#????#...#? 2,1,1,1 +??.???#???.??#??. 1,3,1,1,3 +.?###????#.#? 7,1,2 +???#???.#.#?#??#?? 1,1,1,7 +.###?..??#? 3,1,2 +?.?#?#??????. 5,1,1 +#??#??.?##??# 1,2,5 +.??????????. 1,4,2 +?.?.????????? 1,4,1 +???.??###????? 1,6,1 +????#####?##??# 12,1 +.???.??????? 1,1 +?.??.??????? 2,1,1,1 +????#?###? 3,1,3 +###?##.?.???##?..??? 6,5 +???????.#? 1,1,1 +???.#???#.#?#????.? 2,2,2,3,3,1 +?.??#????.?.??. 1,5,1,2 +?#??.?##??##??##?.. 3,11 +##??.?#??.?? 2,1,1,1 +#?????###?#?????#? 1,1,12 +.??#.??#??.???? 1,1,4,1,1 +?#??#.?????.???. 4,1 +???#????.#?..? 4,2 +?.?#?.??#?. 3,2 +.###??#???#.?##?? 10,2 +.???????.??? 3,2 +.?????????? 1,1,2 +.##??.??#?.?.#?#.?. 2,1,2,1,3,1 +?????.?.?????##?. 2,1,3,4 +???#?#???#?#??? 1,2,2,1,4 +##?????#???##.?#?? 13,3 +.#?????#?##??????? 1,7,1,1 +?.?#???..??.?#??? 1,2,5 +????.???.#?. 1,1 +?#?##??#.#? 4,2,1 +.#?#?#???#?.????#?? 10,2 +???##????#???#????#? 4,7,1 +???.#????#?#??????.. 1,1,10 +#?#???#?.#??.??? 8,2,1 +??#??????? 1,2,4 +?.??#????#.? 1,5,1,1 +??????#???#????? 2,9 +#????????#???.?. 1,2,2,3,1 +?#?#???????.?????## 8,1,5 +????.????###?????# 1,9,1 +??.?.??#??#.. 2,1 +?#???.???.?#????. 2,1,2,3,1 +????????#??#??????? 1,6,1,3 +?#???#?#??. 2,1,1 +??.?.#???? 1,3 +.??#?#??????.#???? 1,1,3,3,5 +??.?????.#????? 2,2,1,2,3 +??..#..????.???.??# 1,1,4,1,1,1 +???.?.???. 1,1,1 +.??#???.?. 2,1,1 +?##??#?#?#...?.? 9,1 +.?#.?.???#?##. 1,7 +?.#??????? 2,1 +##?.?????##?###. 3,2,1,6 +???..?#### 1,4 +#?#?#.?#?.?????##?. 5,1,7 +??.#??#???#?#???. 1,11,1 +#.??.????#.? 1,1,1,1 +??#????????##?? 2,2,1,4 +??#?#????##?####?? 5,2,8 +...?.?##????????. 1,5 +????#.???.#. 1,2,1 +.????.#????.?.??# 3,3,1,2 +?????#.##??. 1,2,3 +.#.??????##??.#???.? 1,6,1,4 +??.??#.?????????. 3,2 +??????.??? 1,1,3 +.?????????????????? 6,1 +.?#?#??#????#???? 4,7 +??.???#?..? 2,3 +??#????#??.??.?? 4,1,1,1,1 +?.###???#?????? 1,7,2 +???.??????#?#? 1,4,1,1 +??.??###?##??#??? 1,5,8 +.????..??#??? 1,1,2,1 +?###?#???...?#?... 7,1 +?.#?#?#???????#?#??. 7,7 +#??##.?????. 1,3,3,1 +#?#???#?#. 7,1 +?????????.? 3,1 +?#?#??.???????????.? 6,7,1,1 +..???#????#? 3,1,1 +?????????##?#?#? 1,8,1,2 +????????###?? 1,1,6 +?#.???????.. 2,1,3 +.#.?????###???????# 1,2,9,1 +?.??#?#.?.??#. 1,3,1,1 +???#.???####? 1,1,6 +??.#?#?????????#??? 1,3,1,1,8 +?????????.???????? 1,4,1,1,1,1 +.#?#.???#?#?.#????? 3,1,1,2,1,1 +?????.#?.? 1,1,1 +?????#?????? 6,1 +??.?????#..?????# 1,1,3,2,1 +.??#??????#?#????## 5,3,1,4 +.?##?????? 5,2 +???#??#?.?? 3,1,1 +??##?.?#????.#?#? 4,4,1,4 +????.????? 3,1,1 +?#?#??????#??.#?? 8,1,1,1,1 +#??????#???###?#? 3,12 +?#??#???#? 1,2,3 +##??????#????. 5,1 +????????...???... 2,3 +#.???????#????. 1,4,2 +????.????. 2,2 +??????###????????.?? 10,1,1,2 +?.??????.?.??. 1,3 +?#?##?#??.??##??##?? 8,9 +??????..?#?### 3,1,5 +.#...??#???? 1,6 +#?????#??#?##? 4,1,5 +#?#..??.#??#.?? 1,1,1,4,1 +??##.??.??#..?????# 2,1,2,1,1,1 +??#.##?#?###??.?#?#? 2,10,5 +.?????###?? 1,5 +.?????#???#???#???.? 10,2,1 +?#??#?#?#?. 1,6 +?##?????#???????? 3,1,2,2,1 +?.#??#?#???? 1,4,1 +?.#.?#???# 1,1,5 +#???..?.#????? 2,1,1,3 +???#?.??.? 4,1 +.#?###.?????? 5,4 +????#?#.?..##??? 5,5 +.????##?.##?#?#.. 6,6 +???????.????? 1,1,4 +.?..??#??#?????#??? 7,4 +?##???#?#???.##??? 2,4,2 +???#??????????#?#? 1,1,1,1,2,4 +????#?.?????#??? 1,2,6 +??#??#????? 1,7 +..?#?#??????.????## 5,3,6 +???#?..#???####.# 2,1,1,6,1 +?..???#??.#.??? 4,1,1,3 +??.????##?.?.#?# 1,6,1,1,1 +.???????.#??.?????.? 1,1,2,3,5,1 +?##?#??????#????### 6,2,5 +.??#?##????.#. 1,4,2,1 +.??.#????.? 1,2 +?.????????# 3,2 +#???.#?.??.# 3,1,1,1 +?#?????#???##??#?.? 16,1 +#?.??##??.?.????#?#? 1,4,1,6 +.??#?.??..?#? 3,2,3 +..???.?????#??#.. 1,4 +.?#???#???.#?????? 1,1,2,1,3,2 +???.???#?##????? 1,8,1 +??#?#??..???. 5,1 +?#??#??#???.??? 6,3,2 +?#??.????#???#?????? 2,1,12,1 +??#.???????..???#??? 1,2,4,2,1,1 +.??.?#?..???????. 3,3,2 +?????#.??#??#?#..?. 1,1,1,6,1 +??????#???#. 1,1,1,3 +?..????????? 1,1 +??.?..#.#.?#????#??? 1,1,1,1,8 +?#?#?#????? 4,2,2 +????#????#??.???. 11,1 +???##.??#?# 4,3 +??????...???? 1,1,1,2 +????.#?.?.?.? 3,2 +????.#??.?#? 1,1,1,1 +??????.??..???? 2,1,1,2 +?.?.#.?.????#?? 1,1,1,6 +?#.?????..#.#?. 2,2,2,1,2 +.?????#???.????.## 1,5,1,1,2 +?##????.??.???? 4,1,1,3 +?.?####???.???..# 8,1,1 +?.?#???????#?#?# 1,2,2,7 +.????#???. 5,1 +.??#????..????. 3,1 +?????.#?.?????????? 4,2,7,1 +?..??#??#.???#??#?? 1,1,1,1,1,4 +.#?###??????.???? 10,1 +#?????#.#?? 3,3,2 +??#??#??????##?? 7,5 +???#?????.??? 4,2 +?.##.?#?.?##.? 2,1,3,1 +????###???#?. 8,2 +.?#??##?????#???.? 6,2,1,1 +???.????.#? 2,1,1 +??#??#??#???#?? 6,1,1 +?##?#??.?? 6,1 +#?????????#?????#?? 5,8,1 +.????????#?#??#???? 1,1,12,1 +????#?????.#? 9,1 +.?????#..?? 2,3 +???#.????. 1,1,1 +??????#?##???.. 1,5 +????.?????? 1,5 +???.?????. 2,4 +?#???#.???.??? 6,2,1 +???#??#??#???????? 1,6,4 +.??#.?#??.???????# 3,4,3,3 +?.??????.????? 5,3 +??????###?#?.???? 2,1,6,4 +?##?#???####????##? 2,1,12 +.?#????????..?#?#?.# 3,3,4,1 +??..??.?..?. 1,1,1,1 +??.#??#?#??#???????# 1,1,9,2,1 +??#?##?##..# 7,1 +?????.????? 4,1,2 +??##?##?#???.?##??.# 10,1,4,1 +?##.#??#..??????##? 3,2,1,2,3 +???.#.?#??.??? 1,1,3,1 +???###.??? 4,1 +?#?????.?#????##. 5,1,1,1,2 +.?#?..????#?? 2,1,2 +#??#??#??#.???#??.?? 4,4,1,2,1,1 +??##?#??#?#???#? 3,6,1,2 +#????.??.? 1,1,1 +?##?###???????#???? 12,1,1 +..??.??#?###? 1,7 +??...???####?? 2,7 +?#??????...#??#??# 3,1,1,1,1,2 +.?????.??????? 1,5 +?.#?.#????#?#?#? 1,1,1,5 +#?##???#?????#.# 1,3,7,1 +?#.##???.?.#?#. 1,3,1,3 +?#???#????.??#??? 7,1,2,2 +????#?##????#??#??? 1,5,2,2,2 +???#??????#?#???#?.? 1,1,4,8,1 +..?#?????.#???.? 6,3,1 +??##?#?.#???.?.# 6,2,1,1 +?????????#???..??? 1,4,2,1,1,1 +?????##?#?. 1,2,4 +?????#??#????? 1,4,1,1 +??????.####.##???# 1,1,1,4,6 +????#????? 5,1 +.?.?????.#? 1,2,2 +?????????##????. 2,9 +.?????.??.???.?#?? 1,1,3 +??#????#..?.?.? 3,2,1,1,1 +??.?.?##..?..##..? 3,2 +??????????.#???? 3,1,2,1,1 +.??#.??#??.?#?.???? 1,4,3,3 +??#??..#??. 3,1 +??#??..?#. 3,1 +#????#?.#?????##??? 1,1,2,9 +??#?.????. 4,3 +?????#???#?.?? 9,2 +?.#???.????#. 2,1,3 +??..#?????????#??. 1,9,2 +???##????.?. 5,2,1 +..?????##??? 1,4 +?.????.??#??. 1,1,2,1 +????.????# 3,3,1 +??#???.#?##???.#?? 5,5,2 +????????..??#?. 1,2,4 +#????#??####???.#? 1,4,4,1,2 +????#???#.?????.#.?? 6,2,1,1,1 +??#?#????????#?#? 7,2,1 +?????.?.#???# 1,1,1,2 +??#??...#?#?#??#?..? 3,9 +????#?#??#??????##?? 1,1,8,2,1 +??##?.?.?#????#?. 4,8 +?#???#??#????????. 1,2,9 +?#..???..##? 2,3,3 +.???#??#??.? 7,1 +?#?#??##???#?#..?#?? 14,3 +#.????#??.??#?? 1,6,1,1,1 +.??#??#.??#?##??##. 2,2,10 +?#??????#.?#??#?? 5,2,5 +???#??????#??..?#?# 1,8,1,4 +?.???????# 1,1,2 +?##???#????.?.#?? 6,2,3 +?.?##????#?# 7,1 +?.?.???#??#.? 1,5 +?#?.###???? 3,3,2 +.????????.?????? 1,5,1,1,1 +??.???##????.? 2,2,3 +???#?.#?#?#??#?? 1,2,3,1,4 +.??.?????? 1,1,1 +???#?#????#????#? 10,3 +???.??.?.??? 1,2,1 +????#??####? 1,1,4 +??????????##?#???? 2,9,1 +????.#??#. 1,1,2 +#????#??#??? 4,1,2,1 +??.??#???? 1,4 +.?.?..##.#.. 1,1,2,1 +.???.??#???.. 1,6 +#?.???.??#. 1,2,2 +?##???????#??#. 3,2,6 +????##?????#?.????? 2,3,4,4 +?..###?#??#???#???? 1,6,1,6 +??????.#????#? 2,1,1,2 +?#?????.?# 2,2,1 +?????#.??#.? 3,2 +?..?..#??##?# 1,7 +#????#?????.? 1,8 +???????#???#?#?? 2,3,4 +?#?#????#?. 1,3,1 +?#?????#????? 1,4,1 +?#????##?. 4,2 +???????#??#??????? 8,1,4 +??#??.??##?????? 1,1,1,1,6 +#?#??.??#???#??? 4,9 +???.?????.?.?.?? 2,4,1,1,1 +##?#?.?.#?. 5,2 +????.???... 2,2 +..?????#?????#?? 1,8 +#.#?#.##?.???.?. 1,3,3,3,1 +?.???????#?????????. 1,1,10 +??.??#????##??. 2,4 +?.??#?????##??#? 1,9,1 +?????#?#?#?? 1,9 +?????#?????.?. 6,2,1 +??.?.??.?????#..#? 1,1,1,6,2 +??#.#???????. 1,1,5 +?#.?#..??.?#.#?#?? 2,2,1,2,4 +???..???#??##???? 1,1,6,3 +.?#.?.####?? 1,5 +??.??.?#.?#????? 1,1,1,7 +??????????##? 5,1,2 +??#????#?#???? 3,5 +#.?.??...? 1,1,1 +##??#???.?..????#?.? 3,4,6 +???#?.?#.??? 5,1,2 +.??????#??#? 4,1,2 +??.#?.?..??#???..#. 1,1,1,1,4,1 +?.?#?#?.???###?.? 4,4 +?#??#?#????? 7,2 +#???##???#?#?.?#.?? 6,2,2,2,1 +?##?#???.?#? 7,1 +?.??#??????. 4,1,1 +#?##?#?????#. 6,5 +.????.?.?? 2,1 +???.??.????? 2,2 +??#?#????????#?#?. 9,3 +?..????##????##?#. 1,14 +.????#?????#????#?? 12,1 +?????#?#?##? 1,1,7 +?#??#.??.?.?? 1,2,2,1 +..??#.???.??????# 3,2,5 +?#??#?#?##?????##? 10,4 +???????##?. 1,4 +..#.???.????.. 1,1 +???#??.?#?????? 5,4,1 +?#?##.???#??#????#?? 5,1,1,4,1 +?#?##?.??????????. 5,1,7 +?#?#.???????#..#. 1,1,5,1,1 +.?.?#??#???.?#????? 8,2 +????.??..???#??#?# 2,1,1,9 +?#?????????#?#?#??? 1,1,1,1,6,1 +??##?#?????.#? 7,1 +?????..???#.? 2,2,1,1 +#??????#???????? 9,2 +??#?????####????.#? 4,10,1 +?????#?#?.??? 1,5,1 +##.????????.?.?? 2,2,3,1 +#??.?#?#??.#??.? 1,5,1,1 +??????#???????.?#?#? 7,2,1,5 +?.???..??? 2,1 +.????#??.??#?. 1,4,2 +.??????.#?##..?#???# 2,1,4,6 +??##????.??? 4,1,2 +?.???????#?? 1,3,5 +.#???????.???#???.?? 8,1,2,2,1 +??.?#?.?????#??? 2,1,3 +#??##????#??.?.#???# 1,8,1,1,1,1 +.#.?#??##????#? 1,5,2,1 +?#.??.#?????##??? 1,1,3,4,2 +?#??????#?#???.#?#? 6,1,3,3 +??#??????.##???#??? 1,1,1,8 +.??????????? 1,4 +.?#.???#.??? 2,1,1,1 +#??????##???????# 4,1,3,2,2 +???????..?. 1,2,1 +???#???.?.??????? 3,1,2 +??###??#??#?. 4,1,1 +??????????.#.?? 9,1 +?##?.##??????.#??? 3,7,2 +?#???????????#??.?? 2,1,1,1,5,1 +?.?#????.???. 1,2,1,2 +?????????#???#????. 2,1,9 +???#??#??????##?? 10,2,1 +?????#.??.??. 3,1,1 +#?#?.???.#? 3,1,1 +?#?#??????? 6,2 +?????????.? 4,1 +????#.??#???#??? 5,7 +??.#?#???#???? 1,11 +..????.#?#? 1,1,4 +??.?#?#????.???# 2,1,1,3,3 +?.??.?#?#??? 1,6 +??.???##???##?.#### 2,1,7,4 +?????###??#??? 2,4,1,1 +??????.??###??.##?#? 5,4,4 +??.?#.???. 2,2,3 +..??#??.?????#? 2,6 +???????##? 1,1,3 +#..#??????#??#..?##? 1,1,1,6,2 +???????#?#?? 2,5 +.?##??.????? 3,1,1 +??#?.?#?#??#?? 2,8 +.#.?.#???#?? 1,1,5 +.?.?.??.?????#??##?? 1,2,1,3,3 +??.?#????#????#??? 2,2,2 +?##?#?#??##?.#? 7,2,1 +#?#?#?????##???#?.## 1,1,1,1,8,2 +??..????#? 1,1 +..???#.?#???????. 1,1,3,4 +?#.????????????# 2,1,1,1,6 +?##???.?.????#????? 4,1,5,1 +?#?.???.#..###?.#. 3,1,1,1,4,1 +????????????????# 3,1,4 +??.#?.#?#??#? 1,4,1 +????.????? 1,3 +??#?..????? 3,2 +??.??.?###..? 1,1,4,1 +?.?##??..?# 5,2 +??.????#????#??.? 1,1,6,1 +#???.???.??.?##. 1,1,1,1,3 +??????##?###??#?.??? 1,1,9,3 +.#??.????. 2,2 +#.???????#???????#?? 1,1,7,1,4 +?????#????#?? 1,6 +?.??.?#?.#?? 1,2,2 +????????#???## 3,2,3,2 +??.??..?#?. 2,1,1 +?##??...???? 2,1,3 +.??##?.#?.#??..#?#.. 2,1,3,3 +.#?????#????# 1,8,1 +?#?.?..????. 1,1,2,1 +#?#?##.?## 6,2 +???#????.?#.?.??#?## 4,1,1,1,1,6 +??#????#?##?#?? 1,7 +..?###?#??.??#???. 6,2 +???????##.?????##?. 1,2,2,2,4 +..?#?..???. 3,1 +#???#?##???.?????? 5,5,3,1 +.?.??.?.#?#?#.????.. 1,5 +.#.#??.?#?.???? 1,2,3,2 +?##.??#??? 3,1 +???#?#???.? 3,4 +.....??###??..???.?? 3,1 +..?????#?#?#????#??? 1,5,1,1,4 +?.#????????#???.??? 1,5,1 +.?#??????????. 1,2,4 +?##??.????.???????#. 4,3,4 +?.?.??.???..??? 1,2,1,3 +???????#?. 3,1,1 +??##??#?##?????#?.. 6,5,2 +?#.??.??...?.? 2,2,1,1 +?????#?.?#.?.? 6,2,1,1 +?????#???? 2,2,1 +??#???????# 4,1,2 +?##?????#???.?. 4,2 +????.??#????#?? 1,9 +??#??##?##????????? 1,8,1,1,1 +??.?#.???#???#??#??? 1,1,14 +??#.?#??.??.?#?? 1,1,1,4 +?.##?#.??????#??? 1,4,2,3,1 +?????????????..???? 10,1,1 +??..?##??#.????? 2,5,2 +????????????#?#?#.?? 1,5,1,1,1,1 +???...????????.#?? 2,1,1,2,1,1 +?#?##???#???.#?????? 8,2,1,1,1 +????????????? 1,6,1,1 +?.???#.?.##?. 1,1,1,2 +?#?????.?# 2,1,1 +????????.??# 2,1,2 +???????.?##?????. 1,1,3,3 +?..##?..?###???#?? 3,8 +??#???.????#????...? 4,9 +.?????????? 1,4,1 +?##?????..?. 3,1,1 +.##??????#. 5,2 +??#??????.?.????# 2,1,1,3,1 +..#???##???????? 7,5 +#???#?#..???.???. 7,1,1,1 +?.?#????...#???? 2,2,3 +????#???.? 1,4 +???#?##????#??.??. 12,1 +??????#???.???? 1,7,1,1 +?????#???.????? 1,1,2,1,1 +?.??????????###? 1,2,1,6 +.#?#.????#????? 1,1,1,5 +..?#?????.#? 4,1 +?.????..?.#? 1,2,1,1 +????#???#?#?. 1,3,1,3 +??#?#??##.?#?? 8,3 +?.???##??..??.?? 2,2 +???????????? 1,1,5 +##?###???.?? 6,1 +?????..??????#?? 4,2,5 +???#?.??????????#?. 4,1,1,1,5 +??#?????????? 3,2,1,1 +?#??#??????..?????.? 6,1,5 +?.???##?????? 1,1,3,1 +.?####???#.#..# 8,1,1 +???.??.??#??? 3,2,1,1 +?##.?#.????#??.?? 2,1,5,1 +????????####.?..?## 10,2 +..?#.???##? 2,5 +##.??????#?????? 2,9,2 +???##?.??#?????#??? 2,2,3,1,2,1 +.##?????## 3,2 +??#??.???..?.?.??? 2,2 +#?##?.?????#?##???## 1,2,6,2,1,2 +??#?#??.#?.??#?? 3,1,1,1,5 +?.#.????#??#????? 1,6 +???#???????.??? 1,3,2,2 +?#?#?..????.?#? 1,2,1,1,1 +?#?#???#?#??????#?? 3,7,4 +??#???#????#??.. 2,2,1,4 +.#????#?#?. 3,3 +?#?..?##?#??##? 1,8 +.??#?#???#?.??#??? 6,2,6 +?#.???.???? 2,2,3 +..?#??.?##??#??.?? 3,7 +?#?????.?#??????? 4,1,1,1,1 +?##??#???.????#? 8,2,1 +?.#???#??. 1,3 +???##??#?#???#..?? 5,1,1,1,1 +???.???????#????? 2,2,8,1 +????##???#??????#..# 5,3,1,1,1 +?.???????????.?.? 1,8,1 +???.#?#??##?#???#?#? 1,15 +????#?????????##? 6,6 +??#??????????#??##?? 4,5,4 +??.???????.? 1,2,1 +#???..?##.. 1,2,3 +.#####?.?.????# 6,1,1,1 +?.#???#???##???.#.? 1,1,3,4,1,1 +?#???##??????? 2,5,2 +????????..??? 1,3,1,1 +???????#???.?. 5,1,1 +???.???#????.?????? 1,2,5,3 +?????.??.? 2,1 +???#???#?.?.#????#? 7,7 +??????.#??# 3,4 +??#?.??##?##???#?? 3,9 +..?##?#????. 3,4 +???#????##?#???.. 12,1 +???.?#?.?.?.??#????? 1,3,1,1,3,1 +#??#??#.??#????###?# 1,5,3,7 +?????.?????. 1,2 +??????.?.?? 4,1 +#???.??#?#?????????? 1,1,7,1,1 +.????#??#? 5,2 +##.??.##??#?#???#?? 2,1,2,1,1,5 +???#??.#??##??????? 1,4,5,1,1,1 +?#?#####????? 8,1 +##?.??##?#??#.? 2,8,1 +??#?.??????????????? 2,7,1,1,1 +?.???#?.#??#??? 1,3,7 +???????#?#??.?? 12,1 +.??#??..#??##?#?. 3,7 +??#????.?????.?? 3,1,2,2 +????.??#???? 1,1,3,1 +???#?##??????# 1,6,4 +#???##.??????# 6,1,1,1 +.?????##???#??###? 2,8,4 +??#?.#?????? 2,2,1 +?#?????????. 3,2 +??????????.?# 5,1,2,1 +.?##?.???... 4,3 +??#???????.?# 1,1,4,1 +?#???##????.??#? 1,5,4 +.?????#???? 2,5 +??.?.???##? 1,1,3 +.#?#????..???? 3,1,1,1 +.???#????# 5,1,1 +????.??.?# 3,1,1 +.??????..??# 2,1,3 +??#???????.????. 3,3 +???.#????#?????#? 1,1,2,5,2 +.????#?????????. 8,5 +.#?.###?##?? 1,7 +?.#.??.??#???####. 1,1,1,1,5 +.?##?###????? 9,1 +.?.?#?#?#?#. 1,4,3 +?#?.##???????. 3,4,2 +#.??.????????????#?# 1,1,1,8,1,1 +#?.??????#????#?#??? 1,1,1,1,4,6 +???.??.??# 2,1,1 +#??????#???.#. 10,1 +?.???#??????.?.?#??# 1,10,1,2,1 +?.?##???#?? 3,2 +???#...???? 2,2 +?#??????????#?## 3,1,1,4 +??.??.?#???? 1,1,3,1 +.?????#??#???. 4,3 +.?#?.?#?.?? 3,1,2 +???.??#????.? 1,3,1,1 +?#??????.#?????? 3,2 +???#????##??#???. 1,1,10 +.#?#??????? 5,1 +..?.?????????#?#?? 1,13 +?????..??????? 4,3,2 +?#..?????##?#???.??? 1,9,1,1 +?.??#?.??.?? 1,4,1,1 +???##?##???.?? 1,8,2 +?#???.##?.??? 2,1,3,2 +???##?#?#??##??#??? 1,15 +.???.??#.#?? 1,3,1,1 +??..??#???#??? 7,1 +...??.?.?#.?????. 1,1 +.?????.??#???#??? 1,2,4,1,1 +???.????#????? 2,6,1 +.??#?.#??.???#####?? 1,1,2,7 +???.???#???? 1,1,6 +?.??..????#????#?? 1,6,3 +.?#????#????##???.? 12,1 +?????????#???? 1,1,4 +????.??#?#??? 1,1,1,5 +??#.?.???? 1,1,1 +?.??#????#?. 1,9 +????????#????.. 6,1 +?#.?#???##???###?? 1,3,8 +???????.???. 3,1 +.????..???#? 1,2,3 +??.??#...?????.?.#? 1,2,2,1,1,2 +???.?.????#?###?#??? 2,12 +#.?.??#????# 1,1,1,4 +#.???.#?????. 1,1,6 +#.????.#?# 1,2,3 +?????..??##.?# 1,1,3,1 +.??#?#?#???? 5,2,1 +.??##???#????#??.... 2,8 +??????.#.?#?#??#??? 1,3,1,10 +#?#??.#?##.???.#..? 3,1,1,2,1,1 +?.??#??#????# 1,10 +?.???#???????#??# 1,7,5 +?.#?????## 2,3 +?#?#?.???.?# 2,1,1,2 +#.????????.###?# 1,1,3,1,5 +?##????.??? 6,1 +??.?#?##?#?.??.? 1,5,1,2 +.?.#??????.?? 1,2,1,2 +.????.##??..?#..? 3,1 +?#??##.????#???#?? 2,3,3,1,4 +???#?.???.?? 1,2,3,1 +#?#???#.????###? 4,1,7 +???.##?????#?#?##?. 1,2,2,7 +.##..??.#?#???#???#? 2,2,7,1 +...#??#??????? 1,2,2,1 +?????..??#???? 5,1,2 +???.???????.??? 1,6,1 +?.??.?#???#.### 1,1,1,1,3 +????.##???###? 1,2,6 +..?#??..?.??#?##???. 2,9 +.?.??..???? 2,1 +??.???.#?#????###??. 1,1,3,8 +?.???#????#?##. 1,1,1,6 +??.#?????##??#?## 1,1,6,5 +?.#??#?.??..??# 5,1,1 +?????###.??#???#???# 3,3,4,5 +?#..???????.?? 1,5 +????##?#?.?????.? 5,3 +????#?????. 4,2 +?..?.?#???#???? 1,1,2,1,2 +??##?#????#???..? 4,2,5 +.?.?..????.. 1,1,1,2 +?????????.??##????? 1,5,3,1 +?.#.???????# 1,3,4 +?.??###?#??#..??#??. 9,1,2 +?????????? 1,1,1 +?##?#???.?????#????? 8,1,1,2,1 +??#??##?????. 8,1 +.???..?##?.??? 3,4 +?????#?.#??##???#?? 2,1,5,3 +.#?#?#????.???# 8,4 +??..?.???? 2,1,3 +.??.???##????. 2,1,3,1 +.##???#????#?. 8,3 +???.#??#???.#? 1,1,2,2 +.???#?#?#?#?##???#?. 10,7 +??...???#???# 1,5,2 +?????.??.?#? 1,1,1,1 +???.???????????###? 1,1,1,7,3 +????????#???? 1,3 +???.???#????.??# 2,7,1,1 +?#?#????#??##? 1,1,4,3 +??????#???#?? 4,4 +????#?.?.??????#.?. 3,1,1,4,1,1 +?#??#???????? 1,10 +.???#?#??#???##?? 1,7,5 +.???.#???#???? 1,2 +??#???#.?##?#? 3,1,6 +??????#???#? 4,1,1,1 +??#??##??#.#.?#?? 6,1,1,2 +????.??#??.?#.?.? 4,4,2 +.????#???.?#? 5,2 +?.##?#????##???? 6,6 +?#??.#??.???##. 1,3,2 +???#.#?#?#??..??.? 1,1,7,1,1 +.??#?###.?# 7,1 +????..?#?? 1,2,2 +?#???##?##. 1,6 +.#.?.?????????#. 1,3,2,2 +?#?#??.?#???##?? 5,1,4 +?#?.??????????#. 1,2,5 +..??.??????..?#?? 1,1,1,1,4 +??##???#????????. 6,1,1,1,1 +???#?##??????. 5,1 +?#?.?.???? 2,3 +????#????#?##????#?? 1,10,3 +#?##??????? 6,1 +??#???.???#??. 4,2 +??##??#???#???#. 5,6,1 +?...#???????#?.?.?? 1,2,5,1 +???????##?##?#?##??? 1,14,1 +?#???#.??????##?#? 4,1,1,6 +????????##?#. 4,1,2,1 +?#.???????? 1,2,3 +.?.???#?#???#? 1,1,8 +???##??#???.. 5,1,1 +????#??????.?# 2,3,3,2 +?#?????##?? 2,1,5 +??.#???#.???#? 5,3 +??#.?#?#???? 3,3,2 +?.?.#?..#? 1,2,2 +????#.???? 3,1 +?#????????. 3,3 +.????.????.? 3,3,1 +?##.#??#?#???#?? 2,6,1,2 +????##.##????.? 1,4,3,1 +.#.???#???. 1,1,3 +.?????#.??.?? 3,1 +???????#??.# 6,1 +?.??????????#. 4,3 +??#?#?#?#???#???#. 12,1 +?#.??#?#?##?? 2,8 +??.??#??#??.???#??? 1,7,4 +#.????.?.#??? 1,1,1,4 +.?#.?????#??? 2,6,2 +???#??.##?#?#??#???. 2,12 +?????????####?.????? 1,1,7,4 +??.?????????.?.????? 2,1 +??##?#?##.??#? 9,2 +??#.#.?????#.???# 3,1,2,1,1 +???#?????#??##?.?? 2,7 +?#?#?.???..???. 3,1 +#?#.?????? 3,2 +.??#?##???.?.????? 7,1,1,1 +??#?#???.#?. 3,1 +#.?.???????? 1,2,3 +??#??????. 3,2 +.?.??.?#?? 1,1,1 +.??#.#??#?.#.????#?? 1,1,5,1,7 +??????..#.??? 1,1,1,2 +.????????#.??????? 2,3,5 +?.??????##??##????. 1,8,6 +?.?#?#??..##?????# 5,8 +?????#?.?.? 2,1 +??#??##???#?#. 1,1,9 +??#?#??.?#???#?? 4,7 +.??.?#.??#??? 2,4 +?#?????????#???#?#?. 1,1,1,1,1,6 +??????.#??? 5,3 +?????###??.#???? 2,6,4 +?????#?#???? 1,1,5,1 +?.??????#?###? 1,2,1,5 +##??#??.?#???#? 5,1,1,1 +#???#???.?? 1,5 +???.?????#?? 1,8 +???????.?##??#.??# 5,1,3,1,1,1 +?.?.????.#?#???#???? 1,1,1,7,1 +????#???#???#????? 2,1,2,4,1 +??#?????????? 2,1,4 +???#?.#????. 2,4 +?.??#???.##.? 2,2 +?#.#??.??????##?# 1,1,1,7,1 +?..?#?#.??#???.?. 3,4 +????.#???#??#??#??#. 2,1,2,1,2,2 +??????#.##?##?.?.? 1,1,1,6,1 +????????##?#?# 2,1,6 +.#????#.???????? 6,2,3 +#??#???#????##??. 8,1,2,1 +?.?.?????#?#??????#? 1,9,1,1,1 +#???#?..?#??#??.??. 1,4,1,1,1,1 +??##?##.??###????.? 6,7,1 +.?????????? 1,3 +.?????.?#.??#???.. 1,2,5 +.??.???.??? 2,1,1 +???#????#?#??#.#.?? 1,8,1,1,1 +?.???..?.? 1,1 +..??####?#.????#.? 6,3 +?????#????.???#?# 7,1,3 +###..????????##??. 3,8 +??.?#???#???????# 1,2,6,2 +????.???#?..? 3,4 +.???.??#???## 1,8 +???????#?.? 1,2 +?.?###.??? 4,1 +????????.# 4,1 +??????????????. 2,1,1,1,1 +?????????? 1,2,2 +#???.?????.??# 3,1,1,3 +?###??..?##???.?.?# 4,5,1 +???.?##??.?#???#??# 3,3,1,1,4 +.???????????. 1,2,1,1 +????...???. 2,3 +???##.???????? 1,3,2,4 +##?#??.????##????.?? 5,6,1,1 +???#?????##.#.?#? 1,2,5,1,2 +.?.??..???? 2,3 +???.???.??##???.# 2,1,4,1,1 +#????#?#?? 2,5 +?.??.?#?#? 1,1,3 +.?.??#??.??#.????? 1,4,3,1,2 +#.?????.????.??.?. 1,3,1,1,1,1 +???#?#?#.#??#??????# 1,1,3,7,2 +????????.??? 1,1,1,1 +???????#?. 2,2 +.???????..?#??? 1,1,2,1,1 +?.??.?????#???.? 1,1,2,6,1 +????##?????.??? 1,3,1,1,1 +????#???#..??.? 1,4,1,1 +??????#???.?? 5,1 +????.?.?????? 3,1,2,2 +?.??.??.???#????# 1,4,4 +.?????.##?????? 1,2,8 +????.???#???#??? 2,8 +.?????????.???.?.?. 7,2 +?#.?#??#?#???#?.???. 1,1,8,1,1 +???????#??##???#?# 1,2,1,8 +???#?#?.?. 1,4 +.#.?.#??##??? 1,7 +.????????.. 2,3 +???.?#???.???? 1,5,1 +???#?#?????????##?#? 7,6,1 +?#???#?.?#...? 5,1 +????#??.#? 1,2,2 +??#????#??# 2,1,5 +.##??##??#?.. 2,2,2 +#???.???#?.?.#???? 4,1,2,1,1,1 +?##????.?????????.?? 7,1,1,3,1 +??.??.#????? 1,1,2,1 +???#???.???# 1,4,1,1 +?.????#??#??##? 1,1,3,6 +??.??????#.?.?#???? 1,1,1,1,1,4 +??.????.?.#?????? 3,6 +??###??##???#?#? 6,2,5 +??#?.##.?#? 1,2,1 +?..??????.??. 1,4,1 +?#?#??????.??#??? 8,3 +.##?#???????? 7,2 +?.?#.?.#???.. 2,4 +?#??#????#??#?? 2,3,6 +?...???.???#?#??? 2,6 +?##.?????.??? 3,2,2 +??#???.????.#? 4,2,1 +??#????????..#???. 1,4,3,3 +??#..??.?#?. 1,1,3 +?.##????#??#. 3,1,1,1 +???#??.?#??????. 4,6 +?.???#?#??.??#.#?? 1,2,3,3,2 +??#?????.???. 3,1,3 +???##?.?#.?.??? 1,3,2,1,1 +???##??##?????? 1,11 +?#.??#??????. 2,1,1,1 +?..?#????.#??? 6,1,1 +????#???#??#?. 4,4 +.??#?#???#?? 1,1,6 +#?????.??.#?? 1,4,2 +?#???.??????#?.#? 2,2,5,1,2 +??#?##??.? 1,5,1 +??????#?.??? 1,5,1,1 +???.?#????.?##????? 5,4 +??.?#???.??#??? 4,2 +??#?#??#?##?#?.??? 5,6 +??????#??????.. 1,7 +?#?#??#.???.?#? 4,1,3,1 +?##???...#????????## 5,3,5 +??#?#????????????? 1,8,1,3 +??#???????.. 4,2 +????..??????#???? 2,11 +?#.??#?#?????..?#. 1,5,1,1,1 +.#??????#????#.? 2,2,1,1,1 +????????.???.??#??.? 2,1,2,2,5 +?????????.#?##?#?.? 2,6 +?..?.???#???###?? 1,8 +????.??????###???? 2,7 +?#?.??.#???#?### 1,2,1,1,5 +.#????.?#? 3,1,1 +?.??#?#.#?..# 5,1,1 +???...?..????. 1,1 +?.???#?#?#?#.? 6,3 +##..#???#????? 2,1,4,1 +?????##?#?#???#???? 1,15 +??.????#???????? 1,1,6,1 +?.???#?.?????? 5,1,2 +??#?.?.?#?#??.? 3,1,1,1,1 +???#??????????? 2,7 +.????????#???# 7,1,1,1 +?##?#???.???? 2,1,3 +??#??#?#.?????#???. 7,1 +??.????#????#?#?# 1,14 +.????#???#???? 1,6 +##??#?#.?#.#? 7,2,1 +??..?.?##?. 2,2 +??#?#???.#..#.??? 6,1,1,1 +.##?.???.#? 3,1,1 +????#????#?#?? 2,8,1 +.???????????????? 1,3,1,4 +?#????###????????? 4,7,1,1 +#?.?#???.?#?#?#?? 2,1,1,7 +???#????..?? 5,1 +?#.?#?????.?# 1,1,2,1 +??##?#??#??#??.?#?? 9,1,1,2 +##?#?.??#?? 4,2 +..#???#?.??#####?.? 6,5 +??##????#? 3,4 +##.#?#??#??##?.? 2,1,9 +????#??????.?#???#?? 1,8,6,1 +??#??#.?#.?#??.??.?. 5,1,1,1,1,1 +?..#???.???#???? 1,2,1,2,2 +.???#??????????##. 4,2,4 +##??#????.??.??? 2,3,1,1,3 +?????.???##???? 4,5,1 +.?#?????##???# 1,5,1,1 +?#?????#... 3,2 +????????.?#?#?? 1,3,3 +??.??#??..?##? 1,4,4 +?????????#?????? 3,1,6,2 +??????????.#? 1,1,5,2 +????.###????????? 4,10 +???#??..?.??#????? 1,4,1,1,1,1 +?.??##?##???###? 1,12 +?????????? 1,1,1 +???#?.???#? 1,2,3 +?.????#..??? 1,5,1 +????##??..?#?. 1,5,1 +?#?#?#?#?????#?.?. 6,1,1,2,1 +??#??##??#?.??..???? 1,7,2,1 +.????????????# 2,1,1,2 +.#?#??.??#??#? 4,2,2 +??#?#????? 4,3 +????????????##??? 1,1,7 +??.????????? 1,2,1,1 +##??????..????? 5,1,1,3 +.##?#?###???##??? 4,9,1 +#?????.?#..? 2,1,1,1 +#????#????#?.??#.#. 3,6,1,1 +.?#????#?#??????.?#? 2,1,1,5,2 +.????#?#.#???? 7,4 +..#???#????.?#??..?. 1,3,3,1,1,1 +???..??##?#????? 1,9 +?.?.??##?..# 1,2,1 +???###????#??????..? 1,6,1,3,1 +.??.??????.?? 1,4,1 +.??.#.#?.#?. 2,1,1,1 +?.???#??#???.??#?.?? 2,1,4,3,2 +??#??.???#??# 2,1,4 +#?.#??..?? 1,1,1 +??#?#.????????#?. 1,1,1,1,8 +?..?#?.#?##.#??##??? 1,1,4,1,5 +???.???#?? 1,3 +.??#.??#?#????##?#?? 2,13
\ No newline at end of file diff --git a/aoc2023/src/day14/input.txt b/aoc2023/src/day14/input.txt new file mode 100644 index 0000000..7263053 --- /dev/null +++ b/aoc2023/src/day14/input.txt @@ -0,0 +1,100 @@ +....#.#....O...OO..#..#....OO...#.#..OO#.#O.#.O.#.....O....O......O..........O.....O....#..#O..#O... +O#....O..#O........O.#...OO....#O...O#.#.....O.....O.O....##...O.O..O.#.O......#....O.O.....###....# +....#.#O..........O...............O.O..#....#..O#.#.........#..#......#..O..O.OO..O.O#O.OO..O..OO..# +...#OO....O.......O#.OO#.O#..O#.O..O#OO..#OO.O.#..OO......O...##.....#..O##O.#O.......OO.#......#... +.#..#.O..#....#O....#O..OO...#O.#..O..#.....O#....OO......OOO#.#.....#..O.##.OO....#...O.#.O#....#O. +..#.#OO#..#.O..O.#..#O.......O...###......#.#.O..#.O.#...O.....O.O#...OO...#..O..#...O....#....#.O#. +......OO....OO...#O.......O##..#........#O....O.........#.###..O...O.O........OO#.....O#.#.##......O +..#....#.#...O...#..##...#O....##..#..#....O..O...O.#.....O.#.......O.OO....#OOOO.#.....O#.#..OOO... +.O..##.#O...#...O......OOO.......#O.O..#.#....#.....OO.O...OO#.O.O....#.#.............O##....##O##.. +O#..O........#..#...#.....#..#O.#O....###...#....#..#OOO.....O.O###.O..#O...O...##..O....O..O....O.# +...O....#..O.....O..O...O....#.O...#.#....OO..O.##....#.OO..O...##....#..#OOO.#O#...O#O#.....#..OO.. +.....#.##.#..OO..#..#O#O#OO.O......O....#.O..##O....#..#..#...O#O.#.O..O....O.......##.O#...O..#...# +.....OO.....#.....OO........#.OOO.O.#OO......#.#....#....#.##..O..###.....#....O.O.......OO.OO.#.#.. +#.............OO......OO.OO#.#...#.##.......#.#..O#..#.O.#.....#.O..O...O.O........#O..O..O..O....#. +O..O.O..OO#O...OO...O...#.O....#...O...O#...#.........O...#.#OO..OO..O.O........#OO.##.O#..O......OO +..##.##.O.##O.O...O.OO#...........#O...O..O..#O...........#.#.###.#.#.O.O....##..#.O.OO...#.....O#.. +....O......OO.O..#.......O..O.#.#O....O..O.#....O..##.O#...#..O#.#.##..O...#O...#.O.....#.O...O#.... +.#.O.O.#....##...#..##..#.#.O.#..O.....#..##..#..O.......#....O......O.O.........OO.#...#.#O...O.O.O +....O#..#....OO#..OO.OO.O..#OO#.O.......#OO.#O..O.#..#..#OO...O.....#...O........#..#..O...O..O.O#.. +#.O..........OO#O...........OO....##.#.O.....OOO.#.......#.......O...#..OO....#....#.......O.O....#. +..O#......O.OO......O##......O#O....#OO...#.OO....OO#.O#.O.#O..O.....O......O.....#.#O...#OO#..O.#O. +.#...#OOO...O....O...OO..#OO.#.O.OO.O.O.O.O...#..O.....O.#O#.O.O.....O##...#....O##.#.O....#..O...OO +...........#..........O#...#.....O#..O.....#O.O.....O.O..O.#.OO.O...O#......O....O#......OO..O.O..#. +#..#.OO..#.O.##O.O..#....#O#O#..#...#OO..O....O...O..##....OOO.....O#..O..##O..O.O##.OO..#.........O +O.O.##......#...#O.##.#.OO..O....O.O.O#..O..####........O......O....O.......O#.....O.O.#.O#.O.#OO#.. +.....OO.#..OO..O..O.#.#....#..OO..OO.....O#......O.#.#........#...........#....#......O....O..OO.#.O +O##..O.#...OO#..#..##O...O##.#O##.O.........O...OO#..O.#.....#O.#.O.....#...##..#O.#...OO.#O.#.#.#.. +...#..O..O....OOOOO..#..#OO..O.#...#....#...O........#.#........O.....O..O....OOO.....#.O..##..O.##O +.O.#O.....#O.O#...#..#.OOO.O#.O....#.O...........#.....#...#...O....O.#...O..#...O#.......O..O...... +..........O##...O....##.....O..#.......##.....#..##.#O....#..O..##O...OO...O.....#.O..#..###O.##..O# +..###O.O.#.#O....O#.##..O.#..##.##O.O.#..O#.#.O#.O.##...O.......#...O.#.......#..##.O...#..O....O.O. +...O..O#.##O.....O.O.#O..O#.O##.O.#....O#.#O.O..#......#..###.O#O.##.........O...O...O#....O........ +.O....O.#....#.OO#..#O...#.......#......OOO.#OO.O#.#.O......#O#OO..#O.O..#..#.O.............O#.OO#.# +#O.O.....#.O.O#...OO.......O...O..O.#..........O......O.O..#O.#.......O..#O#...O...OO.#..#.#...#...O +.....#....#.....#O..O...O...#.....#OO....#..#O.O.#OO..#.O.O#...#.O.O..#..#..#OO#..#..#..O...#..O#..O +....O..OOO.##...#.O#......#O.O.O....#O..#.O..#........O#.O...O........#O#O..#..#.O...O.##.O.O.....O# +.O..O#.O..#.....###..#......#OO..........O.#.O#..OOO.###.....#..OO.#O...O...OOOO...O.........O...... +O...O.........O......OO...#..O.##..#..#..O.....O..O.........O.O..OO....#..O.#..##OO#.#....#.###..... +.OO.O.#......#.O.......##..O.O.O#..O.OO...O#..#.......#.........OO#.....#..O..O...O.O....#.O..O#.... +O...#..O.OO..O.#.O...#.......#.O.O.O.....#.....O..OOO#...O.#O.O#..O...O#...........O#..O........O... +O#O.#O..#.......#..O.#..#....#..O..#..O.#......O.OO.O.....#.O.#....O.#.......O......O#.O...#.#.#.O.. +..O#O.OO..#......#.#.#....#..#...#..O.#..#O.O.......O.##...O.O.O.#O...O.O.O##O..#..O...O..OO.#..#.#. +...O.#.....#O...O....O....O....OO..........O.O#O.O.O###...##O.#O...#O.#.OO...#..#..O##...O......#... +.##.##..O..O#...#O...OO.#...O..##....O....#.OO...#O.O..#..O.#.....O.O.#.##O..O..O.O.......O...O...#. +O.OO.O.##.O..##OO.............#.....O....#O..O#...#.##.#.#.........OO..OO..O....OO.#O.O..O.......... +#..O.O....OO..O..#...O.....O.#.O#.O.#.#OO#......O.O..O.O...#.OO.#.O#..#O.#..OO.#..#.##.....#OO...OO. +..OO##.#........OOO..O.##....O.O#...OOO......O...O..O.#......#.O...O.#..O.O..O.O..O.O...#O.....OO.#O +O..#..O.#.O...#OO##......O.O.....#O.#O#O.#..#..#.OO..#.O##......O.#O....#.....#...#...O#...O.O....#. +O.........O#O#.#.#......#.O##.O.O#......O.#...OO....#...#..#O#.OO#.###.O.#.#..O..#..#OOO#O#.O...#O.# +.O#.O....O..OO..OO#...#O........O.OO.O#O##.O#O#....#...#O#........#.#O.O#..#..O##..##.........#.O##. +...##...O.#O.##....#.....O....#..OO..O...#.O.O......OO#..O#..#####.#O..#.#....O.#...O...........#O.. +.O.#.O..OO.O...#.#....#...O#....#O..#O.#.O.O.O..#..O#.O...O..O.O#O.....O......#O......#O..#.#O.O..OO +......#........O.#O.OO.#...O...##.....#......OO...#O#OO..OOO....#......#..##..#.O...OOOO.#....O...#. +O...#O..OO.....OO.OOOOO#.O....#...#...O..#..#O....##.OO.#OO.OO..#O..#O.O#.OOO.............#OOO....## +.#.O.O..O.....#..#....#...OO...#...OO.#........O.O....##..........#.#O...OO###OOO..#...#..OOO..O..O# +O#...OO..O.#........##......#O....#.........#....O#.#....#..O...O#..O.#......OOO.#....O..OO...O##.OO +....#O#.O..O.O..#O.O#....O.#.O...OO...O..OOO..O.O.O#.#...#.......O.O..#....O...#O.##.....#.#O#.OOO#. +.O###...#...OO.O.....O.....#..OOO.##O....OO.O.............O......O..#.O..#....#..#...#..#O..O...#OO. +...O...#..........#.O..O.........O.O.....#..#....O#O...#.O.#OO.##O...OO..........#O..#....#O....O... +..O..O.#.....O#O..#O##O.#O.O##.#.....O.O.O.#.O.....OO..OOO.O#.OO.#...O..O...#.O.OO#..OO.#..OO####OO. +O.......O#..O.O.#.#...O.OOO...#O....#O.O.O.O...#......O.##...#........#..#..#.#.O##..O.OO.#O..O..... +..O..OO..#....O..OO.#.##....#.......#..#.#..O#..#.#OO#..........#O#O...O.OO...O..#....O...#.......O. +....#.#.#O..O........#.O#.O#..#.......#.#...##OOOOO.OO.O#..#....OO..OOO.O......O.........#..OO.O.#.O +O...O.....#O###..O.OO.O...O...#...#O.....OO...#.....O.O.O..#...O.O..#O..O.O.#...#O.O..#..O....#OO..# +...#..#......#.O#....#O#.O....O..O..O..O....O...#..#O..#.....#...O.....OOO..OO.#O#.......#.O...OOOOO +OOO#.O.O.#O....O..#...O..O#O..O#...#...#..O#..O..O.O#......O...#O..O#.O...#.O.#...O...OO.#....O..... +O..#O...O#..#...O.#.O......#.#..#.O...##.O..#O...O#.#.O.....O...OO.OOO.O.#..#.O....##.#.#O..OO...#OO +...O.O..O.OO.O..O.OOO.O#.#..O.....OO#..OOO.#.#....O.#O.#.O.OO....O..#..O#O###OO#.......##........#.. +#...#..O.###.O.#O......OO#......O.O..#O......OO.O.#....#....O...OO##OO#O...O.........O#OOO.......... +..O.O..............O.....OOOO#.OO..O#..O.###.O..O.#.O.O.....O.#O.OOO..OO#..OO.#.....#.......O#...O.. +O...#.OOO....OO......O..O......O.....O....O..#O..#.O.............O.#..............#....#O....#O#O... +.OO.OOO.........OOO#.OO....#...#....OO...O..O.....#...#O..#O.O.#.O.#O......O.O.O#..O.O.#...#O....O#. +O.....#OO......#.#..OO.O.##O#......#......O..#...#O#..#O..O..#.........O..##.O..##O.#.#.O.#..OOO#..O +...O....#..#....OO.O.##...OO#.O##..........##.#..OO.#..O#.#.O..#...O..#..O..#....O..#....O..#.###O.. +.O....O...O#....O#O..O..OO...#O.O.....#...#.......#...##.O..#...#.....O......O..##...##......O.#...O +O#.O#OO.O.#O.#.#O..#.O..O..#O#O.#O...........O#.O...O...O....O......O.OO......O..O##..O....OO#...##O +..O..O.OOO....#O#..O#...#.O....#....#O..O#..##.O.....O.O#O..O.....##...#..#............#....O.O.#.O# +.....O.#..O..#.OO.....O...O..#.......O....#.##.O#O....O.O...#.OO....##O....O....#OO#O.......O#..#O.O +#O.O.#......#.O....O....#..O##......O.#.#....#OO.....O.OOO...#.O.....O#.O.O#..O#..#.....#.OO...OO.O. +..#O........O.O.O.O.....O..#...O.O.#O.OO....O...#.......##...O.......OO.#O.O.O..O.##...O.O#..##..#O. +O#O....O.O.O#.###O...#.....O..#....#.#.O.....O..####.O.O..#..OO.#..O....##..#O.##.....O...O.....OO.. +#...OO.#.#.#...O.#O....#O#.............###.O..O.O.O.#...##O..O#...OO#OO.....###.O..#.#...O.....O..O. +.O.OO#..O..OO#.O#.O..##....O#...O...O....OO.....#.#O.....O......O##......#....#..#......O##.#....#O# +.#O#O..#....##.OO.............O..##....O......#.........#.......#O..O##....#.....#..#......#O.OOO... +.O.O#OO..#..........O.#O.OO......##....#..O###O..OO..O..O.##O..#.......#..O..#..#.#......O...#....#. +.#.O....OO.O....#O..OOO.#....O.....OO..O..O...O...#..O....O......O...........#.O.....#...##..O.O#.OO +.O.O..O#O.OO..OO#.OO.#O.....O...#.OOO....O#......O.OO..#.#..O.....#..O.O#O.O#..O##O..O....O....O.... +..OO......#..#O...OO..O.#..#O##....O..#.#.O...O..#O....#.O.....OO.O.OO...OO...O#.O.....OOO...#....#. +#OO..#.....#OO...O.......O....#...O...O.#O....O....O....#.......O....#..O.....#....OO.##.OO#O.O#.... +#..#O....O#...#.#OO..............#OO#OO#.O....O..OO.O.O#...O...#..#O.#.......O....#O..#..#O.....##O. +...#.....#.#..#OOOO..O.O#O..O..#..O..O.............OO...#.....#O.OO..#..#.....OO.....#O....#..O#.... +...O.#.O.#O.O.O##..O..O.O......O#O##...........O..#..#...........O.O.O...O..#.....OO.O.......#O..... +#.O#O.....#O......O#.......OO.O.O..#..#..#O....#......#.O..O..#O#.###.#..#..#...O.OO....#.#O#..O...# +#..O..#.O.O......#...#......#..#......O...O..#....O#.O.O..O...O..#..#O.OOO..O...#.......O..OO.O....# +...O..OO#O..#....#....###O...O#.#OO..O...O....O#.#....#.O......#..#...#..#.O......O..O...#.O....#.O. +OO..#..O##.O..O...O..#O....#....#.O.O....O#....OO.#.OO..O..OO..O#...O....OO..#.OOOO.#..O.O.....#..## +.OO.O....O...O#O.....##....O..#O##....O.....##....O.#..#O#O.OOOO..O..O.O.......OO..O.#....O.....O..O +.O.O..O#..#OO..O.O.....OO..OO..##.#..O...........#.O..#.O.#...O...O..OOO..O.#O.#....O.#.OO..O#...... +..O#..O#.O...##..#.#.###....O#..O.O##.O.#.O....OO.#..O.OO.#....O..O#O.#...##...OO#.OO..O.....#.....O +...#OO#.......O.O.##...#O..O#.O#O#..OO..O..O#O..O.#.OO#.....#.....O...O.O.....#O#.OO.O...O.O#..#O..#
\ No newline at end of file diff --git a/aoc2023/src/day17/input.txt b/aoc2023/src/day17/input.txt new file mode 100644 index 0000000..04d0721 --- /dev/null +++ b/aoc2023/src/day17/input.txt @@ -0,0 +1,141 @@ +111143231245512453233532231135242346643223434366453543664553534426223663625563233556655232522464453223446255523366641115221525545241115541324 +431121345255453245532513346436354562424226665435625542452543534236556535432235356366222264336444256255334564563564226352335454152333342425531 +211555234333213145543413562433332533444634432342622623343343455746676435745474465524463464332524462636562533446346254251543254415111115352424 +341511535443122253134546264233423566232562433526456565542774357646735536654673474477533643232255236632236625425666662645545552141115242422515 +341111243411143233254353542425566625642433362644332467546476655667755374563574564666444577323426235362444224643634223545235541134121215423153 +531254335432123321511666236453536252626542365563233477476436375343677375447543535337476464737335222455333555262365434346341345121543421555545 +352535514521514111243342542545234362225656644366655563365373766737565463557476566764463743673533232534423432654354532444434614515232111523231 +534444213321253145553225546453244552566243427573456456543553566474735356663557433377547454546773337365265654362565366242546625513555231514252 +323313551435534512622225362562263434433225636635664736767633535463645434646666633445555455344676663776363645426625355443264235342154354541551 +313344353445542136265245463656643456254675743474744556363764667356336334435764645543447755363434777747562523535253545462232443334115422245343 +411545355323353632256366354543644422255357345374367446347554465766367637555443653555375756736537575763375343236242446526465226534224412555332 +533131433141412662643523326542423234474465776365555735754776645376734774677646654667473753373634447774446536352326333564334433362123135411531 +512414542555163643526524526245525623733466554345447435364657576457576376563367444354735757756765547755635545232536536433564236626315454145425 +222144425355524633235543562342566454344764575745367646565574575636547773457356646456657637437547666745757773472565443652346664466335313555551 +425225555322663532264234233335563664747574765576347743444637647676737567333767356736363333744734647436646746476523664454633653546545122514442 +433432345135556643645433433353363575647663645376464776466577573557373364773353335555374554433464633534445576673653325425446624523422432115313 +331554441535436542646663554246654555367643355653745635636355676647567487764456667645455574637564434547453345476356634245324255236624234322155 +412551332642256525656556644673435575337544534765547457535765745875846744677848864748453556456475334367766655534547433255523464263563352324545 +443534155643554356242335334673736746664536333346353556577644664845484655676855576588488476647745635435535753465654355645265546422335564424541 +325113645335432555665355233555675344354467477467666744857886746774544874557756677867665777554343734443655754353756656432453432656526442431243 +435351452355523445664565747636637443475667333666457866648755647865645478687666547687547448455776553463657435344656637472443446523245236631254 +412143553424345325232454645555356743366537373758877467577647678654487674848784877787468644447756553677573465574353736576542332442522366564144 +431363252452364445356544557475337767655336557686768756474568654665465464884556855744876886546758447344734334637754557774553226363256242242651 +554256445333463534225356746736736743336763377746888675584476754588545785578747858657577787754874858864355637365443444365474546636352256656323 +425454462356554263636434334444466455765534574648745458464655777887654744458644875776467657545757755464375636667554445537457232633344456335351 +322453463334656455234546433475533746373377467777858787845857478676767845586566768464584884875677444488543533447537536376643424666645653654426 +432326546526255522353556547373665657473456445577748547665675868677547547785865454645454554774845748574876563377757437467553465624365666252336 +553526552222562635473565556657553364657548886884887656456865855666787554686645654858555566768654648745854464677634735446546732553642463664265 +664326265443345443746744735336634755665574447844755544578487644586454874856778477455686458576478578547554484667445666574665353445232224622335 +236532234245355276756476464355554554458887564887776455877644448447886868476548867546888764476866776558545547574453545467364757744326636223642 +632462455662552665443463346747745775658756746854568758745668675885889865596789855788675844755468675857556885843566367733464537666322366344223 +266666434363243576375767356665666877464755765578746575486748669688797696588866786698768646566485868545858886667435664777734463342523665555235 +443556525665656734577633335664448556655454678484454777545656666779696855688567966656964658877444685858567566545447466467443774467266252546652 +624455255224344733376335533753476658646544876564465586875955788776686876776867985856986576866568765548476654745754674775433435367623356456444 +262555462622446474437456377453868684444668468464476655987967866795876695585957798678969855857886488747765845586764675544766563666356435634332 +665624325625734563547365736536784556858567746767459867695988595777767769865658796865788965789678867667866557578674565534645577447432435556524 +333523334637534573776476636576557488766777764446687995988678876956786678875775556987997957898658565656667557575548444354657655335367544525324 +456466363423657475573575435664578688587455448765669969578697785989658879886787878568857799889578874487556756544556443334633446546536443652664 +222244452574756367757776634686545577855644575756668896567598879867997957659885755779787658957586658876446588645487856454536434636745444545545 +232636356457556536556365668745444488466474574987976697975796699686796855588666956768955895958675868455454458767755755376733663633374544556332 +332332622576377345736534646747554866678866788995569677878555787567775875779596796566579977885676656586446765845854744577365444454343372523366 +555664262474645377674577674647867577478684688557896658796655557657577765775656667969779597586797679965585456677454664556665646757366673426233 +356255527734373436547644678865777848585857997655679875687575776559878678858588867877856678657789789868858554664844468646634734744447367636636 +552366365773455644547347758554786677468775568778877797978995878598699565857955898857969565997667878757554646688678786867367546447363537255433 +234653475644663446373734847876648467867886788586887579567587799999866977967976866766799575567556897979657666685654448547664746376435346465542 +252443375445565446367565867885578575654575966679888956889877897698678786876967769856955595897679599865976488848485865647735437666446344436434 +243525237374773653566366744564464668675869676798668978579668697966669789967787689668989669967785588576658588654658478886653675446657763525423 +562444777554463656777574486488654468576556956965987679867969676669986697889777667866868559769957958968686745774765777755575354754635335676536 +264352744565456657667484888447847467598998779789689696779679766996889786776689888878996777588978666887977978585445584446655336663435446574336 +463534645476375645554684778858555786676885996565697889699888899766678879678998899799887896956567777585869788585685647484757343657653773563665 +432465634665435774545666885858845649887698657968779889688769778768696698686869888977969768555995578977568967465456666555784577674443567347654 +242537757554573534676885677655767659695959757675998797988778888678799667799866896879686987675557878578887699478448447774787663353534367754553 +524667356567664767788788786864867869567798856688887886998887976986998886686668767699776989677585877675977659745685675557555653563563733554246 +532356647776353655754665854564646466686577777586598677698878676969777768866697689778788897669979897577868888984565784456765466355374543736764 +353546744764545745656756586777658658697565657989587766697669768667797768668968778798869989666758756995866965667844757477467833575363475573665 +442363475553366336665585574875754767958869656955766897687769989798869789778887686787686676968967586798766967684684745655757855634753733757752 +663437377653673574868444644474888676596699778559668686678686966786679878697997667998668668679678775566688577957447548475848855753337766577654 +245676667643445744476584585486889868856958677757876786686678679686978889886998888999768868796876597559998755655765588557465675655453656434644 +623664534334746636755767677464487956975558566697767697896988988986888777988897867888887969667768658555778858798767857588765444464637377577456 +524435763477353755875846887578787556979997766576796978767969777889977779899788987687978888689776897659786666856748548645756774746364367376634 +252436533765577358467857485675499965699779976868778779896779686779787987877779796678799678678799677596566778799678664684774444556767456547463 +425573537536465645667877564778768875796687778666777866678866888788777997889889889698977679979667875765578958585784474754466784455733343567735 +464333643643774675646874764777889966956967776676876886799688979878878778878789889986887997868689965998667998898957544586884784556635746634644 +467634766367575447675444786885857898689798675679979967666789787898898779879998789996988787997866879557586768558865648756677648655653544434374 +343746456733555668756758766647798687656987598967767769799669777877779899879877997887788976797777786786686766555655656558576555537543536634463 +263736676335556377774776475777798578965889979797877679967769989798889889987997789799998866789986877778878665966865757677884784553474773577764 +436645433455747776854766587748677575858967897999889678767678779989877889979988889997876876767987687678559995869785556756658784533445456534364 +457333367374443446568888867558968899899755558786887989669778779799789777789789877797786878778769899759866986568874778856465478635343345547556 +653357365735437544784775777648977566996787598779866797796688878798979898888979997778969666688778767767968675685577484857666844654735677553374 +454465553543537354546566487886759755777886869789896779676678877997997979878787978898769888779699678677788756997994554564684577435566665665735 +645535635654537444576458775888989557678676898899899898879778777789998888888977799999876678677779969957869757677687688584466575575557463464574 +633446673336665785786556488457569967799656676688968667697989989999998988788999877898996869789799978989768599766594875486774675764367566653437 +365763544374353687774557856867888579757898686969676796986689878797978997979877977999799987889766778769957988885866744454548487444537747767446 +333636755475457746774775664885768689998686877878978686686998999898899898989888977798768997778786769665986876885655876855777745646444453543776 +257347366566556755557468747484878859559855958778679799887889887788997889779777777788977698668899997569799999896694654866676457747663766657374 +554664657744433558785576687586858965859676988969678669886988889998798779998998788898786688897788767697957657558568566856664764845635356777743 +437633353637643445485457545565887558959759869766978967769977997997797798898879888977777798877668879696986885979575658888674584733534445447645 +336773576566535576644748576564988895569965579877899669988897888788798979797979977997979687769689677585858655985875545766888476856753753775643 +447375436754766447678756554674875656886886797769889788989967878998987877797878888989798769897678795698885689978868887845785867854575334643545 +533774774334356485744844667888778799675896759697877967979877898888989779897787899796896869887878898896679879895846474568577556875467653377434 +526636647656677568754477458676456866878885686668989676699978797889989979777797888789689887999898765668796877998956878884644777453766767665573 +345776437655574577556784475666467865969688769689967879888899898787979977987989787869968767788798958965676985977558887786764565334636477577473 +462757555367744435776477675765555899756777555889787899796876786789979777799889999696968778897788975596967795797586768684467474533464663474556 +345335634367663334474446748788558686895898855886668998998877799988977999887787778696789977998687999799569767555576845465465587544735477547753 +352747473367547538454567786546446657585759898569988897798777688798687998988998969877688876686969789765886558558776665847888845556554375745442 +525653575563555774887556547555749798556987599756797867867689696667867966889689666776786689697968958698665787755764558846666855575573747534345 +326455665753733645448778877747875897567979969887898786977796667699978788696867677769979676996787658598765877957588784457484655764635365737434 +532467433765464655746576865775654596585859789697688867896988996977778898788669689878989769996769668658678679877544854467444775477564333674625 +335554544454457654447885484444866987787685589987766897996999779767969767678887676699997786677685669976768778997556877487444743767346766557456 +266536345774333444487446686656585797768599588595599776878699669999678767879886989896988777767965756768698777544665754856565457554453756356643 +342464363736646775655856546787754867795697769679858888796987869768899868797687697688878796789895765557688688985446585777584467466735366644363 +523237467646754656468466848574555667758689797896579777988779889977689668778896667696797676667785685755986597446645664545687753465567453354335 +323327756536477335755748475656576547887995887876985968976869696887779786776968996997867687879755599699567657755468776866885345435457655334225 +465352366554666376467456666544455546795667757799755996999978667976979767898877678768888758985566989859967794845764466677657453363336553674426 +555533553546357444765675856588657557878975766698966577867797677999988677666767968786787775798789997676876774564485686564547464355336356456634 +653433475335664753473446858774765764677666859687678977599767969767797969796977878998788799568865956576659644565846455864883376645435553556424 +565624333374353367374378478655648748848595599966858998869589999997986786677787987969558898667876766679797576857877576788664777573454645755524 +243444333564746346366668646545674655784777777596558976769676598668789667999889879766877787867797657978894768877458688756477776644647454654652 +323463545665546577475645558786854468657757569879597766865559566996799678799877666898856695986577997898647684875678677855454775654547364424426 +444345546665673463753634768476874774848587769865579789687878579978877559996587865859858789976885557859466565567686888557474764574774566345235 +463425647566774574744333678886747686865457799567576858589676667856577976986668978996686799577977886677544648876855645547444577633464636553523 +525644666573444644576675468484675575784565795957567577578956797786787796869877557895769667588675596744747766568788564546563666667763666225253 +434232334334645346434743378448585848667846577675678568857556598869978967698795766555887989895656586784848574867846777433673543643643345636354 +536245546237555656364544635858554588856888685777969769765876857989857999778897756695765797865577585676877858667674464376646773636576723344236 +563432433237543453765335674454676568784657684785679757868567556875775895977656667977959855575979944776757767668868556665477773367647645655455 +345662256237647446335653655474847777777457855878575955988896666669879768598869889768857697696556455457585858777745474363376763373677455666452 +236454255236363665663365567376855855468585857577666775857999657659868999786755866568579898667756458558654648847578447446356744353365436332433 +236656544552467767567677567448876458465585754786588555756756796978557899579678886778787886777445766574578586476464377437556375345344545245426 +662325463226374566436333654547585676688868454444785599797776865969998677956976597586658865956686866776584577484553367473533563564746536336443 +645354345344537355546665737533754846786764888785557644675696956878965869566966978688779976776866567854756646786873676654337473445524622236626 +233264254235366666736346437575764477565768544667785545578799879958588586787879788669995878745846576785646778646655574347764645533625345535563 +432433242246235746473543477553563665775475774755874587665558965695658699586897695998868747444878848474546545784334377573356763473236426645266 +243532622522636755753437535657447776765475565645845684687588454765579856966696756574665577485786546848546585774336373636476643336442355233566 +424366665443243666567346434354557355888674468846456668847655454648844584447647747545884765768788475648857654773677576566637647654653266642645 +355566553355543667644766357475663334576684855756856557474768868686854785488845464657775755684775878866867574456477457355345767654443322524456 +252226355555353432774774553656764464764766745687577646548754448444648855656476668476765857676478568588685475446655746336375532535436262246655 +124465325536222534633336746764356663557877585584548488677874547445477547864878867577864565556567445544564676546443567455743324244266455364265 +444646453636346242245546654333667346776464746865665867844474866746647865554675844644775465548557754474556375345735665646364353323526625624235 +412366252635624522466346354375765373635554864778855885678875757885648677787758444554675487467557768856743453437365564667776246434655322223525 +155662534242554334526573346673376775437747347484686774778445745547688488858484846876546748684767564753677657367475756735363326425522532252354 +111522322233565252443476336555573575463347454766857665787786477486485455577564475876657687767758584655535533636353747434645522266562523335624 +542422536235454325532645676434563747567556555574458874646877684645545674855674568675844866465685676443356746355677555555666633655263646665442 +211224626424363426643222663657775566775366634363464577678645547647756688757557454788857466767766573445336567467663545634344363446256343542532 +524353365435226556556322567464746534674443466757337368478575456847447776487687768855745786663475737763753364433366577364223462546556234245115 +351231443465264363362336352643774674346454366777533445747664448478677857785488484766644654674764373357565474433475733244565424353322356533151 +554223355636366655362352555655373675564737667663367637476378475656775876558465484467733734736556746773634646373557532336625245362343245314352 +415315224565323443623244633253477545773643635677437734464354663476745457476448456747555563574755374344343366743744432254533234544233652442452 +155321252324634365262226535534446766435373535475553354733776334766573455373756333733573667436757467643766753335642442322554323423224452212311 +554231145244425252354633334356244765663464645674467736446536735636374435547767747353673645457676564473344375654424643234566252323463342424331 +145124531215355646265623243325355765435544464565637674665536435365374465373674364755336673456445565567547775765322264364462642335223541214445 +245544533254142563235523522653435334444477535443567574737475663654776577746444777346766467745333753447653577332363336365532325543231234334451 +251214311244114545554462446423624626676363375354453335776637374775465676343453547674544736356577777464764476336235452444566243644313151353524 +251353112524455635524245344436546325534376365643536356555677555675344355745373347466346575334347466467665642344265334364324562252124525455152 +454211332313421263343625436544345634543275377555633667545444553367537367674333374344744754673653556564665546434666555266442463652431455221541 +115242354251513424524244565345324542344352356476443353667354646467467637463545337377445445357757536673532523352342633456335464421222514545231 +234551552324343221533222663526446236435634463664377555475474346673535434445744753657775466665644563245222634266653436345463353354354144115325 +325412113545232114263462446356336532466543425623356673677337363765363633556375433575757664356773345344465345555625252465465324322523535532422 +533444522324551243515564322652262342524325235554667764445446656633535736363765574763563335776423624463325533625243355442245443123534323312511 +334123531454531311142443565534562563644542436563665634765457377675756443636777543663643633363324553544365344443234345365224343523341515544422 +425513541335541443232314324425223643632666545263242622235765443475754557635364446664563322663626426463256624543536634556155552222222255121512 +443141524454451431355221565364643463663664635262463364522342652467643777543675336434624463452333536354565653344664465611411152424331223125543
\ No newline at end of file diff --git a/aoc2023/src/day2/input.txt b/aoc2023/src/day2/input.txt new file mode 100644 index 0000000..34a6672 --- /dev/null +++ b/aoc2023/src/day2/input.txt @@ -0,0 +1,100 @@ +Game 1: 1 green, 4 blue; 1 blue, 2 green, 1 red; 1 red, 1 green, 2 blue; 1 green, 1 red; 1 green; 1 green, 1 blue, 1 red +Game 2: 2 blue, 2 red, 6 green; 1 red, 6 green, 7 blue; 10 green, 8 blue, 1 red; 2 green, 18 blue, 2 red; 14 blue, 3 green, 1 red; 8 green, 1 red, 9 blue +Game 3: 6 green, 5 blue, 9 red; 4 blue, 1 green, 13 red; 9 green, 14 red, 1 blue +Game 4: 14 green, 3 blue, 16 red; 20 red; 4 green, 2 red, 1 blue; 10 blue, 11 green, 18 red; 3 red, 3 blue, 6 green; 2 green, 18 red, 9 blue +Game 5: 5 green, 4 blue; 1 red, 3 blue, 2 green; 4 green, 2 red, 15 blue; 11 blue, 8 green, 4 red; 4 red, 3 green; 4 red, 3 green, 7 blue +Game 6: 6 blue, 10 green; 2 red, 6 green, 2 blue; 4 red, 4 blue, 1 green; 2 blue, 7 green, 2 red +Game 7: 14 green, 3 red, 2 blue; 5 blue, 3 green, 2 red; 1 green, 3 blue +Game 8: 7 red; 3 blue, 9 red, 1 green; 5 green, 5 blue, 7 red; 1 red, 2 blue +Game 9: 3 green, 4 blue, 1 red; 3 blue, 12 green, 18 red; 7 green, 9 red, 8 blue; 2 blue, 10 red, 12 green; 4 blue, 1 red, 1 green; 4 blue, 6 green, 6 red +Game 10: 2 blue, 4 green, 2 red; 7 green, 4 red; 5 red, 8 green +Game 11: 1 blue, 10 green, 15 red; 1 blue, 2 green, 2 red; 5 green, 10 blue, 8 red; 13 red, 7 blue; 1 red, 9 green, 4 blue; 9 blue, 9 red, 8 green +Game 12: 1 green, 10 red, 3 blue; 14 red, 1 green, 4 blue; 6 red, 3 green, 12 blue; 13 blue, 1 green, 18 red; 4 green, 14 red, 7 blue +Game 13: 1 red, 3 green; 2 green, 1 red, 5 blue; 1 blue; 1 green, 7 blue, 1 red; 1 red, 2 green, 7 blue +Game 14: 7 blue, 9 red, 1 green; 8 red, 2 blue; 11 red, 18 blue, 4 green; 2 blue, 3 green, 1 red; 1 green, 8 red, 9 blue; 2 blue, 8 red, 1 green +Game 15: 8 blue, 3 green, 15 red; 13 red, 10 blue; 2 red +Game 16: 1 green, 1 red; 1 blue, 2 green, 2 red; 1 blue, 4 red, 1 green; 3 green; 2 blue, 3 green, 4 red +Game 17: 1 green, 3 red, 14 blue; 1 red, 2 blue, 2 green; 3 red +Game 18: 1 red, 2 green, 8 blue; 2 blue, 14 red; 4 blue, 2 red, 2 green; 6 red +Game 19: 2 red, 11 blue, 18 green; 3 red, 6 green, 3 blue; 7 green, 1 red, 10 blue +Game 20: 10 red, 1 blue, 4 green; 4 green, 3 blue; 10 green, 13 red, 4 blue; 2 red, 7 green; 4 red, 3 blue, 5 green; 13 red, 1 green, 4 blue +Game 21: 20 red, 4 green, 5 blue; 10 red, 11 green, 4 blue; 1 red, 8 blue, 14 green; 11 green, 8 blue, 15 red; 8 blue, 2 green, 13 red +Game 22: 2 red, 11 blue, 4 green; 1 blue, 3 red, 6 green; 6 green, 1 red, 1 blue; 4 green, 7 blue, 3 red; 11 blue, 6 green, 4 red +Game 23: 6 green, 3 red, 1 blue; 17 green, 11 red; 1 red, 2 blue, 13 green; 13 green, 19 red +Game 24: 1 blue; 12 red, 1 blue; 1 red; 12 red, 1 green, 1 blue; 11 red, 1 blue; 12 red, 1 green +Game 25: 12 blue, 6 red, 3 green; 8 green, 14 blue; 11 green, 5 blue, 6 red; 4 red, 12 blue, 8 green +Game 26: 15 red, 13 green, 9 blue; 9 blue, 8 green, 7 red; 2 green, 6 red, 3 blue; 1 blue, 7 red, 3 green; 13 blue, 4 green, 18 red +Game 27: 9 blue, 5 red; 15 red, 12 blue, 3 green; 12 red, 12 blue, 1 green +Game 28: 18 red, 4 green; 4 green, 6 red; 1 blue, 6 green, 19 red; 9 green, 17 red; 4 green, 5 blue, 18 red +Game 29: 7 green, 6 red, 6 blue; 6 blue, 19 red, 4 green; 4 green, 4 blue, 13 red; 5 blue, 15 red, 10 green; 2 green, 6 blue, 5 red; 8 red, 10 green, 6 blue +Game 30: 1 green, 13 red, 12 blue; 1 red, 2 blue; 11 blue, 1 red, 1 green +Game 31: 8 green, 18 blue, 17 red; 4 red, 8 green, 6 blue; 9 blue, 7 green; 3 green, 1 blue, 12 red; 5 red, 10 blue, 11 green +Game 32: 17 red, 17 green, 7 blue; 18 red, 16 green; 1 blue +Game 33: 16 blue, 3 red; 9 blue, 1 red, 2 green; 3 green, 7 blue; 1 green, 4 red; 3 green, 1 red, 8 blue; 5 blue +Game 34: 5 blue, 8 red, 1 green; 9 red, 10 blue, 7 green; 1 green, 14 blue; 8 blue, 4 red, 10 green; 15 blue, 8 green, 7 red; 2 red, 6 green, 3 blue +Game 35: 13 red, 9 blue; 7 blue, 16 red, 10 green; 4 red, 6 blue; 3 blue, 12 green, 7 red; 8 blue, 6 red; 10 blue, 3 green, 2 red +Game 36: 1 blue, 9 red, 2 green; 11 red, 3 blue, 2 green; 2 green, 6 red; 8 green, 11 red, 3 blue; 4 green, 7 blue, 11 red; 9 green, 8 red, 2 blue +Game 37: 8 green, 3 blue, 4 red; 14 blue, 10 green, 3 red; 19 green, 2 blue, 7 red +Game 38: 2 green, 3 red, 3 blue; 3 green, 9 red; 13 blue, 8 red; 6 red, 5 green, 13 blue +Game 39: 8 red, 5 blue; 4 green, 5 blue, 3 red; 18 red, 2 green, 6 blue; 2 green, 5 blue, 17 red; 1 green, 2 red; 5 green, 6 blue +Game 40: 12 red, 4 blue, 1 green; 11 green, 20 blue, 4 red; 10 blue, 4 red +Game 41: 2 green, 2 blue; 2 red, 2 green; 2 green, 2 blue, 10 red +Game 42: 6 green, 3 blue; 2 red, 2 green, 1 blue; 3 blue, 5 green, 6 red; 6 red; 1 blue, 6 green, 12 red +Game 43: 1 blue, 4 green; 1 blue; 2 blue, 8 red, 2 green; 2 blue, 1 red, 4 green; 1 blue, 4 red, 4 green; 4 green, 7 red +Game 44: 8 green, 9 red; 1 red, 2 blue, 13 green; 4 blue, 8 green, 17 red; 13 red, 13 green; 1 red, 9 green; 19 red, 3 green, 3 blue +Game 45: 10 blue, 2 red, 1 green; 6 green, 5 red, 8 blue; 3 blue, 1 red; 4 green, 10 blue, 4 red +Game 46: 3 red, 8 blue; 6 blue, 7 green, 6 red; 6 green, 1 blue, 7 red; 8 red, 1 green, 5 blue; 9 red, 12 blue, 10 green; 7 green, 5 red, 1 blue +Game 47: 5 red; 2 blue, 2 green, 5 red; 3 green, 7 red; 14 red, 3 green, 2 blue +Game 48: 7 blue, 12 green, 2 red; 11 green, 10 blue, 1 red; 1 red, 13 blue, 2 green; 14 green, 2 red, 9 blue; 2 red, 12 green, 3 blue; 2 red, 7 blue +Game 49: 4 green, 5 blue; 9 blue; 10 blue, 5 green, 2 red; 10 blue, 2 red, 2 green; 1 red, 1 green, 4 blue; 2 blue +Game 50: 2 red, 2 blue, 7 green; 7 red, 9 green, 3 blue; 5 red, 10 green +Game 51: 15 red, 9 blue, 4 green; 5 red, 2 blue, 15 green; 4 blue, 3 green, 20 red; 12 green, 1 red, 10 blue; 10 green, 5 blue, 13 red; 9 red, 10 green, 11 blue +Game 52: 3 blue, 12 green, 1 red; 6 green; 1 red, 8 green; 1 blue, 1 green, 1 red +Game 53: 10 green, 7 red, 12 blue; 9 blue, 6 green, 2 red; 8 green, 5 blue, 5 red; 7 blue, 16 green, 11 red; 6 red, 8 blue, 13 green +Game 54: 10 green, 6 blue, 3 red; 6 green, 2 red, 8 blue; 9 blue, 11 green, 2 red; 10 green, 1 blue, 3 red +Game 55: 4 blue, 1 red; 3 red, 7 blue; 12 red, 4 green, 8 blue; 3 green, 5 blue, 1 red; 13 blue, 12 red, 1 green +Game 56: 12 blue, 15 green; 1 green, 7 red, 11 blue; 5 green, 9 blue, 1 red; 8 red, 5 green, 6 blue +Game 57: 4 green, 11 blue, 18 red; 14 blue, 14 red, 16 green; 7 red, 15 green, 3 blue; 18 red, 20 green, 8 blue; 12 blue, 9 red, 16 green +Game 58: 10 blue, 9 green, 8 red; 13 green, 6 blue, 8 red; 8 green, 4 red; 4 blue, 1 red, 18 green; 7 red, 10 green, 10 blue; 15 blue, 10 green, 3 red +Game 59: 17 green, 2 blue, 2 red; 2 blue, 1 red, 8 green; 14 green, 1 red, 1 blue; 15 green, 3 blue, 2 red; 2 blue, 8 green, 1 red; 1 blue, 1 red, 8 green +Game 60: 1 green, 1 blue, 1 red; 4 blue, 3 red, 2 green; 13 green; 2 blue, 2 red, 8 green; 4 red, 12 green, 4 blue; 4 green, 4 blue, 4 red +Game 61: 3 blue, 7 red; 5 blue, 8 red, 1 green; 1 blue, 8 red; 10 blue, 2 red, 1 green; 1 green, 5 blue, 2 red +Game 62: 10 red, 2 green; 8 blue, 7 red, 2 green; 4 green, 2 blue, 10 red +Game 63: 1 green, 3 blue, 5 red; 6 green, 5 blue, 2 red; 3 blue, 7 red +Game 64: 6 red, 20 blue; 4 red, 3 blue, 2 green; 3 green, 19 blue, 6 red; 2 green, 6 blue, 3 red; 13 blue, 5 green, 5 red +Game 65: 6 red, 9 blue, 20 green; 6 red, 16 green, 4 blue; 12 red, 6 green, 5 blue +Game 66: 2 blue, 5 red, 4 green; 13 blue, 2 green; 1 green, 6 blue +Game 67: 4 green, 5 blue, 2 red; 1 red, 14 blue, 6 green; 1 green, 14 red, 5 blue; 18 red, 16 blue; 15 blue, 8 red, 18 green; 1 green, 18 red, 6 blue +Game 68: 1 blue, 9 red, 7 green; 7 red, 1 blue, 6 green; 5 green, 1 blue, 8 red +Game 69: 12 green, 3 blue, 4 red; 9 green, 8 red, 7 blue; 4 blue, 5 red, 10 green; 4 red, 5 green, 7 blue; 9 green, 4 red, 2 blue; 3 green, 13 blue, 1 red +Game 70: 9 red, 1 green, 8 blue; 11 green, 13 blue, 12 red; 3 blue, 5 green, 8 red; 1 red, 14 blue +Game 71: 10 blue; 2 green, 8 blue, 9 red; 5 red, 1 blue +Game 72: 3 green, 5 blue, 5 red; 1 blue, 1 red, 2 green; 4 red, 4 blue, 1 green; 5 blue, 4 red, 1 green; 6 blue, 3 green, 5 red; 5 blue, 1 red, 4 green +Game 73: 3 red, 1 green, 1 blue; 7 green, 2 red, 1 blue; 2 green, 1 blue, 3 red; 1 red, 4 green, 1 blue; 3 red, 5 green +Game 74: 5 blue, 1 red, 4 green; 3 red, 2 green; 4 red, 6 blue; 2 red, 2 blue; 1 green, 4 red, 8 blue; 5 blue, 4 red +Game 75: 3 red, 5 blue, 3 green; 9 green, 6 blue, 7 red; 2 green, 3 red, 12 blue; 14 green, 4 blue, 10 red +Game 76: 1 blue, 7 red, 1 green; 6 red, 1 blue, 2 green; 4 red, 2 green; 3 red, 1 blue; 16 red, 1 green +Game 77: 3 red, 10 blue, 1 green; 4 red, 7 blue, 3 green; 7 blue, 6 green, 7 red; 5 green, 15 blue, 7 red; 12 green, 5 red +Game 78: 6 red, 10 blue, 15 green; 6 green, 11 red, 4 blue; 6 blue, 8 red; 4 blue, 7 red, 2 green; 11 green, 7 red, 11 blue; 3 blue, 14 green, 6 red +Game 79: 14 red, 6 green, 4 blue; 13 red, 6 blue; 6 red, 13 green, 4 blue +Game 80: 8 red, 2 blue, 8 green; 6 red, 10 green, 4 blue; 3 red, 9 green; 2 green, 8 blue, 7 red; 7 blue, 3 red, 11 green; 1 red, 12 green, 8 blue +Game 81: 9 red, 4 blue, 11 green; 1 blue, 4 red, 2 green; 5 red; 3 blue, 2 red, 2 green; 14 red, 12 green +Game 82: 5 green; 2 blue; 2 red; 1 blue, 2 red, 11 green; 8 green, 2 red, 1 blue +Game 83: 3 green, 7 red, 6 blue; 7 red, 7 green, 11 blue; 7 blue, 13 green, 7 red; 12 blue, 10 red, 2 green; 1 green, 11 red, 7 blue; 12 blue, 9 red, 9 green +Game 84: 5 blue, 1 green; 16 green, 4 blue, 8 red; 7 red, 5 blue, 16 green +Game 85: 9 green, 20 blue, 7 red; 19 blue, 14 red, 2 green; 10 green, 2 red, 10 blue +Game 86: 1 green, 3 red, 5 blue; 9 red, 2 blue, 6 green; 8 green, 14 red, 3 blue; 18 green, 2 blue, 7 red; 2 blue, 10 red, 14 green; 17 green, 4 blue, 12 red +Game 87: 4 green, 8 red, 13 blue; 7 red, 13 blue, 4 green; 1 green, 8 blue +Game 88: 9 blue, 11 red; 5 green, 7 blue, 12 red; 10 red, 2 green, 1 blue; 2 blue, 5 red, 5 green; 7 red, 6 green, 9 blue; 1 green, 10 red, 5 blue +Game 89: 7 red, 2 green, 1 blue; 1 blue, 2 green; 6 red, 1 green; 7 red, 1 blue; 3 green, 3 red +Game 90: 8 blue, 2 red, 3 green; 9 green, 4 blue, 3 red; 7 green, 11 blue, 2 red; 13 green, 12 blue, 8 red; 10 blue, 2 green; 5 green, 1 red, 9 blue +Game 91: 2 red, 2 green, 4 blue; 5 blue, 2 red, 16 green; 11 green; 3 blue, 2 red, 8 green; 4 green, 3 blue +Game 92: 8 red, 12 blue, 3 green; 11 red, 10 blue, 6 green; 14 red, 8 green, 14 blue +Game 93: 3 green, 2 red, 3 blue; 3 green, 3 red, 1 blue; 2 blue, 16 red, 3 green; 2 green; 5 green, 2 blue, 2 red +Game 94: 5 red, 2 green; 9 red, 3 blue; 2 green, 2 blue, 5 red; 3 blue, 8 red, 2 green; 8 red, 1 blue, 1 green +Game 95: 3 blue, 4 green, 7 red; 7 red, 1 green, 15 blue; 6 blue, 2 green, 7 red +Game 96: 2 blue, 1 red, 6 green; 7 blue, 8 green; 1 red, 7 green; 2 green, 14 blue, 1 red; 3 blue, 1 red, 7 green; 4 blue, 11 green +Game 97: 2 red, 9 blue, 8 green; 3 green, 5 blue; 6 green, 1 red, 9 blue; 2 red, 13 green, 1 blue; 2 green, 2 red, 2 blue +Game 98: 2 blue, 1 green, 1 red; 4 blue, 5 red, 1 green; 4 blue, 3 red, 2 green +Game 99: 17 red, 2 blue, 4 green; 4 green, 8 red, 6 blue; 5 red +Game 100: 6 red, 4 green; 3 red, 2 blue, 9 green; 1 blue, 5 green, 14 red; 1 blue, 2 red, 2 green; 9 red, 1 blue, 14 green; 2 blue, 11 green, 8 red
\ No newline at end of file diff --git a/aoc2023/src/day20/input.txt b/aoc2023/src/day20/input.txt new file mode 100644 index 0000000..6949a60 --- /dev/null +++ b/aoc2023/src/day20/input.txt @@ -0,0 +1,58 @@ +%hb -> mj +%mx -> mt, xz +%xh -> qc +%tg -> cq +%kp -> xz, nj +%mj -> jj, lv +%cq -> jm +%mt -> sj, xz +&jj -> hb, lz, rk, xv, vj, vh, lv +%rm -> bz, xq +%hx -> bz +%xv -> lz +%xx -> kp, xz +%pt -> vx +&xz -> bq, gr, sj, rv, zf +%vx -> gf, cv +%xb -> xz, bq +%xk -> gf, rd +%lv -> zk +&rk -> gh +%kn -> gf, tz +&gh -> rx +%sj -> vp +%jm -> vm, bz +%rr -> rv, xz +%tz -> rz +%gg -> kn +&cd -> gh +%qc -> kh, bz +%kb -> gf +%vp -> xz, xx +%fb -> bz, tg +%rd -> cp +%qn -> vh, jj +%xr -> jj +%tp -> rm, bz +%cp -> gg +&bz -> qx, cq, xh, fb, tg +%qq -> pt, gf +%xq -> bz, hx +%gx -> jj, qv +%bq -> rr +%cv -> gf, kb +%zk -> jj, xv +&zf -> gh +&qx -> gh +%vh -> gx +%qv -> xr, jj +%lz -> qn +broadcaster -> fb, xk, gr, vj +%nj -> xz +%gr -> xz, xb +%kh -> tp, bz +%vm -> bz, xh +%rz -> qq, gf +&gf -> tz, cd, rd, xk, pt, cp, gg +%rv -> mx +%vj -> hb, jj
\ No newline at end of file diff --git a/aoc2023/src/day22/input.txt b/aoc2023/src/day22/input.txt new file mode 100644 index 0000000..f2e2fd8 --- /dev/null +++ b/aoc2023/src/day22/input.txt @@ -0,0 +1,1273 @@ +2,4,151~4,4,151 +5,4,169~5,7,169 +3,5,167~3,7,167 +4,6,197~4,8,197 +6,5,98~6,7,98 +3,8,7~5,8,7 +8,2,293~8,5,293 +2,1,76~2,4,76 +2,6,102~2,9,102 +4,0,201~4,2,201 +1,6,103~1,8,103 +7,5,214~9,5,214 +1,2,213~3,2,213 +4,6,263~4,8,263 +6,0,263~6,0,266 +3,5,145~5,5,145 +6,5,60~6,8,60 +0,6,13~2,6,13 +4,7,277~6,7,277 +5,7,87~5,7,89 +0,7,72~0,9,72 +6,4,48~6,6,48 +7,2,20~9,2,20 +5,4,128~5,7,128 +7,7,257~7,9,257 +6,5,227~9,5,227 +8,4,67~9,4,67 +5,9,236~7,9,236 +3,5,137~6,5,137 +2,3,137~4,3,137 +0,2,63~0,4,63 +0,2,299~1,2,299 +6,5,234~6,7,234 +1,0,137~1,3,137 +6,5,271~6,7,271 +0,2,79~2,2,79 +4,3,297~6,3,297 +0,0,80~0,2,80 +1,9,56~3,9,56 +4,3,49~4,6,49 +9,6,114~9,8,114 +0,5,212~2,5,212 +5,2,161~7,2,161 +4,1,100~4,3,100 +6,6,226~8,6,226 +2,1,63~4,1,63 +1,8,44~3,8,44 +5,3,9~8,3,9 +8,6,240~9,6,240 +6,1,111~7,1,111 +0,5,222~2,5,222 +9,4,150~9,6,150 +4,2,66~4,5,66 +3,9,186~5,9,186 +5,6,20~8,6,20 +6,3,224~6,5,224 +2,8,48~3,8,48 +2,2,18~2,5,18 +4,5,106~6,5,106 +8,6,19~8,7,19 +7,5,175~9,5,175 +5,7,146~5,9,146 +3,3,197~5,3,197 +9,4,25~9,6,25 +6,6,205~9,6,205 +8,0,34~8,3,34 +4,6,224~6,6,224 +2,9,104~4,9,104 +2,4,134~2,6,134 +5,2,209~9,2,209 +5,6,187~7,6,187 +5,9,104~6,9,104 +6,5,139~6,7,139 +6,6,209~6,8,209 +7,4,201~7,8,201 +1,2,45~1,3,45 +3,5,129~5,5,129 +4,1,88~7,1,88 +0,4,1~0,5,1 +7,5,79~9,5,79 +6,0,124~6,0,124 +1,6,108~2,6,108 +7,5,114~7,7,114 +4,0,296~4,0,299 +0,0,65~0,2,65 +8,7,276~8,8,276 +5,7,40~7,7,40 +9,4,101~9,5,101 +3,0,264~5,0,264 +3,0,26~5,0,26 +2,6,151~5,6,151 +0,1,294~0,4,294 +5,4,293~7,4,293 +1,2,298~1,4,298 +5,6,189~5,7,189 +4,0,111~4,3,111 +4,5,109~4,7,109 +2,7,41~4,7,41 +6,1,172~8,1,172 +6,5,50~6,7,50 +9,2,74~9,4,74 +0,0,120~0,0,120 +2,1,1~2,1,3 +5,4,291~8,4,291 +8,1,111~8,2,111 +6,2,95~6,2,96 +9,3,158~9,6,158 +3,3,262~5,3,262 +1,1,308~1,4,308 +5,6,135~5,9,135 +6,6,3~9,6,3 +7,7,39~9,7,39 +2,7,98~4,7,98 +7,6,233~7,9,233 +6,2,119~9,2,119 +3,7,207~3,9,207 +8,4,245~8,5,245 +9,2,136~9,2,138 +7,2,111~7,4,111 +0,8,70~3,8,70 +3,5,217~5,5,217 +4,9,223~5,9,223 +3,2,282~4,2,282 +5,7,258~5,7,260 +4,5,266~4,8,266 +8,4,48~8,4,50 +6,0,173~6,2,173 +4,7,131~4,9,131 +1,9,2~2,9,2 +7,5,17~9,5,17 +0,2,120~1,2,120 +4,1,102~4,3,102 +6,6,101~6,8,101 +5,5,12~5,5,12 +0,0,292~3,0,292 +7,8,119~9,8,119 +7,6,82~8,6,82 +4,2,117~6,2,117 +2,9,220~4,9,220 +8,1,42~9,1,42 +7,9,147~7,9,147 +8,7,125~8,7,127 +2,7,240~2,9,240 +8,0,276~8,2,276 +1,0,251~4,0,251 +0,6,172~1,6,172 +3,9,95~5,9,95 +1,5,61~5,5,61 +8,6,33~8,8,33 +1,7,292~1,7,293 +3,5,147~3,7,147 +0,9,74~1,9,74 +1,2,239~4,2,239 +2,5,146~3,5,146 +2,0,280~2,3,280 +3,6,46~6,6,46 +2,8,245~3,8,245 +3,6,171~7,6,171 +4,2,122~4,3,122 +5,2,301~5,5,301 +4,4,208~5,4,208 +8,6,72~8,7,72 +2,7,232~5,7,232 +4,4,236~4,4,237 +3,3,255~4,3,255 +1,1,107~1,3,107 +0,0,84~0,1,84 +3,4,244~4,4,244 +0,9,5~2,9,5 +3,2,94~6,2,94 +1,8,137~4,8,137 +2,1,291~5,1,291 +4,3,52~4,6,52 +3,6,232~5,6,232 +3,7,63~3,9,63 +5,5,244~7,5,244 +8,1,285~8,2,285 +2,2,172~2,3,172 +6,1,16~6,4,16 +3,3,34~3,6,34 +4,6,91~4,9,91 +1,9,177~3,9,177 +5,2,232~8,2,232 +7,2,207~7,3,207 +7,5,37~9,5,37 +3,4,177~3,6,177 +1,3,136~1,4,136 +4,6,105~4,7,105 +5,9,139~7,9,139 +4,9,244~7,9,244 +5,8,105~8,8,105 +6,4,77~6,6,77 +0,8,11~2,8,11 +3,6,42~3,8,42 +2,3,194~6,3,194 +5,6,119~5,7,119 +0,1,176~2,1,176 +8,1,123~8,4,123 +6,3,10~6,5,10 +0,2,23~2,2,23 +8,4,120~8,5,120 +4,2,210~4,4,210 +5,2,214~7,2,214 +0,4,108~3,4,108 +5,3,295~5,6,295 +6,5,126~6,6,126 +1,5,14~2,5,14 +9,1,152~9,1,152 +8,4,101~8,6,101 +2,5,98~2,5,99 +8,5,180~8,8,180 +2,4,212~2,4,214 +4,3,268~6,3,268 +5,7,36~5,8,36 +6,5,135~6,7,135 +5,5,97~5,7,97 +1,6,298~2,6,298 +4,0,6~6,0,6 +6,0,255~6,2,255 +6,8,9~8,8,9 +4,9,45~6,9,45 +6,6,120~9,6,120 +2,1,32~4,1,32 +9,3,116~9,4,116 +1,4,245~1,6,245 +8,6,235~8,6,237 +2,2,277~5,2,277 +9,5,40~9,6,40 +4,6,255~5,6,255 +8,6,44~8,8,44 +6,9,212~9,9,212 +6,0,3~9,0,3 +3,2,168~3,4,168 +4,2,27~7,2,27 +5,2,103~7,2,103 +3,6,31~3,8,31 +7,1,89~9,1,89 +2,0,290~2,2,290 +3,1,152~3,2,152 +6,5,262~6,7,262 +5,6,138~5,6,140 +7,7,149~9,7,149 +2,3,148~2,5,148 +3,0,30~3,0,32 +3,7,253~3,8,253 +0,5,146~0,7,146 +7,1,229~7,4,229 +8,5,80~8,6,80 +8,8,182~9,8,182 +3,4,125~5,4,125 +0,8,168~2,8,168 +7,4,156~9,4,156 +6,4,119~9,4,119 +4,5,98~4,5,100 +8,2,108~9,2,108 +1,9,250~3,9,250 +6,2,165~6,3,165 +5,6,197~8,6,197 +8,0,214~8,3,214 +8,4,47~8,6,47 +3,2,192~5,2,192 +8,1,254~8,3,254 +2,1,103~2,3,103 +8,5,108~8,8,108 +2,9,243~4,9,243 +4,0,146~4,2,146 +1,3,246~1,7,246 +6,4,179~6,6,179 +2,4,119~2,6,119 +1,6,83~2,6,83 +5,7,72~5,8,72 +8,5,113~9,5,113 +8,5,67~8,5,69 +2,2,110~2,4,110 +3,6,36~3,8,36 +1,8,129~3,8,129 +3,2,56~3,4,56 +1,5,13~2,5,13 +0,1,42~2,1,42 +3,7,6~3,9,6 +5,0,77~5,4,77 +5,2,78~5,3,78 +5,4,192~5,7,192 +3,6,194~5,6,194 +7,6,134~7,8,134 +4,2,139~4,4,139 +1,0,201~3,0,201 +6,2,141~6,4,141 +6,0,65~6,0,66 +5,7,34~6,7,34 +4,4,181~4,4,182 +3,2,75~4,2,75 +4,5,293~4,9,293 +1,2,127~3,2,127 +4,9,183~7,9,183 +5,6,248~5,8,248 +4,3,115~4,6,115 +1,6,97~2,6,97 +1,1,104~3,1,104 +0,1,139~0,4,139 +5,9,79~5,9,81 +3,2,181~5,2,181 +4,2,233~7,2,233 +6,1,64~8,1,64 +0,2,40~1,2,40 +5,5,214~5,8,214 +3,7,163~3,7,165 +8,2,272~8,4,272 +7,3,141~8,3,141 +3,8,242~5,8,242 +0,1,44~0,1,45 +1,9,144~2,9,144 +4,8,114~4,8,115 +3,5,108~3,6,108 +4,4,225~4,5,225 +2,5,276~4,5,276 +8,4,171~8,4,173 +1,5,16~1,7,16 +4,5,94~4,8,94 +7,2,113~7,2,114 +6,2,2~6,4,2 +5,7,14~8,7,14 +2,0,175~2,2,175 +4,3,200~6,3,200 +1,0,35~1,1,35 +5,0,42~8,0,42 +0,7,160~0,8,160 +3,2,2~5,2,2 +5,6,157~5,9,157 +1,7,104~2,7,104 +6,9,68~6,9,68 +3,5,203~4,5,203 +8,4,3~8,4,3 +4,5,223~4,8,223 +5,1,80~5,4,80 +2,4,21~2,4,22 +3,7,278~3,8,278 +6,7,20~7,7,20 +8,2,1~8,4,1 +7,8,139~9,8,139 +8,4,36~8,6,36 +4,6,76~6,6,76 +7,0,102~7,3,102 +8,2,212~8,5,212 +8,7,49~8,8,49 +6,1,32~8,1,32 +6,5,263~7,5,263 +7,4,132~7,6,132 +1,5,171~1,7,171 +7,6,121~9,6,121 +3,4,96~3,6,96 +5,5,254~5,8,254 +7,2,259~7,3,259 +1,0,295~1,3,295 +3,2,99~3,4,99 +4,6,65~4,8,65 +2,4,104~2,4,104 +7,5,2~9,5,2 +1,1,287~1,1,289 +5,2,253~5,2,255 +1,7,288~1,9,288 +5,3,65~7,3,65 +5,3,256~7,3,256 +0,3,149~0,5,149 +3,6,153~3,9,153 +3,5,166~5,5,166 +5,1,258~5,3,258 +0,5,148~0,8,148 +8,0,226~9,0,226 +9,5,13~9,5,13 +3,8,156~4,8,156 +9,0,28~9,3,28 +6,4,285~6,6,285 +3,1,116~3,4,116 +4,9,158~5,9,158 +5,7,273~8,7,273 +2,5,10~2,8,10 +5,0,41~5,3,41 +4,4,50~4,6,50 +7,2,23~7,4,23 +3,4,55~3,6,55 +3,8,125~6,8,125 +5,1,69~5,3,69 +4,3,11~5,3,11 +7,1,92~7,4,92 +5,8,210~5,9,210 +2,8,140~2,9,140 +2,6,86~4,6,86 +8,4,244~8,7,244 +8,2,237~8,4,237 +4,6,269~7,6,269 +0,4,116~1,4,116 +0,3,68~0,5,68 +1,2,301~4,2,301 +0,1,69~0,3,69 +8,0,281~8,3,281 +5,7,255~5,8,255 +4,4,268~4,6,268 +4,7,8~4,8,8 +8,2,98~8,3,98 +2,0,80~3,0,80 +4,7,67~4,7,69 +6,3,133~8,3,133 +4,9,129~7,9,129 +2,0,55~4,0,55 +6,8,177~8,8,177 +0,4,115~1,4,115 +6,4,245~7,4,245 +3,3,161~4,3,161 +2,8,109~5,8,109 +6,5,145~6,5,147 +1,6,143~1,9,143 +1,8,115~3,8,115 +3,4,271~5,4,271 +3,8,8~3,9,8 +6,7,36~7,7,36 +0,2,252~0,4,252 +4,1,109~4,2,109 +1,1,247~3,1,247 +3,2,149~5,2,149 +6,4,181~6,4,184 +1,1,81~1,4,81 +0,2,42~2,2,42 +3,3,7~5,3,7 +0,5,73~0,6,73 +9,8,66~9,9,66 +7,0,132~9,0,132 +1,4,119~1,7,119 +3,4,74~4,4,74 +1,2,165~3,2,165 +5,7,160~7,7,160 +5,5,198~7,5,198 +4,4,10~5,4,10 +5,1,252~8,1,252 +8,3,64~8,6,64 +6,3,71~9,3,71 +2,7,233~3,7,233 +5,7,30~7,7,30 +2,7,276~4,7,276 +2,2,115~2,4,115 +5,1,122~6,1,122 +2,8,222~2,9,222 +2,1,157~5,1,157 +6,7,31~8,7,31 +3,8,175~3,9,175 +1,2,26~1,2,29 +5,2,180~5,5,180 +5,5,142~7,5,142 +7,0,73~7,3,73 +9,6,117~9,8,117 +1,4,113~2,4,113 +0,8,2~0,8,4 +7,1,207~9,1,207 +4,7,134~4,9,134 +3,2,263~5,2,263 +7,7,69~7,8,69 +7,7,63~7,8,63 +4,7,235~4,8,235 +4,2,16~4,4,16 +3,6,49~3,9,49 +8,1,36~8,1,39 +2,0,46~2,3,46 +6,6,143~6,6,146 +2,1,101~2,3,101 +4,1,103~4,2,103 +0,0,71~0,2,71 +7,3,282~7,6,282 +4,4,148~4,6,148 +0,2,245~2,2,245 +1,7,213~3,7,213 +4,0,262~7,0,262 +2,8,53~4,8,53 +1,6,290~1,8,290 +0,8,55~2,8,55 +8,1,255~8,2,255 +5,4,233~5,6,233 +2,1,53~4,1,53 +2,0,61~2,2,61 +1,2,300~1,4,300 +1,5,100~1,7,100 +2,4,3~4,4,3 +1,9,70~1,9,72 +8,7,42~8,9,42 +2,8,67~5,8,67 +7,3,142~9,3,142 +9,6,6~9,6,9 +3,7,241~3,7,243 +5,0,32~5,0,34 +0,6,292~0,6,294 +9,1,281~9,4,281 +5,5,204~5,7,204 +4,0,113~6,0,113 +5,9,224~8,9,224 +4,1,148~6,1,148 +7,5,128~7,7,128 +7,4,79~9,4,79 +1,6,294~1,7,294 +5,5,184~5,7,184 +4,8,159~4,8,162 +6,2,110~6,3,110 +0,9,7~1,9,7 +7,8,239~9,8,239 +4,6,284~4,8,284 +5,2,162~6,2,162 +4,0,15~4,2,15 +1,4,107~2,4,107 +1,4,9~4,4,9 +1,0,37~1,2,37 +8,1,284~9,1,284 +1,6,72~1,8,72 +4,6,134~6,6,134 +7,3,242~9,3,242 +7,1,145~7,3,145 +8,5,114~8,8,114 +3,5,149~4,5,149 +0,3,288~0,5,288 +7,2,279~9,2,279 +6,4,73~8,4,73 +4,5,121~6,5,121 +0,6,291~0,8,291 +3,4,71~5,4,71 +9,1,46~9,3,46 +5,1,275~5,2,275 +9,6,242~9,9,242 +4,8,251~7,8,251 +1,9,66~3,9,66 +4,6,135~4,6,136 +7,0,282~7,2,282 +1,8,3~3,8,3 +6,6,251~8,6,251 +1,9,218~2,9,218 +3,4,234~5,4,234 +5,8,259~5,9,259 +6,3,68~6,6,68 +3,7,173~3,9,173 +2,9,215~4,9,215 +9,7,1~9,9,1 +8,1,257~9,1,257 +7,0,30~7,2,30 +6,6,102~6,6,103 +6,1,257~6,3,257 +1,4,286~1,7,286 +7,1,107~7,4,107 +3,6,281~5,6,281 +6,9,64~9,9,64 +8,7,45~8,8,45 +2,9,263~5,9,263 +5,2,44~7,2,44 +7,6,291~7,8,291 +3,3,43~3,5,43 +4,0,167~7,0,167 +8,1,169~8,4,169 +5,4,121~7,4,121 +2,2,296~2,4,296 +7,5,287~8,5,287 +1,2,196~4,2,196 +7,1,1~7,1,2 +7,0,131~7,2,131 +9,5,11~9,8,11 +3,2,251~3,2,252 +9,7,153~9,7,154 +4,2,114~4,3,114 +2,7,155~5,7,155 +0,2,255~0,5,255 +1,5,83~3,5,83 +7,0,285~9,0,285 +8,5,198~8,7,198 +3,1,119~3,1,122 +4,4,96~5,4,96 +4,8,5~6,8,5 +3,2,241~5,2,241 +1,5,64~1,5,66 +7,2,239~7,3,239 +2,4,95~2,4,97 +1,2,19~3,2,19 +5,5,49~5,8,49 +6,4,146~9,4,146 +4,0,257~6,0,257 +5,6,59~5,6,61 +5,3,175~5,5,175 +5,8,261~7,8,261 +9,2,43~9,4,43 +2,8,256~3,8,256 +7,2,133~9,2,133 +7,7,12~9,7,12 +8,0,273~8,2,273 +1,3,238~1,6,238 +4,1,159~4,1,161 +2,3,134~5,3,134 +4,9,99~6,9,99 +0,2,291~0,4,291 +3,2,13~6,2,13 +8,9,45~9,9,45 +2,0,303~4,0,303 +1,5,249~3,5,249 +0,8,51~2,8,51 +3,2,188~5,2,188 +5,9,262~8,9,262 +6,7,255~8,7,255 +0,5,237~0,7,237 +1,3,256~1,4,256 +2,5,237~2,5,240 +1,3,108~1,3,110 +8,5,285~8,8,285 +5,1,250~5,4,250 +9,0,45~9,1,45 +7,6,112~9,6,112 +3,2,27~3,3,27 +5,2,125~5,3,125 +2,4,211~2,7,211 +9,4,209~9,7,209 +6,5,177~6,5,178 +4,7,62~7,7,62 +0,6,119~0,9,119 +2,4,26~2,4,28 +6,3,94~8,3,94 +5,5,147~5,6,147 +7,1,173~7,3,173 +7,0,105~9,0,105 +2,2,129~3,2,129 +0,0,30~1,0,30 +8,3,154~8,5,154 +4,0,64~4,0,67 +5,1,298~5,1,298 +9,2,134~9,5,134 +0,5,236~2,5,236 +3,7,159~3,8,159 +6,0,205~6,0,207 +2,3,32~2,4,32 +4,5,235~6,5,235 +4,6,59~4,9,59 +2,4,7~2,6,7 +9,4,160~9,7,160 +4,9,185~4,9,185 +0,4,132~3,4,132 +0,4,253~4,4,253 +7,1,288~9,1,288 +2,0,97~3,0,97 +4,7,200~4,7,202 +1,0,148~4,0,148 +5,0,163~5,2,163 +0,1,83~0,3,83 +3,6,240~3,8,240 +6,4,82~6,6,82 +0,5,70~0,7,70 +5,7,66~8,7,66 +4,2,189~4,5,189 +6,0,19~9,0,19 +5,1,197~5,2,197 +1,1,202~3,1,202 +2,2,31~2,4,31 +1,9,245~2,9,245 +9,1,26~9,1,27 +7,0,223~9,0,223 +3,2,34~6,2,34 +1,8,166~1,8,167 +0,6,299~0,6,300 +0,2,59~4,2,59 +2,4,6~2,6,6 +3,4,221~3,6,221 +4,9,92~6,9,92 +8,2,189~8,4,189 +6,1,11~6,3,11 +6,3,175~6,5,175 +8,4,275~8,6,275 +3,0,96~3,3,96 +5,8,143~8,8,143 +9,4,28~9,5,28 +6,9,267~8,9,267 +2,5,60~4,5,60 +4,1,61~6,1,61 +5,8,52~7,8,52 +5,7,61~7,7,61 +1,8,164~3,8,164 +6,0,45~7,0,45 +3,1,246~3,3,246 +5,3,251~5,3,253 +4,9,47~7,9,47 +5,2,211~5,3,211 +4,8,258~6,8,258 +3,9,292~5,9,292 +4,5,103~4,7,103 +2,1,6~3,1,6 +4,7,132~4,7,132 +0,6,110~3,6,110 +0,1,293~2,1,293 +4,2,160~4,2,162 +3,3,209~3,5,209 +0,1,41~0,3,41 +6,1,108~6,5,108 +3,8,104~5,8,104 +7,7,146~7,9,146 +2,4,79~2,7,79 +2,1,44~2,4,44 +2,5,231~4,5,231 +0,7,172~2,7,172 +2,4,297~2,6,297 +6,4,247~6,5,247 +4,4,288~6,4,288 +6,2,225~6,4,225 +6,1,163~8,1,163 +2,3,145~5,3,145 +7,7,254~7,8,254 +4,8,128~4,9,128 +1,3,286~3,3,286 +4,1,14~6,1,14 +6,6,232~8,6,232 +3,3,59~5,3,59 +4,4,154~7,4,154 +3,4,54~3,6,54 +5,3,76~5,5,76 +6,4,187~8,4,187 +6,3,143~8,3,143 +6,3,265~6,5,265 +1,9,180~2,9,180 +8,1,96~8,5,96 +2,7,138~2,9,138 +0,5,76~0,5,78 +2,5,274~2,7,274 +5,7,183~7,7,183 +4,0,260~8,0,260 +8,6,39~9,6,39 +3,3,40~3,5,40 +8,3,159~8,7,159 +6,9,185~8,9,185 +7,8,13~9,8,13 +3,3,30~3,6,30 +7,1,205~7,4,205 +8,9,75~8,9,77 +7,0,217~7,2,217 +6,3,261~6,6,261 +5,4,32~7,4,32 +6,4,162~8,4,162 +5,7,81~7,7,81 +1,0,248~1,1,248 +2,1,9~2,2,9 +0,5,166~2,5,166 +7,3,121~9,3,121 +0,0,202~1,0,202 +8,7,46~9,7,46 +3,0,142~4,0,142 +6,7,253~6,7,254 +3,1,33~4,1,33 +2,2,185~5,2,185 +6,7,37~9,7,37 +6,2,63~8,2,63 +0,5,159~0,7,159 +3,0,121~6,0,121 +5,4,23~5,6,23 +7,7,109~9,7,109 +6,4,26~7,4,26 +0,1,286~0,4,286 +7,7,260~7,8,260 +7,7,204~7,7,205 +7,2,176~9,2,176 +9,6,151~9,9,151 +2,6,252~2,8,252 +6,5,40~8,5,40 +7,7,17~8,7,17 +8,5,61~9,5,61 +0,2,81~0,2,81 +3,0,166~5,0,166 +6,0,267~6,0,269 +6,6,69~6,6,70 +1,5,102~1,5,105 +6,3,177~8,3,177 +2,4,62~2,6,62 +6,4,264~6,5,264 +3,4,62~3,6,62 +4,6,157~4,9,157 +6,4,143~9,4,143 +8,8,116~8,9,116 +6,6,236~6,8,236 +9,5,228~9,7,228 +5,1,5~5,4,5 +3,5,58~3,6,58 +3,4,204~3,7,204 +2,9,221~3,9,221 +6,6,229~8,6,229 +4,4,123~5,4,123 +2,6,14~2,8,14 +1,6,89~4,6,89 +4,3,73~6,3,73 +7,3,97~7,3,99 +4,6,10~6,6,10 +5,4,222~8,4,222 +6,3,59~6,6,59 +5,7,7~6,7,7 +4,2,38~5,2,38 +3,1,163~3,4,163 +4,5,174~4,7,174 +7,5,210~8,5,210 +0,1,43~0,3,43 +0,5,173~1,5,173 +2,6,294~2,7,294 +7,9,85~7,9,88 +1,2,217~1,4,217 +7,2,235~8,2,235 +1,5,112~1,7,112 +5,6,117~8,6,117 +2,0,299~2,1,299 +7,6,143~7,6,146 +4,3,168~4,5,168 +4,4,226~4,7,226 +7,6,208~7,6,210 +9,1,149~9,4,149 +3,6,11~5,6,11 +4,5,262~4,7,262 +2,8,73~2,8,76 +7,1,21~7,4,21 +5,2,279~5,3,279 +7,4,43~7,5,43 +0,1,180~0,3,180 +8,6,163~8,9,163 +6,2,143~8,2,143 +6,9,65~8,9,65 +6,8,222~8,8,222 +7,7,293~8,7,293 +7,1,295~7,4,295 +5,6,218~5,9,218 +3,1,171~3,3,171 +9,6,86~9,8,86 +1,4,240~3,4,240 +5,2,29~5,4,29 +3,0,266~3,0,268 +9,7,120~9,9,120 +7,5,220~7,9,220 +5,7,282~5,9,282 +8,8,188~8,9,188 +9,3,120~9,5,120 +7,7,138~7,8,138 +9,0,30~9,1,30 +6,6,79~6,8,79 +7,5,231~9,5,231 +7,8,236~9,8,236 +5,4,50~5,5,50 +3,9,99~3,9,102 +4,7,159~6,7,159 +6,0,8~7,0,8 +5,6,211~5,8,211 +3,5,163~5,5,163 +5,3,132~8,3,132 +2,7,60~4,7,60 +4,1,2~4,1,2 +9,7,131~9,7,134 +8,5,110~8,6,110 +7,1,48~7,3,48 +7,4,161~9,4,161 +1,1,294~2,1,294 +9,5,15~9,7,15 +5,1,136~5,3,136 +0,2,155~0,4,155 +7,7,275~7,9,275 +2,0,112~2,3,112 +3,5,7~3,7,7 +5,8,102~5,9,102 +7,0,106~8,0,106 +2,4,165~2,6,165 +3,0,50~3,1,50 +4,0,204~6,0,204 +3,5,74~3,5,76 +3,1,254~3,1,257 +4,4,70~7,4,70 +3,0,102~3,2,102 +5,3,146~6,3,146 +8,7,69~8,9,69 +4,0,63~6,0,63 +0,5,234~2,5,234 +8,0,25~8,1,25 +1,7,1~3,7,1 +8,7,128~9,7,128 +9,7,49~9,7,51 +4,3,264~6,3,264 +2,6,59~2,6,60 +8,2,144~8,2,146 +7,4,279~7,6,279 +5,5,290~7,5,290 +3,5,170~3,9,170 +3,1,155~3,2,155 +1,1,49~4,1,49 +0,5,6~0,6,6 +4,7,111~4,7,113 +5,7,107~5,8,107 +6,2,17~8,2,17 +4,5,229~4,7,229 +6,7,147~8,7,147 +7,2,105~9,2,105 +2,2,182~3,2,182 +9,6,229~9,6,230 +1,0,115~3,0,115 +5,2,271~8,2,271 +5,0,80~6,0,80 +8,8,5~8,8,6 +6,6,142~8,6,142 +1,4,302~1,4,305 +7,1,298~7,3,298 +3,2,194~6,2,194 +4,2,237~7,2,237 +4,9,103~6,9,103 +3,9,96~6,9,96 +0,2,216~2,2,216 +7,4,46~7,4,48 +8,7,286~8,7,286 +2,6,95~4,6,95 +4,0,91~4,2,91 +5,7,84~5,7,84 +6,8,61~6,9,61 +8,9,70~8,9,72 +3,1,253~3,3,253 +6,0,195~6,3,195 +3,1,243~3,3,243 +9,3,68~9,4,68 +7,1,275~7,2,275 +5,7,108~6,7,108 +6,5,69~6,5,70 +3,4,131~3,6,131 +0,1,60~0,4,60 +2,5,96~2,7,96 +1,5,1~1,5,3 +0,1,283~3,1,283 +4,7,268~4,8,268 +0,8,14~0,8,16 +7,8,294~9,8,294 +1,6,86~1,6,87 +8,3,78~9,3,78 +3,1,98~5,1,98 +5,2,68~5,4,68 +0,2,66~0,4,66 +7,8,54~7,8,55 +7,2,240~7,2,242 +6,1,33~9,1,33 +6,7,206~9,7,206 +7,6,180~7,9,180 +5,5,149~8,5,149 +7,0,133~9,0,133 +3,0,24~3,2,24 +7,0,76~7,0,78 +0,8,171~1,8,171 +7,3,41~7,6,41 +1,7,105~3,7,105 +3,0,79~5,0,79 +0,0,178~0,2,178 +1,6,235~3,6,235 +3,0,62~3,0,63 +1,3,282~3,3,282 +5,8,2~8,8,2 +3,5,39~3,7,39 +4,5,96~6,5,96 +8,6,259~8,8,259 +4,0,120~4,3,120 +2,9,55~5,9,55 +7,5,250~7,7,250 +3,0,145~5,0,145 +2,2,157~4,2,157 +4,8,212~4,9,212 +3,5,45~3,7,45 +3,2,73~3,5,73 +7,4,224~7,4,227 +7,5,49~9,5,49 +2,4,16~2,5,16 +2,4,162~2,6,162 +4,3,82~7,3,82 +4,3,214~4,5,214 +0,9,242~2,9,242 +3,3,55~4,3,55 +5,7,247~8,7,247 +3,5,36~4,5,36 +4,1,85~4,3,85 +1,7,209~3,7,209 +1,2,247~1,3,247 +5,9,2~7,9,2 +2,6,56~3,6,56 +9,4,115~9,6,115 +0,3,137~0,5,137 +4,3,219~4,3,219 +4,4,131~4,6,131 +2,0,102~2,2,102 +6,6,174~6,9,174 +5,5,9~5,7,9 +3,6,251~3,8,251 +0,6,57~0,8,57 +7,2,130~7,5,130 +1,5,289~1,5,289 +1,6,58~2,6,58 +3,7,69~3,8,69 +3,4,219~6,4,219 +7,6,22~7,6,24 +2,4,207~4,4,207 +9,0,278~9,0,280 +6,0,18~6,2,18 +8,0,109~8,0,111 +2,0,199~2,2,199 +8,5,232~9,5,232 +7,5,207~7,8,207 +3,3,62~4,3,62 +9,0,290~9,3,290 +3,1,26~3,3,26 +7,5,288~7,8,288 +1,8,138~1,8,140 +7,1,103~9,1,103 +3,2,35~4,2,35 +7,0,136~8,0,136 +2,2,100~2,4,100 +4,0,193~4,3,193 +3,0,58~3,0,60 +3,6,176~3,9,176 +2,6,159~2,8,159 +2,6,106~5,6,106 +4,3,211~4,6,211 +3,8,208~3,8,210 +1,5,57~3,5,57 +6,2,268~7,2,268 +8,6,246~8,8,246 +3,5,195~6,5,195 +1,0,1~3,0,1 +2,6,271~5,6,271 +3,6,195~3,8,195 +6,1,126~8,1,126 +3,4,277~3,6,277 +1,3,250~1,4,250 +0,1,152~0,4,152 +2,2,299~2,5,299 +7,4,297~7,6,297 +2,3,144~5,3,144 +5,2,274~6,2,274 +7,0,162~7,2,162 +9,2,25~9,2,27 +1,0,117~1,2,117 +1,5,243~1,7,243 +1,6,61~3,6,61 +6,7,130~7,7,130 +1,5,220~4,5,220 +0,8,162~0,9,162 +3,2,30~3,2,32 +7,5,253~9,5,253 +6,4,127~6,6,127 +6,4,35~6,4,37 +0,9,52~3,9,52 +0,3,70~0,3,70 +0,0,68~0,0,70 +6,3,42~9,3,42 +2,1,302~4,1,302 +2,6,121~2,7,121 +4,3,259~6,3,259 +3,2,160~3,4,160 +5,4,35~5,6,35 +7,4,204~7,6,204 +3,4,48~3,6,48 +3,2,210~3,4,210 +6,7,4~6,8,4 +0,2,242~2,2,242 +8,3,10~8,3,11 +3,0,141~3,3,141 +6,6,5~8,6,5 +1,5,92~1,7,92 +1,8,112~4,8,112 +8,7,1~8,9,1 +6,6,123~6,8,123 +3,5,84~5,5,84 +0,3,182~0,3,184 +3,6,41~4,6,41 +8,2,12~8,4,12 +7,3,243~7,5,243 +5,9,82~8,9,82 +2,6,239~2,7,239 +6,5,283~8,5,283 +0,5,248~0,7,248 +3,4,255~3,4,257 +7,6,74~7,8,74 +2,4,92~2,6,92 +4,7,42~4,9,42 +0,3,4~0,5,4 +7,9,6~9,9,6 +5,4,93~7,4,93 +4,2,163~4,2,164 +7,0,220~7,4,220 +0,2,25~0,3,25 +4,1,199~5,1,199 +0,4,112~2,4,112 +6,2,36~6,3,36 +2,9,246~5,9,246 +7,7,222~7,7,222 +5,1,120~5,3,120 +3,9,209~6,9,209 +1,1,109~1,2,109 +9,4,103~9,6,103 +2,5,252~2,5,252 +3,0,295~5,0,295 +8,0,277~9,0,277 +2,0,301~4,0,301 +1,0,129~1,3,129 +6,7,217~8,7,217 +2,3,102~3,3,102 +1,3,170~1,6,170 +0,4,103~2,4,103 +4,3,64~5,3,64 +0,8,118~2,8,118 +4,2,266~6,2,266 +8,7,265~8,9,265 +0,5,290~0,5,291 +8,3,152~8,6,152 +2,5,20~2,5,22 +0,0,52~3,0,52 +1,9,290~3,9,290 +7,5,59~7,7,59 +5,7,75~5,9,75 +1,4,173~1,4,176 +2,1,296~5,1,296 +3,2,248~5,2,248 +7,5,300~7,5,302 +6,6,176~6,6,178 +2,2,243~2,3,243 +2,0,207~4,0,207 +1,0,33~1,2,33 +8,2,134~8,3,134 +1,5,120~1,6,120 +5,5,172~7,5,172 +0,4,145~0,5,145 +9,2,282~9,2,285 +0,7,247~2,7,247 +8,9,4~8,9,5 +8,4,241~8,6,241 +2,5,118~4,5,118 +7,5,60~8,5,60 +6,6,73~7,6,73 +8,0,229~8,0,232 +4,6,56~7,6,56 +0,9,67~2,9,67 +7,7,41~7,7,44 +2,6,237~3,6,237 +7,9,89~9,9,89 +5,5,77~5,9,77 +4,6,260~4,8,260 +2,7,215~2,7,217 +5,3,139~7,3,139 +2,6,291~2,8,291 +1,2,201~3,2,201 +7,1,273~7,4,273 +0,2,247~0,2,249 +3,5,201~5,5,201 +0,1,66~0,1,66 +1,3,169~4,3,169 +7,2,29~9,2,29 +5,4,33~8,4,33 +2,9,281~5,9,281 +5,1,278~8,1,278 +2,3,24~2,5,24 +0,4,141~0,4,143 +0,0,142~0,2,142 +4,6,274~5,6,274 +0,2,124~0,4,124 +1,0,204~2,0,204 +3,5,282~3,6,282 +9,6,123~9,9,123 +3,1,114~4,1,114 +5,3,299~5,6,299 +7,7,84~9,7,84 +3,3,6~3,5,6 +0,3,181~0,3,181 +2,3,75~4,3,75 +1,5,5~1,6,5 +2,4,241~5,4,241 +6,7,252~6,8,252 +1,3,117~3,3,117 +4,2,280~4,2,280 +5,8,140~5,9,140 +3,2,124~5,2,124 +0,0,119~1,0,119 +4,4,178~5,4,178 +9,7,244~9,9,244 +7,5,99~9,5,99 +7,2,110~9,2,110 +3,3,258~3,3,260 +0,7,158~2,7,158 +0,5,140~0,7,140 +4,7,225~5,7,225 +7,7,67~7,9,67 +7,3,283~7,3,284 +5,0,29~7,0,29 +8,6,124~8,7,124 +3,2,164~3,3,164 +3,1,138~6,1,138 +0,6,173~0,6,173 +4,6,55~5,6,55 +2,4,81~2,8,81 +7,2,25~7,4,25 +5,9,182~7,9,182 +2,5,85~3,5,85 +4,6,280~4,9,280 +7,1,22~8,1,22 +0,0,72~1,0,72 +8,5,257~8,7,257 +1,4,49~3,4,49 +1,0,29~3,0,29 +1,9,247~1,9,248 +7,6,122~7,6,125 +3,2,260~5,2,260 +6,1,110~7,1,110 +2,8,126~4,8,126 +0,2,21~2,2,21 +0,4,295~0,4,296 +1,1,284~4,1,284 +2,5,245~5,5,245 +0,5,51~3,5,51 +1,2,122~3,2,122 +1,4,12~1,4,14 +7,4,276~7,4,278 +5,8,14~7,8,14 +3,8,161~3,9,161 +1,2,284~1,4,284 +4,7,71~4,7,74 +5,7,216~8,7,216 +8,8,52~8,8,54 +6,5,20~8,5,20 +9,3,77~9,5,77 +4,2,159~5,2,159 +5,5,68~5,7,68 +5,7,70~5,9,70 +1,7,95~4,7,95 +7,3,26~9,3,26 +6,4,27~6,7,27 +2,3,257~4,3,257 +5,5,4~8,5,4 +3,8,45~3,8,47 +6,2,167~8,2,167 +1,6,8~1,7,8 +7,6,8~8,6,8 +6,4,38~6,6,38 +2,7,100~2,9,100 +4,1,216~4,4,216 +9,1,212~9,3,212 +5,2,14~5,4,14 +1,5,240~1,5,242 +1,4,169~3,4,169 +6,2,28~6,4,28 +9,3,282~9,6,282 +9,5,207~9,7,207 +0,5,54~0,7,54 +4,5,237~4,7,237 +4,9,1~4,9,3 +0,3,293~2,3,293 +2,1,287~2,2,287 +7,8,137~7,9,137 +1,9,214~4,9,214 +5,6,302~5,8,302 +4,1,29~4,4,29 +4,6,138~4,9,138 +2,0,147~4,0,147 +4,2,62~4,2,64 +4,2,283~6,2,283 +3,4,162~3,7,162 +6,2,104~6,4,104 +1,6,249~3,6,249 +0,4,134~1,4,134 +8,3,192~8,3,192 +5,9,268~7,9,268 +0,0,53~1,0,53 +0,2,121~0,2,123 +9,1,23~9,4,23 +0,6,297~0,9,297 +3,1,22~3,3,22 +4,4,146~4,6,146 +4,8,1~5,8,1 +7,2,45~8,2,45 +3,9,50~6,9,50 +8,0,21~8,2,21 +4,2,105~4,2,107 +0,6,289~2,6,289 +3,4,280~3,4,282 +8,7,161~8,9,161 +2,4,84~2,4,86 +2,8,292~2,9,292 +6,0,60~6,3,60
\ No newline at end of file diff --git a/aoc2023/src/day23/input.txt b/aoc2023/src/day23/input.txt new file mode 100644 index 0000000..12c7b78 --- /dev/null +++ b/aoc2023/src/day23/input.txt @@ -0,0 +1,141 @@ +#.########################################################################################################################################### +#...#.....#.....................#...#.........###...###...###...#...#.......#...###.....#...#.......###.........#...........#.............### +###.#.###.#.###################.#.#.#.#######.###.#.###.#.###.#.#.#.#.#####.#.#.###.###.#.#.#.#####.###.#######.#.#########.#.###########.### +#...#...#...###...#.............#.#.#.......#.....#...#.#.#...#...#.#.....#.#.#...#...#...#...#...#.#...#.......#.........#.#.#.........#...# +#.#####.#######.#.#.#############.#.#######.#########.#.#.#.#######.#####.#.#.###.###.#########.#.#.#.###.###############.#.#.#.#######.###.# +#.......###...#.#.#...............#...#.....#.........#.#...#.......#.....#...#...###.....#...#.#...#...#.#...###...###...#.#.#.#...###.....# +###########.#.#.#.###################.#.#####.#########.#####.#######.#########.#########.#.#.#.#######.#.#.#.###.#.###.###.#.#.#.#.######### +#.........#.#...#.....................#.....#.###.....#.....#...#...#.......#...#...#####...#.#.#...###.#.#.#.....#...#.#...#.#...#.........# +#.#######.#.###############################.#.###.###.#####.###.#.#.#######.#.###.#.#########.#.#.#.###.#.#.#########.#.#.###.#############.# +#.......#...#.....###.....#...###.....###...#...#.#...#...#.#...#.#.....#...#...#.#.###...#...#...#.#...#.#.#.....#...#.#...#.#.............# +#######.#####.###.###.###.#.#.###.###.###.#####.#.#.###.#.#.#.###.#####.#.#####.#.#.###.#.#.#######.#.###.#.#.###.#.###.###.#.#.############# +#.....#.....#.#...#...#...#.#...#...#...#.#...#...#...#.#.#.#...#.....#.#.#.....#.#.###.#.#...#.....#...#.#...#...#.###.#...#.#.......#...### +#.###.#####.#.#.###.###.###.###.###.###.#.#.#.#######.#.#.#.###.#####.#.#.#.#####.#.###.#.###.#.#######.#.#####.###.###.#.###.#######.#.#.### +#...#.......#.#...#...#...#.#...###...#.#.#.#.........#.#.#.#...#...#.#.#.#.###...#.#...#.....#.###...#.#.#...#...#...#.#...#.#.......#.#.### +###.#########.###.###.###.#.#.#######.#.#.#.###########.#.#.#.###.#.#.#.#.#.###.###.#.#########.###.#.#.#.#.#.###.###.#.###.#.#.#######.#.### +###.....#...#.#...###...#.#.#.#.>.>...#.#.#...#.......#.#.#.#.###.#.#.#.#.#.###.#...#.........#...#.#.#.#...#.>.>.#...#...#.#.#.....#...#...# +#######.#.#.#.#.#######.#.#.#.#.#v#####.#.###.#.#####.#.#.#.#.###.#.#.#.#.#.###.#.###########.###.#.#.#.#######v###.#####.#.#.#####.#.#####.# +#...###...#...#.#.....#.#.#.#.#.#.#...#...#...#...#...#.#.#.#.###.#.#.#.#.#.###.#.#...###...#...#.#.#.#.#.....#.#...#...#.#.#.#.....#...#...# +#.#.###########v#.###.#.#.#.#.#.#.#.#.#####.#####.#.###.#.#.#.###.#.#.#.#.#.###.#.#.#.###.#.###.#.#.#.#.#.###.#.#.###.#.#.#.#.#.#######.#.### +#.#.....#...###.>.###.#.#.#.#.#.#.#.#...###.....#.#.#...#.#.#.>.>.#.#.#.#.#...#.#.#.#.>.>.#...#.#.#.#...#...#.#.#...#.#.#.#.#.#...###...#...# +#.#####.#.#.###v#####.#.#.#.#.#.#.#.###.#######.#.#.#.###.#.###v###.#.#.#.###.#.#.#.###v#####.#.#.#.#######.#.#.###.#.#.#.#.#.###.###.#####.# +#.#...#...#.#...###...#.#.#.#.#.#.#.#...#.....#.#.#.#...#.#...#...#...#.#.###.#.#.#.#...#...#...#...###.....#.#...#.#.#.#.#.#.###...#.#.....# +#.#.#.#####.#.#####.###.#.#.#.#.#.#.#.###.###.#.#.#.###.#.###.###.#####.#.###.#.#.#.#.###.#.###########.#####.###.#.#.#.#.#.#.#####.#.#.##### +#...#.....#.#.....#.#...#.#.#.#.#.#.#.....#...#...#...#.#.#...###...#...#...#...#...#...#.#.###...#...#.....#...#.#.#.#.#.#...###...#.#.....# +#########.#.#####.#.#.###.#.#.#.#.#.#######.#########.#.#.#.#######.#.#####.###########.#.#.###.#.#.#.#####.###.#.#.#.#.#.#######.###.#####.# +###...###.#.#...#.#.#.#...#.#.#.#...###...#.....#.....#.#.#.#.......#.......#.....#.....#.#.#...#...#...#...###.#.#.#.#...###...#...#.#.....# +###.#.###.#.#.#.#.#.#.#.###.#.#.#######.#.#####.#.#####.#.#.#.###############.###.#.#####.#.#.#########.#.#####.#.#.#.#######.#.###.#.#.##### +#...#.#...#...#...#...#.#...#...#.......#.......#.......#...#.....#.......###...#.#.......#.#.........#...#...#.#.#.#.....#...#.....#.#.#...# +#.###.#.###############.#.#######.###############################.#.#####.#####.#.#########.#########.#####.#.#.#.#.#####.#.#########.#.#.#.# +#...#.#...............#...#...###.....#.......#.....#.....#.....#...#.....#.....#.........#.#...#...#.#...#.#.#...#.#...#.#...........#...#.# +###.#.###############.#####.#.#######.#.#####.#.###.#.###.#.###.#####.#####.#############.#.#.#.#.#.#v#.#.#.#.#####.#.#.#.#################.# +#...#...#...#.....#...#...#.#.###...#...#.....#...#.#.#...#...#.#.....#####...........###.#.#.#...#.>.>.#...#...###...#...###...#.........#.# +#.#####.#.#.#.###.#.###.#.#.#.###.#.#####.#######.#.#.#.#####.#.#v###################.###.#.#.#######v#########.#############.#.#.#######.#.# +#.#...#...#.#.###...#...#...#...#.#.#...#.......#.#...#...#...#.>.>.....#.......#...#...#.#.#.......#.....#.....#...#...#.....#.#.......#.#.# +#.#.#.#####.#.#######.#########.#.#.#.#.#######.#.#######.#.#####v#####.#.#####.#.#.###.#.#.#######.#####.#.#####.#.#.#.#.#####.#######.#.#.# +#.#.#.#...#...#...###.......#...#.#.#.#.###.....#.......#.#...#...#.....#.....#...#.....#...#...###...#...#...###.#...#.#.....#.........#.#.# +#.#.#v#.#.#####.#.#########.#.###.#.#.#.###.###########.#.###.#.###.#########.###############.#.#####.#.#####.###.#####.#####.###########.#.# +#.#.#.>.#.###...#...#...#...#...#.#.#.#...#.....#...#...#.....#...#.#.....###.............#...#.......#...###.#...#.....#...#...........#.#.# +#.#.#v###.###.#####.#.#.#.#####.#.#.#.###.#####.#.#.#.###########.#.#.###.###############.#.#############.###.#.###.#####.#.###########.#.#.# +#.#.#...#...#.....#.#.#.#.#.....#.#.#...#.#.....#.#...#.......#...#.#.#...#...#...#.......#.............#...#...###.#...#.#.#...#.......#...# +#.#.###.###.#####.#.#.#.#.#.#####.#.###.#.#v#####.#####.#####.#.###.#.#.###.#.#.#.#.###################.###.#######.#.#.#.#.#.#.#.########### +#.#.###...#.....#.#.#.#.#.#.#...#.#...#.#.>.>...#.......#.....#...#.#.#.###.#.#.#.#...###...#...#.....#...#...#.....#.#.#.#.#.#.#...#...#...# +#.#.#####.#####.#.#.#.#.#.#.#.#.#.###.#.###v###.#########.#######.#.#.#.###.#.#.#.###v###.#.#.#.#.###.###.###.#.#####.#.#.#.#.#.###v#.#.#.#.# +#...#.....#...#...#...#.#.#.#.#.#...#.#.###...#.#...#...#...###...#...#...#.#.#.#...>.>.#.#.#.#.#.###.....#...#.....#.#.#.#.#.#.#.>.#.#...#.# +#####.#####.#.#########.#.#.#.#.###.#.#.#####.#.#.#.#.#.###.###.#########.#.#.#.#####v#.#.#.#.#.#.#########.#######.#.#.#.#.#.#.#.#v#.#####.# +#.....#...#.#.#.......#.#.#...#.#...#...#.....#...#...#.#...#...#...#####...#.#.###...#.#.#.#.#.#.#.......#.......#.#.#.#.#...#...#...#...#.# +#.#####.#.#.#.#.#####.#.#.#####.#.#######.#############.#.###.###.#.#########.#.###.###.#.#.#.#.#.#.#####.#######.#.#.#.#.#############.#.#.# +#.......#...#...#.....#...#.....#.###...#...........###.#.#...#...#.........#...#...###...#.#.#.#.#.....#.......#.#...#...#.............#...# +#################.#########.#####.###.#.###########.###.#.#.###.###########.#####.#########.#.#.#.#####.#######.#.#########.################# +#.............#...#...#...#.#.....#...#...#.........#...#.#...#.#.......#...###...#.......#.#.#.#.#...#.......#...#.......#.................# +#.###########.#.###.#.#.#.#.#.#####.#####.#.#########.###.###.#.#.#####.#.#####.###.#####.#.#.#.#.#.#.#######.#####.#####.#################.# +#...........#...###.#.#.#.#...#...#.....#...#...#...#...#...#...#.....#.#.#.....###.#.....#...#.#.#.#.........###...#...#...#...............# +###########.#######.#.#.#.#####.#.#####.#####.#.#.#.###.###.#########.#.#.#.#######.#.#########.#.#.#############.###.#.###.#.############### +#...........#.......#...#.#...#.#.#...#.......#...#...#.#...###.......#...#.........#...###...#...#.............#...#.#.....#...........#...# +#.###########.###########.#.#.#.#.#.#.###############.#.#.#####.#######################.###.#.#################.###.#.#################.#.#.# +#...#.........#...........#.#.#.#.#.#.#...#.........#.#...#...#.........#.............#...#.#.#...#.........#...###.#.....#...#...###...#.#.# +###.#.#########.###########.#.#.#.#.#.#.#.#.#######.#.#####.#.#########.#.###########.###.#.#.#.#.#.#######.#.#####.#####.#.#.#.#.###v###.#.# +###.#.#.....#...#...#.....#.#.#.#.#.#.#.#...#...###...#...#.#.#...#.....#...........#.#...#.#...#.#.....#...#.....#...#...#.#.#.#.#.>.###.#.# +###.#.#.###.#.###.#v#.###.#.#.#.#.#.#.#.#####.#.#######.#.#.#.#.#.#.###############.#.#.###.#####.#####.#.#######.###.#.###.#.#.#.#.#v###.#.# +#...#.#...#...#...#.>.#...#.#.#.#.#.#.#.......#.....#...#.#.#...#...#.......#.......#...#...#.....###...#.........#...#.#...#.#.#.#.#.....#.# +#.###.###.#####.###v###.###.#.#.#.#.#.#############.#.###.#.#########.#####.#.###########.###.#######.#############.###.#.###.#.#.#.#######.# +#.....###.......#...###...#.#.#.#.#.#.###...........#...#.#...........#.....#...#.....###...#.#.....#.#...#.....#...#...#...#...#...#.....#.# +#################.#######.#.#.#.#.#.#.###.#############.#.#############.#######.#.###.#####.#.#.###.#.#.#.#.###.#.###.#####.#########.###.#.# +#.................###.....#.#.#.#.#.#...#...#.........#.#...#...........#...###.#.#...#...#.#.#.#...#...#...#...#...#.#.....#...#.....#...#.# +#.###################.#####.#.#.#.#.###.###v#.#######.#.###.#.###########.#.###v#.#.###.#.#.#.#.#.###########.#####.#.#.#####.#.#.#####.###.# +#...................#.......#.#.#.#...#...>.>.#.......#.#...#.......#...#.#.#.>.>.#.###.#.#.#.#.#.###...#...#.###...#.#...#...#.#.....#...#.# +###################.#########.#.#.###.#####v###.#######.#.#########v#.#.#.#.#.#v###.###.#.#.#.#.#.###.#.#.#.#v###.###.###.#.###.#####.###.#.# +#...................###.....#.#.#.#...#.....###.#.....#.#.......#.>.>.#.#.#.#.#...#.#...#.#.#...#.....#...#.>.>.#...#.#...#...#.#...#...#.#.# +#.#####################.###.#.#.#.#.###.#######.#.###.#.#######.#.#v###.#.#.#.###.#.#.###.#.#################v#.###.#.#.#####.#.#.#.###.#.#.# +#.....................#...#.#...#...###.#.....#.#.###.#.....###...#...#.#.#...###.#...###.#.......#.........#.#.#...#...#...#.#.#.#.#...#.#.# +#####################.###.#.###########.#.###.#.#.###.#####.#########.#.#.#######.#######.#######.#.#######.#.#.#.#######.#.#.#.#.#.#.###.#.# +#.....................#...#.#...#.....#...#...#.#.#...#.....#...#...#.#.#.#.......###...#.........#.......#.#.#...#.....#.#...#.#.#...#...#.# +#.#####################.###.#.#.#.###.#####.###.#.#.###.#####.#.#.#.#.#.#.#.#########.#.#################.#.#.#####.###.#.#####.#.#####.###.# +#.........#...#...#...#...#.#.#.#...#.#...#.###.#.#.....#.....#.#.#...#.#.#...........#.........#.......#.#...#...#.#...#.....#...#...#.....# +#########.#.#.#.#v#.#.###.#.#.#.###.#.#.#.#v###.#.#######.#####.#.#####.#.#####################.#.#####.#.#####.#.#.#.#######v#####.#.####### +#.......#...#...#.>.#...#.#.#.#.#...#.#.#.>.>.#...#...###...###.#.....#...#####.................#.....#...#...#.#.#.#.....#.>.#...#.#.#...### +#.#####.#########v#####.#.#.#.#.#.###.#.###v#.#####.#.#####.###.#####.#########.#####################.#####.#.#.#.#.#####.#.#v#.#.#.#.#.#.### +#.....#.###...#...#####.#.#...#.#...#...###.#...#...#.#...#...#.......###...#...#...###...#...###...#.###...#.#.#.#...#...#.#...#...#...#...# +#####.#.###.#.#.#######.#.#####.###.#######.###.#.###.#.#.###.###########.#.#.###.#.###.#.#.#.###.#.#v###.###.#.#.###.#.###.###############.# +#.....#.....#.#.......#.#.#.....#...#...#...#...#.#...#.#.#...###...#...#.#.#.....#.#...#...#.#...#.>.>.#.###.#.#...#.#.....#.......#.......# +#.###########.#######.#.#.#.#####.###.#.#.###.###.#.###.#.#.#####.#.#.#.#.#.#######v#.#######.#.#####v#.#.###.#.###.#.#######.#####.#.####### +#.......#...#.#.......#...#...#...#...#.#...#.#...#...#.#.#.#...#.#.#.#.#.#.#...#.>.>.#.....#.#...###.#...#...#...#.#.#.......#...#.#.....### +#######.#.#.#.#.#############.#.###.###.###.#.#.#####.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#v###.###.#.###.###.#####.#####.#.#.#.#######.#.#.#####.### +#...###...#.#.#.............#...#...#...#...#.#...#...#.#.#.#.#.#.#.#.#...#.#.#.#.#.###...#.#...#.#...#...#.......#...#.........#.#.#...#...# +#.#.#######.#.#############.#####.###.###.###.###.#.###.#.#v#.#.#.#.#.#####.#.#.#.#.#####.#.###.#.#.###.#.#######################.#.#.#.###.# +#.#.........#...............###...###...#...#.....#.....#.>.>.#...#.#.....#...#...#.......#...#...#.....#.....#...................#...#.....# +#.#############################.#######.###.###############v#######.#####.###################.###############.#.############################# +#.........#.............#.......###...#.#...###...#...#...#.###...#...#...#.................#.#...............#.........#...............#...# +#########.#.###########.#.#########.#.#.#.#####.#.#.#.#.#.#.###.#.###.#.###.###############.#.#.#######################.#.#############.#.#.# +#.......#...#...........#...........#.#.#...#...#...#.#.#.#.....#...#...###...............#.#.#.#.............###.......#.#.............#.#.# +#.#####.#####.#######################.#.###.#.#######.#.#.#########.#####################.#.#.#.#.###########.###.#######.#.#############.#.# +#.....#.....#...........#.............#.....#.......#.#.#.#...#.....#...#.................#...#...###...#...#...#.....#...#...........#...#.# +#####.#####.###########.#.#########################.#.#.#.#.#.#.#####.#.#.###########################.#.#.#.###.#####.#.#############.#.###.# +#...#.....#.#...#...#...#.............#...###.......#...#.#.#.#...#...#.#.....#.....#.....#...#.......#...#.#...#.....#.#...#.........#.#...# +#.#.#####.#.#.#.#.#.#.###############.#.#.###.###########.#.#.###.#.###.#####.#.###.#.###.#.#.#.###########.#.###.#####.#.#.#.#########.#.### +#.#.......#...#...#...#.......#.......#.#...#...........#.#.#.#...#.#...#...#...###...#...#.#.#...........#...###...#...#.#...#.........#...# +#.#####################.#####.#.#######.###.###########.#.#.#.#.###.#.###.#.###########.###.#.###########.#########.#.###.#####.###########.# +#...#...#...#.....#...#.....#.#.......#.#...#...###.....#...#...#...#...#.#...#.......#.#...#.###...#.....#.....###...#...#.....#...........# +###.#.#.#.#.#.###.#.#.#####.#.#######.#.#.###.#.###.#############.#####.#.###.#.#####.#.#.###.###.#.#.#####.###.#######.###.#####.########### +###.#.#.#.#...###...#.#.....#.#.......#.#...#.#.#...#...........#...#...#.#...#.....#...#.#...#...#...#####...#...#...#.....#...#...........# +###.#.#.#.###########.#.#####.#v#######.###.#.#.#.###.#########.###.#.###.#.#######.#####.#.###.#############.###.#.#.#######.#.###########.# +###.#.#.#.#...........#.....#.>.>.......#...#.#.#.....#.........###.#...#.#.#...###...###.#.###...........#...#...#.#.#.......#.#.....#...#.# +###.#.#.#.#.###############.###v#########.###.#.#######.###########.###.#.#.#.#.#####.###.#.#############.#.###.###.#.#.#######.#.###.#.#.#.# +###...#...#.......#...#####.#...#.........#...#...#...#...#.......#...#...#.#.#.......#...#.#...#.........#...#...#.#.#.......#...###...#...# +#################.#.#.#####.#.###.#########.#####.#.#.###.#.#####.###.#####.#.#########.###.#.#.#.###########.###.#.#.#######.############### +###...#...###...#...#.###...#...#.#####...#.....#.#.#.#...#.#.....#...#.....#.........#...#.#.#.#.....###...#...#.#.#.###.....#.......#.....# +###.#.#.#.###.#.#####.###.#####.#.#####.#.#####.#.#.#.#v###.#.#####.###.#############.###.#.#.#.#####v###.#.###.#.#.#.###.#####.#####.#.###.# +#...#...#...#.#.#.....#...###...#...#...#.#...#.#.#.#.>.>...#...###...#.......#.......#...#.#.#.#...>.>.#.#.#...#.#.#...#.......#.....#...#.# +#.#########.#.#.#.#####.#####.#####.#.###.#.#.#.#.#.###v#######.#####.#######.#.#######.###.#.#.#.###v#.#.#.#.###.#.###.#########.#######.#.# +#.........#.#.#.#...#...#...#.#...#...###.#.#...#.#.###.....#...#...#.#.......#.....#...###...#...###.#.#.#.#...#.#.#...#...#...#...#...#.#.# +#########.#.#.#.###.#.###.#.#.#.#.#######.#.#####.#.#######.#.###.#.#.#.###########v#.###############.#.#.#.###.#.#.#.###.#.#v#.###.#.#.#.#.# +###...#...#.#.#.#...#.....#.#.#.#.#...###.#.....#.#.#.......#...#.#.#.#...#.......>.>.#...............#...#.....#.#.#...#.#.>.#.....#.#...#.# +###.#.#.###.#.#.#v#########.#.#.#.#.#.###.#####.#.#.#.#########.#.#.#.###.#.#######v###.#########################.#.###.#.###v#######.#####.# +#...#.#...#.#.#.#.>.#.....#.#.#.#...#...#.......#...#.........#...#...#...#.#.......###.....#.....#...#.........#.#.#...#.#...###...#.#.....# +#.###.###.#.#.#.#v#.#.###.#.#.#.#######.#####################.#########.###.#.#############.#.###.#.#.#.#######.#.#.#.###.#.#####.#.#.#.##### +#...#.....#.#.#.#.#.#...#.#.#.#.#...###.........#.............#.....###.....#.......###...#...#...#.#.#.#.......#...#.....#...#...#...#.....# +###.#######.#.#.#.#.###.#.#.#.#.#.#.###########.#.#############.###.###############.###.#.#####.###.#.#.#.###################.#.###########.# +###...#...#.#.#.#.#.....#...#...#.#...#.........#...#...#.......#...#...###...#...#...#.#.....#.....#...#.#...........#.......#.###.........# +#####.#.#.#.#.#.#.###############.###.#.###########.#.#.#.#######.###.#.###.#.#.#.###.#.#####.###########.#.#########.#.#######.###.######### +#.....#.#.#...#...###.....#...###...#...###...#####...#...#.......#...#.#...#...#.....#.....#.#...#...###...#.....#...#...#...#...#.........# +#.#####.#.###########.###.#.#.#####.#######.#.#############.#######.###.#.#################.#.#.#.#.#.#######.###.#.#####.#.#.###.#########.# +#.......#.#...#...#...#...#.#.....#.......#.#...#...#...###.......#.#...#.#.....###...#...#.#...#.#.#.###...#...#...#...#.#.#.....#.........# +#########.#.#.#.#.#.###.###.#####.#######.#.###.#.#.#.#.#########.#.#.###.#.###.###.#.#.#.#.#####.#.#.###.#.###v#####.#.#.#.#######.######### +#.........#.#.#.#.#...#.###.#.....#...#...#.#...#.#.#.#.#...#...#.#.#.###...###...#.#.#.#.#.....#...#...#.#.#.>.>...#.#.#...#...###.......### +#.#########.#.#.#.###.#.###.#.#####.#.#v###.#.###.#.#.#.#.#.#.#.#v#.#.###########.#.#.#.#.#####.#######.#.#.#.#####.#.#.#####.#.#########v### +#.........#.#.#.#...#.#...#.#...#...#.>.>...#...#.#.#.#.#.#.#.#.>.>.#.#...#...#...#.#.#.#.#...#.....###.#.#.#...#...#.#...#...#.#.....#.>.### +#########.#.#.#.###.#.###.#.###.#.#############.#.#.#.#.#.#.#.#######.#.#.#.#.#.###.#.#.#.#.#.#####.###.#.#.###.#.###.###.#.###.#.###.#.#v### +#.........#.#...#...#...#.#...#.#.#...#.........#.#.#.#...#.#.#.....#...#...#.#.....#.#.#.#.#.#...#...#.#.#.#...#.#...#...#.#...#...#...#...# +#.#########.#####.#####.#.###.#.#.#.#.#.#########.#.#.#####.#.#.###.#########.#######.#.#.#.#.#.#.###.#.#.#.#.###.#.###.###.#.#####.#######.# +#.........#.....#.#...#.#.#...#.#...#.#...#.....#.#.#.#.....#.#...#...........#.......#.#...#...#.#...#...#.#...#.#...#...#.#...#...#.......# +#########.#####.#.#.#.#.#.#.###.#####.###.#.###.#.#.#.#.#####.###.#############.#######.#########.#.#######.###.#.###.###.#.###.#.###.####### +###.......#...#.#...#...#.#.###.....#.#...#.###.#.#.#.#...#...###.......#.....#.###...#.......#...#.......#.#...#.#...#...#.#...#.###.......# +###.#######.#.#.#########.#.#######.#.#.###.###.#.#.#.###.#.###########.#.###.#v###.#.#######.#.#########.#.#.###.#.###.###.#.###.#########.# +#...#...#...#.#...#...#...#.......#...#.....#...#.#...#...#.....###.....#.###.>.>.#.#.#.......#.....#...#.#.#.#...#.#...#...#...#...#.......# +#.###.#.#.###.###.#.#.#.#########.###########.###.#####.#######.###.#####.#######.#.#.#.###########.#.#.#.#.#.#.###.#.###.#####.###.#.####### +#.#...#.#.###...#...#.#.#...#...#.###...#.....#...#.....#.....#.#...#...#.#.......#.#.#...#.......#.#.#...#.#.#.#...#.#...#.....#...#.......# +#.#.###.#.#####.#####.#.#.#.#.#.#.###.#.#.#####.###.#####.###.#.#.###.#.#.#.#######.#.###.#.#####.#.#.#####.#.#.#.###.#.###.#####.#########.# +#.#.#...#.....#...#...#.#.#.#.#.#.#...#...#...#...#.#...#.#...#.#...#.#.#.#.....#...#...#...#...#.#.#.#.....#.#.#.#...#.#...#...#.#.........# +#.#.#.#######.###.#.###.#.#.#.#.#.#.#######.#.###.#.#.#.#.#.###.###.#.#.#.#####.#.#####.#####.#.#.#.#.#.#####.#.#.#.###.#.###.#.#.#.######### +#...#.........###...###...#...#...#.........#.....#...#...#.....###...#...#####...#####.......#...#...#.......#...#.....#.....#...#.........# +###########################################################################################################################################.#
\ No newline at end of file diff --git a/aoc2023/src/day3/input.txt b/aoc2023/src/day3/input.txt new file mode 100644 index 0000000..1903642 --- /dev/null +++ b/aoc2023/src/day3/input.txt @@ -0,0 +1,140 @@ +............830..743.......59..955.......663..........................................367...........895....899...............826...220...... +.......284.....*............*.....$...+.....*...377..................*.......419.............488...*.......*...................*..-....939.. +....%.........976..679.461.7..........350..33.........$.380...$...151.897..........295..#......*....105.....418.............481........&.... +...992.....#......=...../........701................508...*..578........................259...331.................795..945........79........ +.........868........................*.............................17*..........348................441*852........*.....-...........@.....922 +....................*200............311..63................452.......323.#778.*....674....................680......696...372.....*.......... +.......266.......209......589.....=......*...365.........7.*...233.............755....*......644...272........697..*....*.....682..225...... +..836..........................949....607..........&....*..899...*....679.527.........331..........$....788../.....43....89................. +........367.....328.&......%...............680...69..717.......60.......*.*............................*..........................728...264. +........*.........*..119.253.......................................626....129...274............97...679.......752........*.......*....*.*... +........360......471........../.........573-.702.............866...@...........*......772....../........259....*.........430....136.742.543. +.........................../.852...............*...775...............643....455....../...........832....*.....41..535....................... +.............-..........340.................103....*..........$...51*..................74................438......%...776...+.23*..663...... +.15.......806...............990.....................427....924............530.........=..............................*....968.....=....480.. +......#..............@914...*..............*........................%......*................................/.....406.................*..... +....201.........79........592............70.894.....247..513+....367..$299.698......199................-.....223....../.........563....783.. +......................448........489................*.................................*....440...889...715..........351.....39.............. +.138....../766...........*.......................152.........................377....599.......*...*...........................@............. +....%.820.......10*43.670..$87....100*244..@706..........668..319#...........................831.736....@............./..693.....321%....... +......=...930#..................@...................493....*............152......569.................=.914....764.....9.-................... +378$...............&.....854..505.........%........&.....124......12........117.....*591..979..76..133..........+............/..........883. +...............602.141.....*...............770.....................*.........*................../.........874.@....../684....778............ +...........................954.....*397.........................394...........614..307*74..457..............+.514.......................327. +........335*25.....-....31..........................................$...719.................*........6..214................878.............. +...............86*.269....*...480........................*....140..947....*..&.......................*......972..............*..364*274..... +501-.......805..........285...*..................6....335.167...*........18...332.............741...127......+.............246.............. +......616.......752*276.....470.848..599.........*............779..=................539...961..$.........204.......-..201*.....%............ +.491.....*..521.........*94.......*.-.....&...163........285/......51..99*......474..*...-.......945.....&......839.......140...201.....$... +....$.795..*........539.........500.......662.............................421....*...459..../.......*407.............../................471. +...........110.......*...............252.............................%..........730......551..509.............824...230....569....48=....... +......150...................................+..70.565=.&320.........983....155................=.....54.......%............*....@......../... +...............972..146...........49.433..137..............................*....%..................@....................436.451..........328 +568-...@.552%....-.-................*.................957................93......74...........*........156.566../....#...........285........ +.....565..............693....443......................*....394.@58...362...................383.583.............542.38............./..890.... +...*.................*........*........&.223...........506.............=..................................300...............477........&.... +..612..459..........462....663......125....................720..............355.....253...............904......................*............ +........$................................622..............=................*...........*30.........#.$........................284........383 +............&.999....&.......................%........240....295*681.846....53.....806......793..646....626./76..737....479.........558.@... +.........892..#.......885.....804..587*....340.........*..............%............*.........*..........*................%............/..... +660..635...........-............./.....213........$....512.....551.............*....910........................@............................ +........*..........361..270*.....................328..............*.........853........................*.....985...965............232...948. +..501@......................213...412$.....375..................631..916.......................254...284.........#....*..252........*....... +...................695............................872*876..622..........-.........*..575...851*..................910.395..*....*717.248..... +.....91.........80....*..390...........497....496............*.......@.........297..*................&....873.............946.8.........647. +.......*.424.......108.....=.............*..................686....418.............131........600.96.327...=...561...321............343*.... +....731....*..............................938..........256..............909.......................................*......................... +.........811...=....................680...........167...*...601.....................892..#.......142*.......151..108............201......... +................653........879....@.*.........%...*...699..*..............726............695.870.....526.$................*8............234. +....54....311..............=...320..619.......495.375.......926....914.........654..............*........236...$.......444.....@613......... +...*........*......450*............................................*...786.625.......804.850.....674..........305........................... +..593.512....517.......155.....646*239....286......+...........96..264....*......471.*......*.........314*901..............879.............. +..........................................=.....419....820......&..................+.......163....148........................*....586....... +.....331.....................637....126.................*..147............650...............................................315....*........ +.......%......................$....../.................392....@...943..34...*......752.............................161..30.........970.521.. +.........984.412#.......-.569...@................464....................*.275..&.....#.126*506....................*.......=.168-............ +.724..................570....*.914.388.........%..$.........274.......263.......130..............102.....2....21+.268....................226 +..........776=...6........759.......*..283..309.....682......$..........................................%........................446........ +....%284.........-....#...........119....*......622...@....+............/.......929..178...........141/............../650...628.+........... +....................440........88.........335...*.......804............968..976*....+...................$.421..431..................*....... +.....880@.......871.....30......................249...........134....*................*...............95....-...*.....856...353...94.....963 +...............*....97..&.......989./.........*.....522+..$.....*.226.436.905......347.396.707...511..........342.....-.....*...........*... +........936*....299.........217.&...478....931.457........62.391............&...............*..../...884*....................370........483. +....965.....992.............*......................................371*771.............37..382...........990...391.......852................ +.......*........985.......753.&..........561.204.......................................*......................*...........@..........+935... +......677.....................164.883...............325........951.....847....%......433....*944.50...753..344.............................. +.829.......583........429............*34......243...*.........*.............329.%........421...........*..........803..746............675... +...*..................*....512............999.......102......398.................640................401....310.............164...452..*..... +269........9........705....*........782....%.......................615.734....-..............289...........*.....................=....661... +........37.#..............14.......*........../.......586.............*........623.......129........324.....601...%.....@................... +...165................#.........861............463.......*.......361*..............356........175.....*.........906.897..716....118..#...... +.....*.............728....417.........+...395#.........443...........829.....390-....................399...............*..........+..813.... +....176..253...846......$...........719..........132............897...............334......................20...........51.....%............ +..............*....*..278................958........*.......=.................183*.......427.......766.......*..914.282......674............ +....&......344...249.....................*.....445.770.....67.....301................295*.........*....715.390...*...../...............424.. +.....541......................160.580...........#................=...........*677..............394.......*........327....739...179.360..*... +..........=................%.....*................-954......%.............406......765..................930.....*.........../.....*.....370. +....%.....979.379..........415...............318..........284....440../............-....133.........157......579.550................747..... +.240..........*.....................@...........*642............*.....84.....%.331................2*...................582...=........*..... +......=.....246....167...............704.............763........999.......781...*.....-109............126..801............*.484....632..542. +....%..488.........@..........................$954....*../.....................779..........232................510.....149.................. +...27..........984.........*....485.....937........982..234..............225..................*..........122.............................16. +...........473.#..........558..*.............410-...........93............#..655....846....829.....760......=...................=....+...... +.....=390..*...................624........#.................+..473..............#......=...........+...577#......$...481.......651.869.806.. +747.......543.259.../717............&...346.......948..........$...........472.............230+......=.........206......*................... +................*........+.224/...798.........311...*..896*220...............&.+..................825....../............378...370........... +...............485.641.674.....................*......................618.......389........................565..&674...........*............ +..........475.................=.162............461.441...................*..........652......&....508..856...........364....464............. +...............154...452#...693....*................*.......391.........979....344..&.......814..............501.......=.................... +...............*................425....25#...........788............879...........*.....29....................&....................850...794 +393.............523...507*683..............174@..........-.............=...369....439....-.......*305.891..........952............*......... +..........+...............................................535..911.........................*....1.........441.....-.........88...906........ +..........997...17.............779..............960...................209........545......513................*...........98...........+608.. +.....................63.968...*.........340.......*...858..339...........%.-767...+...173........47.........906............*210............. +.............&..575..*....@.788.........*.........178.....*.......949.................+...........*.............-.....399.............@..... +..........571....%....984............414...............$.912.....*......302.............594.240..724....341..645.......*.......=..848.642... +....282@...........*......=......189.....138...227*.906.........70......*..................*.............=..........957...657.81../......... +..........*...$.813.179.901.592.....*....................................7....127.............$692...............$..........*.........*..... +.......207..91..............*.....784...872..756.........&..322..............*.........*19.........749.......548..624.694..858...512..598... +.................+.........352...........*.....*.934..126...*.....351..........40...616.......153.....*661............*...........*......... +...823........829...346...........821...826.304...%.......115.......*..........*...............*.............../...622...523.......606...... +...*...............*.............*...................186...........813....716@.372....16..300...489..108.....770.......................697.. +..........919...782.......912................@.........*.%485............................*..........*...............208.220....853.......... +...308......*............*......269.........539.......2.............853.......941.660.532........246.......980..357*....+.....*......./..... +..../......32.164.......15.479.=.............................=...............*....*......................#....*......+......-.855.....415... +.......305..../.....649....*......633...925...634............121............355....578.......14*....422..543.297....429..142................ +..960..+..............*.....536......*..@....-.......51..-.........592#..........+..............9..*........................................ +.....*......515......434............908..........189......430..................332...722..-.........450..#.........................139...... +..259......*.............................39..33.....$..................................*...159..443.....925.............743....414.&...=437. +......58..475...........227%.......217..../...*................../...............&....506..........................63..*.......*............ +.......=......-..............993....%.........166........605....293........977+..498......%.....834...455...........*.....%....981.991...... +...........636..728...*.......*.......494...............................................205........*.@...........528....226.........#....785 +664.9..............$..9...494.272...............725*....775...$....854..........226.243..........832....637*73................165........... +...*...340+.............@...*.......548.............405....*...768..*..............*.......81.........................10.787.$.......918.... +.......................145...265....+..........110........45.........90..299.....$........&.....696...475.-452..290....*...*..........@..... +......+....246.108.305...................894....=............121.588......*....69...................................236..97......348........ +.......709........*...........-...........-..........411...=...*.......135........................738..383.....634*..........429.@.......... +...........%........%217......119.....................@..47.........+.......923..............606...*.......960..............-............... +....835.....744...................546.......215.............512.....950.......%...444......&...$.833......./.........813.......400..%...48.. +........362.......898..#.......................*.732........*.............965....&.........584..................521..#...........-.995...... +....64.*.........*.....265........781..376...320.#........998...450.......%............................$...............................304.. +....-...966...875..981........742*.......*...........*276.........*...............541.....219.279..357..164...551..%717...............%..... +...................*...786.$..........*...163.....915...........960...%...509.135*...........*................-...........%.539............. +....666..699......179..+...612..=734..545...........................88.....&.......392...46..........483=..&.......548.135.....*.413.#620... +...$....*....948..........................530.656....%..484....*..................*......./...741..........444......*.......150...*......... +......................524...928..........=........858....=..562.571........117@.195..896......*......662.......148.388.............320...... +...166..48.../....-............#...159.......487.....................260...............#...713.........*.347................................ +......*.......657..837.....273.......%........*...155.................*........225..................228.....*370..../.......724.....764..... +......654.679.................@.........-....918...................681..461.............................776......737.................+...... +...........*....859......881#............625......$...........888.........+...57...............887.$.......*............................#911 +...46*....72...&...................................102.............651........*......*530.......-..667....850..829*.869%........298......... +......925..........892.352*........6.41....................+...160.$.....*.72..878..1.....................................738......*926..32. +...............279.........721......*..............694....799..&......878....*................219....+...482..368$...........*../........... +......604........*....................583*506........-...........740..........347............*....576......*................498..478.974.... +..486.-....................626..................320........&....../.................*979.=....863........497........111..............%...... +...................................538..78...*.....*......7...455.......223......939......673..........=......559-....*...834............58. +.......644....&.......#..669+.1.......*.....782.....865......*....779..#..............110...../....937..312...........489................... +.......*....571.....69........*.......169...................919....*.....808.................335...*.............................24*896..... +.......233................590.553..............198=..450.........661.......*.....................15...-....................-575............. +...........919*.....................................*.......234.........492..%...........300...........301........./866..........*.......... +...............470.....440.874...116....240........299......................27......409.......................................639.136.......
\ No newline at end of file diff --git a/aoc2023/src/day4/input.txt b/aoc2023/src/day4/input.txt new file mode 100644 index 0000000..0391b6a --- /dev/null +++ b/aoc2023/src/day4/input.txt @@ -0,0 +1,203 @@ +Card 1: 8 86 59 90 68 52 55 24 37 69 | 10 55 8 86 6 62 69 68 59 37 91 90 24 22 78 61 58 89 52 96 95 94 13 36 81 +Card 2: 6 42 98 5 17 31 13 36 63 61 | 99 88 14 20 63 5 56 33 6 21 92 13 17 7 31 93 30 74 98 15 11 36 61 42 47 +Card 3: 16 58 72 77 1 67 33 82 68 7 | 16 37 15 75 78 1 49 82 22 45 83 58 77 79 50 88 98 67 33 72 42 29 35 7 68 +Card 4: 75 35 37 6 29 54 64 57 82 4 | 8 33 27 85 84 54 75 37 4 57 70 29 64 94 17 6 38 41 82 81 71 35 47 51 19 +Card 5: 23 85 52 77 81 50 28 59 87 82 | 70 65 12 35 9 41 62 31 47 66 58 15 76 46 68 67 55 86 17 38 18 1 75 79 13 +Card 6: 77 64 13 36 68 88 16 75 25 95 | 25 64 55 58 75 66 23 16 27 68 69 88 13 9 39 42 29 65 83 97 32 89 53 96 94 +Card 7: 31 12 76 29 48 96 41 49 21 37 | 94 81 65 82 15 33 53 91 88 37 46 29 3 80 95 67 11 27 31 30 49 89 78 41 90 +Card 8: 20 5 52 31 46 25 88 95 39 83 | 36 62 48 39 69 3 81 11 61 95 43 85 34 46 5 8 13 45 10 17 2 88 70 52 89 +Card 9: 8 85 89 55 77 9 40 5 57 37 | 56 84 62 42 49 50 51 35 75 25 13 74 68 1 99 48 41 94 45 66 17 69 23 29 67 +Card 10: 74 1 7 89 97 82 75 9 11 42 | 94 71 41 30 50 58 23 81 35 6 97 57 67 85 98 10 87 43 96 77 31 8 54 72 65 +Card 11: 38 29 6 5 4 84 34 1 94 23 | 89 48 51 84 49 33 50 65 79 53 12 8 5 1 35 69 83 57 11 42 67 26 9 6 55 +Card 12: 35 83 44 75 36 65 85 87 60 72 | 8 3 91 33 59 29 56 26 21 60 80 88 25 5 51 47 46 44 41 31 62 79 76 89 55 +Card 13: 8 56 97 66 32 70 25 76 18 20 | 15 50 91 65 3 67 98 81 9 44 18 92 13 64 96 47 87 46 7 33 66 71 82 88 90 +Card 14: 37 52 63 28 19 89 44 76 98 24 | 70 13 59 31 17 84 90 6 62 19 74 36 94 1 15 12 29 95 47 92 23 67 60 58 53 +Card 15: 71 70 25 51 95 86 66 37 27 53 | 14 20 30 17 59 96 11 68 46 13 75 44 40 62 32 7 81 91 73 64 93 83 35 80 49 +Card 16: 97 4 63 22 75 73 5 52 34 26 | 33 98 64 47 90 94 28 35 43 30 73 51 7 27 10 40 97 37 34 32 22 71 63 21 80 +Card 17: 15 18 29 55 14 25 69 4 59 75 | 66 4 82 23 94 22 26 16 55 69 75 20 76 25 29 59 15 18 70 2 28 39 95 14 40 +Card 18: 26 40 70 42 37 68 25 76 56 97 | 33 97 28 13 24 50 66 53 67 84 26 68 42 56 92 40 65 76 25 32 70 93 85 37 94 +Card 19: 56 61 7 53 48 88 77 73 27 79 | 50 81 29 15 46 19 33 89 54 85 58 73 68 34 84 2 40 27 44 94 88 62 14 1 56 +Card 20: 34 89 62 72 6 30 16 53 78 2 | 2 78 73 89 85 40 47 30 34 8 60 23 72 26 62 96 6 91 29 16 57 46 59 53 94 +Card 21: 65 18 22 53 8 31 32 84 39 9 | 75 16 70 3 14 61 34 9 38 71 8 49 53 52 81 18 45 82 41 44 32 63 65 51 69 +Card 22: 44 80 76 71 36 1 50 87 23 27 | 1 76 83 67 87 68 25 80 8 23 57 29 52 4 50 64 24 44 77 45 27 32 36 73 71 +Card 23: 68 90 10 43 73 63 85 47 11 96 | 9 29 53 84 4 6 25 82 11 21 73 83 20 95 66 27 80 26 70 33 85 47 17 74 98 +Card 24: 51 68 2 69 39 86 55 70 6 54 | 72 17 14 26 91 52 96 86 66 64 51 2 92 53 36 39 89 42 40 68 55 37 6 54 7 +Card 25: 74 92 43 35 29 93 39 53 10 54 | 86 35 10 18 92 43 56 25 44 53 93 39 29 54 11 12 55 61 83 41 21 69 81 4 74 +Card 26: 80 19 99 93 76 67 70 60 39 9 | 98 2 26 95 21 49 44 9 31 58 83 46 14 99 4 78 12 56 89 71 66 29 47 64 96 +Card 27: 92 52 5 46 49 62 74 72 44 87 | 37 93 24 29 5 88 72 81 62 50 69 33 52 19 23 8 84 1 70 87 95 96 61 63 49 +Card 28: 79 80 98 59 54 45 91 16 11 4 | 80 10 98 45 78 91 1 65 12 11 4 82 88 79 54 55 8 99 59 67 68 16 25 3 70 +Card 29: 52 30 9 13 44 71 48 63 65 27 | 90 31 17 80 44 39 85 93 58 65 8 63 16 35 40 1 73 68 52 6 97 99 13 10 61 +Card 30: 12 19 35 9 82 20 72 61 50 67 | 11 84 77 14 46 29 62 28 81 98 43 12 15 72 35 99 19 97 75 1 20 7 82 60 52 +Card 31: 21 58 93 11 50 25 88 77 64 29 | 42 1 31 30 99 69 54 32 88 24 95 15 55 56 14 45 19 33 87 34 7 93 79 23 74 +Card 32: 39 87 70 22 46 95 69 3 58 80 | 85 95 24 45 84 22 37 12 33 43 93 96 27 56 70 67 91 58 10 68 69 40 97 82 13 +Card 33: 91 42 78 76 77 27 22 98 94 70 | 80 17 63 21 37 52 46 44 2 7 73 86 49 40 23 4 92 60 43 76 29 22 24 69 42 +Card 34: 11 50 70 95 32 81 26 57 7 76 | 83 64 65 46 87 56 28 98 90 11 96 40 99 3 16 12 61 19 97 76 51 92 93 34 15 +Card 35: 80 28 55 51 98 5 92 54 73 78 | 78 66 10 38 36 51 1 83 94 33 42 17 62 56 59 21 86 25 46 48 63 12 45 31 65 +Card 36: 63 76 16 74 10 14 50 73 81 35 | 3 68 1 76 62 53 67 97 13 85 28 65 32 72 34 98 57 20 71 17 64 48 8 56 44 +Card 37: 37 1 38 62 56 27 17 8 21 98 | 78 31 14 23 18 62 4 2 97 88 59 34 57 46 81 16 36 58 86 35 72 61 7 80 28 +Card 38: 56 30 92 44 33 11 16 45 72 60 | 74 86 59 87 22 81 46 32 52 21 78 10 57 1 13 85 49 75 95 29 8 38 77 54 50 +Card 39: 66 83 99 18 79 70 57 25 86 55 | 8 41 50 87 77 7 78 84 53 35 43 26 13 29 30 69 91 65 32 59 31 45 56 15 48 +Card 40: 64 46 22 83 33 38 95 75 69 89 | 82 65 45 68 75 33 69 49 22 95 89 74 53 46 38 25 83 64 8 59 81 16 94 27 60 +Card 41: 90 26 49 5 76 98 92 64 19 32 | 47 35 49 45 13 67 73 55 4 64 79 63 89 57 5 75 85 91 25 88 74 70 28 68 86 +Card 42: 45 52 92 43 76 96 4 86 53 62 | 96 53 55 18 95 44 25 45 47 66 62 2 52 60 10 3 1 37 87 92 98 70 9 86 23 +Card 43: 9 64 57 76 21 30 38 98 85 1 | 11 22 92 81 58 59 48 75 2 32 15 84 27 56 86 99 98 66 54 96 20 37 67 12 29 +Card 44: 11 41 84 1 76 6 64 8 31 44 | 11 1 33 58 55 6 84 44 70 20 64 41 90 98 72 42 8 38 4 39 76 17 18 69 31 +Card 45: 88 12 95 1 24 71 70 49 79 8 | 86 57 43 12 90 78 70 76 24 95 39 8 1 13 47 71 49 75 15 32 2 77 58 79 21 +Card 46: 84 91 96 41 17 76 9 36 81 1 | 82 5 99 19 43 20 86 69 37 44 95 41 55 65 96 70 24 47 77 15 31 36 2 79 22 +Card 47: 48 80 18 4 40 11 90 17 27 68 | 33 40 15 99 48 12 25 27 44 17 50 94 68 63 11 29 80 4 18 42 32 90 19 2 91 +Card 48: 44 30 51 97 22 57 87 17 53 11 | 35 17 81 22 11 30 75 80 74 54 79 16 78 97 89 87 51 37 43 72 53 57 27 94 23 +Card 49: 31 2 7 13 9 33 95 41 57 34 | 25 90 77 13 1 95 18 17 34 92 10 33 80 2 82 66 91 73 70 86 21 7 42 47 19 +Card 50: 16 44 77 76 23 81 47 29 62 22 | 35 27 83 47 88 76 98 64 31 86 48 42 95 67 25 44 17 51 18 26 12 1 90 99 62 +Card 51: 55 68 41 17 28 83 64 62 22 13 | 24 6 23 22 64 7 83 74 44 34 28 68 13 32 26 50 62 17 12 41 97 55 16 1 9 +Card 52: 96 79 43 83 37 25 86 24 66 34 | 79 18 6 2 64 62 86 48 65 34 29 68 9 87 76 71 3 69 61 41 40 35 37 55 32 +Card 53: 46 1 10 43 47 17 62 52 58 75 | 58 14 52 71 31 75 55 50 8 99 63 23 4 13 10 62 16 17 82 43 56 46 76 83 65 +Card 54: 75 33 27 30 87 32 68 89 44 17 | 73 28 31 97 27 9 57 14 15 20 39 82 38 36 43 58 75 4 44 30 33 80 16 48 17 +Card 55: 70 11 9 44 14 32 83 10 99 71 | 65 48 21 75 83 71 92 2 34 22 11 14 39 31 63 25 88 15 80 76 96 90 52 70 99 +Card 56: 17 38 6 13 3 67 87 64 37 68 | 41 7 53 11 5 62 93 28 65 8 56 32 1 69 47 18 82 40 20 12 80 37 89 43 2 +Card 57: 64 29 46 22 61 56 32 20 97 72 | 31 14 29 44 74 22 1 56 4 52 58 45 50 78 67 11 97 72 16 20 27 57 61 83 85 +Card 58: 62 85 13 46 79 37 99 81 91 8 | 98 17 85 23 33 94 35 2 47 20 3 11 36 96 43 46 25 60 59 10 22 55 87 58 28 +Card 59: 58 36 55 31 69 91 21 51 56 10 | 19 49 73 6 34 27 40 65 11 55 44 67 37 97 14 85 84 89 72 29 64 15 70 68 94 +Card 60: 46 40 95 45 75 74 7 38 10 81 | 32 38 4 61 78 5 39 99 86 33 2 98 83 42 11 75 27 73 81 9 54 37 40 12 80 +Card 61: 40 29 73 56 91 44 24 77 1 5 | 87 52 80 45 70 48 47 44 69 17 16 6 82 66 37 42 39 3 10 15 97 13 40 99 62 +Card 62: 54 55 29 80 70 50 97 89 33 68 | 21 3 76 73 6 42 2 91 19 18 72 92 94 11 77 32 52 8 81 48 35 16 27 12 84 +Card 63: 19 45 77 86 6 33 83 91 52 36 | 18 68 60 58 84 29 9 67 21 99 24 80 69 96 25 85 46 50 95 27 61 4 90 63 88 +Card 64: 88 23 57 8 93 17 20 42 54 51 | 12 78 82 80 85 43 73 44 84 89 15 36 30 10 25 29 7 99 61 60 86 14 26 28 83 +Card 65: 92 13 3 54 4 95 28 72 8 15 | 15 60 66 33 82 95 94 69 71 59 54 99 40 31 83 17 13 80 28 72 4 92 45 87 46 +Card 66: 1 42 10 66 94 21 46 95 73 32 | 64 99 3 86 69 71 95 78 60 28 5 19 35 85 67 7 32 16 39 66 89 42 31 43 58 +Card 67: 87 50 23 52 5 22 88 82 59 72 | 26 59 48 90 82 55 50 37 87 35 2 52 72 11 40 23 54 88 19 33 5 97 86 22 30 +Card 68: 21 89 80 14 73 61 9 7 68 48 | 18 89 38 26 32 21 79 15 14 86 44 55 95 41 80 7 9 29 73 1 13 48 68 28 61 +Card 69: 9 82 65 50 57 40 96 36 83 60 | 96 17 88 60 40 74 33 19 41 23 82 89 92 72 50 83 4 7 56 34 9 36 52 57 65 +Card 70: 40 63 61 64 3 21 52 11 66 53 | 82 42 13 30 44 72 74 83 45 70 38 33 80 8 64 48 49 73 19 51 85 47 90 84 92 +Card 71: 92 24 98 94 89 41 1 93 28 32 | 28 61 92 13 53 89 43 23 32 66 81 93 94 38 90 36 24 68 1 91 98 41 29 67 64 +Card 72: 29 61 68 1 78 69 33 45 39 18 | 81 12 36 28 73 75 18 35 42 33 95 68 3 79 39 8 24 82 87 45 11 91 23 51 1 +Card 73: 15 33 51 46 80 95 67 71 97 16 | 23 7 93 94 55 33 5 84 28 32 15 59 98 6 46 17 86 43 39 81 36 42 63 71 82 +Card 74: 95 9 16 72 30 20 41 97 45 90 | 30 72 49 66 36 9 82 98 95 16 48 57 46 86 47 90 20 85 54 74 73 4 22 60 32 +Card 75: 82 55 49 44 75 57 19 59 38 4 | 21 78 35 6 93 75 28 41 83 72 55 22 64 89 70 47 23 29 20 99 48 53 27 65 13 +Card 76: 19 31 41 50 27 43 74 21 51 44 | 24 79 71 16 49 37 60 14 8 33 52 40 98 6 34 62 56 4 10 30 39 48 99 67 22 +Card 77: 39 23 28 96 98 50 40 34 79 74 | 85 68 79 33 48 23 56 10 89 38 50 71 17 28 6 74 53 4 98 26 8 22 39 31 66 +Card 78: 80 31 82 32 70 17 68 44 22 97 | 72 6 95 57 13 94 37 44 70 46 32 69 22 56 40 15 77 88 17 82 31 47 71 18 68 +Card 79: 37 53 75 59 72 43 65 74 81 26 | 37 23 11 48 45 86 74 2 59 58 92 12 65 78 16 97 57 76 67 26 18 41 43 54 49 +Card 80: 63 41 23 39 40 10 26 93 24 73 | 30 19 74 40 49 90 22 65 78 10 24 93 73 41 51 7 61 15 29 39 63 16 64 23 37 +Card 81: 88 68 74 9 97 46 11 87 39 10 | 40 3 14 85 64 43 42 97 90 9 39 13 29 72 47 10 48 4 68 96 99 25 98 65 57 +Card 82: 81 48 21 57 65 39 12 66 95 33 | 16 33 79 85 92 52 50 34 15 22 9 45 74 17 24 63 28 72 84 62 58 77 41 64 83 +Card 83: 45 33 86 43 63 96 25 88 53 15 | 73 93 79 18 2 26 21 65 28 57 52 88 1 80 33 38 76 3 56 35 6 23 34 24 13 +Card 84: 31 74 96 40 36 99 91 92 63 10 | 78 38 59 27 84 34 31 72 19 91 12 45 57 92 32 44 70 50 10 24 87 33 49 65 61 +Card 85: 24 20 39 42 78 57 12 64 40 44 | 68 34 77 20 21 12 35 23 97 3 50 65 42 18 84 41 43 69 94 37 76 57 31 45 79 +Card 86: 51 48 14 80 3 72 92 15 35 43 | 50 69 18 76 63 30 58 19 65 16 70 55 54 12 87 62 60 68 93 83 1 44 26 98 27 +Card 87: 11 4 31 73 5 81 2 32 29 51 | 3 47 9 18 16 19 66 36 23 70 91 64 69 87 51 84 43 65 35 42 63 72 82 54 93 +Card 88: 94 10 52 17 78 45 99 66 8 81 | 11 31 71 59 41 88 67 30 47 98 33 21 37 15 53 20 36 58 57 91 39 28 49 70 86 +Card 89: 28 68 50 39 98 57 78 71 11 48 | 95 67 79 86 53 17 66 60 77 6 44 54 19 31 74 80 63 99 47 12 91 21 70 8 10 +Card 90: 36 90 94 26 59 84 63 38 48 39 | 69 56 39 88 89 97 26 38 83 55 87 13 33 68 95 94 18 48 36 44 59 84 63 90 66 +Card 91: 89 3 61 68 53 85 66 81 11 78 | 29 10 81 58 22 47 19 3 36 98 61 85 89 78 39 17 50 53 11 66 68 24 4 86 25 +Card 92: 57 5 56 91 64 38 89 47 55 74 | 73 51 48 19 57 98 64 9 74 65 53 47 54 72 69 38 56 1 21 6 91 40 55 5 89 +Card 93: 6 86 18 53 9 82 70 81 89 26 | 21 69 75 10 8 86 89 70 47 23 78 96 98 53 6 9 2 81 31 56 39 55 18 1 42 +Card 94: 86 78 79 57 3 2 5 69 30 53 | 80 2 53 90 3 30 48 79 5 78 19 35 62 59 97 56 13 12 70 86 10 69 51 55 57 +Card 95: 64 51 15 84 25 94 88 80 20 33 | 1 90 50 47 32 15 20 51 84 65 64 55 39 94 19 66 40 25 88 43 80 34 29 3 92 +Card 96: 83 88 94 87 79 45 49 91 99 33 | 91 53 72 37 87 40 26 88 33 49 89 99 24 59 94 52 75 83 79 71 62 50 92 28 6 +Card 97: 51 91 36 6 68 9 97 78 39 80 | 18 97 68 34 91 61 78 3 23 84 8 16 36 96 65 99 59 80 58 90 14 32 1 41 74 +Card 98: 92 41 9 7 52 86 83 40 8 63 | 47 17 14 35 34 22 19 52 79 7 81 92 1 82 93 73 25 58 60 39 59 27 3 16 41 +Card 99: 72 47 22 4 62 58 31 91 34 50 | 49 65 94 71 82 25 24 9 64 62 50 60 14 84 16 93 1 46 8 19 47 44 21 10 11 +Card 100: 96 18 53 37 54 98 30 84 58 45 | 30 59 89 23 8 35 85 6 36 54 37 17 92 79 27 39 4 61 11 80 19 58 72 51 47 +Card 101: 67 26 23 99 78 60 55 82 83 11 | 60 22 91 21 18 29 67 62 34 93 56 59 49 52 38 79 28 11 17 77 76 20 2 99 92 +Card 102: 28 94 4 54 77 42 17 44 59 48 | 24 13 61 6 5 83 50 77 76 37 90 71 79 47 8 98 41 75 59 70 89 16 30 17 45 +Card 103: 65 69 32 77 64 99 24 71 73 90 | 20 26 72 17 16 46 86 2 28 13 88 45 5 70 95 55 33 65 49 68 50 58 85 83 22 +Card 104: 78 17 88 26 65 79 8 18 47 25 | 31 86 76 30 84 44 62 97 81 42 14 72 25 32 82 5 54 69 98 52 68 13 92 3 58 +Card 105: 72 63 74 24 23 67 34 26 50 73 | 11 70 76 89 84 92 79 33 82 44 71 48 35 8 59 14 93 15 29 18 55 3 38 77 28 +Card 106: 36 40 51 81 60 96 34 49 85 89 | 72 15 7 40 60 97 68 52 36 55 87 96 85 89 49 61 78 34 37 27 76 5 51 81 12 +Card 107: 56 6 20 66 35 45 14 19 62 52 | 15 27 93 17 77 19 35 43 80 72 47 88 8 70 71 92 83 82 10 97 25 90 44 69 87 +Card 108: 33 44 49 78 10 26 20 65 77 13 | 33 54 2 24 17 20 26 7 93 5 3 77 81 46 92 78 49 65 32 51 44 95 13 29 10 +Card 109: 51 25 49 60 83 75 46 43 50 41 | 96 12 53 50 78 92 60 15 76 6 5 34 41 23 25 70 20 75 86 73 30 39 32 48 95 +Card 110: 13 22 99 91 47 53 35 34 37 77 | 79 35 1 13 88 57 76 89 81 15 53 56 99 34 6 68 77 32 91 47 87 37 4 24 16 +Card 111: 17 21 92 30 95 1 52 5 27 46 | 86 24 6 51 99 68 16 34 19 76 31 10 56 63 58 97 87 26 40 73 8 54 69 18 90 +Card 112: 52 83 38 39 95 12 57 14 46 85 | 12 95 85 14 89 50 52 17 92 18 38 34 55 83 16 66 19 88 4 20 46 57 77 39 11 +Card 113: 6 25 93 3 52 46 2 13 70 7 | 67 46 40 2 3 77 35 50 57 52 55 75 53 72 97 89 34 84 15 31 23 7 58 25 21 +Card 114: 24 53 25 12 17 82 14 50 3 74 | 91 83 57 50 96 68 52 11 56 44 89 95 15 13 54 20 76 48 30 88 53 55 93 65 47 +Card 115: 95 81 49 37 80 70 7 60 75 99 | 29 74 98 94 49 59 60 86 75 93 72 56 87 82 76 32 33 4 46 70 27 83 1 35 2 +Card 116: 80 67 54 68 98 47 12 56 77 60 | 45 81 47 78 29 39 56 42 80 54 68 90 37 2 16 96 5 38 14 59 7 30 6 67 20 +Card 117: 6 59 84 35 1 53 28 77 94 24 | 97 62 40 54 93 44 90 63 26 64 91 75 6 4 22 82 80 2 69 12 77 21 53 49 10 +Card 118: 86 30 39 49 32 29 27 68 97 50 | 2 48 36 99 83 4 38 5 47 77 66 1 20 10 14 15 63 78 89 91 85 80 41 28 54 +Card 119: 87 78 77 15 85 99 2 35 45 11 | 58 51 62 42 63 90 37 22 8 83 34 31 67 35 72 17 91 7 88 49 13 39 59 4 18 +Card 120: 80 21 33 94 26 68 73 35 83 3 | 67 9 94 49 27 50 40 30 60 90 86 91 98 69 6 15 36 71 38 31 17 33 41 70 84 +Card 121: 81 17 27 59 99 69 49 14 83 91 | 20 77 55 73 87 36 25 56 54 58 45 68 80 18 3 15 65 31 96 40 75 30 92 42 23 +Card 122: 22 44 29 27 77 20 86 34 5 99 | 63 19 97 74 4 39 7 52 87 31 81 45 23 18 53 47 50 73 80 2 70 94 26 66 14 +Card 123: 39 40 61 53 56 60 96 5 68 25 | 97 98 6 79 81 32 51 26 59 13 10 2 3 77 88 80 63 90 52 12 87 29 49 18 76 +Card 124: 78 19 92 75 56 95 2 16 43 44 | 95 2 56 4 92 66 53 88 21 16 43 78 17 44 85 48 12 19 52 40 69 75 59 82 26 +Card 125: 14 43 38 9 8 62 17 28 12 11 | 80 19 38 43 11 34 29 9 32 12 62 28 77 72 17 69 33 96 94 78 67 8 93 90 4 +Card 126: 60 95 93 99 11 49 20 75 37 54 | 54 42 19 49 92 95 11 34 74 93 60 52 99 5 7 75 20 12 68 98 43 50 36 37 56 +Card 127: 73 24 71 80 58 62 17 41 61 43 | 68 43 79 58 87 67 6 62 20 41 93 71 27 88 23 17 24 42 52 13 61 80 81 84 73 +Card 128: 99 10 91 58 70 47 80 30 96 57 | 46 57 3 72 4 87 70 10 59 7 96 48 28 97 91 58 47 76 36 80 8 23 19 30 99 +Card 129: 50 3 78 8 80 11 57 52 94 47 | 63 60 38 92 50 65 91 88 53 17 96 42 66 28 1 25 75 76 73 87 90 36 82 24 68 +Card 130: 38 42 33 70 61 58 73 88 74 29 | 83 92 77 58 56 74 55 93 38 46 29 28 37 68 33 73 91 61 12 64 25 88 42 31 70 +Card 131: 92 46 42 96 12 14 95 84 57 78 | 11 6 82 41 73 55 8 93 76 98 99 86 31 21 78 29 32 70 62 23 95 15 9 77 52 +Card 132: 40 97 45 2 19 99 29 98 37 20 | 5 56 36 21 33 83 32 98 66 20 16 37 97 93 40 78 43 77 99 29 87 96 2 30 39 +Card 133: 97 81 10 23 75 6 53 27 35 47 | 37 93 8 92 68 65 15 85 25 67 61 56 5 42 88 18 76 87 60 46 59 94 86 57 91 +Card 134: 96 66 54 61 10 85 98 40 13 41 | 90 58 9 38 28 24 57 52 5 81 80 62 34 54 79 49 2 95 1 18 41 65 82 32 42 +Card 135: 54 79 66 83 45 35 10 27 41 94 | 67 42 4 89 51 95 1 63 90 40 65 23 98 7 86 9 97 3 11 61 92 69 77 80 2 +Card 136: 37 86 74 45 70 95 33 28 82 32 | 67 13 62 8 63 41 78 40 24 91 11 48 7 85 59 81 44 37 45 90 66 70 35 33 94 +Card 137: 75 89 5 18 91 57 37 63 85 40 | 27 34 9 51 76 41 69 86 95 81 36 82 1 38 10 99 7 47 21 77 8 30 19 71 60 +Card 138: 9 67 82 54 5 98 7 6 40 96 | 13 83 90 88 44 17 82 24 47 84 23 85 62 45 72 91 58 46 38 32 25 79 70 59 33 +Card 139: 1 6 65 80 35 91 63 22 60 50 | 79 84 81 92 75 36 88 90 86 16 53 17 44 43 15 94 73 51 14 42 33 98 74 57 4 +Card 140: 24 43 8 76 91 79 42 68 81 70 | 65 36 56 57 16 69 38 86 85 37 22 9 98 33 45 25 95 28 52 2 27 6 14 46 55 +Card 141: 62 32 78 2 21 45 75 48 91 85 | 38 42 3 20 21 56 48 75 86 45 40 91 33 73 25 85 16 78 2 24 72 26 32 61 62 +Card 142: 90 10 32 43 65 91 24 22 34 62 | 91 26 72 81 7 11 32 10 90 33 34 87 35 24 29 3 59 62 2 65 22 43 57 74 79 +Card 143: 16 52 66 56 50 57 77 71 73 40 | 71 43 80 59 36 39 77 40 11 4 64 16 85 52 49 73 56 57 10 9 86 46 66 6 50 +Card 144: 61 56 14 66 2 73 39 8 33 97 | 26 8 47 67 16 18 37 39 14 9 61 33 97 2 66 56 73 4 75 11 62 68 49 44 34 +Card 145: 75 65 92 85 73 18 70 95 49 22 | 25 8 49 2 16 13 97 33 93 66 75 85 73 71 65 18 22 53 92 38 44 50 62 70 95 +Card 146: 78 62 86 83 26 23 80 2 77 87 | 23 96 38 63 83 22 20 86 77 21 67 66 75 5 36 47 26 61 80 87 82 16 78 46 2 +Card 147: 84 36 18 42 50 12 64 61 99 91 | 18 75 61 76 74 12 1 41 28 91 64 24 55 36 27 3 84 99 42 50 95 83 31 7 22 +Card 148: 61 91 60 18 68 50 73 29 23 87 | 18 76 33 5 27 97 31 37 21 38 56 91 60 87 23 55 58 61 50 45 14 29 72 68 73 +Card 149: 46 97 81 18 85 95 91 43 72 87 | 32 23 1 49 66 96 24 16 42 22 81 51 72 8 20 37 44 71 45 25 90 88 5 94 74 +Card 150: 17 99 20 36 33 78 9 87 81 84 | 37 8 79 65 31 99 45 36 81 90 73 11 49 46 87 84 3 33 19 12 57 9 20 48 17 +Card 151: 35 46 49 80 66 75 99 77 8 53 | 75 24 5 67 4 53 49 61 19 23 26 97 93 77 46 66 35 40 99 39 30 80 76 25 8 +Card 152: 11 80 39 1 30 36 16 85 33 66 | 26 66 60 2 94 16 81 48 80 43 85 96 51 68 33 63 88 54 6 36 37 59 5 1 47 +Card 153: 49 86 25 83 96 8 93 88 24 57 | 66 60 51 33 57 95 49 79 63 2 93 58 65 70 55 76 87 27 1 46 11 52 80 84 54 +Card 154: 38 41 75 30 91 6 14 66 47 57 | 34 56 11 70 71 60 22 81 41 74 39 67 79 98 87 42 62 3 32 57 55 46 33 16 51 +Card 155: 25 31 45 21 68 57 73 20 71 32 | 20 18 98 53 60 7 38 10 12 19 77 64 79 74 17 33 83 88 28 16 32 21 89 69 65 +Card 156: 19 35 39 37 84 50 62 95 96 56 | 89 24 92 67 4 47 54 59 72 84 3 5 76 96 23 1 58 86 32 21 78 88 68 44 48 +Card 157: 24 68 39 72 23 93 81 51 45 25 | 96 33 76 99 5 70 93 18 24 68 6 64 49 92 45 80 15 77 4 57 25 13 44 28 2 +Card 158: 51 18 46 75 2 80 20 72 17 29 | 97 55 47 23 20 4 39 24 64 11 31 16 90 29 93 72 18 45 27 46 61 70 80 68 67 +Card 159: 34 10 70 56 51 9 99 32 15 74 | 13 31 44 56 63 20 99 81 40 78 84 90 50 52 85 19 41 10 45 71 22 28 26 8 14 +Card 160: 69 49 13 23 36 64 24 18 57 7 | 54 62 96 36 7 10 28 64 1 85 3 63 73 21 27 37 49 47 75 34 97 30 77 32 9 +Card 161: 35 16 44 25 42 62 95 77 89 34 | 29 26 11 78 97 23 28 36 10 96 54 81 17 22 80 27 77 44 41 34 20 51 76 24 75 +Card 162: 60 17 28 76 67 12 41 15 53 70 | 41 19 35 64 65 15 37 22 80 66 55 40 45 81 17 98 85 74 57 4 16 91 49 5 68 +Card 163: 57 3 82 45 28 70 50 17 85 48 | 68 87 47 62 58 31 88 92 98 90 46 29 5 85 93 24 95 99 39 75 55 33 65 49 14 +Card 164: 33 81 13 87 53 48 79 70 17 91 | 92 57 21 4 36 27 62 1 46 80 31 72 5 94 58 99 75 67 83 25 51 9 26 52 63 +Card 165: 55 70 45 36 72 59 81 16 69 98 | 60 7 43 54 66 78 83 23 25 94 48 67 26 56 53 58 2 4 27 31 34 39 49 85 74 +Card 166: 94 64 48 15 36 35 79 23 77 33 | 78 80 25 5 18 34 92 69 84 86 26 13 89 65 29 3 7 39 71 31 42 21 51 48 55 +Card 167: 13 34 54 2 20 16 89 79 88 9 | 47 75 25 82 72 76 51 37 95 22 71 55 54 74 9 33 97 83 27 2 79 28 17 91 24 +Card 168: 33 82 70 88 7 46 96 67 26 89 | 73 8 22 1 59 45 92 24 43 41 15 64 3 58 83 63 57 82 20 18 91 13 77 60 19 +Card 169: 91 4 32 45 55 98 80 52 9 33 | 20 45 37 28 69 61 60 81 12 33 51 74 15 97 50 86 72 99 2 41 70 58 19 40 39 +Card 170: 45 72 63 87 70 33 89 41 4 18 | 25 9 19 49 26 63 11 73 54 64 70 37 45 82 30 1 90 24 87 42 4 40 91 71 18 +Card 171: 74 99 84 26 66 10 95 8 75 68 | 34 62 37 97 57 65 75 74 6 67 68 96 4 1 95 55 52 82 13 47 63 48 94 26 77 +Card 172: 62 99 47 83 94 8 51 70 9 76 | 94 99 83 26 57 76 18 67 22 80 61 34 8 39 65 78 13 81 70 51 62 93 9 3 33 +Card 173: 42 99 9 18 48 61 36 83 13 84 | 7 69 44 61 35 54 27 3 60 55 99 84 32 48 18 19 72 42 89 65 4 92 79 75 13 +Card 174: 48 34 46 43 53 51 72 35 19 3 | 72 43 57 51 14 34 2 36 53 25 94 81 87 61 19 35 23 4 99 26 48 46 7 90 86 +Card 175: 46 59 27 28 82 13 99 35 18 6 | 36 90 70 87 64 31 42 71 50 27 76 45 99 32 21 20 9 88 23 93 17 46 80 85 59 +Card 176: 92 44 3 29 10 7 66 4 57 21 | 36 68 61 87 65 1 53 95 60 2 34 47 75 42 82 8 83 79 54 74 93 26 69 22 32 +Card 177: 89 23 17 80 22 65 98 11 94 3 | 91 28 37 99 63 60 42 87 23 98 71 39 82 93 57 68 62 13 75 77 22 26 53 48 90 +Card 178: 11 75 56 47 64 88 91 66 59 12 | 41 97 40 26 42 67 23 28 31 99 85 30 11 94 81 55 74 89 52 64 65 69 3 38 43 +Card 179: 31 97 46 27 96 57 45 30 64 82 | 36 42 81 54 85 31 1 29 8 84 28 50 64 76 10 67 77 39 21 4 75 78 99 47 12 +Card 180: 10 32 84 45 87 16 82 14 95 8 | 21 8 41 66 56 42 77 83 90 9 55 61 19 38 23 50 28 62 99 58 33 11 84 39 98 +Card 181: 90 54 11 49 95 88 15 75 18 2 | 30 5 68 41 71 52 56 10 50 60 81 51 27 94 42 55 6 87 78 66 72 96 36 12 62 +Card 182: 73 1 91 2 99 75 30 29 48 89 | 46 51 34 7 18 57 64 9 23 68 16 19 85 70 66 72 5 87 12 4 25 97 10 89 60 +Card 183: 16 20 31 39 75 36 78 33 88 69 | 57 17 8 70 79 37 6 48 51 85 30 45 98 26 3 83 29 58 87 54 61 35 74 43 66 +Card 184: 69 50 38 49 9 96 75 82 80 14 | 23 99 30 83 78 9 50 40 14 74 75 8 37 69 82 42 26 49 96 1 38 58 80 84 7 +Card 185: 44 66 49 89 36 28 30 85 32 68 | 44 28 66 72 33 65 31 67 36 30 99 89 12 25 32 76 68 85 48 90 78 92 13 49 82 +Card 186: 46 48 6 52 24 19 51 76 11 47 | 93 63 78 33 31 86 68 10 74 70 3 83 36 4 54 79 8 77 38 57 97 27 22 29 53 +Card 187: 49 12 70 83 40 68 15 78 88 95 | 72 31 40 69 37 65 71 35 9 44 49 95 89 68 50 41 20 58 16 60 90 22 28 96 10 +Card 188: 86 47 96 63 55 29 91 31 59 23 | 55 77 30 23 91 75 86 47 29 31 78 67 4 92 96 26 63 37 80 54 1 11 32 15 98 +Card 189: 40 97 46 63 66 58 54 35 33 59 | 75 17 57 71 55 62 43 96 85 98 83 37 40 23 65 94 93 25 72 78 46 47 28 33 56 +Card 190: 94 41 57 47 6 24 65 59 44 20 | 95 86 26 77 87 47 18 27 16 85 57 61 66 37 35 38 23 42 50 60 98 71 62 8 25 +Card 191: 57 32 39 19 48 77 27 96 10 61 | 68 82 86 70 75 35 11 24 69 56 45 95 67 44 25 36 90 47 74 39 27 55 66 87 12 +Card 192: 50 94 12 32 88 76 95 23 46 49 | 60 9 6 37 42 50 96 15 95 66 34 94 91 4 33 29 14 92 16 80 98 64 12 57 36 +Card 193: 32 25 53 7 71 31 80 42 92 63 | 84 78 28 90 27 24 5 67 63 75 81 12 31 55 46 60 89 98 37 16 86 23 72 43 22 +Card 194: 79 47 88 9 97 76 62 23 72 84 | 77 78 67 65 91 79 64 38 41 26 89 16 10 71 86 82 47 75 61 11 34 66 7 3 70 +Card 195: 22 47 95 56 66 98 44 73 50 30 | 92 33 28 65 16 60 8 45 56 2 47 84 25 55 58 17 35 88 38 95 81 63 43 57 98 +Card 196: 76 23 10 43 9 32 46 62 84 79 | 22 4 49 42 23 55 13 35 90 9 24 52 65 26 95 94 18 37 47 79 56 59 54 86 48 +Card 197: 65 44 24 84 49 62 6 54 42 20 | 25 72 90 58 77 60 59 73 11 39 91 19 21 28 62 8 41 66 87 56 64 52 80 82 24 +Card 198: 63 44 64 86 78 25 92 90 99 70 | 62 29 51 81 21 6 75 58 54 90 18 10 59 98 97 41 4 52 53 64 80 28 92 11 9 +Card 199: 7 15 47 28 44 22 74 76 40 56 | 78 24 95 38 25 36 77 46 89 45 18 42 3 75 62 90 52 81 83 85 80 26 4 23 71 +Card 200: 85 88 3 44 54 19 9 71 29 53 | 72 42 56 55 33 68 65 86 58 3 57 83 12 31 96 9 13 62 70 80 17 29 41 27 6 +Card 201: 10 51 69 82 56 40 94 9 90 78 | 57 92 89 1 99 87 5 73 80 28 2 6 67 70 33 18 17 78 16 95 69 44 38 24 55 +Card 202: 44 47 79 75 24 50 86 80 62 87 | 66 91 36 15 28 81 57 69 30 14 10 20 27 18 77 46 95 72 39 23 38 34 60 37 26 +Card 203: 59 31 79 81 4 21 24 54 48 62 | 37 90 25 51 70 77 18 17 97 52 40 75 43 3 91 50 87 67 42 15 14 63 6 13 5
\ No newline at end of file diff --git a/aoc2023/src/day5/input.txt b/aoc2023/src/day5/input.txt new file mode 100644 index 0000000..3ee1477 --- /dev/null +++ b/aoc2023/src/day5/input.txt @@ -0,0 +1,223 @@ +seeds: 3136945476 509728956 1904897211 495273540 1186343315 66026055 1381149926 11379441 4060485949 190301545 444541979 351779229 1076140984 104902451 264807001 60556152 3676523418 44140882 3895155702 111080695 + +seed-to-soil map: +2122609492 2788703865 117293332 +751770532 1940296486 410787026 +2652142963 2905997197 464992562 +3442443139 3721315963 573651333 +3117135525 2356966701 133002244 +742051533 3370989759 9718999 +2239902824 720032349 393589935 +1162557558 58715335 661317014 +1823874572 2489968945 298734920 +2633492759 2351083512 5883189 +4016094472 3442443139 278872824 +58715335 1256960288 683336198 +3250137769 1126389299 130570989 +2639375948 1113622284 12767015 + +soil-to-fertilizer map: +1839905294 2992775329 34548650 +266781855 3027323979 163164353 +1874453944 1681649719 388228515 +671359508 847997583 161400465 +0 2547368955 266781855 +3203005759 3207454799 385245393 +832759973 813886658 34110925 +3671840261 3598096086 304246395 +1377823717 351805081 65559824 +1443383541 417364905 396521753 +3985931590 3902342481 309035706 +2954410911 2069878234 236077421 +2262682459 2814150810 19476781 +429946208 2305955655 241413300 +3981482550 3203005759 4449040 +3976086656 3592700192 5395894 +1026018636 0 351805081 +2282159240 1009398048 672251671 +866870898 2833627591 159147738 +3588251152 4211378187 83589109 + +fertilizer-to-water map: +2408925737 4214441342 80525954 +1405678964 176700146 234310964 +2103148712 0 114754845 +289811242 411011110 140151672 +19025194 1085844786 2698717 +2799367899 3104502118 25793488 +3686730518 3130295606 74796096 +628099810 1273935988 19704264 +1112219380 661022482 39037869 +467844674 876473087 160255136 +1356562401 1036728223 49116563 +0 2195479548 19025194 +1778400105 1801270370 10408868 +3201290155 3772851666 86331548 +1795901930 1713284032 67001953 +1151257249 1907547144 205305152 +4156855349 4121566803 26796069 +160254887 2112852296 19696655 +1788808973 114754845 7092957 +1639989928 1780285985 20984385 +3990635607 2938282376 166219742 +2864292987 3316407580 74613579 +3761526614 4148362872 26946870 +2048296368 121847802 54852344 +3054903767 3975180415 146386388 +21723911 737942111 138530976 +647804074 1811679238 95867906 +3580274539 3391021159 106455979 +2489451691 2628366168 309916208 +1049288783 2132548951 62930597 +4183651418 3205091702 111315878 +3360834108 2408925737 219440431 +743671980 1293640252 305616803 +3287621703 3699639261 73212405 +2938906566 3859183214 115997201 +429962914 700060351 37881760 +1775001290 2214504742 3398815 +3788473484 3497477138 202162123 +2825161387 4175309742 39131600 +1660974313 1599257055 114026977 +1862903883 1088543503 185392485 +179951542 551162782 109859700 + +water-to-light map: +2182426048 2230942562 75597875 +3871195410 3518497934 102047632 +2258023923 1068663414 38503018 +1376483871 1748535271 120845081 +3267723970 3442138354 23090394 +3687599530 4146748183 69194895 +1687874044 1117179928 229976398 +1024656105 0 9213951 +2036492700 1503963494 145933348 +1339060619 127856209 37423252 +3600067928 3079307704 87531602 +3778928632 3171781100 38997592 +485121354 165279461 136305184 +1266011073 1649896842 73049546 +1917850442 9213951 118642258 +2296526941 1107166432 10013496 +3973243042 2847069441 75895604 +3177917323 2989501057 89806647 +136410837 1347156326 156807168 +4049138646 3166839306 4941794 +3817926224 3465228748 53269186 +2631950731 2587548926 259520515 +478937106 2064525337 6184248 +3756794425 2922965045 22134207 +621426538 487303746 242996590 +3299937194 3372641330 69497024 +1240422190 1722946388 25588883 +1497328952 1873980245 190545092 +2587548926 2945099252 44401805 +864423128 2070709585 160232977 +1033870056 1869380352 4599893 +2891471246 3629668396 286446077 +1158126414 866711173 82295776 +4054080440 3210778692 62083789 +1038469949 949006949 119656465 +0 730300336 136410837 +4116164229 3272862481 99778849 +3290814364 3620545566 9122830 +3369434218 3916114473 230633710 +293218005 301584645 185719101 + +light-to-temperature map: +2047881931 2133163196 61773729 +2768352591 2658645540 147815435 +663892205 789634091 62723057 +962320572 2260439344 13990400 +4174477469 3668516433 35699725 +3949428604 3175207948 225048865 +2918680909 3704216158 118365848 +976310972 47881164 71382440 +736841121 215530327 84565848 +1481137268 593966122 45807826 +3406939292 2891251077 174249820 +2916168026 3907788997 2512883 +854252812 1457767969 108067760 +2658645540 3065500897 109707051 +0 1842095595 291067601 +821406969 119263604 32845843 +2182554848 897903253 121629531 +1047693412 1565835729 166620621 +3847603798 3400256813 16617815 +1259860138 152109447 53195021 +3581189112 3424865230 243651203 +1470195525 1364566318 10941743 +653613314 30205504 10278891 +1430142037 1324512830 40053488 +291067601 1773419829 68675766 +2109655660 2194936925 65502419 +1856219803 2274429744 191662128 +359743367 300096175 293869947 +3398948690 3416874628 7990602 +3864221613 3822582006 85206991 +2609164425 1750403060 23016769 +1707010741 2466091872 49002444 +1756013185 1732456350 17946710 +1214314033 852357148 45546105 +1313055159 2515094316 117086878 +2175158079 40484395 7396769 +3824840315 3910301880 22763483 +1526945094 639773948 149860143 +2304184379 1019532784 304980046 +3037046757 3933065363 361901933 +1773959895 1375508061 82259908 +726615262 205304468 10225859 +1676805237 0 30205504 +4210177194 2806460975 84790102 + +temperature-to-humidity map: +2704404081 3383155981 190240562 +3678765766 3078657339 304498642 +2894644643 2740175301 304339717 +3375985319 2704404081 35771220 +3198984360 3840405770 142858638 +3341842998 3044515018 34142321 +3411756539 3573396543 267009227 + +humidity-to-location map: +3843755612 3461421206 53203349 +3797023193 2837279508 46732419 +1328442859 1820435049 165058603 +2358032500 2069263501 110029787 +776537476 129658954 20092280 +2041812400 3514624555 271685061 +4004991793 2179293288 239800545 +1813819309 1372459189 171674343 +890079235 609776153 19282104 +129748073 629058257 107944033 +2472688430 2519585064 209661612 +1039983756 866750363 166281406 +3896958961 2729246676 108032832 +1004757286 149751234 35226470 +850718450 90298169 39360785 +3150066893 4231246292 63721004 +0 737002290 129748073 +909361339 1154885545 95395947 +2682350042 2911243637 44822034 +318816223 1586615093 233819956 +796629756 531466240 54088694 +705961941 460890705 70575535 +3669300252 2884011927 27231710 +4244792338 3015820858 50174958 +3352063456 3786309616 317236796 +552636179 0 75876832 +3213787897 4103546412 55695414 +294595004 585554934 24221219 +2799176542 3110530855 350890351 +1691965533 1033031769 121853776 +2468062287 2956065671 4626143 +2727172076 4159241826 72004466 +1493501462 262426634 198464071 +280173667 75876832 14421337 +1986683356 2960691814 55129044 +628513011 184977704 77448930 +2313497461 3065995816 44535039 +1206265162 1250281492 122177697 +3269483311 1986683356 82580145 +237692106 1544133532 42481561 +3696531962 2419093833 100491231
\ No newline at end of file diff --git a/aoc2023/src/day7/input.txt b/aoc2023/src/day7/input.txt new file mode 100644 index 0000000..b1d1932 --- /dev/null +++ b/aoc2023/src/day7/input.txt @@ -0,0 +1,1000 @@ +3Q373 470 +K53JT 351 +A9JK9 856 +2T333 515 +867T4 541 +58K22 253 +5JA6J 994 +K4A4K 865 +94377 519 +92J2Q 901 +J7676 389 +2KK36 938 +JQ2KK 987 +Q7A82 509 +TTTA5 243 +72J27 502 +AKKKA 387 +23222 674 +55335 161 +AA655 73 +QKKQA 686 +5J2T5 680 +666AT 385 +ATA3A 761 +TTT8J 364 +98A2T 282 +59A44 260 +6T9QJ 130 +T7TKQ 721 +9274T 656 +T9AJ4 182 +A2222 259 +TQKJ7 67 +4J844 560 +AAATA 636 +9J36J 546 +QJQQQ 119 +249TT 295 +877J7 221 +4KA23 116 +929Q2 929 +99JQQ 445 +Q9QJ8 432 +4Q7TJ 963 +4J2J8 783 +5J657 257 +88788 183 +KKK7K 909 +KK396 637 +J45AT 117 +84448 806 +A2698 820 +A9AA5 320 +A3934 19 +Q45Q5 392 +78686 254 +A55A5 701 +98A4K 655 +5AJ88 95 +AK3KK 55 +773KK 33 +J9J9J 356 +2KAKK 563 +655K5 287 +55T56 475 +54444 308 +5J5QA 811 +QKA76 792 +2K288 42 +JTKA2 694 +88668 889 +8TQ64 212 +23QQ2 261 +8K8K5 365 +JKKAA 234 +3J894 880 +667Q2 817 +888T4 599 +T5Q83 315 +3QK29 670 +JK4KK 322 +75T8T 144 +AAA7K 291 +7T333 495 +A49K4 448 +JJ3J3 251 +5999J 278 +38438 890 +6K3Q9 122 +TTT99 93 +94775 240 +K8QJ3 369 +59674 107 +267J4 355 +QTQTQ 187 +46J44 961 +Q7AK2 580 +69969 609 +876A5 474 +A3866 642 +Q3QQA 526 +JAA88 425 +35Q9K 986 +QQTQJ 550 +54535 357 +2J222 639 +QK5J7 743 +222Q2 191 +T4T44 855 +QTQQ2 338 +JA7A2 300 +AAAJ2 508 +4J455 23 +A77AA 339 +5KK25 899 +252J2 737 +7QJ76 888 +K46QK 795 +A4T3J 640 +8A8K8 176 +AA5AA 41 +J2Q24 958 +58855 632 +333J3 610 +74474 807 +K3AAA 78 +JJ222 765 +44224 688 +76733 361 +5845K 181 +TT4T2 974 +23J33 102 +QQJ6Q 34 +Q9AQQ 150 +22747 717 +KAA5A 121 +7AA7J 286 +J786T 780 +3K8TT 32 +A6KAA 25 +9A362 166 +A29Q2 499 +6688K 57 +KKQKA 947 +999JJ 975 +6A666 927 +TTT3K 658 +JQQ7T 467 +8A247 934 +7JK8J 712 +KK39K 612 +6666Q 17 +77Q37 868 +A66AJ 169 +KKKKJ 535 +7Q7JJ 591 +K9848 646 +46888 931 +A86A8 326 +743TA 527 +QKK67 977 +KKJ6K 471 +AAJ7A 571 +55292 330 +3A222 390 +6453J 109 +JKKKA 403 +4J9T5 21 +K7A5K 486 +6TT34 793 +3479Q 60 +44624 443 +6KK3K 164 +4447J 112 +QQ27Q 452 +JAK65 522 +Q5Q5Q 354 +J5Q6A 540 +68999 711 +3QJ4Q 155 +A6AAA 314 +222KK 767 +55T9A 373 +T5T57 913 +TTTTA 794 +8J258 190 +3Q87J 489 +AAQAQ 950 +Q4JJ4 588 +6T64T 9 +636K5 228 +AA222 248 +7KJ35 616 +26646 507 +44A4J 829 +23323 904 +TA265 135 +JJQT9 136 +KATJ8 644 +J2862 713 +4JQ28 152 +Q3K2T 56 +6Q232 812 +9A622 885 +KJKKJ 773 +3859T 374 +99333 101 +TKTTK 205 +3333A 35 +5A4AQ 548 +T4944 967 +43353 813 +423JK 869 +T99T7 219 +3AAAA 394 +T65Q6 740 +J9243 352 +6656J 496 +444K4 574 +Q8T6K 98 +AQ55K 917 +7QQJ7 605 +TJ5TT 615 +68JQ5 852 +7A3J2 745 +369AK 217 +57755 343 +A8844 61 +Q76QQ 698 +36333 774 +237Q7 12 +KT694 283 +88286 154 +4T552 990 +Q9J54 759 +K6697 350 +A3A33 937 +AA9AA 246 +QQ7KK 748 +TT4A6 380 +4J992 845 +A66AA 573 +5QQ2Q 28 +86J37 214 +2A443 362 +Q9QKK 654 +44434 964 +77773 74 +44355 235 +9QK75 863 +3AJ33 766 +T2TJT 53 +44494 860 +883A9 309 +QQ59Q 360 +A88A8 584 +A83A4 395 +7J9TA 299 +55955 833 +QJK35 188 +4656A 514 +8KTQ4 554 +56J47 985 +J272J 184 +9J999 671 +72295 31 +53555 264 +4A537 750 +7A4JJ 875 +QK834 463 +88KKA 570 +QQ9JK 906 +6Q646 858 +53336 359 +QJ8QJ 587 +424TJ 607 +KTKK6 285 +Q5AQQ 84 +899A8 542 +K8TKK 250 +4JA4A 705 +6J75J 896 +888K8 312 +5583J 660 +6T335 614 +Q757T 945 +3AKKA 629 +KK946 825 +3393Q 406 +7J288 367 +49999 907 +99729 837 +66265 384 +K47JQ 263 +2AJ4K 566 +TTKKA 186 +8J877 418 +56844 666 +JTTTT 531 +6TJ94 26 +JQ5J5 344 +7J772 85 +33747 510 +KJA2A 729 +333TQ 578 +JQAT4 955 +75766 834 +QQ6QQ 980 +32K33 306 +TTTJ6 231 +2QTTT 213 +999AQ 608 +33353 202 +Q8Q8Q 756 +KK555 490 +746K8 691 +98A75 853 +JQ858 816 +KK9KK 536 +9T999 933 +TA8A8 39 +8558J 919 +J8KQK 15 +73Q2K 503 +2K2KJ 585 +JK9K5 903 +TJ7T7 545 +J723T 453 +KT895 583 +TTTKT 123 +39535 393 +K4K88 893 +43KK6 821 +6AA8J 504 +972TA 597 +7J736 592 +536A8 63 +J23Q3 402 +83K9Q 405 +28337 396 +9T558 776 +7AA78 946 +QTT24 441 +26QT3 401 +AJQAQ 953 +6T6AJ 304 +JK5KK 162 +2JJ2J 484 +73773 6 +8J864 630 +78782 557 +6TJ52 424 +487JQ 830 +8J698 82 +AJAAA 866 +228J8 204 +622J4 823 +6J2QJ 79 +22K22 232 +A86A6 444 +83K8Q 965 +JK586 944 +JA848 465 +8888A 45 +2T28T 803 +73J73 450 +27272 857 +7A777 544 +A998J 679 +46466 458 +KJ233 192 +4453J 378 +TQQJT 451 +A3K5J 512 +888Q6 968 +6AA66 841 +QQ222 883 +3K5A3 233 +JA4AA 379 +62288 778 +44456 51 +4A644 862 +55647 981 +A77A7 327 +KQ3A3 687 +QQ7Q7 976 +T4A2T 293 +46226 628 +Q59Q5 348 +36AJ2 984 +54433 532 +JJQ24 831 +7455J 381 +78845 218 +72AQ5 276 +52T22 618 +99399 68 +36AA3 118 +69669 839 +33Q5J 785 +TJ766 626 +T28J4 556 +T883Q 142 +73928 932 +TJ884 494 +AJ36Q 485 +9Q999 324 +T725Q 267 +22622 88 +92364 685 +97792 789 +J673K 620 +99943 625 +77JJ7 921 +8828Q 572 +7777J 353 +TAAJT 926 +99T29 787 +AQ4J4 520 +9J559 5 +J3T94 706 +K9KK9 918 +KK252 439 +79925 97 +TT47T 497 +848T4 126 +6TTT6 426 +K8825 925 +888J8 62 +K5K85 972 +AAKKA 449 +J5555 663 +89J99 27 +4Q444 922 +A9A99 397 +5A555 163 +8J3K8 662 +29989 645 +95222 751 +Q4Q4Q 193 +555K5 982 +74AJ8 735 +KKQ6K 668 +7676Q 916 +A28T7 784 +K57KK 388 +A4J4J 115 +2K442 229 +33TT3 956 +TT6TA 741 +TT782 131 +TJ5JQ 238 +TQ7T7 415 +29KQQ 598 +A8AAT 676 +46A28 650 +6698K 696 +6J969 158 +6694A 271 +QTQ5T 498 +Q2QQQ 613 +2A7QJ 210 +6T466 683 +QJ575 799 +Q63Q3 822 +Q9J28 848 +TTTT7 7 +KA9AA 854 +K2JJT 859 +28228 179 +K29KJ 429 +JJ8JJ 222 +A99A5 457 +QQTTT 983 +43KK2 134 +984JJ 1 +97J97 892 +2AAA8 689 +9Q77J 819 +98TJK 517 +56KA5 71 +7J66J 294 +55855 335 +TTT8T 596 +33663 407 +7J774 911 +3JQ55 564 +QQQ7Q 329 +85668 120 +KK333 301 +Q3553 867 +7K557 988 +Q8488 400 +96J99 643 +29224 714 +T8ATA 346 +99J93 462 +K83J3 697 +3KQJ4 653 +5KJQ2 824 +4JJ3A 897 +56248 727 +JJ666 702 +355T5 245 +45KAK 553 +88AAA 236 +K55J5 581 +AJJ49 65 +A8Q3J 197 +AAAKQ 529 +55976 707 +77776 930 +A9995 227 +K7J7K 912 +29K99 244 +4Q464 80 +22972 195 +666JQ 189 +26278 241 +79288 601 +5454A 427 +JTAKQ 138 +88833 549 +84J54 215 +AATAK 114 +58959 145 +8ATTJ 431 +QJ26K 265 +A3JA3 81 +T8T4J 242 +4T3A3 37 +44777 871 +JQ542 561 +A97Q9 693 +A76T4 412 +28T4A 481 +T485A 861 +78286 303 +K6776 52 +T8TKQ 754 +KJ938 957 +Q444Q 840 +25A89 455 +58588 673 +K8858 634 +K8KJ8 170 +K6KKK 851 +53353 140 +2T2K6 593 +QQAQA 48 +TT6J6 305 +922J2 920 +AA22K 22 +J555Q 725 +TTAAT 781 +2244J 171 +A95K7 436 +2J299 651 +78AAA 321 +2KKK2 690 +2J565 649 +77J5K 77 +T999T 762 +J4445 879 +J888Q 873 +J884J 1000 +98898 413 +29299 442 +QKQ3Q 678 +A652A 993 +55272 898 +KA5K5 664 +8KJAQ 147 +Q56QJ 734 +K77J3 739 +J7677 661 +T5569 206 +2AA2J 757 +TJTJT 342 +T2TTT 682 +88J82 363 +9KK78 700 +AT4T4 730 +86968 736 +99995 207 +7A3J4 172 +8KK87 991 +TKKJJ 16 +J7532 165 +J9888 996 +9AJTA 92 +43T78 310 +93J77 317 +J4424 805 +43J86 703 +952TJ 127 +54363 146 +8T2J7 435 +88848 832 +TAAAQ 791 +8228T 256 +699QT 815 +KQQQK 30 +T82J3 49 +36222 4 +AK288 86 +6792A 194 +2Q22T 667 +J3545 270 +9QJK4 280 +QQ22Q 371 +K9247 446 +A422A 943 +765K3 469 +9J5A6 874 +4A4QA 775 +8Q8Q8 124 +T8Q62 850 +8Q8Q5 747 +6KT88 738 +82888 722 +3TQQQ 349 +2J3TT 539 +7TQ59 72 +8998T 733 +JQJT3 414 +82428 589 +92856 423 +89833 54 +79T4A 523 +95839 979 +TJJT5 936 +33839 29 +37433 511 +TKJ2T 681 +JT973 633 +Q8Q8J 971 +Q5555 440 +K8886 24 +Q75A4 43 +3AQ33 298 +T446T 719 +577J5 753 +KJTKT 167 +52528 8 +25222 641 +QJ2T8 621 +A8JQJ 316 +7T7A7 772 +KQQTQ 141 +83734 758 +6Q66Q 434 +QJ6Q2 638 +AAA7A 196 +57555 203 +4QJQ4 216 +82J5Q 763 +A73A3 940 +46AJQ 559 +T4936 103 +89Q29 262 +7872T 466 +A5J58 274 +AAAQA 290 +37399 844 +A759Q 328 +TJ9TT 273 +77887 268 +64A2J 978 +6T76Q 110 +QQ467 742 +9J7Q5 422 +4K6Q3 91 +336K3 826 +6K63Q 382 +23552 105 +243AA 505 +Q887J 764 +2J92A 749 +68A3Q 416 +7T8T8 199 +225J5 404 +24774 153 +T7T77 870 +3J393 347 +Q5Q8J 128 +7Q777 796 +QKKKK 617 +86686 108 +44KT4 75 +56858 622 +5AJK4 960 +3245Q 311 +36536 370 +6644Q 11 +JKAAA 104 +T2426 579 +J3399 83 +33933 602 +A299J 777 +26J22 224 +8666J 594 +J3J38 669 +3AJ84 239 +52Q8T 877 +QJQQK 779 +QJ6T8 797 +43339 399 +9AJ74 476 +T499Q 13 +2TAKA 928 +T3K78 809 +2923K 201 +J8858 798 +T8888 818 +98399 168 +8T266 555 +23A57 652 +3KKK3 113 +22T22 460 +AJJAA 106 +7QKA8 464 +QQ8TQ 368 +99A99 341 +62Q5A 223 +J9T47 568 +Q7388 894 +69662 744 +96J2T 323 +2A779 89 +Q2874 269 +77797 948 +5359A 864 +AJ9K4 482 +Q3Q44 567 +JT958 665 +A38J3 438 +J4666 296 +428J5 501 +38K8K 410 +6T979 709 +3533T 284 +2285A 910 +933T6 882 +K6666 786 +56Q32 992 +5J752 198 +AJJQJ 600 +KK5KK 3 +38T94 180 +67QTJ 69 +J6636 200 +229J8 493 +QJTQ3 247 +5KQ5K 149 +654AT 528 +T84T4 878 +Q23QQ 905 +QQQ74 325 +4JTQQ 408 +T4T78 340 +3T5T5 551 +3J3J3 391 +88844 631 +TTT9T 810 +57775 935 +A777J 604 +4555T 2 +A5J8T 942 +22AJJ 506 +22323 997 +A3323 624 +84442 516 +2T992 76 +J7T76 828 +J8552 995 +KTKK3 886 +33853 782 +53233 129 +44J4J 372 +KQQT2 480 +K5649 576 +3J63K 760 +2J666 827 +6JT68 318 +45Q64 849 +49884 801 +9KTTK 902 +66737 952 +5Q8J4 708 +57Q92 724 +627J7 331 +K22J6 473 +4T444 923 +J4444 552 +78J8J 491 +4K328 477 +4AA3A 808 +7A34Q 437 +AQ888 428 +8TA99 768 +AA9A9 143 +9K5AT 211 +77722 40 +TQTTT 941 +Q2A4K 492 +236T9 677 +J8686 746 +J585K 64 +TJKQT 582 +T3TTJ 157 +22266 38 +KT5TK 692 +QJQQJ 908 +4K623 279 +7JJJ7 173 +64A66 524 +J7AJ8 417 +K43Q3 769 +T662T 148 +54J2J 488 +K6485 44 +J6666 970 +J26J9 209 +8337Q 334 +A27A4 319 +A7T78 132 +K777A 842 +KKK4K 249 +99K9K 430 +8745K 151 +Q2QTJ 433 +QKQ76 525 +25Q2Q 533 +5QK6J 800 +77T77 558 +5K323 939 +33KK4 590 +K8A52 111 +ATQJ6 569 +ATK89 50 +4433A 836 +3KKKQ 891 +46TK4 538 +5249Q 447 +2462K 675 +8JT6T 336 +466J7 459 +7K7KK 838 +544Q4 959 +58773 483 +823J5 999 +2TKA5 752 +AKJ58 386 +7T833 99 +KQ88Q 659 +KJ3A4 790 +K9595 307 +3K3J4 534 +3838T 220 +32522 720 +366Q3 500 +J8868 989 +T7KTK 376 +JQQQA 14 +42555 409 +5T5T5 648 +4KK4Q 383 +K7777 884 +736A3 543 +343Q3 366 +TJ856 237 +JJ555 46 +K5QQQ 275 +QAQQ7 672 +8KTJQ 731 +QQQ3Q 47 +J257Q 575 +6Q3QQ 87 +QKK43 924 +TTATJ 998 +K44K5 771 +37895 881 +48823 521 +KKK74 456 +99J79 139 +J4542 635 +AJ96K 954 +K8937 411 +5J355 895 +96967 185 +333T3 562 +TAJ77 755 +J38A8 487 +AAT79 313 +A6Q73 398 +386JA 10 +J35Q8 623 +27758 969 +3K3KJ 966 +7928Q 627 +AAA4A 59 +2AA52 478 +848J8 133 +55225 843 +TTQT9 619 +3Q79K 255 +27AK8 58 +TKTKK 272 +KTTAT 333 +55666 802 +47748 454 +Q3T56 699 +63T3T 302 +8754Q 723 +4J86T 358 +8TTQ9 226 +5523J 125 +88588 606 +58AAA 208 +TK273 137 +4Q7KQ 160 +29292 577 +Q333Q 611 +22TT2 716 +A55AA 258 +64822 468 +22228 847 +2242T 788 +JA26Q 472 +8JAAA 174 +K5Q8A 175 +Q5AT4 732 +J4434 530 +76666 337 +9998Q 547 +9T2J9 100 +3Q982 90 +7727Q 281 +92944 973 +K2597 814 +K444K 36 +26KJ6 292 +34K38 962 +5A378 225 +636J9 375 +TTTT4 420 +A66TA 461 +69QK5 345 +76293 479 +66966 804 +A3383 297 +T82TT 657 +2QJJQ 156 +K2JK3 94 +K6K66 252 +K58QJ 876 +6J979 513 +92647 718 +QQ9Q9 586 +862Q5 20 +5465K 915 +KQ44Q 595 +T66T6 288 +TJT7T 710 +5JT8K 159 +KJTK3 603 +KKJTQ 949 +67776 914 +J4323 177 +22229 704 +96999 178 +8AJKA 70 +69T69 419 +65556 770 +87738 537 +547J4 835 +44766 421 +3355J 684 +2K266 647 +5TTT5 266 +3T3TT 332 +88JJ8 96 +QQ5K3 887 +K7JKK 377 +J8Q2Q 66 +2KKJ6 230 +TTKQT 277 +22Q92 18 +JTTTK 695 +J993Q 846 +88898 728 +88T87 715 +Q74J4 872 +4T999 951 +T997Q 289 +92QA9 726 +AJ394 900 +TT2T2 518 +JJJJJ 565
\ No newline at end of file |