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はもっとわかりやすくなりそう。