------------------------------------------------------------------------ -- The Agda standard library -- -- Combinatorics operations ------------------------------------------------------------------------ {-# OPTIONS --cubical-compatible --safe #-} module Data.Nat.Combinatorics.Base where open import Data.Bool.Base using (if_then_else_) open import Data.Nat.Base open import Data.Nat.Properties using (_!≢0) -- NOTE: These operators are not implemented as efficiently as they -- could be. See the following link for more details. -- -- https://math.stackexchange.com/questions/202554/how-do-i-compute-binomial-coefficients-efficiently ------------------------------------------------------------------------ -- Permutations / falling factorial -- The number of ways, including order, that k objects can be chosen -- from among n objects. -- n P k = n ! / (n ∸ k) ! infixl 6.5 _P′_ _P_ -- Base definition. Only valid for k ≤ n. _P′_ : ℕ → ℕ → ℕ n P′ zero = 1 n P′ (suc k) = (n ∸ k) * (n P′ k) -- Main definition. Valid for all k as deals with boundary case. _P_ : ℕ → ℕ → ℕ n P k = if k ≤ᵇ n then n P′ k else 0 ------------------------------------------------------------------------ -- Combinations / binomial coefficient -- The number of ways, disregarding order, that k objects can be chosen -- from among n objects. -- n C k = n ! / (k ! * (n ∸ k) !) infixl 6.5 _C′_ _C_ -- Base definition. Only valid for k ≤ n. _C′_ : ℕ → ℕ → ℕ n C′ k = (n P′ k) / k ! where instance _ = k !≢0 -- Main definition. Valid for all k. -- Deals with boundary case and exploits symmetry to improve performance. _C_ : ℕ → ℕ → ℕ n C k = if k ≤ᵇ n then n C′ (k ⊓ (n ∸ k)) else 0