package math.statistics;

import math.Maths;

/**
 * @author Daniel Weschke
 */
public class Probability {
	
	/**
	 * Permutation. n!. e. g. n = 6 balls with different properties.
	 * Number of arrangements.
	 * @param n total number of things
	 * @return permutation
	 * @see Maths#factorial(long)
	 */
	public static long permutation(int n){
		return Maths.factorial((long)n);
	}
	
	/**
	 * Permutation. n!/k!. e. g. n = 6 balls, k = 3 balls of same property (same color), n-k with different properties.
	 * Number of arrangements.
	 * @param n total number of things
	 * @param k number of same properties
	 * @return permutation
	 */
	public static long permutation(int n, int k){
		return permutation(n)/permutation(k);
	}
	
	/**
	 * Permutation. n!/k!.
	 * e. g. n = 6 balls, k = [3 balls of one same property (black), 3 balls of other same property], n-k with different properties.
	 * Number of arrangements.
	 * @param n total number of things
	 * @param ki multiple number of same properties
	 * @return permutation
	 */
	public static long permutation(int n, int... ki){
		int i;
		long k = 1;
		for(i=0; i<ki.length; i++)
			k *= permutation(ki[i]);
		return permutation(n)/k;
	}
	
	/**
	 * Combinations refer to the combination of n things taken k at a time without repetition.
	 * Binomial coefficient. (n choose k) = n!/((n-k)!k!).
	 * Pick.
	 * @param n total number of things
	 * @param k taken thinks
	 * @return combinations without repetition
	 */
	public static long combinations(int n, int k){
		return permutation(n)/permutation(n-k)/permutation(k);
	}
	
	/**
	 * Combinations refer to the combination of n things taken k at a time with repetition.
	 * Binomial coefficient. ((n choose k)) = (n+k-1 choose k) = (n+k-1)!/((n-k)!k!).
	 * Pick.
	 * @param n total number of things
	 * @param k taken thinks
	 * @return combinations with repetition
	 */
	public static long combinationsRepetiton(int n, int k){
		return permutation(n+k-1)/permutation(n-k)/permutation(k);
	}
	
	/**
	 * Variations refer to the arranged variation of n things taken at k at a time without repetition.
	 * k!(n choose k) = n!/(n-k)!
	 * Arrange and Pick.
	 * @param n total number of things
	 * @param k taken things
	 * @return variations without repetition
	 */
	public static long variation(int n, int k){
		return permutation(n)/permutation(n-k);
	}
	
	/**
	 * Variations refer to the arranged variation of n things taken at k at a time without repetition.
	 * n<sup>k</sup>.
	 * Arrange and Pick.
	 * @param n total number of things
	 * @param k taken things
	 * @return variations with repetition
	 */
	public static long variationRepetition(int n, int k){
		return Maths.pow(n, k);
	}

	public static void main(String[] args) {
	}

}
