aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Porto <s@porto5.com>2021-04-24 20:36:42 +1000
committerLouis Pilfold <louis@lpil.uk>2021-04-29 20:24:23 +0100
commit37279f753cb241016be2d3e25a0fa665072b643c (patch)
tree7d19bc498487a9a4e1c796976429d042721d8141
parent1887709e22f969b43e7e9c2ff9918bd8bc9ec114 (diff)
downloadgleam_stdlib-37279f753cb241016be2d3e25a0fa665072b643c.tar.gz
gleam_stdlib-37279f753cb241016be2d3e25a0fa665072b643c.zip
Add list.combinations
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/gleam/list.gleam46
-rw-r--r--test/gleam/list_test.gleam41
3 files changed, 88 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d3607ed..66df392 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@
- The `dynamic` module gains the `tuple3`, `tuple4`, `tuple5`, `tuple6`
functions and their typed equivalents `typed_tuple3`, `typed_tuple4`,
`typed_tuple5`, `typed_tuple6`.
-- The `list` module gains the `drop_while`, `map_fold`, `take_while`, `reduce`,
+- The `list` module gains the `combinations_by`, `combinations_by_2`, `drop_while`, `map_fold`, `take_while`, `reduce`,
`chunk`, `sized_chunk`, `last` and `scan` functions.
- The `iterator` module gains the `index`, `iterate`, `zip`, `scan`, `last`,
`take_while`, `drop_while`, `chunk`, `sized_chunk`, `intersperse`, `interleave`, `reduce`,
diff --git a/src/gleam/list.gleam b/src/gleam/list.gleam
index 17ee57d..873f5ad 100644
--- a/src/gleam/list.gleam
+++ b/src/gleam/list.gleam
@@ -1452,3 +1452,49 @@ pub fn last(list: List(a)) -> Result(a, Nil) {
list
|> reduce(fn(elem, _) { elem })
}
+
+/// Return unique combinations of elements in the list
+///
+/// ## Examples
+///
+/// ```
+/// > combinations_by([1, 2, 3], 2)
+/// [[1, 2], [1, 3], [2, 3]]
+///
+/// > combinations_by([1, 2, 3, 4], 3)
+/// [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
+/// ```
+///
+pub fn combinations_by(items: List(a), n: Int) -> List(List(a)) {
+ case n {
+ 0 -> [[]]
+ _ ->
+ case items {
+ [] -> []
+ [x, ..xs] -> {
+ let first_combinations =
+ map(combinations_by(xs, n - 1), with: fn(com) { [x, ..com] })
+ append(first_combinations, combinations_by(xs, n))
+ }
+ }
+ }
+}
+
+/// Return unique pair combinations of elements in the list
+///
+/// ## Examples
+///
+/// ```
+/// > combinations_by_2([1, 2, 3])
+/// [tuple(1, 2), tuple(1, 3), tuple(2, 3)]
+/// ```
+///
+pub fn combinations_by_2(items: List(a)) -> List(tuple(a, a)) {
+ case items {
+ [] -> []
+ [x, ..xs] -> {
+ let first_combinations = map(xs, with: fn(other) { tuple(x, other) })
+ append(first_combinations, combinations_by_2(xs))
+ }
+ }
+}
diff --git a/test/gleam/list_test.gleam b/test/gleam/list_test.gleam
index 5fe2dd5..294c9f4 100644
--- a/test/gleam/list_test.gleam
+++ b/test/gleam/list_test.gleam
@@ -653,3 +653,44 @@ pub fn last_test() {
list.last([1, 2, 3, 4, 5])
|> should.equal(Ok(5))
}
+
+pub fn combinations_by_test() {
+ list.combinations_by([1, 2, 3], 0)
+ |> should.equal([[]])
+
+ list.combinations_by([1, 2, 3], 1)
+ |> should.equal([[1], [2], [3]])
+
+ list.combinations_by([1, 2, 3], 2)
+ |> should.equal([[1, 2], [1, 3], [2, 3]])
+
+ list.combinations_by([1, 2, 3], 3)
+ |> should.equal([[1, 2, 3]])
+
+ list.combinations_by([1, 2, 3], 4)
+ |> should.equal([])
+
+ list.combinations_by([1, 2, 3, 4], 3)
+ |> should.equal([[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]])
+}
+
+pub fn combinations_by_2_test() {
+ list.combinations_by_2([1])
+ |> should.equal([])
+
+ list.combinations_by_2([1, 2])
+ |> should.equal([tuple(1, 2)])
+
+ list.combinations_by_2([1, 2, 3])
+ |> should.equal([tuple(1, 2), tuple(1, 3), tuple(2, 3)])
+
+ list.combinations_by_2([1, 2, 3, 4])
+ |> should.equal([
+ tuple(1, 2),
+ tuple(1, 3),
+ tuple(1, 4),
+ tuple(2, 3),
+ tuple(2, 4),
+ tuple(3, 4),
+ ])
+}