エクセルで順列列挙(順列の書き出し)
作りやすさから尾固定循環型(仮)を採用
(前頁「配列・ベクトル・行列(6)」の順列の種類で言うと4.尾固定小行列循環シフト型(仮) r070404追記)
まずは半自動・半手作業で作成してみる
1行目のF11:K11部分(薄緑色)は
F11= 1
G11= =F11+1
11行= G11を必要部分までコピペ(今回はG11:L11)
2x2行列に対応する順列増分(下に拡張)(薄青色)
F12= =MOD(F11-2,2)+1
G12= F12をコピペ
3x3行列に対応する順列増分(右に拡張)(薄赤色)
H12= =H11
3x3行列に対応する順列増分(下に拡張)(薄青色)
F13= =MOD(F11-2,3)+1
F13:H16= F13をコピペ
4x4行列に対応する順列増分(右に拡張)(薄赤色)
I12= =I11
I12:I16= I12をコピペ
4x4行列に対応する順列増分(下に拡張)(薄青色)
F17= =MOD(F11-2,4)+1
F17:I34= F17をコピペ
5x5行列に対応する順列増分(右に拡張)(薄赤色)
J12= =J11
J12:J34= J12をコピペ
5x5行列に対応する順列増分(下に拡張)(薄青色)
F35= =MOD(F11-2,5)+1
F35:J130= F35をコピペ
以下同様 (不正確さを減らすため「順列」を「順列増分」に修正 r070404)
次に作業セル(A~D列)を駆使して全て同じ式にしたバージョン
A列= データの行番号
A11= =ROW()-ROW($F$11)+1
A11:A733= A11をコピペ
B列= A列の「階乗の逆関数」の切り上げ(「階乗の逆関数」は用意できなかったので代替手段で)
B11= 1
B12= =IF(C11<A12,1,0)+B11
B12:B733= B12をコピペ
C列= B列の階乗
C11= =FACT(B11)
C11:C733= C11をコピペ
D列= B列-1の階乗
D11= =FACT(B11-1)
D11:D733= D11をコピペ
F~L列= ifで場合分けして順列部分全てを1つの式にまとめた
F11= =IF($A11>1,IF(F$11>$B11,F$11,MOD(INDIRECT("r[-"&$D11&"]c[0]",0)-2,$B11)+1),F$9)
F11:L733= F11をコピペ
(列の説明はr070404に追記)
作業セルA~D列を使わずに同一の式で順列を列挙して行列式も計算した
F11= =IF(ROW()-ROW($F$11)+1>1,IF(F$11>MATCH(ROW()-ROW($F$11),FACT({1,2,3,4,5,6,7}),1)+1,F$11,MOD(INDIRECT("r[-"&(FACT(MATCH(ROW()-ROW($F$11),FACT({1,2,3,4,5,6,7}),1)))&"]c[0]",0)-2,MATCH(ROW()-ROW($F$11),FACT({1,2,3,4,5,6,7}),1)+1)+1),COLUMN()-COLUMN($F$11)+1)
F11:L733= F11をコピペ
Q11= {=-1^SUM(IF({1;2;3;4;5;6;7}<{1,2,3,4,5,6,7},1,0)*IF(TRANSPOSE($F11:$L11)>$F11:$L11,1,0))} (配列数式)
Q11:Q733= Q11をコピペ
R11= =INDEX($R$1:$X$7,F11,R$9)
R11:X733= R11をコピペ
Z11= =PRODUCT($Q11:S11)
Z11:Z12= Z11をコピペ
AA11:AA16= Z11をコピペ
AB11:AB34= Z11をコピペ
AC11:AC130= Z11をコピペ
AD11:AD730= Z11をコピペ
Z7= =SUM(Z11:Z733)
Z7:AD7= Z7をコピペ
Z5= =MDETERM(R1:S2)
AA5= =MDETERM(R1:T3)
AB5= =MDETERM(R1:U4)
AC5= =MDETERM(R1:V5)
AD5= =MDETERM(R1:W6)
余談1 Q11について r070404追記
次頁「配列・ベクトル・行列(8)」で説明
余談2 mod関数について r070404追記
mod関数は「0始まりの循環(仮)」(正しい単語が分からない)なので、順列で利用するために「1始まりの循環(仮)」に修正する
=mod(対象-1, 循環の数)+1
そしてそれではただの同じ数になってしまうので循環させるために対象を「+1」か「-1」する。「+1」は今回の順列列挙において「・・・3 2 1」で終了しないので「-1」を採用
=mod(対象-1-1, 循環の数)+1
この式がこの頁の最初の図の薄青部分
余談3 r070404追記
2番目の画像の「階乗の逆関数」の切り上げの代替手段について
b12= {=match(A12-1,fact({1,2,3,4,5,6,7}),1)+1} (配列数式 エクセル・リブレオフィス)
b12= =ArrayFormula(match(A12-1,fact({1,2,3,4,5,6,7}),1)+1) (配列数式 グーグルドライブ)
もし大きい数が必要なら配列定数を拡大したり配列セル式(仮)(column(範囲))を活用すればよい
余談4 r070425追記
たとえば「現セルの6つ上」を今回はindirect関数とr1c1形式を使って実現した。検索してみると他にも使えそうな方法があるようなので後で試してみたい。
1. indirect関数とaddress関数(こっちの方が正統派かも)
2. offset関数(循環参照になりそう?)
ただindirect関数もoffset関数も揮発性関数と言って処理が重くなるので可能なら避けた方が良いらしい。index関数で実現できないかも試してみたい。