mirror of
https://github.com/nushell/nu_scripts.git
synced 2024-08-16 17:00:32 +03:00
Add cartesian product to math module (#624)
related to - https://github.com/nushell/nushell/pull/10383 this PR resurrects the `cartesian product` command from https://github.com/nushell/nushell/pull/10383 and adds it to the `maths` module of the `nu_scripts`: - a new `cartesian product` command - some unit tests for it ## use the command i've installed the `nu_scripts` with `nupm`, thus i'm able to do ```nushell use nu-scripts/modules/maths/math_functions.nu "cartesian product" cartesian product ... ``` ## run the tests from the root of the `nu_scripts`, checked out on this PR, run ```nushell use std; std testing run-tests --path modules/maths/ --test cartesian_product ```
This commit is contained in:
parent
6947014306
commit
9d21cd5cd3
@ -157,3 +157,84 @@ export def scale-minmax-table [a, b,input?] {
|
||||
($x | column2 $i) | scale-minmax $a $b | wrap ($name_cols | get $i)
|
||||
} | reduce {|it, acc| $acc | merge {$it}}
|
||||
}
|
||||
|
||||
|
||||
# compute the cartesian product of any number of lists
|
||||
#
|
||||
# basically, if you give `iter cartesian product` *n* lists, from *i_1* to *i_n*,
|
||||
# it will compute recursively the cartesian product of the first one with the
|
||||
# `iter cartesian product` of the rest, i.e. if we call CP the two-set cartesian
|
||||
# product and ICP the multi cartesian product here, we have
|
||||
#
|
||||
# *ICP(i_1, i_2, ..., i_n) == CP(i_1, ICP(i_2, ..., i_n))*
|
||||
#
|
||||
# # Example
|
||||
#```nushell
|
||||
# use std ["assert equal" "iter iter cartesian product"]
|
||||
#
|
||||
# let res = (
|
||||
# iter cartesian product [1, 2] [3, 4]
|
||||
# )
|
||||
#
|
||||
# assert equal $res [
|
||||
# [1, 3],
|
||||
# [1, 4],
|
||||
# [2, 3],
|
||||
# [2, 4],
|
||||
# ]
|
||||
# ```
|
||||
export def "cartesian product" [
|
||||
...iters: list<any> # the iterables you want the cartesian product of
|
||||
]: nothing -> list<list<any>> {
|
||||
def aux [a: list<list<any>>]: nothing -> list<list<any>> {
|
||||
if ($a | is-empty) {
|
||||
return []
|
||||
}
|
||||
|
||||
let head = $a | first
|
||||
let tail = aux ($a | skip 1)
|
||||
|
||||
if ($head | is-empty) {
|
||||
return $tail
|
||||
} else if ($tail | is-empty) {
|
||||
return $head
|
||||
}
|
||||
|
||||
$head | each {|h| $tail | each {|t| [$h, $t]}} | flatten | each { flatten }
|
||||
}
|
||||
|
||||
aux $iters
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
def cartesian_product [] {
|
||||
use std assert
|
||||
|
||||
# emptyness
|
||||
assert equal (cartesian product [] []) []
|
||||
assert equal (cartesian product []) []
|
||||
assert equal (cartesian product) []
|
||||
|
||||
# symmetry
|
||||
assert equal (cartesian product [1, 2] []) [1, 2]
|
||||
assert equal (cartesian product [] [1, 2]) [1, 2]
|
||||
# NOTE: `cartesian product` might not preserve the order of the elements produced
|
||||
assert equal (
|
||||
cartesian product [1, 2] [3, 4] | each { sort } | sort
|
||||
) (
|
||||
cartesian product [3, 4] [1, 2] | each { sort } | sort
|
||||
)
|
||||
|
||||
assert equal (
|
||||
cartesian product [1, 2] [3, 4]
|
||||
) [
|
||||
[1, 3], [1, 4], [2, 3], [2, 4]
|
||||
]
|
||||
|
||||
assert equal (
|
||||
cartesian product [1, 2] [3, 4] [5, 6]
|
||||
) [
|
||||
[1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user