LoginSignup
5
2

More than 3 years have passed since last update.

JavaScript: 順列 / 組み合わせ / 重複順列 / 重複組み合わせ を まとめて関数にしてみた。

Last updated at Posted at 2020-11-07

前にも同じような記事を書いたけど、考えてみれば 重複順列 / 重複組み合わせ も一緒だなあと思い、まとめてみました。

関数版

// 共通の内部再帰関数
const innerPC = filterFunc => selecteds => k => options =>  
  (k === 0)? [selecteds]
  : options.flatMap(
      (e, i) =>
        innerPC( filterFunc )( [...selecteds, e] )( k-1 )( filterFunc(i)(options) ) 
    )

// 順列
const permFilter = i => options =>
  [...options.slice(0, i), ...options.slice(i + 1)]
const perm =  
  innerPC( permFilter )( [] )

// 組み合わせ
const combiFilter = i => options =>
  options.slice(i + 1)
const combi = 
  innerPC( combiFilter )( [] )

// 重複順列
const repPermFilter = i => options =>
  options
const repPerm = 
  innerPC( repPermFilter )( [] )

// 重複組み合わせ
const repCombiFilter = i => options =>
  options.slice(i)
const repCombi = 
  innerPC( repCombiFilter )( [] )

// 使用例:
perm(2)([0, 1, 2])  
/*
[ [ 0, 1 ], [ 0, 2 ], [ 1, 0 ], [ 1, 2 ], [ 2, 0 ], [ 2, 1 ] ]
*/
combi(2)([0, 1, 2])  
/* 
[ [ 0, 1 ], [ 0, 2 ], [ 1, 2 ] ]
*/
repPerm(3)([0, 1])  
/*
[ [ 0, 0, 0 ],
  [ 0, 0, 1 ],
  [ 0, 1, 0 ],
  [ 0, 1, 1 ],
  [ 1, 0, 0 ],
  [ 1, 0, 1 ],
  [ 1, 1, 0 ],
  [ 1, 1, 1 ] ]
*/
repCombi(3)([0, 1]) 
/*  
[ [ 0, 0, 0 ], [ 0, 0, 1 ], [ 0, 1, 1 ], [ 1, 1, 1 ] ]
*/

ジェネレータ版

const innerPCG = filterFunc => selecteds => k => options => function*(){
  if(k===0){ 
    yield  selecteds
    return
  }
  for(const i of options.keys()) {
    yield* innerPCG( filterFunc )( 
      [...selecteds, options[i]] )( k-1 )( filterFunc(i)(options) )
  }
}()

// 順列
const permFilter = i => options =>
  [...options.slice(0, i), ...options.slice(i + 1)]
const permG =  innerPCG( permFilter )( [] )

// 組み合わせ
const combiFilter = i => options =>
  options.slice(i + 1)
const combiG = innerPCG( combiFilter )( [] )

// 重複順列
const repPermFilter = i => options =>
  options
const repPermG = 
  innerPCG( repPermFilter )( [] )

// 重複組み合わせ
const repCombiFilter = i => options =>
  options.slice(i)
const repCombiG = 
  innerPCG( repCombiFilter )( [] )

// 使用例:
;
[...permG(2)([0,1,2])];  
[...combiG(2)([0,1,2])];
[...repPermG(3)([0,1])];
[...repCombiG(3)([0,1])];
// 結果はそれぞれ関数版に同じ

おかしなところがあれば、コメントよろしくです。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2