mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-30 03:10:06 +00:00
Merge pull request #3717 from Feoramund/big-combo
Add permutation & combination procs to `core:math/big`
This commit is contained in:
@@ -0,0 +1,60 @@
|
|||||||
|
package math_big
|
||||||
|
|
||||||
|
/*
|
||||||
|
With `n` items, calculate how many ways that `r` of them can be ordered.
|
||||||
|
*/
|
||||||
|
permutations_with_repetition :: int_pow_int
|
||||||
|
|
||||||
|
/*
|
||||||
|
With `n` items, calculate how many ways that `r` of them can be ordered without any repeats.
|
||||||
|
*/
|
||||||
|
permutations_without_repetition :: proc(dest: ^Int, n, r: int) -> (error: Error) {
|
||||||
|
if n == r {
|
||||||
|
return factorial(dest, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := &Int{}
|
||||||
|
defer internal_destroy(tmp)
|
||||||
|
|
||||||
|
// n!
|
||||||
|
// --------
|
||||||
|
// (n - r)!
|
||||||
|
factorial(dest, n) or_return
|
||||||
|
factorial(tmp, n - r) or_return
|
||||||
|
div(dest, dest, tmp) or_return
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
With `n` items, calculate how many ways that `r` of them can be chosen.
|
||||||
|
|
||||||
|
Also known as the multiset coefficient or (n multichoose k).
|
||||||
|
*/
|
||||||
|
combinations_with_repetition :: proc(dest: ^Int, n, r: int) -> (error: Error) {
|
||||||
|
// (n + r - 1)!
|
||||||
|
// ------------
|
||||||
|
// r! (n - 1)!
|
||||||
|
return combinations_without_repetition(dest, n + r - 1, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
With `n` items, calculate how many ways that `r` of them can be chosen without any repeats.
|
||||||
|
|
||||||
|
Also known as the binomial coefficient or (n choose k).
|
||||||
|
*/
|
||||||
|
combinations_without_repetition :: proc(dest: ^Int, n, r: int) -> (error: Error) {
|
||||||
|
tmp_a, tmp_b := &Int{}, &Int{}
|
||||||
|
defer internal_destroy(tmp_a, tmp_b)
|
||||||
|
|
||||||
|
// n!
|
||||||
|
// ------------
|
||||||
|
// r! (n - r)!
|
||||||
|
factorial(dest, n) or_return
|
||||||
|
factorial(tmp_a, r) or_return
|
||||||
|
factorial(tmp_b, n - r) or_return
|
||||||
|
mul(tmp_a, tmp_a, tmp_b) or_return
|
||||||
|
div(dest, dest, tmp_a) or_return
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
This file exports procedures for use with the test.py test suite.
|
This file exports procedures for use with the test.py test suite.
|
||||||
*/
|
*/
|
||||||
package math_big_tests
|
package test_core_math_big
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: Write tests for `internal_*` and test reusing parameters with the public implementations.
|
TODO: Write tests for `internal_*` and test reusing parameters with the public implementations.
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package test_core_math_big
|
||||||
|
|
||||||
|
import "core:math/big"
|
||||||
|
import "core:testing"
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
test_permutations_and_combinations :: proc(t: ^testing.T) {
|
||||||
|
{
|
||||||
|
calc, exp := &big.Int{}, &big.Int{}
|
||||||
|
defer big.destroy(calc, exp)
|
||||||
|
big.permutations_without_repetition(calc, 9000, 10)
|
||||||
|
big.int_atoi(exp, "3469387884476822917768284664849390080000")
|
||||||
|
equals, error := big.equals(calc, exp)
|
||||||
|
testing.expect(t, equals)
|
||||||
|
testing.expect_value(t, error, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
calc, exp := &big.Int{}, &big.Int{}
|
||||||
|
defer big.destroy(calc, exp)
|
||||||
|
big.combinations_with_repetition(calc, 9000, 10)
|
||||||
|
big.int_atoi(exp, "965678962435231708695393645683400")
|
||||||
|
equals, error := big.equals(calc, exp)
|
||||||
|
testing.expect(t, equals)
|
||||||
|
testing.expect_value(t, error, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
calc, exp := &big.Int{}, &big.Int{}
|
||||||
|
defer big.destroy(calc, exp)
|
||||||
|
big.combinations_without_repetition(calc, 9000, 10)
|
||||||
|
big.int_atoi(exp, "956070294443568925751842114431600")
|
||||||
|
equals, error := big.equals(calc, exp)
|
||||||
|
testing.expect(t, equals)
|
||||||
|
testing.expect_value(t, error, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user