// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.

/**
 * Builds all possible orders of all elements in the given array
 * Ignores equality of elements, meaning this will always return the same
 * number of permutations for a given length of input.
 *
 * @template T The type of the elements in the array.
 *
 * @param inputArray The array to build permutations from.
 *
 * @returns An array of all possible permutations of the given array.
 *
 * @example Basic usage
 * ```ts
 * import { permutations } from "@std/collections/permutations";
 * import { assertEquals } from "@std/assert/assert-equals";
 *
 * const numbers = [ 1, 2 ];
 * const windows = permutations(numbers);
 *
 * assertEquals(windows, [
 *   [ 1, 2 ],
 *   [ 2, 1 ],
 * ]);
 * ```
 */
export function permutations<T>(inputArray: Iterable<T>): T[][] {
  const result: T[][] = [];

  const array = [...inputArray];

  const k = array.length;

  if (k === 0) {
    return result;
  }

  // Heap's Algorithm
  const c = new Array<number>(k).fill(0);

  result.push([...array]);

  let i = 1;

  while (i < k) {
    if (c[i]! < i) {
      if (i % 2 === 0) {
        [array[0], array[i]] = [array[i], array[0]] as [T, T];
      } else {
        [array[c[i]!], array[i]] = [array[i], array[c[i]!]] as [T, T];
      }

      result.push([...array]);

      c[i] += 1;
      i = 1;
    } else {
      c[i] = 0;
      i += 1;
    }
  }

  return result;
}

// denoCacheMetadata={"headers":{"x-jsr-backend":"modules","server":"cloudflare","access-control-allow-origin":"*","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=5sA0BvgVedGKGyIqz6DUgMPW424DKabPjVkOBvlGC5wIGBiWyNfqX%2BVVYsZWXa0aJX18UOyaCOOH4ausv7Q6UVCcG%2FMgZHoMTTa8Zkp4sfrSD1b0aeFRr%2BA%3D\"}]}","cf-ray":"a223e6564f2d7db6-LAX","cache-control":"public, max-age=31536000, immutable","content-security-policy":"default-src 'none'; script-src 'none'; style-src 'none'; img-src 'none'; font-src 'none'; connect-src 'none'; frame-src 'none'; object-src 'none'; frame-ancestors 'none'; sandbox; form-action 'none';","x-content-type-options":"nosniff","set-cookie":"__cf_bm=KRdGSuniRY0ppmuL.GT6uzU5cb6NC0XX2AEQnfPTDrI-1785241874.9626446-1.0.1.1-cIfDGQfn1gKI5MotpskMkbzKHZhpfI9V6dYtThnhQjDg2CDH8TLqyVDn6B8ztmt_kZSNqMuAhjgmnXnfvRvnL3pv9FFQOlbiaD_HZAHea21S42ldxNiU1cL1DAzljTcO; HttpOnly; SameSite=None; Secure; Path=/; Domain=jsr.io; Expires=Tue, 28 Jul 2026 13:01:15 GMT","content-type":"text/typescript","access-control-expose-headers":"*","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","content-length":"1479","etag":"\"3d0981a42a66dcd182dc00314a39d291\"","vary":"Origin","cross-origin-resource-policy":"cross-origin","x-robots-tag":"noindex","date":"Tue, 28 Jul 2026 12:31:15 GMT","alt-svc":"h3=\":443\"; ma=86400"},"url":"https://jsr.io/@std/collections/0.224.2/permutations.ts","time":1785241875}