permutations function

dynamic permutations(
  1. dynamic n,
  2. dynamic rInput, {
  3. Function? func,
  4. bool simplify = true,
  5. Random? random,
  6. int? seed,
})

Generates all permutations of elements from n taken r at a time.

Mimics the behavior of the sample function in R.

Parameters:

  • n:
    • If n is a positive integer, generates permutations from 1 to n.
    • If n is a List, generates permutations from the elements of the list.
  • r: The number of elements to take in each permutation (must be between 1 and the length of n).
  • func (optional): A function to apply to each permutation.
  • simplify (optional, default: true):
    • If true, returns a flat List of results from applying func to each permutation.
    • If false, returns a List of Lists, where each inner list contains the permutation and the result of applying func.
  • seed (optional): A seed value for the random number generator to ensure repeatability.
  • random (optional): Random number generator to ensure repeatability.

Note: When simplify is true, the structure of the result depends on the output of func for the first permutation. This might cause issues if func doesn't produce consistent output lengths.

Examples:

print(permutations(3, 2)); // [[1, 2], [2, 1], [1, 3], [3, 1], [2, 3], [3, 2]]

Implementation

dynamic permutations(dynamic n, dynamic rInput,
    {Function? func, bool simplify = true, Random? random, int? seed}) {
  int r = rInput is Complex ? rInput.real.toInt() : (rInput as num).toInt();
  if (random == null) {
    random = seed != null ? Random(seed) : Random();
  } else if (seed != null) {
    throw ArgumentError("Cannot provide both seed and random");
  }

  if (n is int) {
    n = List<int>.generate(n, (i) => i + 1);
  } else if (n is! List) {
    throw ArgumentError("x must be an integer or a List");
  }
  if (r < 1 || r > n.length) {
    throw ArgumentError("m must be between 1 and the length of x");
  }

  List<List> result = [];

  void generatePermutations(int index, List<dynamic> current) {
    if (index == r) {
      result.add(List.from(current));
      return;
    }

    for (int i = 0; i < n.length; i++) {
      if (!current.contains(n[i])) {
        current.add(n[i]);
        generatePermutations(index + 1, current);
        current.removeLast();
      }
    }
  }

  generatePermutations(0, []);

  if (func != null) {
    if (simplify) {
      return result.map((perm) => func(perm)).toList();
    } else {
      return result.map((perm) => [perm, func(perm)]).toList();
    }
  } else {
    return result;
  }
}