aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ.J <thechairman@thechairman.info>2024-05-30 21:50:02 -0400
committerJ.J <thechairman@thechairman.info>2024-05-30 21:50:02 -0400
commit612fd986ab1e00b6d34dc1937136250e08e89325 (patch)
treea3c93952040c6afdf348b5831619a45db7ba0a2e
parent231c2b688d1e6cf0846d46e883da30e042a9c6cf (diff)
downloadgleam_aoc-612fd986ab1e00b6d34dc1937136250e08e89325.tar.gz
gleam_aoc-612fd986ab1e00b6d34dc1937136250e08e89325.zip
cleanup
-rw-r--r--aoc2023/aoc.toml4
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cachebin0 -> 2442 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cache_metabin0 -> 85 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.erl55
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.cachebin0 -> 595 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.cache_metabin0 -> 293 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.erl278
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.cachebin0 -> 591 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.cache_metabin0 -> 231 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.erl142
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent_ffi.erl12
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.cachebin0 -> 473 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.cache_metabin0 -> 131 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.erl61
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.cachebin0 -> 1544 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.cache_metabin0 -> 85 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.erl74
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.cachebin0 -> 1537 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.cache_metabin0 -> 69 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.erl53
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.cachebin0 -> 443 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.cache_metabin0 -> 67 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.erl25
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.cachebin0 -> 824 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.erl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.cachebin0 -> 385 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.erl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.cachebin0 -> 1299 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.erl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.cachebin0 -> 1306 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.erl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.cachebin0 -> 1731 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.cache_metabin0 -> 60 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.erl83
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cachebin0 -> 1083 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cache_metabin0 -> 439 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.erl155
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.cachebin0 -> 885 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.erl8
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.cachebin0 -> 3284 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.cache_metabin0 -> 89 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.erl131
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.cachebin0 -> 15307 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.cache_metabin0 -> 67 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.erl54
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.cachebin0 -> 8905 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.cache_metabin0 -> 129 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.erl30
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.cachebin0 -> 1954 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.cache_metabin0 -> 227 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.erl230
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.cachebin0 -> 1555 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.cache_metabin0 -> 292 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.erl76
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.cachebin0 -> 1140 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.cache_metabin0 -> 179 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.erl53
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.cachebin0 -> 1657 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.cache_metabin0 -> 195 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.erl46
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.cachebin0 -> 484 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.cache_metabin0 -> 140 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.erl61
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.cachebin0 -> 5136 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.cache_metabin0 -> 421 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.erl749
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.cachebin0 -> 3269 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.cache_metabin0 -> 118 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.erl93
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.cachebin0 -> 5550 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.cache_metabin0 -> 144 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.erl229
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.cachebin0 -> 903 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.erl8
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.cachebin0 -> 5651 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.cache_metabin0 -> 76 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.erl143
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.cachebin0 -> 3712 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.cache_metabin0 -> 101 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.erl57
-rw-r--r--aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime_ffi.erl187
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/adglent.app17
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/adglent.beambin0 -> 3024 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/adglent@day.beambin0 -> 8236 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/adglent@init.beambin0 -> 6260 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/adglent_ffi.beambin0 -> 1496 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/priv@aoc_client.beambin0 -> 3648 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/priv@errors.beambin0 -> 3744 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/priv@prompt.beambin0 -> 2696 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/priv@template.beambin0 -> 1756 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/priv@templates@solution.beambin0 -> 752 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/priv@templates@test_main.beambin0 -> 756 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/priv@templates@testfile_gleeunit.beambin0 -> 776 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/priv@templates@testfile_showtime.beambin0 -> 776 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/priv@toml.beambin0 -> 3848 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime.beambin0 -> 6980 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@cli.beambin0 -> 892 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@common_event_handler.beambin0 -> 4276 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@test_result.beambin0 -> 1852 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@test_suite.beambin0 -> 1380 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@discover.beambin0 -> 8636 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@event_handler.beambin0 -> 4320 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@module_handler.beambin0 -> 2968 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@runner.beambin0 -> 2360 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@compare.beambin0 -> 3320 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@formatter.beambin0 -> 20416 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@styles.beambin0 -> 4148 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@table.beambin0 -> 7556 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@meta.beambin0 -> 872 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@should.beambin0 -> 5368 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@test.beambin0 -> 3360 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/ebin/showtime_ffi.beambin0 -> 7652 bytes
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/adglent_Example.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/priv@toml_TomGetError.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/priv@toml_TomParseError.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@common_event_handler_Finished.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@common_event_handler_HandlerState.hrl5
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ArgList.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertEqual.hrl3
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertMatch.hrl3
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_AssertNotEqual.hrl3
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ErlangException.hrl6
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ErrorInfo.hrl3
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Expected.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Expression.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_File.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GenericException.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GleamAssert.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_GleamError.hrl3
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Ignored.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_LetAssert.hrl7
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Line.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Module.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Num.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Pattern.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_ReasonLine.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TestFunctionReturn.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Trace.hrl5
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TraceList.hrl3
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_TraceModule.hrl6
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_result_Value.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_CompletedTestRun.hrl6
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTest.hrl6
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTestRun.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_EndTestSuite.hrl3
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_OngoingTestRun.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_StartTest.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_StartTestSuite.hrl3
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestFunction.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestModule.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@common@test_suite_TestSuite.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignLeft.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignLeftOverflow.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignRight.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_AlignRightOverflow.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Aligned.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Content.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Separator.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_StyledContent.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@internal@reports@table_Table.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@tests@meta_Meta.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_Eq.hrl5
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_Fail.hrl1
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_IsError.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_IsOk.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@tests@should_NotEq.hrl5
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@tests@test_MetaShould.hrl4
-rw-r--r--aoc2023/build/dev/erlang/adglent/include/showtime@tests@test_Test.hrl4
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cachebin0 -> 417 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cache_metabin0 -> 68 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.erl21
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023@@main.erl35
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.cachebin0 -> 310 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.cache_metabin0 -> 45 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.erl8
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.cachebin0 -> 1869 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.erl52
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.cachebin0 -> 5552 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.cache_metabin0 -> 168 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.erl340
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.cachebin0 -> 1955 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.erl68
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.cachebin0 -> 2106 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.cache_metabin0 -> 115 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.erl130
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.cachebin0 -> 1749 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.erl38
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.cachebin0 -> 1807 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.cache_metabin0 -> 157 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.erl145
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.cachebin0 -> 2017 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.erl88
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.cachebin0 -> 2461 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.cache_metabin0 -> 116 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.erl149
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.cachebin0 -> 1953 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.erl68
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.cachebin0 -> 2304 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.cache_metabin0 -> 152 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.erl149
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.cachebin0 -> 1839 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.erl32
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.cachebin0 -> 3255 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.cache_metabin0 -> 153 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.erl177
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.cachebin0 -> 1938 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.erl68
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.cachebin0 -> 2482 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.cache_metabin0 -> 176 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.erl253
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.cachebin0 -> 1282 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.erl42
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.cachebin0 -> 4282 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.cache_metabin0 -> 223 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.erl231
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.cachebin0 -> 2138 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.erl84
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.cachebin0 -> 3679 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.cache_metabin0 -> 154 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.erl218
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.cachebin0 -> 2462 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.erl96
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.cachebin0 -> 9169 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.cache_metabin0 -> 191 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.erl459
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.cachebin0 -> 1858 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.cache_metabin0 -> 109 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.erl50
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.cachebin0 -> 1198 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.cache_metabin0 -> 134 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.erl118
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.cachebin0 -> 1457 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.erl42
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.cachebin0 -> 6830 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.cache_metabin0 -> 192 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.erl460
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.cachebin0 -> 1518 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.erl24
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.cachebin0 -> 566 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.cache_metabin0 -> 60 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.erl56
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.cachebin0 -> 1872 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.erl56
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.cachebin0 -> 6319 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.cache_metabin0 -> 227 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.erl369
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.cachebin0 -> 2817 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.erl120
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.cachebin0 -> 6015 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.cache_metabin0 -> 213 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.erl337
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.cachebin0 -> 2496 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.cache_metabin0 -> 109 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.erl54
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.cachebin0 -> 1464 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.cache_metabin0 -> 115 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.erl166
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.cachebin0 -> 1918 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.cache_metabin0 -> 109 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.erl68
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.cachebin0 -> 5763 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.cache_metabin0 -> 152 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.erl254
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.cachebin0 -> 2283 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.cache_metabin0 -> 109 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.erl52
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.cachebin0 -> 2131 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.cache_metabin0 -> 208 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.erl169
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.cachebin0 -> 2401 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.cache_metabin0 -> 109 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.erl160
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.cachebin0 -> 5185 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.cache_metabin0 -> 157 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.erl269
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.cachebin0 -> 1812 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.cache_metabin0 -> 109 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.erl36
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.cachebin0 -> 1964 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.cache_metabin0 -> 135 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.erl131
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.cachebin0 -> 1823 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.cache_metabin0 -> 109 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.erl48
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.cachebin0 -> 3250 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.cache_metabin0 -> 174 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.erl242
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.cachebin0 -> 1885 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.cache_metabin0 -> 109 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.erl58
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.cachebin0 -> 1835 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.cache_metabin0 -> 236 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.erl179
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.cachebin0 -> 1813 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.cache_metabin0 -> 109 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.erl40
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.cachebin0 -> 1876 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.cache_metabin0 -> 115 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.erl133
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.cachebin0 -> 3067 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.cache_metabin0 -> 122 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.erl82
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.cachebin0 -> 3223 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.cache_metabin0 -> 118 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.erl70
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.cachebin0 -> 3195 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.cache_metabin0 -> 47 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.erl60
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023.app14
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023.beambin0 -> 1924 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023@@main.beambin0 -> 2724 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023_test.beambin0 -> 1040 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day10@day10_test.beambin0 -> 2460 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day10@solve.beambin0 -> 12760 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day11@day11_test.beambin0 -> 2348 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day11@solve.beambin0 -> 6176 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day12@day12_test.beambin0 -> 2344 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day12@solve.beambin0 -> 6760 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day13@day13_test.beambin0 -> 2380 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day13@solve.beambin0 -> 6560 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day14@day14_test.beambin0 -> 2400 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day14@solve.beambin0 -> 6860 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day15@day15_test.beambin0 -> 2368 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day15@solve.beambin0 -> 7624 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day16@day16_test.beambin0 -> 2352 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day16@solve.beambin0 -> 9808 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day17@day17_test.beambin0 -> 2064 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day17@solve.beambin0 -> 9644 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day18@day18_test.beambin0 -> 2540 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day18@solve.beambin0 -> 8472 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day19@day19_test.beambin0 -> 2824 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day19@solve.beambin0 -> 15424 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day1@day1_test.beambin0 -> 2472 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day1@solve.beambin0 -> 5240 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day20@day20_test.beambin0 -> 2068 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day20@solve.beambin0 -> 15148 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day21@day21_test.beambin0 -> 1992 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day21@solve.beambin0 -> 2788 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day22@day22_test.beambin0 -> 2344 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day22@solve.beambin0 -> 15808 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day23@day23_test.beambin0 -> 2572 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day23@solve.beambin0 -> 12844 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day2@day2_test.beambin0 -> 2608 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day2@solve.beambin0 -> 6980 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day3@day3_test.beambin0 -> 2380 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day3@solve.beambin0 -> 11244 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day4@day4_test.beambin0 -> 2600 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day4@solve.beambin0 -> 8080 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day5@day5_test.beambin0 -> 2712 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day5@solve.beambin0 -> 11092 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day6@day6_test.beambin0 -> 2348 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day6@solve.beambin0 -> 6204 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day7@day7_test.beambin0 -> 2372 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day7@solve.beambin0 -> 9656 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day8@day8_test.beambin0 -> 2448 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day8@solve.beambin0 -> 7512 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day9@day9_test.beambin0 -> 2344 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/day9@solve.beambin0 -> 5604 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/utilities@array2d.beambin0 -> 5188 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/utilities@memo.beambin0 -> 3980 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/ebin/utilities@prioqueue.beambin0 -> 3364 bytes
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/include/day2@solve_Game.hrl1
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/include/day5@solve_Almanac.hrl4
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/include/day5@solve_MRange.hrl1
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/include/day5@solve_SRange.hrl1
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/include/utilities@array2d_Posn.hrl1
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/include/utilities@memo_Cache.hrl3
-rw-r--r--aoc2023/build/dev/erlang/aoc2023/include/utilities@prioqueue_PriorityQueue.hrl4
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cachebin0 -> 6154 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cache_metabin0 -> 282 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.erl538
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.cachebin0 -> 2548 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.erl15
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.cachebin0 -> 4916 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.cache_metabin0 -> 47 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.erl156
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.cachebin0 -> 948 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.erl8
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.cachebin0 -> 8126 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.cache_metabin0 -> 166 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.erl202
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap_ffi.mjs431
-rw-r--r--aoc2023/build/dev/erlang/gap/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/gap/ebin/gap.app8
-rw-r--r--aoc2023/build/dev/erlang/gap/ebin/gap.beambin0 -> 15520 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/ebin/gap@comparison.beambin0 -> 1024 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/ebin/gap@myers.beambin0 -> 6464 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/ebin/gap@styled_comparison.beambin0 -> 868 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/ebin/gap@styling.beambin0 -> 7440 bytes
-rw-r--r--aoc2023/build/dev/erlang/gap/include/gap@comparison_ListComparison.hrl4
-rw-r--r--aoc2023/build/dev/erlang/gap/include/gap@comparison_Match.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gap/include/gap@comparison_NoMatch.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gap/include/gap@comparison_StringComparison.hrl4
-rw-r--r--aoc2023/build/dev/erlang/gap/include/gap@styled_comparison_StyledComparison.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gap/include/gap@styling_All.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gap/include/gap@styling_Highlighters.hrl5
-rw-r--r--aoc2023/build/dev/erlang/gap/include/gap@styling_Part.hrl5
-rw-r--r--aoc2023/build/dev/erlang/gap/include/gap@styling_Styling.hrl5
-rw-r--r--aoc2023/build/dev/erlang/gleam.lock0
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cachebin0 -> 63325 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache_metabin0 -> 114 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.erl263
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_ansi/ebin/gleam_community@ansi.beambin0 -> 10532 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_ansi/ebin/gleam_community_ansi.app8
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cachebin0 -> 28499 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_metabin0 -> 123 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.erl513
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cachebin0 -> 3174 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_metabin0 -> 96 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.erl75
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community@colour.beambin0 -> 19680 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community@colour@accessibility.beambin0 -> 4096 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community_colour.app7
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/include/gleam_community@colour_Hsla.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_colour/include/gleam_community@colour_Rgba.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.cachebin0 -> 14592 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.cache_metabin0 -> 183 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.erl172
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.cachebin0 -> 8261 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.cache_metabin0 -> 64 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.erl218
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.cachebin0 -> 4617 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.cache_metabin0 -> 46 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.erl24
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.cachebin0 -> 31030 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.cache_metabin0 -> 66 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.erl286
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.cachebin0 -> 12151 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.cache_metabin0 -> 284 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.erl281
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.cachebin0 -> 34263 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.cache_metabin0 -> 201 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.erl563
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.cachebin0 -> 8829 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.cache_metabin0 -> 222 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.erl118
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.cachebin0 -> 6512 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.cache_metabin0 -> 166 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.erl202
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.cachebin0 -> 3951 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.cache_metabin0 -> 166 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.erl163
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/maths.mjs95
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@arithmetics.beambin0 -> 7228 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@combinatorics.beambin0 -> 7572 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@conversion.beambin0 -> 1864 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@elementary.beambin0 -> 9272 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@metrics.beambin0 -> 9256 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@piecewise.beambin0 -> 16456 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@predicates.beambin0 -> 5532 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@sequences.beambin0 -> 7032 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@special.beambin0 -> 7588 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community_maths.app7
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.cachebin0 -> 9002 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.cache_metabin0 -> 122 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.erl90
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cachebin0 -> 2925 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache_metabin0 -> 50 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.erl26
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cachebin0 -> 879 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.erl15
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.cachebin0 -> 28770 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.cache_metabin0 -> 72 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.erl190
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cachebin0 -> 3128 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache_metabin0 -> 54 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.erl33
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.cachebin0 -> 3355 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.cache_metabin0 -> 46 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.erl27
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cachebin0 -> 31850 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache_metabin0 -> 115 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.erl374
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam_erlang_ffi.erl263
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang.beambin0 -> 4304 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@atom.beambin0 -> 1804 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@charlist.beambin0 -> 1344 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@file.beambin0 -> 5960 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@node.beambin0 -> 1932 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@os.beambin0 -> 1784 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@process.beambin0 -> 14832 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam_erlang.app7
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam_erlang_ffi.beambin0 -> 13908 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@file_FileInfo.hrl15
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Abnormal.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_CalleeDown.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Cancelled.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ExitMessage.hrl4
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ProcessDown.hrl4
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_ProcessMonitor.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang@process_Subject.hrl4
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang_ApplicationFailedToStart.hrl4
-rw-r--r--aoc2023/build/dev/erlang/gleam_erlang/include/gleam@erlang_UnknownApplication.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.cachebin0 -> 15648 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.cache_metabin0 -> 149 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.erl626
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.cachebin0 -> 4404 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.cache_metabin0 -> 161 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.erl153
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.cachebin0 -> 8343 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.cache_metabin0 -> 195 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.erl202
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.cachebin0 -> 5339 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.cache_metabin0 -> 150 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.erl97
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.cachebin0 -> 3249 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.cache_metabin0 -> 138 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.erl82
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam_http_native.erl88
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam_http_native.mjs38
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http.beambin0 -> 21872 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@cookie.beambin0 -> 7028 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@request.beambin0 -> 8932 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@response.beambin0 -> 4952 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@service.beambin0 -> 4260 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/ebin/gleam_http.app7
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/ebin/gleam_http_native.beambin0 -> 4896 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/include/gleam@http@cookie_Attributes.hrl8
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/include/gleam@http@request_Request.hrl10
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/include/gleam@http@response_Response.hrl5
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MoreRequiredForBody.hrl5
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MoreRequiredForHeaders.hrl4
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MultipartBody.hrl5
-rw-r--r--aoc2023/build/dev/erlang/gleam_http/include/gleam@http_MultipartHeaders.hrl4
-rw-r--r--aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.cachebin0 -> 4339 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.cache_metabin0 -> 199 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.erl118
-rw-r--r--aoc2023/build/dev/erlang/gleam_httpc/ebin/gleam@httpc.beambin0 -> 4836 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_httpc/ebin/gleam_httpc.app10
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.cachebin0 -> 13827 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.cache_metabin0 -> 196 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.erl273
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.cachebin0 -> 2504 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.cache_metabin0 -> 47 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.erl53
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.cachebin0 -> 354 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.erl8
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.cachebin0 -> 16928 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.cache_metabin0 -> 200 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.erl322
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.cachebin0 -> 5924 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.cache_metabin0 -> 103 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.erl43
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.cachebin0 -> 4487 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.cache_metabin0 -> 78 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.erl111
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.cachebin0 -> 743 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.cache_metabin0 -> 130 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.erl28
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp_external.erl43
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@actor.beambin0 -> 10880 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@intensity_tracker.beambin0 -> 2476 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@port.beambin0 -> 828 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@supervisor.beambin0 -> 12984 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@system.beambin0 -> 1992 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@task.beambin0 -> 5320 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp.app8
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp.beambin0 -> 2344 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp_external.beambin0 -> 3036 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Continue.hrl4
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Ready.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@actor_Spec.hrl5
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@intensity_tracker_IntensityTracker.hrl5
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@supervisor_ChildSpec.hrl5
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@supervisor_Spec.hrl6
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@system_StatusInfo.hrl7
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@task_Exit.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_otp/include/gleam@otp@task_Task.hrl6
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/dict.mjs957
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cachebin0 -> 1320 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_metabin0 -> 52 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.erl20
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cachebin0 -> 5111 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_metabin0 -> 49 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.erl102
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cachebin0 -> 4332 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_metabin0 -> 84 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.erl66
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cachebin0 -> 2045 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_metabin0 -> 52 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.erl33
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cachebin0 -> 7238 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_metabin0 -> 48 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.erl162
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cachebin0 -> 6422 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_metabin0 -> 98 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.erl87
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cachebin0 -> 12512 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_metabin0 -> 49 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.erl97
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cachebin0 -> 49789 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_metabin0 -> 173 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.erl808
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cachebin0 -> 11605 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_metabin0 -> 48 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.erl181
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cachebin0 -> 5953 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.erl67
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cachebin0 -> 18473 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_metabin0 -> 67 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.erl332
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cachebin0 -> 2986 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_metabin0 -> 49 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.erl27
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cachebin0 -> 38981 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_metabin0 -> 141 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.erl744
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cachebin0 -> 46930 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_metabin0 -> 120 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.erl1129
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cachebin0 -> 4920 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_metabin0 -> 67 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.erl76
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cachebin0 -> 7437 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.erl147
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cachebin0 -> 2841 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.erl79
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cachebin0 -> 1991 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.erl33
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cachebin0 -> 7246 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_metabin0 -> 47 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.erl121
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cachebin0 -> 7037 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_metabin0 -> 49 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.erl33
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cachebin0 -> 10555 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_metabin0 -> 47 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.erl201
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cachebin0 -> 6637 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_metabin0 -> 85 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.erl85
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cachebin0 -> 22141 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_metabin0 -> 136 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.erl352
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cachebin0 -> 10824 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_metabin0 -> 47 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.erl91
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cachebin0 -> 8413 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_metabin0 -> 132 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.erl252
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.erl529
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam_stdlib.mjs875
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@base.beambin0 -> 1668 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_array.beambin0 -> 4644 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_builder.beambin0 -> 3264 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_string.beambin0 -> 2132 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bool.beambin0 -> 3952 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bytes_builder.beambin0 -> 3716 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dict.beambin0 -> 4660 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic.beambin0 -> 32580 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@float.beambin0 -> 6080 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@function.beambin0 -> 5444 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@int.beambin0 -> 9840 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@io.beambin0 -> 1700 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@iterator.beambin0 -> 28364 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@list.beambin0 -> 34448 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@map.beambin0 -> 4040 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@option.beambin0 -> 4516 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@order.beambin0 -> 2336 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@pair.beambin0 -> 1972 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@queue.beambin0 -> 5280 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@regex.beambin0 -> 2068 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@result.beambin0 -> 6824 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@set.beambin0 -> 4728 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string.beambin0 -> 12432 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string_builder.beambin0 -> 4100 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@uri.beambin0 -> 9472 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.app7
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.beambin0 -> 28304 bytes
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl5
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@iterator_Iterator.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@iterator_Next.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@queue_Queue.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_CompileError.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_Match.hrl4
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@regex_Options.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@set_Set.hrl1
-rw-r--r--aoc2023/build/dev/erlang/gleam_stdlib/include/gleam@uri_Uri.hrl9
-rw-r--r--aoc2023/build/dev/erlang/gleam_version1
-rw-r--r--aoc2023/build/dev/erlang/glint/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cachebin0 -> 18971 bytes
-rw-r--r--aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cache_metabin0 -> 278 bytes
-rw-r--r--aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.erl513
-rw-r--r--aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.cachebin0 -> 20519 bytes
-rw-r--r--aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.cache_metabin0 -> 214 bytes
-rw-r--r--aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.erl523
-rw-r--r--aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.cachebin0 -> 1690 bytes
-rw-r--r--aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache_metabin0 -> 116 bytes
-rw-r--r--aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.erl68
-rw-r--r--aoc2023/build/dev/erlang/glint/ebin/glint.app10
-rw-r--r--aoc2023/build/dev/erlang/glint/ebin/glint.beambin0 -> 20148 bytes
-rw-r--r--aoc2023/build/dev/erlang/glint/ebin/glint@flag.beambin0 -> 22060 bytes
-rw-r--r--aoc2023/build/dev/erlang/glint/ebin/glint@flag@constraint.beambin0 -> 3928 bytes
-rw-r--r--aoc2023/build/dev/erlang/glint/include/glint@flag_Flag.hrl1
-rw-r--r--aoc2023/build/dev/erlang/glint/include/glint@flag_FlagBuilder.hrl6
-rw-r--r--aoc2023/build/dev/erlang/glint/include/glint@flag_Internal.hrl4
-rw-r--r--aoc2023/build/dev/erlang/glint/include/glint_Command.hrl5
-rw-r--r--aoc2023/build/dev/erlang/glint/include/glint_CommandInput.hrl4
-rw-r--r--aoc2023/build/dev/erlang/glint/include/glint_Config.hrl4
-rw-r--r--aoc2023/build/dev/erlang/glint/include/glint_Glint.hrl5
-rw-r--r--aoc2023/build/dev/erlang/glint/include/glint_PrettyHelp.hrl5
-rw-r--r--aoc2023/build/dev/erlang/glint/include/glint_Stub.hrl6
-rw-r--r--aoc2023/build/dev/erlang/pqueue/LICENSE21
-rw-r--r--aoc2023/build/dev/erlang/pqueue/README.markdown31
-rw-r--r--aoc2023/build/dev/erlang/pqueue/_build/prod/lib/.rebar3/rebar_compiler_erl/source.dagbin0 -> 470 bytes
-rw-r--r--aoc2023/build/dev/erlang/pqueue/doc/edoc-info3
-rw-r--r--aoc2023/build/dev/erlang/pqueue/doc/erlang.pngbin0 -> 2109 bytes
-rw-r--r--aoc2023/build/dev/erlang/pqueue/doc/index.html17
-rw-r--r--aoc2023/build/dev/erlang/pqueue/doc/modules-frame.html15
-rw-r--r--aoc2023/build/dev/erlang/pqueue/doc/overview-summary.html16
-rw-r--r--aoc2023/build/dev/erlang/pqueue/doc/pqueue.html166
-rw-r--r--aoc2023/build/dev/erlang/pqueue/doc/pqueue2.html143
-rw-r--r--aoc2023/build/dev/erlang/pqueue/doc/pqueue3.html162
-rw-r--r--aoc2023/build/dev/erlang/pqueue/doc/pqueue4.html205
-rw-r--r--aoc2023/build/dev/erlang/pqueue/doc/stylesheet.css55
-rw-r--r--aoc2023/build/dev/erlang/pqueue/ebin/pqueue.app6
-rw-r--r--aoc2023/build/dev/erlang/pqueue/ebin/pqueue.beambin0 -> 86976 bytes
-rw-r--r--aoc2023/build/dev/erlang/pqueue/ebin/pqueue2.beambin0 -> 21548 bytes
-rw-r--r--aoc2023/build/dev/erlang/pqueue/ebin/pqueue3.beambin0 -> 14216 bytes
-rw-r--r--aoc2023/build/dev/erlang/pqueue/ebin/pqueue4.beambin0 -> 1219608 bytes
-rw-r--r--aoc2023/build/dev/erlang/pqueue/rebar.config14
-rw-r--r--aoc2023/build/dev/erlang/pqueue/src/pqueue.app.src10
-rw-r--r--aoc2023/build/dev/erlang/pqueue/src/pqueue.erl2246
-rw-r--r--aoc2023/build/dev/erlang/pqueue/src/pqueue2.erl483
-rw-r--r--aoc2023/build/dev/erlang/pqueue/src/pqueue3.erl404
-rw-r--r--aoc2023/build/dev/erlang/pqueue/src/pqueue4.erl11662
-rw-r--r--aoc2023/build/dev/erlang/pqueue/src/pqueue_test.hrl49
-rw-r--r--aoc2023/build/dev/erlang/pqueue/test/pqueue_proper.erl156
-rw-r--r--aoc2023/build/dev/erlang/pqueue/test/queue_srv.erl183
-rw-r--r--aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cachebin0 -> 20593 bytes
-rw-r--r--aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cache_metabin0 -> 110 bytes
-rw-r--r--aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.erl287
-rw-r--r--aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile_erl.erl70
-rw-r--r--aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile_js.mjs102
-rw-r--r--aoc2023/build/dev/erlang/simplifile/ebin/simplifile.app7
-rw-r--r--aoc2023/build/dev/erlang/simplifile/ebin/simplifile.beambin0 -> 10372 bytes
-rw-r--r--aoc2023/build/dev/erlang/simplifile/ebin/simplifile_erl.beambin0 -> 4484 bytes
-rw-r--r--aoc2023/build/dev/erlang/snag/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cachebin0 -> 3788 bytes
-rw-r--r--aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cache_metabin0 -> 125 bytes
-rw-r--r--aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.erl74
-rw-r--r--aoc2023/build/dev/erlang/snag/ebin/snag.app7
-rw-r--r--aoc2023/build/dev/erlang/snag/ebin/snag.beambin0 -> 3596 bytes
-rw-r--r--aoc2023/build/dev/erlang/snag/include/snag_Snag.hrl1
-rw-r--r--aoc2023/build/dev/erlang/tom/_gleam_artefacts/gleam@@compile.erl157
-rw-r--r--aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cachebin0 -> 33665 bytes
-rw-r--r--aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cache_metabin0 -> 140 bytes
-rw-r--r--aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.erl2142
-rw-r--r--aoc2023/build/dev/erlang/tom/ebin/tom.app7
-rw-r--r--aoc2023/build/dev/erlang/tom/ebin/tom.beambin0 -> 70916 bytes
-rw-r--r--aoc2023/build/dev/erlang/tom/include/tom_DateTimeValue.hrl5
-rw-r--r--aoc2023/build/dev/erlang/tom/include/tom_DateValue.hrl1
-rw-r--r--aoc2023/build/dev/erlang/tom/include/tom_KeyAlreadyInUse.hrl1
-rw-r--r--aoc2023/build/dev/erlang/tom/include/tom_NotFound.hrl1
-rw-r--r--aoc2023/build/dev/erlang/tom/include/tom_Offset.hrl5
-rw-r--r--aoc2023/build/dev/erlang/tom/include/tom_TimeValue.hrl6
-rw-r--r--aoc2023/build/dev/erlang/tom/include/tom_Unexpected.hrl1
-rw-r--r--aoc2023/build/dev/erlang/tom/include/tom_WrongType.hrl5
-rw-r--r--aoc2023/build/dev/javascript/gleam.lock0
-rw-r--r--aoc2023/build/lsp/erlang/gleam.lock0
-rw-r--r--aoc2023/build/lsp/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cachebin0 -> 70073 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache_metabin0 -> 9398 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cachebin0 -> 35097 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_metabin0 -> 4643 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cachebin0 -> 3946 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_metabin0 -> 804 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cachebin0 -> 1544 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_metabin0 -> 152 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cachebin0 -> 5917 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_metabin0 -> 693 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cachebin0 -> 5175 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_metabin0 -> 420 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cachebin0 -> 2374 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_metabin0 -> 240 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cachebin0 -> 8609 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_metabin0 -> 1776 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cachebin0 -> 7764 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_metabin0 -> 902 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cachebin0 -> 15526 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_metabin0 -> 2241 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cachebin0 -> 61298 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_metabin0 -> 6221 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cachebin0 -> 13601 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_metabin0 -> 2248 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cachebin0 -> 6462 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_metabin0 -> 693 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cachebin0 -> 21826 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_metabin0 -> 3579 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cachebin0 -> 3472 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_metabin0 -> 533 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cachebin0 -> 46843 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_metabin0 -> 6277 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cachebin0 -> 54517 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_metabin0 -> 8752 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cachebin0 -> 5923 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_metabin0 -> 591 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cachebin0 -> 9278 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_metabin0 -> 1429 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cachebin0 -> 3738 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_metabin0 -> 577 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cachebin0 -> 2303 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_metabin0 -> 385 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cachebin0 -> 9242 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_metabin0 -> 1231 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cachebin0 -> 8589 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_metabin0 -> 921 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cachebin0 -> 12172 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_metabin0 -> 1991 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cachebin0 -> 8207 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_metabin0 -> 1157 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cachebin0 -> 25600 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_metabin0 -> 3776 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cachebin0 -> 13687 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_metabin0 -> 1255 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cachebin0 -> 10755 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_metabin0 -> 1996 bytes
-rw-r--r--aoc2023/build/lsp/erlang/gleam_version1
-rw-r--r--aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cachebin0 -> 23502 bytes
-rw-r--r--aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cache_metabin0 -> 2646 bytes
-rw-r--r--aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cachebin0 -> 24407 bytes
-rw-r--r--aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cache_metabin0 -> 2142 bytes
-rw-r--r--aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag@constraint.cachebin0 -> 2127 bytes
-rw-r--r--aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache_metabin0 -> 396 bytes
-rw-r--r--aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cachebin0 -> 5321 bytes
-rw-r--r--aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache_metabin0 -> 705 bytes
-rw-r--r--aoc2023/build/lsp/javascript/gleam.lock0
-rw-r--r--aoc2023/build/packages/adglent/LICENSE201
-rw-r--r--aoc2023/build/packages/adglent/README.md115
-rw-r--r--aoc2023/build/packages/adglent/gleam.toml29
-rw-r--r--aoc2023/build/packages/adglent/include/adglent_Example.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/priv@toml_TomGetError.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/priv@toml_TomParseError.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@common_event_handler_Finished.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@common_event_handler_HandlerState.hrl5
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ArgList.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertEqual.hrl3
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertMatch.hrl3
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_AssertNotEqual.hrl3
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ErlangException.hrl6
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ErrorInfo.hrl3
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Expected.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Expression.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_File.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GenericException.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GleamAssert.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_GleamError.hrl3
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Ignored.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_LetAssert.hrl7
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Line.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Module.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Num.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Pattern.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_ReasonLine.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TestFunctionReturn.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Trace.hrl5
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TraceList.hrl3
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_TraceModule.hrl6
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_result_Value.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_CompletedTestRun.hrl6
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTest.hrl6
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTestRun.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_EndTestSuite.hrl3
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_OngoingTestRun.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_StartTest.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_StartTestSuite.hrl3
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestFunction.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestModule.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@common@test_suite_TestSuite.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignLeft.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignLeftOverflow.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignRight.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@reports@table_AlignRightOverflow.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Aligned.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Content.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Separator.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@reports@table_StyledContent.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@internal@reports@table_Table.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@tests@meta_Meta.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@tests@should_Eq.hrl5
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@tests@should_Fail.hrl1
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@tests@should_IsError.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@tests@should_IsOk.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@tests@should_NotEq.hrl5
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@tests@test_MetaShould.hrl4
-rw-r--r--aoc2023/build/packages/adglent/include/showtime@tests@test_Test.hrl4
-rw-r--r--aoc2023/build/packages/adglent/src/adglent.app.src45
-rw-r--r--aoc2023/build/packages/adglent/src/adglent.erl55
-rw-r--r--aoc2023/build/packages/adglent/src/adglent.gleam56
-rw-r--r--aoc2023/build/packages/adglent/src/adglent/day.gleam126
-rw-r--r--aoc2023/build/packages/adglent/src/adglent/init.gleam110
-rw-r--r--aoc2023/build/packages/adglent/src/adglent@day.erl278
-rw-r--r--aoc2023/build/packages/adglent/src/adglent@init.erl142
-rw-r--r--aoc2023/build/packages/adglent/src/adglent_ffi.erl12
-rw-r--r--aoc2023/build/packages/adglent/src/priv/aoc_client.gleam37
-rw-r--r--aoc2023/build/packages/adglent/src/priv/errors.gleam54
-rw-r--r--aoc2023/build/packages/adglent/src/priv/prompt.gleam38
-rw-r--r--aoc2023/build/packages/adglent/src/priv/template.gleam18
-rw-r--r--aoc2023/build/packages/adglent/src/priv/templates/solution.gleam27
-rw-r--r--aoc2023/build/packages/adglent/src/priv/templates/test_main.gleam7
-rw-r--r--aoc2023/build/packages/adglent/src/priv/templates/testfile_gleeunit.gleam41
-rw-r--r--aoc2023/build/packages/adglent/src/priv/templates/testfile_showtime.gleam41
-rw-r--r--aoc2023/build/packages/adglent/src/priv/toml.gleam52
-rw-r--r--aoc2023/build/packages/adglent/src/priv@aoc_client.erl61
-rw-r--r--aoc2023/build/packages/adglent/src/priv@errors.erl74
-rw-r--r--aoc2023/build/packages/adglent/src/priv@prompt.erl53
-rw-r--r--aoc2023/build/packages/adglent/src/priv@template.erl25
-rw-r--r--aoc2023/build/packages/adglent/src/priv@templates@solution.erl1
-rw-r--r--aoc2023/build/packages/adglent/src/priv@templates@test_main.erl1
-rw-r--r--aoc2023/build/packages/adglent/src/priv@templates@testfile_gleeunit.erl1
-rw-r--r--aoc2023/build/packages/adglent/src/priv@templates@testfile_showtime.erl1
-rw-r--r--aoc2023/build/packages/adglent/src/priv@toml.erl83
-rw-r--r--aoc2023/build/packages/adglent/src/showtime.erl155
-rw-r--r--aoc2023/build/packages/adglent/src/showtime.gleam116
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/common/cli.gleam5
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/common/common_event_handler.gleam101
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/common/test_result.gleam119
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/common/test_suite.gleam63
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/erlang/discover.gleam167
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/erlang/event_handler.gleam91
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/erlang/module_handler.gleam43
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/erlang/runner.gleam59
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/reports/compare.gleam42
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/reports/formatter.gleam480
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/reports/styles.gleam84
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/internal/reports/table.gleam148
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/tests/meta.gleam3
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/tests/should.gleam113
-rw-r--r--aoc2023/build/packages/adglent/src/showtime/tests/test.gleam57
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@common@cli.erl8
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@common@common_event_handler.erl131
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@common@test_result.erl54
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@common@test_suite.erl30
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@erlang@discover.erl230
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@erlang@event_handler.erl76
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@erlang@module_handler.erl53
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@erlang@runner.erl46
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@reports@compare.erl61
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@reports@formatter.erl749
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@reports@styles.erl93
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@internal@reports@table.erl229
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@tests@meta.erl8
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@tests@should.erl143
-rw-r--r--aoc2023/build/packages/adglent/src/showtime@tests@test.erl57
-rw-r--r--aoc2023/build/packages/adglent/src/showtime_ffi.erl187
-rw-r--r--aoc2023/build/packages/gap/LICENSE201
-rw-r--r--aoc2023/build/packages/gap/README.md202
-rw-r--r--aoc2023/build/packages/gap/gleam.toml18
-rw-r--r--aoc2023/build/packages/gap/include/gap@comparison_ListComparison.hrl4
-rw-r--r--aoc2023/build/packages/gap/include/gap@comparison_Match.hrl1
-rw-r--r--aoc2023/build/packages/gap/include/gap@comparison_NoMatch.hrl1
-rw-r--r--aoc2023/build/packages/gap/include/gap@comparison_StringComparison.hrl4
-rw-r--r--aoc2023/build/packages/gap/include/gap@styled_comparison_StyledComparison.hrl1
-rw-r--r--aoc2023/build/packages/gap/include/gap@styling_All.hrl1
-rw-r--r--aoc2023/build/packages/gap/include/gap@styling_Highlighters.hrl5
-rw-r--r--aoc2023/build/packages/gap/include/gap@styling_Part.hrl5
-rw-r--r--aoc2023/build/packages/gap/include/gap@styling_Styling.hrl5
-rw-r--r--aoc2023/build/packages/gap/src/gap.app.src13
-rw-r--r--aoc2023/build/packages/gap/src/gap.erl538
-rw-r--r--aoc2023/build/packages/gap/src/gap.gleam438
-rw-r--r--aoc2023/build/packages/gap/src/gap/comparison.gleam22
-rw-r--r--aoc2023/build/packages/gap/src/gap/myers.gleam122
-rw-r--r--aoc2023/build/packages/gap/src/gap/styled_comparison.gleam4
-rw-r--r--aoc2023/build/packages/gap/src/gap/styling.gleam233
-rw-r--r--aoc2023/build/packages/gap/src/gap@comparison.erl15
-rw-r--r--aoc2023/build/packages/gap/src/gap@myers.erl156
-rw-r--r--aoc2023/build/packages/gap/src/gap@styled_comparison.erl8
-rw-r--r--aoc2023/build/packages/gap/src/gap@styling.erl202
-rw-r--r--aoc2023/build/packages/gap/src/gap_ffi.mjs431
-rw-r--r--aoc2023/build/packages/gleam.lock0
-rw-r--r--aoc2023/build/packages/gleam_community_ansi/LICENCE190
-rw-r--r--aoc2023/build/packages/gleam_community_ansi/README.md72
-rw-r--r--aoc2023/build/packages/gleam_community_ansi/gleam.toml13
-rw-r--r--aoc2023/build/packages/gleam_community_ansi/src/gleam_community/ansi.gleam2317
-rw-r--r--aoc2023/build/packages/gleam_community_ansi/src/gleam_community@ansi.erl263
-rw-r--r--aoc2023/build/packages/gleam_community_ansi/src/gleam_community_ansi.app.src9
-rw-r--r--aoc2023/build/packages/gleam_community_colour/LICENCE190
-rw-r--r--aoc2023/build/packages/gleam_community_colour/README.md36
-rw-r--r--aoc2023/build/packages/gleam_community_colour/gleam.toml11
-rw-r--r--aoc2023/build/packages/gleam_community_colour/include/gleam_community@colour_Hsla.hrl1
-rw-r--r--aoc2023/build/packages/gleam_community_colour/include/gleam_community@colour_Rgba.hrl1
-rw-r--r--aoc2023/build/packages/gleam_community_colour/src/gleam_community/colour.gleam1126
-rw-r--r--aoc2023/build/packages/gleam_community_colour/src/gleam_community/colour/accessibility.gleam173
-rw-r--r--aoc2023/build/packages/gleam_community_colour/src/gleam_community@colour.erl511
-rw-r--r--aoc2023/build/packages/gleam_community_colour/src/gleam_community@colour@accessibility.erl73
-rw-r--r--aoc2023/build/packages/gleam_community_colour/src/gleam_community_colour.app.src9
-rw-r--r--aoc2023/build/packages/gleam_community_maths/LICENCE190
-rw-r--r--aoc2023/build/packages/gleam_community_maths/README.md59
-rw-r--r--aoc2023/build/packages/gleam_community_maths/gleam.toml12
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/arithmetics.gleam618
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/combinatorics.gleam432
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/conversion.gleam183
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/elementary.gleam1256
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/metrics.gleam560
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/piecewise.gleam1228
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/predicates.gleam363
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/sequences.gleam302
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/special.gleam205
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@arithmetics.erl172
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@combinatorics.erl218
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@conversion.erl23
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@elementary.erl284
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@metrics.erl278
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@piecewise.erl553
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@predicates.erl118
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@sequences.erl199
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@special.erl157
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/gleam_community_maths.app.src16
-rw-r--r--aoc2023/build/packages/gleam_community_maths/src/maths.mjs95
-rw-r--r--aoc2023/build/packages/gleam_erlang/LICENSE191
-rw-r--r--aoc2023/build/packages/gleam_erlang/README.md37
-rw-r--r--aoc2023/build/packages/gleam_erlang/gleam.toml18
-rw-r--r--aoc2023/build/packages/gleam_erlang/include/gleam@erlang@file_FileInfo.hrl15
-rw-r--r--aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Abnormal.hrl1
-rw-r--r--aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_CalleeDown.hrl1
-rw-r--r--aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Cancelled.hrl1
-rw-r--r--aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ExitMessage.hrl4
-rw-r--r--aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ProcessDown.hrl4
-rw-r--r--aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_ProcessMonitor.hrl1
-rw-r--r--aoc2023/build/packages/gleam_erlang/include/gleam@erlang@process_Subject.hrl4
-rw-r--r--aoc2023/build/packages/gleam_erlang/include/gleam@erlang_ApplicationFailedToStart.hrl4
-rw-r--r--aoc2023/build/packages/gleam_erlang/include/gleam@erlang_UnknownApplication.hrl1
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam/erlang.gleam158
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam/erlang/atom.gleam79
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam/erlang/charlist.gleam25
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam/erlang/file.gleam737
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam/erlang/node.gleam62
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam/erlang/os.gleam95
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam/erlang/process.gleam744
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam@erlang.erl90
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam@erlang@atom.erl26
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam@erlang@charlist.erl15
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam@erlang@file.erl190
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam@erlang@node.erl33
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam@erlang@os.erl27
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam@erlang@process.erl374
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam_erlang.app.src14
-rw-r--r--aoc2023/build/packages/gleam_erlang/src/gleam_erlang_ffi.erl263
-rw-r--r--aoc2023/build/packages/gleam_http/LICENSE191
-rw-r--r--aoc2023/build/packages/gleam_http/README.md67
-rw-r--r--aoc2023/build/packages/gleam_http/gleam.toml17
-rw-r--r--aoc2023/build/packages/gleam_http/include/gleam@http@cookie_Attributes.hrl8
-rw-r--r--aoc2023/build/packages/gleam_http/include/gleam@http@request_Request.hrl10
-rw-r--r--aoc2023/build/packages/gleam_http/include/gleam@http@response_Response.hrl5
-rw-r--r--aoc2023/build/packages/gleam_http/include/gleam@http_MoreRequiredForBody.hrl5
-rw-r--r--aoc2023/build/packages/gleam_http/include/gleam@http_MoreRequiredForHeaders.hrl4
-rw-r--r--aoc2023/build/packages/gleam_http/include/gleam@http_MultipartBody.hrl5
-rw-r--r--aoc2023/build/packages/gleam_http/include/gleam@http_MultipartHeaders.hrl4
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam/http.gleam560
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam/http/cookie.gleam128
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam/http/request.gleam267
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam/http/response.gleam141
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam/http/service.gleam82
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam@http.erl626
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam@http@cookie.erl153
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam@http@request.erl202
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam@http@response.erl97
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam@http@service.erl82
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam_http.app.src12
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam_http_native.erl88
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam_http_native.mjs38
-rw-r--r--aoc2023/build/packages/gleam_httpc/LICENSE191
-rw-r--r--aoc2023/build/packages/gleam_httpc/README.md52
-rw-r--r--aoc2023/build/packages/gleam_httpc/gleam.toml23
-rw-r--r--aoc2023/build/packages/gleam_httpc/src/gleam/httpc.gleam105
-rw-r--r--aoc2023/build/packages/gleam_httpc/src/gleam@httpc.erl118
-rw-r--r--aoc2023/build/packages/gleam_httpc/src/gleam_httpc.app.src12
-rw-r--r--aoc2023/build/packages/gleam_otp/LICENCE191
-rw-r--r--aoc2023/build/packages/gleam_otp/README.md91
-rw-r--r--aoc2023/build/packages/gleam_otp/gleam.toml19
-rw-r--r--aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Continue.hrl4
-rw-r--r--aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Ready.hrl1
-rw-r--r--aoc2023/build/packages/gleam_otp/include/gleam@otp@actor_Spec.hrl5
-rw-r--r--aoc2023/build/packages/gleam_otp/include/gleam@otp@intensity_tracker_IntensityTracker.hrl5
-rw-r--r--aoc2023/build/packages/gleam_otp/include/gleam@otp@supervisor_ChildSpec.hrl5
-rw-r--r--aoc2023/build/packages/gleam_otp/include/gleam@otp@supervisor_Spec.hrl6
-rw-r--r--aoc2023/build/packages/gleam_otp/include/gleam@otp@system_StatusInfo.hrl7
-rw-r--r--aoc2023/build/packages/gleam_otp/include/gleam@otp@task_Exit.hrl1
-rw-r--r--aoc2023/build/packages/gleam_otp/include/gleam@otp@task_Task.hrl6
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam/otp/actor.gleam504
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam/otp/intensity_tracker.gleam46
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam/otp/port.gleam9
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam/otp/supervisor.gleam410
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam/otp/system.gleam89
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam/otp/task.gleam151
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam@otp@actor.erl273
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam@otp@intensity_tracker.erl53
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam@otp@port.erl8
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam@otp@supervisor.erl322
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam@otp@system.erl43
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam@otp@task.erl111
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam_otp.app.src15
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam_otp.erl28
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam_otp.gleam27
-rw-r--r--aoc2023/build/packages/gleam_otp/src/gleam_otp_external.erl43
-rw-r--r--aoc2023/build/packages/gleam_stdlib/LICENCE191
-rw-r--r--aoc2023/build/packages/gleam_stdlib/README.md39
-rw-r--r--aoc2023/build/packages/gleam_stdlib/gleam.toml16
-rw-r--r--aoc2023/build/packages/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl5
-rw-r--r--aoc2023/build/packages/gleam_stdlib/include/gleam@iterator_Iterator.hrl1
-rw-r--r--aoc2023/build/packages/gleam_stdlib/include/gleam@iterator_Next.hrl1
-rw-r--r--aoc2023/build/packages/gleam_stdlib/include/gleam@queue_Queue.hrl1
-rw-r--r--aoc2023/build/packages/gleam_stdlib/include/gleam@regex_CompileError.hrl1
-rw-r--r--aoc2023/build/packages/gleam_stdlib/include/gleam@regex_Match.hrl4
-rw-r--r--aoc2023/build/packages/gleam_stdlib/include/gleam@regex_Options.hrl1
-rw-r--r--aoc2023/build/packages/gleam_stdlib/include/gleam@set_Set.hrl1
-rw-r--r--aoc2023/build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl9
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/dict.mjs957
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/base.gleam21
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/bit_array.gleam157
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/bit_builder.gleam80
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/bit_string.gleam43
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/bool.gleam428
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/bytes_builder.gleam197
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/dict.gleam544
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/dynamic.gleam1508
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/float.gleam546
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/function.gleam162
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/int.gleam874
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/io.gleam117
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/iterator.gleam1530
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/list.gleam2154
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/map.gleam127
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/option.gleam346
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/order.gleam133
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/pair.gleam85
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/queue.gleam292
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/regex.gleam214
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/result.gleam482
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/set.gleam264
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/string.gleam906
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/string_builder.gleam298
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam/uri.gleam462
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@base.erl20
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@bit_array.erl102
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@bit_builder.erl66
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@bit_string.erl33
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@bool.erl162
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@bytes_builder.erl87
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@dict.erl97
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@dynamic.erl808
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@float.erl181
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@function.erl67
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@int.erl332
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@io.erl27
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@iterator.erl744
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@list.erl1129
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@map.erl76
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@option.erl147
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@order.erl79
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@pair.erl33
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@queue.erl121
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@regex.erl33
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@result.erl201
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@set.erl85
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@string.erl352
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@string_builder.erl91
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam@uri.erl252
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.app.src31
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.erl529
-rw-r--r--aoc2023/build/packages/gleam_stdlib/src/gleam_stdlib.mjs875
-rw-r--r--aoc2023/build/packages/glint/LICENSE201
-rw-r--r--aoc2023/build/packages/glint/README.md104
-rw-r--r--aoc2023/build/packages/glint/gleam.toml23
-rw-r--r--aoc2023/build/packages/glint/include/glint@flag_Flag.hrl1
-rw-r--r--aoc2023/build/packages/glint/include/glint@flag_FlagBuilder.hrl6
-rw-r--r--aoc2023/build/packages/glint/include/glint@flag_Internal.hrl4
-rw-r--r--aoc2023/build/packages/glint/include/glint_Command.hrl5
-rw-r--r--aoc2023/build/packages/glint/include/glint_CommandInput.hrl4
-rw-r--r--aoc2023/build/packages/glint/include/glint_Config.hrl4
-rw-r--r--aoc2023/build/packages/glint/include/glint_Glint.hrl5
-rw-r--r--aoc2023/build/packages/glint/include/glint_PrettyHelp.hrl5
-rw-r--r--aoc2023/build/packages/glint/include/glint_Stub.hrl6
-rw-r--r--aoc2023/build/packages/glint/src/glint.app.src13
-rw-r--r--aoc2023/build/packages/glint/src/glint.erl513
-rw-r--r--aoc2023/build/packages/glint/src/glint.gleam588
-rw-r--r--aoc2023/build/packages/glint/src/glint/flag.gleam478
-rw-r--r--aoc2023/build/packages/glint/src/glint/flag/constraint.gleam66
-rw-r--r--aoc2023/build/packages/glint/src/glint@flag.erl523
-rw-r--r--aoc2023/build/packages/glint/src/glint@flag@constraint.erl68
-rw-r--r--aoc2023/build/packages/packages.toml16
-rw-r--r--aoc2023/build/packages/pqueue/LICENSE21
-rw-r--r--aoc2023/build/packages/pqueue/README.markdown31
-rw-r--r--aoc2023/build/packages/pqueue/doc/edoc-info3
-rw-r--r--aoc2023/build/packages/pqueue/doc/erlang.pngbin0 -> 2109 bytes
-rw-r--r--aoc2023/build/packages/pqueue/doc/index.html17
-rw-r--r--aoc2023/build/packages/pqueue/doc/modules-frame.html15
-rw-r--r--aoc2023/build/packages/pqueue/doc/overview-summary.html16
-rw-r--r--aoc2023/build/packages/pqueue/doc/pqueue.html166
-rw-r--r--aoc2023/build/packages/pqueue/doc/pqueue2.html143
-rw-r--r--aoc2023/build/packages/pqueue/doc/pqueue3.html162
-rw-r--r--aoc2023/build/packages/pqueue/doc/pqueue4.html205
-rw-r--r--aoc2023/build/packages/pqueue/doc/stylesheet.css55
-rw-r--r--aoc2023/build/packages/pqueue/rebar.config14
-rw-r--r--aoc2023/build/packages/pqueue/src/pqueue.app.src10
-rw-r--r--aoc2023/build/packages/pqueue/src/pqueue.erl2246
-rw-r--r--aoc2023/build/packages/pqueue/src/pqueue2.erl483
-rw-r--r--aoc2023/build/packages/pqueue/src/pqueue3.erl404
-rw-r--r--aoc2023/build/packages/pqueue/src/pqueue4.erl11662
-rw-r--r--aoc2023/build/packages/pqueue/src/pqueue_test.hrl49
-rw-r--r--aoc2023/build/packages/pqueue/test/pqueue_proper.erl156
-rw-r--r--aoc2023/build/packages/pqueue/test/queue_srv.erl183
-rw-r--r--aoc2023/build/packages/simplifile/README.md29
-rw-r--r--aoc2023/build/packages/simplifile/gleam.toml17
-rw-r--r--aoc2023/build/packages/simplifile/src/simplifile.app.src8
-rw-r--r--aoc2023/build/packages/simplifile/src/simplifile.erl287
-rw-r--r--aoc2023/build/packages/simplifile/src/simplifile.gleam580
-rw-r--r--aoc2023/build/packages/simplifile/src/simplifile_erl.erl70
-rw-r--r--aoc2023/build/packages/simplifile/src/simplifile_js.mjs102
-rw-r--r--aoc2023/build/packages/snag/LICENCE211
-rw-r--r--aoc2023/build/packages/snag/README.md81
-rw-r--r--aoc2023/build/packages/snag/gleam.toml16
-rw-r--r--aoc2023/build/packages/snag/include/snag_Snag.hrl1
-rw-r--r--aoc2023/build/packages/snag/src/snag.app.src8
-rw-r--r--aoc2023/build/packages/snag/src/snag.erl74
-rw-r--r--aoc2023/build/packages/snag/src/snag.gleam141
-rw-r--r--aoc2023/build/packages/tom/README.md47
-rw-r--r--aoc2023/build/packages/tom/build/dev/erlang/gleam.lock0
-rw-r--r--aoc2023/build/packages/tom/build/dev/javascript/gleam.lock0
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam.lock0
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cachebin0 -> 1301 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_metabin0 -> 52 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cachebin0 -> 5029 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_metabin0 -> 49 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cachebin0 -> 4262 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_metabin0 -> 84 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cachebin0 -> 2010 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_metabin0 -> 52 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cachebin0 -> 7169 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_metabin0 -> 48 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cachebin0 -> 6334 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_metabin0 -> 98 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cachebin0 -> 13535 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_metabin0 -> 49 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cachebin0 -> 49469 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_metabin0 -> 173 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cachebin0 -> 11186 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_metabin0 -> 48 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cachebin0 -> 5875 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cachebin0 -> 18302 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_metabin0 -> 67 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cachebin0 -> 2936 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_metabin0 -> 49 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cachebin0 -> 38550 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_metabin0 -> 141 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cachebin0 -> 46345 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_metabin0 -> 120 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cachebin0 -> 4817 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_metabin0 -> 67 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cachebin0 -> 7361 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cachebin0 -> 2807 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cachebin0 -> 1961 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_metabin0 -> 29 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cachebin0 -> 7180 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_metabin0 -> 47 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cachebin0 -> 6969 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_metabin0 -> 49 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cachebin0 -> 10461 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_metabin0 -> 47 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cachebin0 -> 6587 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_metabin0 -> 85 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cachebin0 -> 21925 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_metabin0 -> 136 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cachebin0 -> 10647 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_metabin0 -> 47 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cachebin0 -> 8334 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_metabin0 -> 132 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleam_version1
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit.cachebin0 -> 3564 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit.cache_metabin0 -> 108 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cachebin0 -> 1212 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache_metabin0 -> 49 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/tom/_gleam_artefacts/tom.cachebin0 -> 33323 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/erlang/tom/_gleam_artefacts/tom.cache_metabin0 -> 140 bytes
-rw-r--r--aoc2023/build/packages/tom/build/lsp/javascript/gleam.lock0
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam.lock0
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/LICENCE191
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/README.md39
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/gleam.toml16
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@dynamic_DecodeError.hrl5
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@iterator_Iterator.hrl1
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@iterator_Next.hrl1
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@queue_Queue.hrl1
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_CompileError.hrl1
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_Match.hrl4
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@regex_Options.hrl1
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@set_Set.hrl1
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/include/gleam@uri_Uri.hrl9
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/dict.mjs957
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/base.gleam21
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_array.gleam157
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_builder.gleam80
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bit_string.gleam43
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bool.gleam428
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/bytes_builder.gleam197
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/dict.gleam493
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/dynamic.gleam1520
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/float.gleam541
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/function.gleam162
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/int.gleam886
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/io.gleam117
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/iterator.gleam1524
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/list.gleam2134
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/map.gleam107
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/option.gleam346
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/order.gleam133
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/pair.gleam85
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/queue.gleam292
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/regex.gleam214
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/result.gleam482
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/set.gleam262
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/string.gleam905
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/string_builder.gleam298
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam/uri.gleam462
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@base.erl20
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_array.erl102
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_builder.erl66
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bit_string.erl33
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bool.erl162
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@bytes_builder.erl87
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@dict.erl171
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@dynamic.erl808
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@float.erl181
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@function.erl67
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@int.erl332
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@io.erl27
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@iterator.erl744
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@list.erl1136
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@map.erl76
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@option.erl147
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@order.erl79
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@pair.erl33
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@queue.erl121
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@regex.erl33
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@result.erl201
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@set.erl85
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@string.erl352
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@string_builder.erl91
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam@uri.erl252
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.app.src31
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.erl529
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleam_stdlib/src/gleam_stdlib.mjs878
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleeunit/LICENCE191
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleeunit/README.md52
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleeunit/gleam.toml17
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.app.src8
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.erl59
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit.gleam92
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit/should.gleam65
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit@should.erl34
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_ffi.erl24
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_ffi.mjs101
-rw-r--r--aoc2023/build/packages/tom/build/packages/gleeunit/src/gleeunit_progress.erl607
-rw-r--r--aoc2023/build/packages/tom/build/packages/packages.toml3
-rw-r--r--aoc2023/build/packages/tom/build/prod/erlang/gleam.lock0
-rw-r--r--aoc2023/build/packages/tom/build/prod/javascript/gleam.lock0
-rw-r--r--aoc2023/build/packages/tom/gleam.toml13
-rw-r--r--aoc2023/build/packages/tom/include/tom_DateTimeValue.hrl5
-rw-r--r--aoc2023/build/packages/tom/include/tom_DateValue.hrl1
-rw-r--r--aoc2023/build/packages/tom/include/tom_KeyAlreadyInUse.hrl1
-rw-r--r--aoc2023/build/packages/tom/include/tom_NotFound.hrl1
-rw-r--r--aoc2023/build/packages/tom/include/tom_Offset.hrl5
-rw-r--r--aoc2023/build/packages/tom/include/tom_TimeValue.hrl6
-rw-r--r--aoc2023/build/packages/tom/include/tom_Unexpected.hrl1
-rw-r--r--aoc2023/build/packages/tom/include/tom_WrongType.hrl5
-rw-r--r--aoc2023/build/packages/tom/manifest.toml11
-rw-r--r--aoc2023/build/packages/tom/src/tom.app.src8
-rw-r--r--aoc2023/build/packages/tom/src/tom.erl2140
-rw-r--r--aoc2023/build/packages/tom/src/tom.gleam1317
-rw-r--r--aoc2023/build/prod/erlang/gleam.lock0
-rw-r--r--aoc2023/build/prod/javascript/gleam.lock0
-rw-r--r--aoc2023/src/day1/input.txt1000
-rw-r--r--aoc2023/src/day12/input.txt1000
-rw-r--r--aoc2023/src/day14/input.txt100
-rw-r--r--aoc2023/src/day17/input.txt141
-rw-r--r--aoc2023/src/day2/input.txt100
-rw-r--r--aoc2023/src/day20/input.txt58
-rw-r--r--aoc2023/src/day22/input.txt1273
-rw-r--r--aoc2023/src/day23/input.txt141
-rw-r--r--aoc2023/src/day3/input.txt140
-rw-r--r--aoc2023/src/day4/input.txt203
-rw-r--r--aoc2023/src/day5/input.txt223
-rw-r--r--aoc2023/src/day7/input.txt1000
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
new file mode 100644
index 0000000..f44ba7b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cache
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cache_meta
new file mode 100644
index 0000000..0af4a84
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..be237c1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.cache
Binary files differ
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
new file mode 100644
index 0000000..1637f81
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@day.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..798878b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.cache
Binary files differ
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
new file mode 100644
index 0000000..2751b68
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/adglent@init.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..e87188f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.cache
Binary files differ
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
new file mode 100644
index 0000000..b6c1617
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@aoc_client.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..3ea27a4
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.cache
Binary files differ
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
new file mode 100644
index 0000000..498e302
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@errors.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..6d858d1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.cache
Binary files differ
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
new file mode 100644
index 0000000..b010daf
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@prompt.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1df1c9d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.cache
Binary files differ
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
new file mode 100644
index 0000000..5e1f919
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@template.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..3f12af2
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.cache
Binary files differ
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
new file mode 100644
index 0000000..3397840
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@solution.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..3ca29d0
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.cache
Binary files differ
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
new file mode 100644
index 0000000..17c867f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@test_main.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..22f49a5
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.cache
Binary files differ
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
new file mode 100644
index 0000000..c996833
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_gleeunit.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..5dc9daa
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.cache
Binary files differ
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
new file mode 100644
index 0000000..120c91f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@templates@testfile_showtime.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..0e5b549
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.cache
Binary files differ
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
new file mode 100644
index 0000000..a423083
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/priv@toml.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..a93f0d6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cache
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cache_meta b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cache_meta
new file mode 100644
index 0000000..96a5705
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..2fd016f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.cache
Binary files differ
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
new file mode 100644
index 0000000..4c3ebd3
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@cli.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..af5456d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.cache
Binary files differ
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
new file mode 100644
index 0000000..cea0c4b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@common_event_handler.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..d460b8c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.cache
Binary files differ
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
new file mode 100644
index 0000000..ae0cd95
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_result.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..054b4d1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.cache
Binary files differ
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
new file mode 100644
index 0000000..b2139f9
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@common@test_suite.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..5a8fdad
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.cache
Binary files differ
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
new file mode 100644
index 0000000..236dd39
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@discover.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..e21ee6b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.cache
Binary files differ
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
new file mode 100644
index 0000000..1223c48
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@event_handler.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..39bc91c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.cache
Binary files differ
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
new file mode 100644
index 0000000..7cd0c75
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@module_handler.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..8251097
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.cache
Binary files differ
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
new file mode 100644
index 0000000..069c9cf
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@erlang@runner.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..8fd4424
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.cache
Binary files differ
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
new file mode 100644
index 0000000..be99189
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@compare.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..69a4738
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.cache
Binary files differ
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
new file mode 100644
index 0000000..86e3c59
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@formatter.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f974100
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.cache
Binary files differ
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
new file mode 100644
index 0000000..c0078b3
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@styles.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..86c39cb
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.cache
Binary files differ
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
new file mode 100644
index 0000000..080524c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@internal@reports@table.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..d9b2000
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.cache
Binary files differ
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
new file mode 100644
index 0000000..7f1bdda
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@meta.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1adcc9d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.cache
Binary files differ
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
new file mode 100644
index 0000000..fcc4e8a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@should.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..06be22a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.cache
Binary files differ
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
new file mode 100644
index 0000000..8354c6f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/_gleam_artefacts/showtime@tests@test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..aad1d26
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/adglent.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/adglent@day.beam b/aoc2023/build/dev/erlang/adglent/ebin/adglent@day.beam
new file mode 100644
index 0000000..b7c03ed
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/adglent@day.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/adglent@init.beam b/aoc2023/build/dev/erlang/adglent/ebin/adglent@init.beam
new file mode 100644
index 0000000..be1eae9
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/adglent@init.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/adglent_ffi.beam b/aoc2023/build/dev/erlang/adglent/ebin/adglent_ffi.beam
new file mode 100644
index 0000000..1c75150
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/adglent_ffi.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@aoc_client.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@aoc_client.beam
new file mode 100644
index 0000000..85aa9ae
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@aoc_client.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@errors.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@errors.beam
new file mode 100644
index 0000000..c8778d1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@errors.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@prompt.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@prompt.beam
new file mode 100644
index 0000000..0228df2
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@prompt.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@template.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@template.beam
new file mode 100644
index 0000000..4a3c938
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@template.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@solution.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@solution.beam
new file mode 100644
index 0000000..aaf50f6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@solution.beam
Binary files differ
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
new file mode 100644
index 0000000..d214095
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@test_main.beam
Binary files differ
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
new file mode 100644
index 0000000..7dc47b7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@testfile_gleeunit.beam
Binary files differ
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
new file mode 100644
index 0000000..3667f53
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@templates@testfile_showtime.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/priv@toml.beam b/aoc2023/build/dev/erlang/adglent/ebin/priv@toml.beam
new file mode 100644
index 0000000..ce828c9
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/priv@toml.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime.beam
new file mode 100644
index 0000000..c1d19b2
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime.beam
Binary files differ
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
new file mode 100644
index 0000000..dec1bcc
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@cli.beam
Binary files differ
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
new file mode 100644
index 0000000..50fe885
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@common_event_handler.beam
Binary files differ
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
new file mode 100644
index 0000000..277fdd1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@test_result.beam
Binary files differ
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
new file mode 100644
index 0000000..42dbbb9
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@common@test_suite.beam
Binary files differ
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
new file mode 100644
index 0000000..9f5d14e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@discover.beam
Binary files differ
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
new file mode 100644
index 0000000..c9a64e1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@event_handler.beam
Binary files differ
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
new file mode 100644
index 0000000..6b95d6c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@module_handler.beam
Binary files differ
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
new file mode 100644
index 0000000..0681641
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@erlang@runner.beam
Binary files differ
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
new file mode 100644
index 0000000..cfe37b1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@compare.beam
Binary files differ
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
new file mode 100644
index 0000000..46b885b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@formatter.beam
Binary files differ
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
new file mode 100644
index 0000000..4fb83b7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@styles.beam
Binary files differ
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
new file mode 100644
index 0000000..aaeb33c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@internal@reports@table.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@meta.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@meta.beam
new file mode 100644
index 0000000..ffaff22
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@meta.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@should.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@should.beam
new file mode 100644
index 0000000..a87184d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@should.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@test.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@test.beam
new file mode 100644
index 0000000..65f2a87
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime@tests@test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/adglent/ebin/showtime_ffi.beam b/aoc2023/build/dev/erlang/adglent/ebin/showtime_ffi.beam
new file mode 100644
index 0000000..982e813
--- /dev/null
+++ b/aoc2023/build/dev/erlang/adglent/ebin/showtime_ffi.beam
Binary files differ
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
new file mode 100644
index 0000000..de3d10c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cache
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cache_meta b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cache_meta
new file mode 100644
index 0000000..29c7ca9
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..105c4ea
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.cache
Binary files differ
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
new file mode 100644
index 0000000..6612dba
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/aoc2023_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..72b188e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.cache
Binary files differ
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
new file mode 100644
index 0000000..eba5ba6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@day10_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..633f740
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..5c3181a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day10@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..508a46b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.cache
Binary files differ
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
new file mode 100644
index 0000000..e03372f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@day11_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..64f1e54
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..0ff3073
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day11@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..849fca3
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.cache
Binary files differ
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
new file mode 100644
index 0000000..51c4010
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@day12_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f0476d1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..d8f9228
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day12@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..5ea210b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.cache
Binary files differ
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
new file mode 100644
index 0000000..034e2de
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@day13_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..0d31dbe
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..ee31fa5
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day13@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..cb5c2df
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.cache
Binary files differ
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
new file mode 100644
index 0000000..af65466
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@day14_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..2bceb68
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..f6a8981
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day14@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..ebef31b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.cache
Binary files differ
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
new file mode 100644
index 0000000..2b2eed1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@day15_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..5f19cbb
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..9fc44a6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day15@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..a8d21d6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.cache
Binary files differ
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
new file mode 100644
index 0000000..7defae5
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@day16_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..35182e1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..70fdb71
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day16@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..923d0a6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.cache
Binary files differ
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
new file mode 100644
index 0000000..1c9c12b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@day17_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..b06fb02
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..aad0cb3
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day17@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..33f80d2
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.cache
Binary files differ
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
new file mode 100644
index 0000000..22ffeb7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@day18_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..c557ff7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..a536e04
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day18@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..32c0bad
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.cache
Binary files differ
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
new file mode 100644
index 0000000..56332b7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@day19_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..45dad16
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..8e99d6a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day19@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..77a1d03
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.cache
Binary files differ
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
new file mode 100644
index 0000000..da0b837
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@day1_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..a1932c5
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..b3e1773
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day1@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7571e58
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.cache
Binary files differ
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
new file mode 100644
index 0000000..74efc1e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@day20_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..a8d7071
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..a6f2f83
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day20@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7eec8c7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.cache
Binary files differ
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
new file mode 100644
index 0000000..10d8749
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@day21_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..eb2a3e9
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..d810856
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day21@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..48b46ff
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.cache
Binary files differ
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
new file mode 100644
index 0000000..c0c6c8a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@day22_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..6fb1a11
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..2a4dc01
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day22@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..3a1c3d1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.cache
Binary files differ
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
new file mode 100644
index 0000000..128bc18
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@day23_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..55cbb25
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..925bbea
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day23@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..60923b3
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.cache
Binary files differ
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
new file mode 100644
index 0000000..6e09c6a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@day2_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f550ee3
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..b39c267
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day2@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..49b0c33
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.cache
Binary files differ
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
new file mode 100644
index 0000000..a5246d6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@day3_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7024510
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..8b7792a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day3@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..4c2e06a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.cache
Binary files differ
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
new file mode 100644
index 0000000..98d2944
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@day4_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..af204ff
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..1db4b46
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day4@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..07488c8
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.cache
Binary files differ
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
new file mode 100644
index 0000000..0ca1b7d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@day5_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..22ec6e4
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..2e8355d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day5@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1b29ca0
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.cache
Binary files differ
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
new file mode 100644
index 0000000..6ae533d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@day6_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..2a735ee
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..e1a7797
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day6@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..d4830bb
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.cache
Binary files differ
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
new file mode 100644
index 0000000..f63dc34
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@day7_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..9d72fb4
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..ff45788
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day7@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..3d89b8b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.cache
Binary files differ
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
new file mode 100644
index 0000000..4082d33
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@day8_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..a03967b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..4389637
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day8@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..32b4cd1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.cache
Binary files differ
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
new file mode 100644
index 0000000..6e5f636
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@day9_test.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..afd006e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.cache
Binary files differ
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
new file mode 100644
index 0000000..7875518
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/day9@solve.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..44f142d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.cache
Binary files differ
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
new file mode 100644
index 0000000..cd522ba
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@array2d.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..204b330
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.cache
Binary files differ
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
new file mode 100644
index 0000000..4253e7c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@memo.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f013f33
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.cache
Binary files differ
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
new file mode 100644
index 0000000..84048ca
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/_gleam_artefacts/utilities@prioqueue.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7fe2a91
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023@@main.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023@@main.beam
new file mode 100644
index 0000000..9e35237
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023@@main.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023_test.beam
new file mode 100644
index 0000000..7fac74c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/aoc2023_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day10@day10_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day10@day10_test.beam
new file mode 100644
index 0000000..0fe1fd6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day10@day10_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day10@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day10@solve.beam
new file mode 100644
index 0000000..5028a72
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day10@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day11@day11_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day11@day11_test.beam
new file mode 100644
index 0000000..3e5c47d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day11@day11_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day11@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day11@solve.beam
new file mode 100644
index 0000000..ac8563e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day11@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day12@day12_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day12@day12_test.beam
new file mode 100644
index 0000000..a98331a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day12@day12_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day12@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day12@solve.beam
new file mode 100644
index 0000000..87869e4
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day12@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day13@day13_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day13@day13_test.beam
new file mode 100644
index 0000000..b194d26
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day13@day13_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day13@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day13@solve.beam
new file mode 100644
index 0000000..38974ae
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day13@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day14@day14_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day14@day14_test.beam
new file mode 100644
index 0000000..2b4629d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day14@day14_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day14@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day14@solve.beam
new file mode 100644
index 0000000..aa76b4f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day14@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day15@day15_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day15@day15_test.beam
new file mode 100644
index 0000000..29aba3b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day15@day15_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day15@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day15@solve.beam
new file mode 100644
index 0000000..d3a892e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day15@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day16@day16_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day16@day16_test.beam
new file mode 100644
index 0000000..785aee1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day16@day16_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day16@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day16@solve.beam
new file mode 100644
index 0000000..b85d427
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day16@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day17@day17_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day17@day17_test.beam
new file mode 100644
index 0000000..973225d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day17@day17_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day17@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day17@solve.beam
new file mode 100644
index 0000000..770b87b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day17@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day18@day18_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day18@day18_test.beam
new file mode 100644
index 0000000..d4668d8
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day18@day18_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day18@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day18@solve.beam
new file mode 100644
index 0000000..1559a28
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day18@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day19@day19_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day19@day19_test.beam
new file mode 100644
index 0000000..b4b142b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day19@day19_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day19@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day19@solve.beam
new file mode 100644
index 0000000..429a9c3
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day19@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day1@day1_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day1@day1_test.beam
new file mode 100644
index 0000000..cc5cc2e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day1@day1_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day1@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day1@solve.beam
new file mode 100644
index 0000000..21582eb
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day1@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day20@day20_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day20@day20_test.beam
new file mode 100644
index 0000000..69c5a85
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day20@day20_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day20@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day20@solve.beam
new file mode 100644
index 0000000..2d186df
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day20@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day21@day21_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day21@day21_test.beam
new file mode 100644
index 0000000..dcd764a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day21@day21_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day21@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day21@solve.beam
new file mode 100644
index 0000000..34bfb6f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day21@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day22@day22_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day22@day22_test.beam
new file mode 100644
index 0000000..511b695
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day22@day22_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day22@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day22@solve.beam
new file mode 100644
index 0000000..dd15c2a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day22@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day23@day23_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day23@day23_test.beam
new file mode 100644
index 0000000..fd46989
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day23@day23_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day23@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day23@solve.beam
new file mode 100644
index 0000000..d1c426f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day23@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day2@day2_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day2@day2_test.beam
new file mode 100644
index 0000000..96a97fc
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day2@day2_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day2@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day2@solve.beam
new file mode 100644
index 0000000..592a360
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day2@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day3@day3_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day3@day3_test.beam
new file mode 100644
index 0000000..12d57d1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day3@day3_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day3@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day3@solve.beam
new file mode 100644
index 0000000..9fa2011
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day3@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day4@day4_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day4@day4_test.beam
new file mode 100644
index 0000000..41d9854
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day4@day4_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day4@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day4@solve.beam
new file mode 100644
index 0000000..a8d5973
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day4@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day5@day5_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day5@day5_test.beam
new file mode 100644
index 0000000..a7e22e1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day5@day5_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day5@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day5@solve.beam
new file mode 100644
index 0000000..d248e2c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day5@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day6@day6_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day6@day6_test.beam
new file mode 100644
index 0000000..11a7360
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day6@day6_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day6@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day6@solve.beam
new file mode 100644
index 0000000..ddb5777
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day6@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day7@day7_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day7@day7_test.beam
new file mode 100644
index 0000000..c4586b8
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day7@day7_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day7@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day7@solve.beam
new file mode 100644
index 0000000..4ae1796
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day7@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day8@day8_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day8@day8_test.beam
new file mode 100644
index 0000000..68fa255
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day8@day8_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day8@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day8@solve.beam
new file mode 100644
index 0000000..d2d7689
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day8@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day9@day9_test.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day9@day9_test.beam
new file mode 100644
index 0000000..f12dde7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day9@day9_test.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/day9@solve.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/day9@solve.beam
new file mode 100644
index 0000000..4920ea7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/day9@solve.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@array2d.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@array2d.beam
new file mode 100644
index 0000000..f265230
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@array2d.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@memo.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@memo.beam
new file mode 100644
index 0000000..09a3274
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@memo.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@prioqueue.beam b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@prioqueue.beam
new file mode 100644
index 0000000..b95d0dd
--- /dev/null
+++ b/aoc2023/build/dev/erlang/aoc2023/ebin/utilities@prioqueue.beam
Binary files differ
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
new file mode 100644
index 0000000..772b42f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cache
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cache_meta b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cache_meta
new file mode 100644
index 0000000..3a247a0
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..90fe99a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.cache
Binary files differ
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
new file mode 100644
index 0000000..e3f3599
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@comparison.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1d21cfe
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.cache
Binary files differ
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
new file mode 100644
index 0000000..6d51dd1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@myers.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..d03c302
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.cache
Binary files differ
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
new file mode 100644
index 0000000..dc9ffd0
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styled_comparison.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..6fdaed1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.cache
Binary files differ
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
new file mode 100644
index 0000000..f580983
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/_gleam_artefacts/gap@styling.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..4eaf513
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/ebin/gap.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gap/ebin/gap@comparison.beam b/aoc2023/build/dev/erlang/gap/ebin/gap@comparison.beam
new file mode 100644
index 0000000..44091a1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/ebin/gap@comparison.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gap/ebin/gap@myers.beam b/aoc2023/build/dev/erlang/gap/ebin/gap@myers.beam
new file mode 100644
index 0000000..d118f3d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/ebin/gap@myers.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gap/ebin/gap@styled_comparison.beam b/aoc2023/build/dev/erlang/gap/ebin/gap@styled_comparison.beam
new file mode 100644
index 0000000..dfce198
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/ebin/gap@styled_comparison.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gap/ebin/gap@styling.beam b/aoc2023/build/dev/erlang/gap/ebin/gap@styling.beam
new file mode 100644
index 0000000..cf975af
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gap/ebin/gap@styling.beam
Binary files differ
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
new file mode 100644
index 0000000..1f67bd7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache
Binary files differ
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
new file mode 100644
index 0000000..a01f4e8
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..e94b760
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_ansi/ebin/gleam_community@ansi.beam
Binary files differ
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
new file mode 100644
index 0000000..c12620f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache
Binary files differ
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
new file mode 100644
index 0000000..3584f7e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..5c98611
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache
Binary files differ
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
new file mode 100644
index 0000000..0c78df4
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..008c06a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community@colour.beam
Binary files differ
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
new file mode 100644
index 0000000..15e491b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_colour/ebin/gleam_community@colour@accessibility.beam
Binary files differ
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
new file mode 100644
index 0000000..b683c40
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.cache
Binary files differ
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
new file mode 100644
index 0000000..23d4726
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@arithmetics.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..e95a3b0
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.cache
Binary files differ
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
new file mode 100644
index 0000000..f8262ee
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@combinatorics.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..6b3ed43
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.cache
Binary files differ
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
new file mode 100644
index 0000000..374a6fb
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@conversion.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..5dbff0c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.cache
Binary files differ
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
new file mode 100644
index 0000000..8a3590f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@elementary.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..6dc087d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.cache
Binary files differ
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
new file mode 100644
index 0000000..ad6a7f1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@metrics.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..d65054e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.cache
Binary files differ
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
new file mode 100644
index 0000000..21c97d4
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@piecewise.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..0ef2e9b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.cache
Binary files differ
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
new file mode 100644
index 0000000..549041c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@predicates.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..e06c185
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.cache
Binary files differ
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
new file mode 100644
index 0000000..3a025a2
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@sequences.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..0fdbab2
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.cache
Binary files differ
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
new file mode 100644
index 0000000..3c21994
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/_gleam_artefacts/gleam_community@maths@special.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7bdc600
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@arithmetics.beam
Binary files differ
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
new file mode 100644
index 0000000..f9cdc85
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@combinatorics.beam
Binary files differ
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
new file mode 100644
index 0000000..bc6d41e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@conversion.beam
Binary files differ
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
new file mode 100644
index 0000000..9850c86
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@elementary.beam
Binary files differ
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
new file mode 100644
index 0000000..513efde
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@metrics.beam
Binary files differ
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
new file mode 100644
index 0000000..652b871
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@piecewise.beam
Binary files differ
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
new file mode 100644
index 0000000..c6fa350
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@predicates.beam
Binary files differ
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
new file mode 100644
index 0000000..1039c56
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@sequences.beam
Binary files differ
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
new file mode 100644
index 0000000..21b9149
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_community_maths/ebin/gleam_community@maths@special.beam
Binary files differ
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
new file mode 100644
index 0000000..a136f2b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.cache
Binary files differ
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
new file mode 100644
index 0000000..12933b2
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..83a03cd
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache
Binary files differ
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
new file mode 100644
index 0000000..be33011
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..b4053cc
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache
Binary files differ
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
new file mode 100644
index 0000000..82cfdb5
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..b447be6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.cache
Binary files differ
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
new file mode 100644
index 0000000..1cb342b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@file.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..acd84e1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache
Binary files differ
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
new file mode 100644
index 0000000..085886a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..c7698fa
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.cache
Binary files differ
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
new file mode 100644
index 0000000..1d5fa83
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@os.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..bb95436
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache
Binary files differ
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
new file mode 100644
index 0000000..ad9209c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..9f714eb
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang.beam
Binary files differ
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
new file mode 100644
index 0000000..a85b4fa
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@atom.beam
Binary files differ
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
new file mode 100644
index 0000000..6d78db3
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@charlist.beam
Binary files differ
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
new file mode 100644
index 0000000..7990b72
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@file.beam
Binary files differ
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
new file mode 100644
index 0000000..d8ebb84
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@node.beam
Binary files differ
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
new file mode 100644
index 0000000..40d121a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@os.beam
Binary files differ
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
new file mode 100644
index 0000000..8a73d73
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam@erlang@process.beam
Binary files differ
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
new file mode 100644
index 0000000..965c70b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_erlang/ebin/gleam_erlang_ffi.beam
Binary files differ
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
new file mode 100644
index 0000000..5bba9de
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.cache
Binary files differ
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
new file mode 100644
index 0000000..dc85da7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..db0066c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.cache
Binary files differ
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
new file mode 100644
index 0000000..1f65dce
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@cookie.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..ea0a2f6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.cache
Binary files differ
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
new file mode 100644
index 0000000..2108b82
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@request.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..70474f1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.cache
Binary files differ
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
new file mode 100644
index 0000000..1f05041
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@response.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..3c1fcc1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.cache
Binary files differ
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
new file mode 100644
index 0000000..c0222d6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/_gleam_artefacts/gleam@http@service.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1d6dab6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http.beam
Binary files differ
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
new file mode 100644
index 0000000..0e9882c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@cookie.beam
Binary files differ
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
new file mode 100644
index 0000000..ef3cd15
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@request.beam
Binary files differ
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
new file mode 100644
index 0000000..a5a1f4c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@response.beam
Binary files differ
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
new file mode 100644
index 0000000..09e3162
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam@http@service.beam
Binary files differ
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
new file mode 100644
index 0000000..b69ece0
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_http/ebin/gleam_http_native.beam
Binary files differ
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
new file mode 100644
index 0000000..84e8417
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.cache
Binary files differ
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
new file mode 100644
index 0000000..a340156
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_httpc/_gleam_artefacts/gleam@httpc.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..d4f3782
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_httpc/ebin/gleam@httpc.beam
Binary files differ
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
new file mode 100644
index 0000000..df2a9bd
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.cache
Binary files differ
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
new file mode 100644
index 0000000..d5f2a3e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@actor.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..a2cc755
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.cache
Binary files differ
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
new file mode 100644
index 0000000..1997b5a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@intensity_tracker.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..a05f0e2
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.cache
Binary files differ
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
new file mode 100644
index 0000000..5f1cb59
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@port.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..2b4bef1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.cache
Binary files differ
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
new file mode 100644
index 0000000..f6f257e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@supervisor.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..c489047
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.cache
Binary files differ
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
new file mode 100644
index 0000000..9f64041
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@system.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..b71f5ea
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.cache
Binary files differ
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
new file mode 100644
index 0000000..e4f89cf
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam@otp@task.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..61dea2d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.cache
Binary files differ
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
new file mode 100644
index 0000000..6b7a3a8
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/_gleam_artefacts/gleam_otp.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7d3fd3e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@actor.beam
Binary files differ
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
new file mode 100644
index 0000000..da2acd0
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@intensity_tracker.beam
Binary files differ
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
new file mode 100644
index 0000000..a4a7340
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@port.beam
Binary files differ
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
new file mode 100644
index 0000000..181508d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@supervisor.beam
Binary files differ
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
new file mode 100644
index 0000000..30d4309
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@system.beam
Binary files differ
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
new file mode 100644
index 0000000..0f710a1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam@otp@task.beam
Binary files differ
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
new file mode 100644
index 0000000..47eb31e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp.beam
Binary files differ
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
new file mode 100644
index 0000000..5ffaafd
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_otp/ebin/gleam_otp_external.beam
Binary files differ
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
new file mode 100644
index 0000000..ec2f726
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache
Binary files differ
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
new file mode 100644
index 0000000..a935fcc
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1019a88
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache
Binary files differ
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
new file mode 100644
index 0000000..bfd3dd8
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..98cc7fa
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache
Binary files differ
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
new file mode 100644
index 0000000..bc4a1a5
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..04638ff
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache
Binary files differ
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
new file mode 100644
index 0000000..f9f229f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7ff9604
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache
Binary files differ
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
new file mode 100644
index 0000000..33ef24c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..2564637
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache
Binary files differ
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
new file mode 100644
index 0000000..7b614aa
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..2aa2fe6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache
Binary files differ
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
new file mode 100644
index 0000000..4410520
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..810ef80
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache
Binary files differ
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
new file mode 100644
index 0000000..9ae5074
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..94e0f92
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache
Binary files differ
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
new file mode 100644
index 0000000..f10b39f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f9fe0f4
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache
Binary files differ
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
new file mode 100644
index 0000000..ffb4624
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..0afeaae
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache
Binary files differ
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
new file mode 100644
index 0000000..2d987e1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..3174256
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache
Binary files differ
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
new file mode 100644
index 0000000..06ce652
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..afd5ec8
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache
Binary files differ
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
new file mode 100644
index 0000000..2dcb80d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..a8c076a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache
Binary files differ
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
new file mode 100644
index 0000000..56b294f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..0c28857
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache
Binary files differ
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
new file mode 100644
index 0000000..03b0ec9
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7ac8412
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache
Binary files differ
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
new file mode 100644
index 0000000..ff8f8df
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..42e5822
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache
Binary files differ
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
new file mode 100644
index 0000000..c304185
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..891b8cd
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache
Binary files differ
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
new file mode 100644
index 0000000..8ee3fd8
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..c7b14d2
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache
Binary files differ
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
new file mode 100644
index 0000000..26ea872
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..ba8d28b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache
Binary files differ
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
new file mode 100644
index 0000000..ab416af
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1d77445
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache
Binary files differ
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
new file mode 100644
index 0000000..732654a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..c86e73f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache
Binary files differ
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
new file mode 100644
index 0000000..ee9607b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..580f9e1
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache
Binary files differ
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
new file mode 100644
index 0000000..300d752
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..a92f14c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache
Binary files differ
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
new file mode 100644
index 0000000..2ef42cf
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f3328fc
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache
Binary files differ
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
new file mode 100644
index 0000000..a8195fc
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1dc5df2
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@base.beam
Binary files differ
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
new file mode 100644
index 0000000..53dc014
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_array.beam
Binary files differ
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
new file mode 100644
index 0000000..bb8b7ad
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_builder.beam
Binary files differ
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
new file mode 100644
index 0000000..529dcbf
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bit_string.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bool.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bool.beam
new file mode 100644
index 0000000..1c09889
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bool.beam
Binary files differ
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
new file mode 100644
index 0000000..5909435
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@bytes_builder.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dict.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dict.beam
new file mode 100644
index 0000000..4e29e67
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dict.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic.beam
new file mode 100644
index 0000000..04a6ff4
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@dynamic.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@float.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@float.beam
new file mode 100644
index 0000000..4e514dd
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@float.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@function.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@function.beam
new file mode 100644
index 0000000..26efa09
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@function.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@int.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@int.beam
new file mode 100644
index 0000000..fdbc861
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@int.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@io.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@io.beam
new file mode 100644
index 0000000..e26d173
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@io.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@iterator.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@iterator.beam
new file mode 100644
index 0000000..27305e5
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@iterator.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@list.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@list.beam
new file mode 100644
index 0000000..3bc877f
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@list.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@map.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@map.beam
new file mode 100644
index 0000000..da9fae6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@map.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@option.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@option.beam
new file mode 100644
index 0000000..fc1c866
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@option.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@order.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@order.beam
new file mode 100644
index 0000000..d2211bd
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@order.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@pair.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@pair.beam
new file mode 100644
index 0000000..c54cf50
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@pair.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@queue.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@queue.beam
new file mode 100644
index 0000000..f9bb77e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@queue.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@regex.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@regex.beam
new file mode 100644
index 0000000..9f9f430
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@regex.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@result.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@result.beam
new file mode 100644
index 0000000..fffb063
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@result.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@set.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@set.beam
new file mode 100644
index 0000000..3f4118e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@set.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string.beam
new file mode 100644
index 0000000..9febebb
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string.beam
Binary files differ
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
new file mode 100644
index 0000000..4dee8d6
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@string_builder.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@uri.beam b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@uri.beam
new file mode 100644
index 0000000..91e2a9c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam@uri.beam
Binary files differ
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
new file mode 100644
index 0000000..7022f4d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/gleam_stdlib/ebin/gleam_stdlib.beam
Binary files differ
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
new file mode 100644
index 0000000..2174df9
--- /dev/null
+++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cache
Binary files differ
diff --git a/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cache_meta b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cache_meta
new file mode 100644
index 0000000..23d66d7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7570f95
--- /dev/null
+++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.cache
Binary files differ
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
new file mode 100644
index 0000000..be367e3
--- /dev/null
+++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..4c08669
--- /dev/null
+++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache
Binary files differ
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
new file mode 100644
index 0000000..355567d
--- /dev/null
+++ b/aoc2023/build/dev/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..80ab9b9
--- /dev/null
+++ b/aoc2023/build/dev/erlang/glint/ebin/glint.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/glint/ebin/glint@flag.beam b/aoc2023/build/dev/erlang/glint/ebin/glint@flag.beam
new file mode 100644
index 0000000..66ef4f0
--- /dev/null
+++ b/aoc2023/build/dev/erlang/glint/ebin/glint@flag.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/glint/ebin/glint@flag@constraint.beam b/aoc2023/build/dev/erlang/glint/ebin/glint@flag@constraint.beam
new file mode 100644
index 0000000..c6377ad
--- /dev/null
+++ b/aoc2023/build/dev/erlang/glint/ebin/glint@flag@constraint.beam
Binary files differ
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
new file mode 100644
index 0000000..28d7520
--- /dev/null
+++ b/aoc2023/build/dev/erlang/pqueue/_build/prod/lib/.rebar3/rebar_compiler_erl/source.dag
Binary files differ
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
new file mode 100644
index 0000000..987a618
--- /dev/null
+++ b/aoc2023/build/dev/erlang/pqueue/doc/erlang.png
Binary files differ
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>) -&gt; <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>) -&gt; <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>) -&gt; 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>) -&gt; 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>) -&gt; <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>) -&gt; 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() -&gt; <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>) -&gt; {{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>) -&gt; {{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>) -&gt; {{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() -&gt; 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>) -&gt; [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>) -&gt; <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>) -&gt; <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>) -&gt; 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>) -&gt; 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>) -&gt; 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() -&gt; <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>) -&gt; {{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>) -&gt; {{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>) -&gt; {{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() -&gt; 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>) -&gt; [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>) -&gt; <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>) -&gt; <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>) -&gt; 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>) -&gt; 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>) -&gt; 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() -&gt; <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()}]) -&gt; <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>) -&gt; {{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>) -&gt; {{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>) -&gt; {{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>) -&gt; [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()) -&gt; boolean()), Q::<a href="#type-pqueue4">pqueue4()</a>) -&gt; <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()) -&gt; boolean()), P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -&gt; <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>) -&gt; <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>) -&gt; <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>) -&gt; 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>) -&gt; 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>) -&gt; 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() -&gt; <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>) -&gt; {{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>) -&gt; {{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>) -&gt; {{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()) -&gt; boolean()), Q::<a href="#type-pqueue4">pqueue4()</a>) -&gt; {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()) -&gt; boolean()), P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -&gt; {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>) -&gt; 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>) -&gt; [{<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
new file mode 100644
index 0000000..218d67e
--- /dev/null
+++ b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/pqueue/ebin/pqueue2.beam b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue2.beam
new file mode 100644
index 0000000..597dc12
--- /dev/null
+++ b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue2.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/pqueue/ebin/pqueue3.beam b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue3.beam
new file mode 100644
index 0000000..ecf341a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue3.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/pqueue/ebin/pqueue4.beam b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue4.beam
new file mode 100644
index 0000000..8e575fc
--- /dev/null
+++ b/aoc2023/build/dev/erlang/pqueue/ebin/pqueue4.beam
Binary files differ
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
new file mode 100644
index 0000000..bf0b1d7
--- /dev/null
+++ b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cache
Binary files differ
diff --git a/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cache_meta b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cache_meta
new file mode 100644
index 0000000..90aa893
--- /dev/null
+++ b/aoc2023/build/dev/erlang/simplifile/_gleam_artefacts/simplifile.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..6631cad
--- /dev/null
+++ b/aoc2023/build/dev/erlang/simplifile/ebin/simplifile.beam
Binary files differ
diff --git a/aoc2023/build/dev/erlang/simplifile/ebin/simplifile_erl.beam b/aoc2023/build/dev/erlang/simplifile/ebin/simplifile_erl.beam
new file mode 100644
index 0000000..2abefda
--- /dev/null
+++ b/aoc2023/build/dev/erlang/simplifile/ebin/simplifile_erl.beam
Binary files differ
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
new file mode 100644
index 0000000..bc9c27c
--- /dev/null
+++ b/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cache
Binary files differ
diff --git a/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cache_meta b/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cache_meta
new file mode 100644
index 0000000..daef1e9
--- /dev/null
+++ b/aoc2023/build/dev/erlang/snag/_gleam_artefacts/snag.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..896068a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/snag/ebin/snag.beam
Binary files differ
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
new file mode 100644
index 0000000..c9b63ee
--- /dev/null
+++ b/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cache
Binary files differ
diff --git a/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cache_meta b/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cache_meta
new file mode 100644
index 0000000..492599b
--- /dev/null
+++ b/aoc2023/build/dev/erlang/tom/_gleam_artefacts/tom.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f6a990a
--- /dev/null
+++ b/aoc2023/build/dev/erlang/tom/ebin/tom.beam
Binary files differ
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
new file mode 100644
index 0000000..d80b6f5
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache
Binary files differ
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
new file mode 100644
index 0000000..c59c230
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_community_ansi/_gleam_artefacts/gleam_community@ansi.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..af5064d
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache
Binary files differ
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
new file mode 100644
index 0000000..ac37397
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..8b0da6a
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache
Binary files differ
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
new file mode 100644
index 0000000..7612e93
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_community_colour/_gleam_artefacts/gleam_community@colour@accessibility.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f2dc094
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache
Binary files differ
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
new file mode 100644
index 0000000..c968106
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..ca7044f
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache
Binary files differ
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
new file mode 100644
index 0000000..738bcf2
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..77e9b13
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache
Binary files differ
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
new file mode 100644
index 0000000..6e3ee81
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..2a3b4ea
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache
Binary files differ
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
new file mode 100644
index 0000000..f2508da
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..50f4eee
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache
Binary files differ
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
new file mode 100644
index 0000000..e31207b
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..e42668c
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache
Binary files differ
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
new file mode 100644
index 0000000..30819f5
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..89892b0
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache
Binary files differ
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
new file mode 100644
index 0000000..1ed64d0
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..74dbf2e
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache
Binary files differ
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
new file mode 100644
index 0000000..1824e4b
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..e2bc5b0
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache
Binary files differ
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
new file mode 100644
index 0000000..5d43230
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..cb804ae
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache
Binary files differ
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
new file mode 100644
index 0000000..6d282ca
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..378413e
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache
Binary files differ
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
new file mode 100644
index 0000000..a84ec42
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..6e28b1a
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache
Binary files differ
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
new file mode 100644
index 0000000..1de48df
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1181c6f
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache
Binary files differ
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
new file mode 100644
index 0000000..157d62a
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..8f20342
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache
Binary files differ
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
new file mode 100644
index 0000000..b063182
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7522564
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache
Binary files differ
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
new file mode 100644
index 0000000..262f199
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..23983c9
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache
Binary files differ
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
new file mode 100644
index 0000000..d8e0f2c
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7e30b9a
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache
Binary files differ
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
new file mode 100644
index 0000000..8431bbf
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1dc9e66
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache
Binary files differ
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
new file mode 100644
index 0000000..0ec7fb6
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..43e7b46
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache
Binary files differ
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
new file mode 100644
index 0000000..a102823
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..4effed9
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache
Binary files differ
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
new file mode 100644
index 0000000..2c308ac
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1c2841b
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache
Binary files differ
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
new file mode 100644
index 0000000..3031e40
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..520070a
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache
Binary files differ
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
new file mode 100644
index 0000000..b8bba7e
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7feabe9
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache
Binary files differ
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
new file mode 100644
index 0000000..1e4a58c
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..66392d2
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache
Binary files differ
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
new file mode 100644
index 0000000..ecac5d1
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..1777ae2
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache
Binary files differ
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
new file mode 100644
index 0000000..0967876
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..9776f55
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cache
Binary files differ
diff --git a/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cache_meta b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cache_meta
new file mode 100644
index 0000000..b0ea973
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint.cache_meta
Binary files differ
diff --git a/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cache b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cache
new file mode 100644
index 0000000..b0d5297
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cache
Binary files differ
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
new file mode 100644
index 0000000..de472d6
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..0b572cc
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache
Binary files differ
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
new file mode 100644
index 0000000..b48a19f
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/glint/_gleam_artefacts/glint@flag@constraint.cache_meta
Binary files differ
diff --git a/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache b/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache
new file mode 100644
index 0000000..7df428a
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache
Binary files differ
diff --git a/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache_meta b/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache_meta
new file mode 100644
index 0000000..f2947eb
--- /dev/null
+++ b/aoc2023/build/lsp/erlang/snag/_gleam_artefacts/snag.cache_meta
Binary files differ
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
+
+[![Package Version](https://img.shields.io/hexpm/v/adglent)](https://hex.pm/packages/adglent)
+[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](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
+
+[![Package Version](https://img.shields.io/hexpm/v/gap)](https://hex.pm/packages/gap)
+[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](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.
+
+[![Package Version](https://img.shields.io/hexpm/v/gleam_community_ansi)](https://hex.pm/packages/gleam_community_ansi)
+[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](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.
+
+[![Package Version](https://img.shields.io/hexpm/v/gleam_community_colour)](https://hex.pm/packages/gleam_community_colour)
+[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](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
+
+[![Package Version](https://img.shields.io/hexpm/v/gleam_community_maths)](https://hex.pm/packages/gleam_community_maths)
+[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](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>
+![CI](https://github.com/gleam-lang/httpc/workflows/test/badge.svg?branch=main)
+
+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>
+![CI](https://github.com/gleam-lang/otp/workflows/test/badge.svg?branch=main)
+
+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>
+![CI](https://github.com/gleam-lang/stdlib/workflows/CI/badge.svg?branch=main)
+
+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
+
+[![Hex Package](https://img.shields.io/hexpm/v/glint?color=ffaff3&label=%F0%9F%93%A6)](https://hex.pm/packages/glint)
+[![Hex.pm](https://img.shields.io/hexpm/dt/glint?color=ffaff3)](https://hex.pm/packages/glint)
+[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3?label=%F0%9F%93%9A)](https://hexdocs.pm/glint/)
+[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/tanklesxl/glint/main)](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
new file mode 100644
index 0000000..987a618
--- /dev/null
+++ b/aoc2023/build/packages/pqueue/doc/erlang.png
Binary files differ
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>) -&gt; <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>) -&gt; <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>) -&gt; 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>) -&gt; 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>) -&gt; <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>) -&gt; 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() -&gt; <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>) -&gt; {{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>) -&gt; {{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>) -&gt; {{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() -&gt; 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>) -&gt; [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>) -&gt; <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>) -&gt; <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>) -&gt; 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>) -&gt; 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>) -&gt; 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() -&gt; <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>) -&gt; {{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>) -&gt; {{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>) -&gt; {{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() -&gt; 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>) -&gt; [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>) -&gt; <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>) -&gt; <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>) -&gt; 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>) -&gt; 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>) -&gt; 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() -&gt; <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()}]) -&gt; <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>) -&gt; {{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>) -&gt; {{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>) -&gt; {{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>) -&gt; [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()) -&gt; boolean()), Q::<a href="#type-pqueue4">pqueue4()</a>) -&gt; <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()) -&gt; boolean()), P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -&gt; <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>) -&gt; <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>) -&gt; <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>) -&gt; 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>) -&gt; 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>) -&gt; 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() -&gt; <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>) -&gt; {{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>) -&gt; {{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>) -&gt; {{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()) -&gt; boolean()), Q::<a href="#type-pqueue4">pqueue4()</a>) -&gt; {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()) -&gt; boolean()), P::integer(), Q::<a href="#type-pqueue4">pqueue4()</a>) -&gt; {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>) -&gt; 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>) -&gt; [{<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
+
+[![Package Version](https://img.shields.io/hexpm/v/simplifile)](https://hex.pm/packages/simplifile)
+[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](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!
+
+[![Package Version](https://img.shields.io/hexpm/v/tom)](https://hex.pm/packages/tom)
+[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](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
new file mode 100644
index 0000000..0a49e16
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache
Binary files differ
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
new file mode 100644
index 0000000..d03bd4e
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@base.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..e75aa37
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache
Binary files differ
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
new 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
Binary files differ
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
new file mode 100644
index 0000000..e64afd2
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_builder.cache
Binary files differ
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
new 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
Binary files differ
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
new file mode 100644
index 0000000..3dd81d8
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bit_string.cache
Binary files differ
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
new 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
Binary files differ
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
new file mode 100644
index 0000000..de4ee67
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache
Binary files differ
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
new file mode 100644
index 0000000..e616ec0
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..98608da
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@bytes_builder.cache
Binary files differ
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
new 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
Binary files differ
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
new file mode 100644
index 0000000..2f469d1
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache
Binary files differ
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
new file mode 100644
index 0000000..277da6b
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..60712c7
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache
Binary files differ
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
new file mode 100644
index 0000000..91b39cc
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..b832a82
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache
Binary files differ
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
new file mode 100644
index 0000000..702d055
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..61d53d4
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache
Binary files differ
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
new file mode 100644
index 0000000..e7b9f9f
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..fdcf634
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache
Binary files differ
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
new file mode 100644
index 0000000..aad5629
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..70774f5
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache
Binary files differ
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
new file mode 100644
index 0000000..48ca73e
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..2ebb0ba
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache
Binary files differ
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
new file mode 100644
index 0000000..43c26de
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@iterator.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f58495d
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache
Binary files differ
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
new file mode 100644
index 0000000..ec9035e
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f5f5c1e
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache
Binary files differ
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
new file mode 100644
index 0000000..f1ed30f
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@map.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f50856a
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache
Binary files differ
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
new file mode 100644
index 0000000..8b36f47
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..f10a597
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache
Binary files differ
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
new file mode 100644
index 0000000..2395015
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..c31d461
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache
Binary files differ
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
new file mode 100644
index 0000000..a2089a5
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..b1e9775
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache
Binary files differ
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
new file mode 100644
index 0000000..6ec02d2
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@queue.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..e9ae9d8
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache
Binary files differ
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
new file mode 100644
index 0000000..d6129ae
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@regex.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..c29fc16
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache
Binary files differ
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
new file mode 100644
index 0000000..f4e8874
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..47c7957
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache
Binary files differ
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
new file mode 100644
index 0000000..5d99ee5
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..4d87904
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache
Binary files differ
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
new file mode 100644
index 0000000..d4739c1
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..c0e91da
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@string_builder.cache
Binary files differ
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
new 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
Binary files differ
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
new file mode 100644
index 0000000..ba5daf8
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache
Binary files differ
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
new file mode 100644
index 0000000..2ae412b
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..8f060b4
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit.cache
Binary files differ
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
new file mode 100644
index 0000000..1c4228b
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..7c85b7e
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache
Binary files differ
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
new file mode 100644
index 0000000..1b7dad9
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/gleeunit/_gleam_artefacts/gleeunit@should.cache_meta
Binary files differ
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
new file mode 100644
index 0000000..2bfceaf
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/tom/_gleam_artefacts/tom.cache
Binary files differ
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
new file mode 100644
index 0000000..3371771
--- /dev/null
+++ b/aoc2023/build/packages/tom/build/lsp/erlang/tom/_gleam_artefacts/tom.cache_meta
Binary files differ
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>
+![CI](https://github.com/gleam-lang/stdlib/workflows/CI/badge.svg?branch=main)
+
+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