順列を求める

Javascriptで順列を求める

考えたコード

  function permutations (ary = [ ], r = ary.length) {

    function recursion (ary, r, A = []) {
      if (r == 0)
        return ary.map (a=> A.concat(a));

      let result = [];
      for (let i = 0; i < ary.length; i++) {
        let
          aaa = [...ary],
          a = aaa.splice (i,1);
        result = result.concat (recursion (aaa, r-1, A.concat(a)));
      }
      return result;
    }
    
    return recursion (ary, r -1);
  }


短く1行で

let  permutations=((f=(A,B=A.length,C=[])=>--B?A.reduce((a,b,c,[...d],_=d.splice(c,1))=>[...a,...f(d,B,[...C,b])],[]):A.map(a=>[...C,a]))=>f)();

console.log (permutation([0,1,2,3]));
  • 再帰処理が必要なため、呼び出す関数をfにする
  • [...d] は複写したものを使わないと元を破壊してしまう
  • _=d.splice(c,1)) で配列から1つ削除するが、ここでは配列を返してしまうので使われない。その代わり同等の b を使う。

classで焼き直し(書きかけ)

class Permutation {
  constructor (ary = [ ], r = ary.length) {
    this.ary = ary;
    this.r = r;
  }

  get n () {
    return this.ary.length;
  }

  get length () {
    const fx = this.constructor.factorial;
    let {n, r} = this;
    return fx (n) / fx (n - r);
  }

  *generator (n = 0) {
    for (let i = 0, I = this.length; i < I; i++) {
      yield this.pattern (i);
    }
  }

  pattern (n) {
    if (n < 0 || this.length < n)
      throw new Error ('値が範囲外です');
    /*書きかけ*/
    return n;
  }

  patternAll () {
    return this.constructor.pattern (this.ary, this.r);
  }

  static factorial (n = 1) {
    let r = 1;
    for (let i = n; i > 1; r *= i--) ;
    return r;
  }

  static pattern (ary = [ ], r = ary.length) {
    function recursion (ary, r, A = []) {
      if (r == 0) {
        return ary.map (a=> A.concat(a));
      }
      let result = [];
      for (let i = 0; i < ary.length; i++) {
        let aaa = [...ary], a = aaa.splice (i,1);
        result = result.concat (recursion (aaa, r-1, A.concat(a)));
      }
      return result;
    }
    return recursion (ary, r - 1);
  }
}