diff options
Diffstat (limited to 'aoc2023/build/packages/gleam_community_maths')
23 files changed, 0 insertions, 7521 deletions
diff --git a/aoc2023/build/packages/gleam_community_maths/LICENCE b/aoc2023/build/packages/gleam_community_maths/LICENCE deleted file mode 100644 index a84f0ec..0000000 --- a/aoc2023/build/packages/gleam_community_maths/LICENCE +++ /dev/null @@ -1,190 +0,0 @@ - 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 deleted file mode 100644 index c912757..0000000 --- a/aoc2023/build/packages/gleam_community_maths/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# gleam-community/maths - -[](https://hex.pm/packages/gleam_community_maths) -[](https://hexdocs.pm/gleam_community_maths/) - -A basic mathematics library that contains some of the most fundamental mathematics functions and utilities. - -The library supports both targets: Erlang and JavaScript. - -## Quickstart - -```gleam -import gleam_community/maths/arithmetics -import gleam_community/maths/combinatorics -import gleam_community/maths/elementary -import gleam_community/maths/piecewise -import gleam_community/maths/predicates -import gleam/float - -pub fn main() { - // Evaluate the sine function - elementary.sin(elementary.pi()) - // Returns Float: 0.0 - - // Find the greatest common divisor - arithmetics.gcd(54, 24) - // Returns Int: 6 - - // Find the minimum and maximum of a list - piecewise.extrema([10.0, 3.0, 50.0, 20.0, 3.0], float.compare) - // Returns Tuple: Ok(#(3.0, 50.0)) - - // Find the list indices of the smallest value - piecewise.arg_minimum([10, 3, 50, 20, 3], float.compare) - // Returns List: Ok([1, 4]) - - // Determine if a number is fractional - predicates.is_fractional(0.3333) - // Returns Bool: True - - // Determine if 28 is a power of 3 - predicates.is_power(28, 3) - // Returns Bool: False - - // Generate all k = 1 combinations of [1, 2] - combinatorics.list_combination([1, 2], 1) - // Returns List: Ok([[1], [2]]) -} - -``` - -## Installation - -`gleam_community` packages are published to [hex.pm](https://hex.pm/packages/gleam_community_maths) -with the prefix `gleam_community_`. You can add them to your Gleam projects directly: - -```sh -gleam add gleam_community_maths -``` diff --git a/aoc2023/build/packages/gleam_community_maths/gleam.toml b/aoc2023/build/packages/gleam_community_maths/gleam.toml deleted file mode 100644 index 9dc5fd7..0000000 --- a/aoc2023/build/packages/gleam_community_maths/gleam.toml +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index 3e0f63a..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/arithmetics.gleam +++ /dev/null @@ -1,618 +0,0 @@ -////<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 deleted file mode 100644 index ee771a1..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/combinatorics.gleam +++ /dev/null @@ -1,432 +0,0 @@ -////<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 deleted file mode 100644 index 017aabd..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/conversion.gleam +++ /dev/null @@ -1,183 +0,0 @@ -////<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 deleted file mode 100644 index 1b518a4..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/elementary.gleam +++ /dev/null @@ -1,1256 +0,0 @@ -////<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 deleted file mode 100644 index 1dab2b4..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/metrics.gleam +++ /dev/null @@ -1,560 +0,0 @@ -////<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 deleted file mode 100644 index 3b40a18..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/piecewise.gleam +++ /dev/null @@ -1,1228 +0,0 @@ -////<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 deleted file mode 100644 index f8d357c..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/predicates.gleam +++ /dev/null @@ -1,363 +0,0 @@ -////<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 deleted file mode 100644 index e7c0388..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/sequences.gleam +++ /dev/null @@ -1,302 +0,0 @@ -////<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 deleted file mode 100644 index dfd9cbb..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community/maths/special.gleam +++ /dev/null @@ -1,205 +0,0 @@ -////<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 deleted file mode 100644 index ca266c8..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@arithmetics.erl +++ /dev/null @@ -1,172 +0,0 @@ --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 deleted file mode 100644 index 17644c4..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@combinatorics.erl +++ /dev/null @@ -1,218 +0,0 @@ --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 deleted file mode 100644 index 0f6decb..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@conversion.erl +++ /dev/null @@ -1,23 +0,0 @@ --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 deleted file mode 100644 index dab5d68..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@elementary.erl +++ /dev/null @@ -1,284 +0,0 @@ --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 deleted file mode 100644 index 2a58da6..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@metrics.erl +++ /dev/null @@ -1,278 +0,0 @@ --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 deleted file mode 100644 index 258d879..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@piecewise.erl +++ /dev/null @@ -1,553 +0,0 @@ --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 deleted file mode 100644 index d991d89..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@predicates.erl +++ /dev/null @@ -1,118 +0,0 @@ --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 deleted file mode 100644 index 74dcff4..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@sequences.erl +++ /dev/null @@ -1,199 +0,0 @@ --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 deleted file mode 100644 index 925f4bb..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community@maths@special.erl +++ /dev/null @@ -1,157 +0,0 @@ --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 deleted file mode 100644 index 091e679..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/gleam_community_maths.app.src +++ /dev/null @@ -1,16 +0,0 @@ -{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 deleted file mode 100644 index 5c5ab31..0000000 --- a/aoc2023/build/packages/gleam_community_maths/src/maths.mjs +++ /dev/null @@ -1,95 +0,0 @@ -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) -} |