いきなり答える備忘録

Google Workspace・Microsoft 365・LibreOfficeなどに関するメモ

(Gスプレッドシート)順列を列挙する

 Googleスプレッドシートで順列を列挙する方法、具体的にはn個の値を重複なく取り出す順番の組み合わせを列挙する方法についてです。
 n!通りの値と対応付ける方法も可能ですが手順が長くなるため、以下では計算量を度外視して1つの式で済ませる方法をとっています。

  • 各種関数の組み合わせにより順列を列挙することが可能です。
  • ただし以下の方法では計算の無駄が多いためn=6あたりで相当重くなります。

手順

 画像はB2セルに式を入力し、n=3のときの順列を出力した結果、つまり3つの値(0,1,2)を取り出す順番をすべて列挙した結果です。
 順列は6通りありますので6行に渡って結果が出力されています。

f:id:accs2014:20200223154355p:plain:w750

 B2セルには入力されている式は次のようなものです。

=FILTER(BASE(SEQUENCE(3^3-1),3,3),REGEXREPLACE("012","["&BASE(SEQUENCE(3^3-1),3,3)&"]","")="")

 FILTER関数の第1引数ではBASE関数とSEQUENCE関数の組み合わせにより「001」から「222」までの26通りの値(文字列)を出力しています。
 一方で第2引数でも同じ文字列を生成し、REGEXREPLACE関数と組み合わせることで「0」「1」「2」の3種の数字を含んでいるかチェックしています。即値で例を挙げると「210」は3種の文字すべての数字を含んでいるため「REGEXREPLACE("012","[210]","")」は空文字列を返しますし、「211」は3種の文字を含んでいないため「REGEXREPLACE("012","[211]","")」は「0」を返します。つまりREGEXREPLACEが空文字を返したら順列と判断するというわけです。

 なお、nを増やす場合は8か所ある「3」の値を変更し、さらに中央付近にある「"012"」を「"0123"」(n=4のとき)などに変更する必要があります。
 

 実際にn=4にしたときの結果です。

f:id:accs2014:20200223154359p:plain:w750

 式は次のようになります。

=FILTER(BASE(SEQUENCE(4^4-1),4,4),REGEXREPLACE("0123","["&BASE(SEQUENCE(4^4-1),4,4)&"]","")="")

 255通りの候補を調べたうえで、24通りの順列を得ています。
 計算に無駄が多いためn=6(順列は720通り)で数秒待たされるようになり、実用的ではなくなってきます。結果が得られたら値に置き換えた方が賢明かと思います。
 

 なお、実用上はそれぞれの数字を配列(セル)に分割する必要があります。
 そこまで含めて行う式の例は次のようなものになります。

f:id:accs2014:20200223154404p:plain:w780

=FILTER(SPLIT(REGEXREPLACE(BASE(SEQUENCE(4^4-1),4,4),"","_"),"_"),REGEXREPLACE("0123","["&BASE(SEQUENCE(4^4-1),4,4)&"]","")="")