combination&permutation

書くのは楽しいけどあとから読んでもよーわからん。carとcdrが逆だった。付け焼刃は怖い。
Pの意味は2個のときに順番入れ替えるもの?
Cは1個のときにそれ自身があるかないか?

Array.prototype.reduce = function (fn, initialValue) {
  return ( this.length == 0 ) ? initialValue : this.slice(1).reduce(fn, fn(this[0], initialValue));  
};
function $A(nodes) {
        var a = [];
        for (var i = 0; i < nodes.length; i++) {
            var n = (nodes[i]);
                a.push(n);
        }
        return a;
}

Array.prototype.flatten = function () {
    var a = []
    for (var i = 0; i < this.length; i++){
        if ( this[i] instanceof Array ) 
                a = a.concat(this[i]);
        else
            a.push();
    }
    return a;
};

function combination() {
    var arg = $A(arguments);
    var car = arg.shift();

    if ( arguments.length == 0) {
            return [ [] ];
    } else {
        return [ [car], [] ].map( function (n) {
               return combination.apply(this, arg).map( function (m) {
                            return (n.concat(m));
                } );
        } ).flatten();
    }
}

function permutation() {
    var args = $A(arguments);
    if ( args.length == 2 ) {
        return [args, args.slice(0).reverse()];
    } else if ( args.length < 2 ) {
        return [args];
    } else {
        return args.map ( function (car) {
            var remains = args.filter ( function (i) { return i != car } );
            var sub = permutation.apply( this, remains );
            return sub.map( function (p ) {
                return [car].concat( p );
            } ) ;
        }).flatten();
    }
} 


combination.apply(this, [1,2,3] ).map( function (i) {
         return permutation.apply(this,i)
} ).flatten();




flatとreduce+concatはおんなじ。

function range(n) {
    var a = [];
    do { a.push(n); } while (--n) ;
    return a;
}

[1,2,3,4].reverse().map( function (n ) {
    return range(n);
} );

こうかいたやつが

[1,2,3,4].reverse().map( function (n ) {
    return range(n);
} ).flatten();


[1,2,3,4].reverse().reduce( function (n, m ) {
    return m.concat( range(n) );
}, [] );

どっちでもかけるけどflatのほうが書くのが楽。

combinationはもっとわかりやすくなりそう。