aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Attard <robert.attard@mail.mcgill.ca>2022-01-03 18:51:10 -0500
committerGitHub <noreply@github.com>2022-01-03 23:51:10 +0000
commit265c228f4a8f233d863f35df9f8e888918902cdc (patch)
treec7a6a35939625c1096670d927951379f9b625523
parent2c7c5d2a511bd5cb6ed65214790c5a91488dd7e5 (diff)
downloadgleam_stdlib-265c228f4a8f233d863f35df9f8e888918902cdc.tar.gz
gleam_stdlib-265c228f4a8f233d863f35df9f8e888918902cdc.zip
Int.digits & int.undigits
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--CHANGELOG.md1
-rw-r--r--src/gleam/int.gleam59
-rw-r--r--test/gleam/int_test.gleam34
4 files changed, 94 insertions, 2 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0bbe10b..919a864 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
node-version: "16.0.0"
- uses: gleam-lang/setup-gleam@v1.0.1
with:
- gleam-version: "0.18.0-rc1"
+ gleam-version: "0.19.0-rc1"
- run: gleam test
- run: npm test
# - run: gleam format --check src test
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7d22e46..fda755b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@
- The `dynamic.DecodeError` now has a `path` field.
- The decoder functions of the `dynamic` module now return multiple errors.
- The `dynamic.tuple*` functions are now partially applied.
+- The `int` module gains the `digits` and `undigits` functions.
## v0.18.1 - 2021-12-19
diff --git a/src/gleam/int.gleam b/src/gleam/int.gleam
index a9dff63..2aff67f 100644
--- a/src/gleam/int.gleam
+++ b/src/gleam/int.gleam
@@ -62,7 +62,7 @@ if javascript {
"../gleam_stdlib.mjs" "to_string"
}
-/// For use in `to_base_string` when base is outside of the allowed range.
+/// Error value when trying to operate with a base out of the allowed range.
pub type InvalidBase {
InvalidBase
}
@@ -323,3 +323,60 @@ fn do_product(numbers: List(Int), initial: Int) -> Int {
[x, ..rest] -> do_product(rest, x * initial)
}
}
+
+/// Splits an integer into its digit representation in the specified base
+///
+/// ## Examples
+///
+/// > digits(234, 10)
+/// Ok([2,3,4])
+///
+/// > digits(234, 1)
+/// Error(InvalidBase)
+///
+pub fn digits(number: Int, base: Int) -> Result(List(Int), InvalidBase) {
+ case base < 2 {
+ True -> Error(InvalidBase)
+ False -> Ok(do_digits(number, base, []))
+ }
+}
+
+fn do_digits(number: Int, base: Int, acc: List(Int)) -> List(Int) {
+ case absolute_value(number) < base {
+ True -> [number, ..acc]
+ False -> do_digits(number / base, base, [number % base, ..acc])
+ }
+}
+
+/// Joins a list of digits into a single value.
+/// Returns an error if the base is less than 2 or if the list contains a digit greater than or equal to the specified base.
+///
+/// ## Examples
+///
+/// > undigits([2,3,4], 10)
+/// Ok(234)
+///
+/// > undigits([2,3,4], 1)
+/// Error(InvalidBase)
+///
+/// > undigits([2,3,4], 2)
+/// Error(InvalidBase)
+///
+pub fn undigits(numbers: List(Int), base: Int) -> Result(Int, InvalidBase) {
+ case base < 2 {
+ True -> Error(InvalidBase)
+ False -> do_undigits(numbers, base, 0)
+ }
+}
+
+fn do_undigits(
+ numbers: List(Int),
+ base: Int,
+ acc: Int,
+) -> Result(Int, InvalidBase) {
+ case numbers {
+ [] -> Ok(acc)
+ [digit, .._rest] if digit >= base -> Error(InvalidBase)
+ [digit, ..rest] -> do_undigits(rest, base, acc * base + digit)
+ }
+}
diff --git a/test/gleam/int_test.gleam b/test/gleam/int_test.gleam
index 07832dd..1fbc102 100644
--- a/test/gleam/int_test.gleam
+++ b/test/gleam/int_test.gleam
@@ -282,3 +282,37 @@ pub fn product_test() {
int.product([1, 2, 3])
|> should.equal(6)
}
+
+pub fn digits_test() {
+ int.digits(123, 10)
+ |> should.equal(Ok([1, 2, 3]))
+
+ int.digits(-123, 10)
+ |> should.equal(Ok([-1, -2, -3]))
+
+ int.digits(123, 2)
+ |> should.equal(Ok([1, 1, 1, 1, 0, 1, 1]))
+
+ int.digits(123, 1)
+ |> should.equal(Error(int.InvalidBase))
+}
+
+pub fn undigits_test() {
+ int.undigits([], 10)
+ |> should.equal(Ok(0))
+
+ int.undigits([1, 2, 3], 10)
+ |> should.equal(Ok(123))
+
+ int.undigits([-1, -2, -3], 10)
+ |> should.equal(Ok(-123))
+
+ int.undigits([1, 1, 1, 1, 0, 1, 1], 2)
+ |> should.equal(Ok(123))
+
+ int.undigits([1, 2, 3], 1)
+ |> should.equal(Error(int.InvalidBase))
+
+ int.undigits([1, 1, 2], 2)
+ |> should.equal(Error(int.InvalidBase))
+}