combinatorics

LoudounCodes Combinatorics

A small, classroom-friendly Java library for combinations, permutations, derangements, power sets, Cartesian products, and more—built for teaching and tinkering.

What this library is for


Quick tour (fluent API in plain English)

A fluent API is a style where you chain method calls so code reads like a sentence:

Combinations.of(12).choose(3)                 // “choose 3 from 12 (no repetition)”
Combinations.of(8).choose(3).inGrayOrder()    // “same set, but Gray (minimal-change) order”
Combinations.of(6).withRepetition().choose(4) // “choose 4 from 6 with repetition”
Permutations.of(5).take(3)                    // “take ordered 3-tuples without repetition”
PowerSet.of(5)                                // “all subsets of a 5-element set”
CartesianProduct.of(2,3,2)                    // “mixed-radix tuples with dims 2×3×2”
Derangements.of(5).all()                      // “all permutations with no fixed points”

Each call returns an iterable view of int[] index tuples (e.g., [0,2,5]). Use IndexingAdapter to map those indices onto real objects like strings, cards, toppings, etc.

What is Gray order for combinations? For Combinations.of(n).choose(k).inGrayOrder(), consecutive k-subsets differ by toggling exactly one element (one leaves, one enters). You get the same combinations as lexicographic order, just in a minimal-change sequence—handy for animations, incremental updates, or bitset diffs.


Example: pizza toppings (combinations → real objects)

import java.util.List;
import org.loudouncodes.combinatorics.Combinations;
import org.loudouncodes.combinatorics.IndexingAdapter;

public class PizzaDemo {
  public static void main(String[] args) {
    List<String> toppings = List.of(
      "Pepperoni","Sausage","Mushrooms","Onions","Green Peppers","Black Olives",
      "Spinach","Bacon","Ham","Pineapple","Tomatoes","Extra Cheese"
    );

    int n = toppings.size();

    // 1) 3-topping pizzas (no repetition, lexicographic)
    var combosLex = Combinations.of(n).choose(3);
    var pizzasLex = new IndexingAdapter<>(combosLex, toppings);
    System.out.println("Three-topping pizzas (lex order):");
    for (var pizza : pizzasLex) System.out.println(pizza);

    // 2) Same combinations but in Gray (minimal-change) order
    var combosGray = Combinations.of(n).choose(3).inGrayOrder();
    var pizzasGray = new IndexingAdapter<>(combosGray, toppings);
    System.out.println("\nThree-topping pizzas (Gray order):");
    for (var pizza : pizzasGray) System.out.println(pizza);

    // 3) 3 scoops from 6 flavors (with repetition — like ice cream)
    var scoops = Combinations.of(6).withRepetition().choose(3);
    System.out.println("\nThree scoops from 6 flavors (with repetition):");
    for (int[] pick : scoops) System.out.println(java.util.Arrays.toString(pick));
  }
}

What’s going on?


Core building blocks (at a glance)

Concept Fluent entry Returns Notes
Combinations (no rep, lex) Combinations.of(n).choose(k) Iterable<int[]> Lexicographic order; size() = C(n,k)
Combinations (no rep, Gray) Combinations.of(n).choose(k).inGrayOrder() Iterable<int[]> Minimal-change sequence (same set as lex); size() = C(n,k)
Combinations (with repetition) Combinations.of(n).withRepetition().choose(k) Iterable<int[]> Nondecreasing arrays; size() = C(n+k−1,k)
Permutations (k-tuples) Permutations.of(n).take(k) Iterable<int[]> Lexicographic; size() = P(n,k)
Derangements Derangements.of(n).all() Iterable<int[]> No fixed points; size() = subfactorial
Power set PowerSet.of(n) Iterable<int[]> Size-then-lex order; count() = 2^n
Cartesian product CartesianProduct.of(d0,d1,...) Iterable<int[]> Rightmost coordinate varies fastest
Index → object new IndexingAdapter<>(tuples, data) Iterable<List<E>> Defensive copies each step
Binary Gray codes (bitstrings) BinaryGray.of(n).asBits() Iterable<int[]> Minimal-change bit patterns (for demos and visualizations)

Availability: Gray order is provided for combinations without repetition. (With-repetition uses lexicographic nondecreasing tuples.)


Design goals


Reports

API Docs


Tips for students