GAIさんへのお返事です。
> 実際の配列と、これを一般化(個数を変えたり、種類を増やしたりできるように・・・)
> するにはどんなプログラムなのか?
No.1199[元記事へ] または No.1200[元記事へ]では、
(直線)順列が生成できるので、これを元に作成できると思います。
ただ、符号化・復号化、辞書順による生成ができませんので、
「パターンそのもの」を記録して、既出のものかどうかのチェックになると思います。
具体例は以下のプログラムを参考にしてください。
「問題1」は、(1つ前段階ですので)そのサンプルを掲載します。
「エラトステネスの篩い」のように、辞書順(自然数の小さい順)にパターンを生成して、
その対称のもの(倍数)を除いていきます。
「篩い」は、符号化・復号化して「0以上の整数」で管理しています。
!白2個、赤2個、青2個を円順列にした場合の数は?
LET N=3 !異なる色の数
DATA 2,2,2 !(白,赤,青)の個数
!PUBLIC STRING S$
LET S$="白赤青"
DIM C(N) !それぞれの個数
MAT READ C
LET S=0 !総数
FOR i=1 TO N
LET S=S+C(i)
NEXT i
IF S<R THEN
PRINT "数が足りません。";S
STOP
END IF
DIM G(S) !(白,赤,青)の並び
MAT G=ZER
DIM F(0 TO PermFactorialM(C,N)-1) !篩い
MAT F=ZER
LET x=0
FOR i=0 TO PermFactorialM(C,N)-1 !「同じものを含む順列」を円型に並べる
CALL Num2PermFactorialM(i, G,S,C,N)
IF F(i)=0 THEN
!MAT PRINT G;
FOR k=1 TO S !「素」の並びを表示する
PRINT S$(G(k):G(k));
NEXT k
PRINT
LET x=x+1 !+1
!!!CALL FilterNecklace(F,G,S,C,N) !反転(裏返し) ※数珠順列 ←←←←←
FOR j=1 TO S-1 !篩いにかける
LET w=G(1) !右シフト ※時計まわりに回転する
FOR k=1 TO S-1
LET G(k)=G(k+1)
NEXT k
LET G(S)=w
LET F(PermFactorialM2Num(G,S,C,N))=1 !この並びは対称なため削除する
!!!CALL FilterNecklace(F,G,S,C,N) !反転(裏返し) ※数珠順列 ←←←←←
NEXT j
END IF
NEXT i
PRINT "場合の数=";x
END
EXTERNAL SUB FilterNecklace(F(),G(),S,C(),N) !反転(裏返し)の篩い
DIM GR(S)
MAT GR=G !反転(裏返し)
CALL reverse(GR,S)
LET F(PermFactorialM2Num(GR,S,C,N))=1 !この並びは対称なため削除する
END SUB
EXTERNAL SUB reverse(A(),N) !並びを逆順にする
FOR i=1 TO INT(N/2)
LET t=A(i) !swap it
LET A(i)=A(N-i+1)
LET A(N-i+1)=t
NEXT i
END SUB
EXTERNAL FUNCTION PermFactorialM(B(),M) !同じものを含む順列の「場合の数」 (p+q+ … +r)!/(p!*q!* … *r!)通り
LET s=B(M) !総数 r, … ,q+ … +r,p+q+ … +r
LET t=1 !組合せ comb(r,r), … ,comb(q+ … +r,q),comb(p+q+ … +r,p)
FOR i=M-1 TO 1 STEP -1
LET s=s+B(i)
LET t=t*COMB(s,B(i)) !組合せ順列
NEXT i
LET PermFactorialM=t
END FUNCTION
EXTERNAL FUNCTION PermFactorialM2Num(A(),N,B(),M) !順列パターンに番号を付ける ※辞書式順序
DIM w(M)
MAT w=B !copy it
LET v=0
FOR i=1 TO N-1 !左端に着目する
LET t=A(i)
FOR j=1 TO t-1 !左端を1~A(i)-1として
IF w(j)>0 THEN !その左端を除いた残りで最大の順列をつくる
LET w(j)=w(j)-1
!!!MAT PRINT w; !debug
LET v=v+PermFactorialM(w,M) !その順列の番号を求める
LET w(j)=w(j)+1
END IF
NEXT j
LET w(t)=w(t)-1 !左端を消して、次へ
NEXT i
LET PermFactorialM2Num=v
END FUNCTION
EXTERNAL SUB Num2PermFactorialM(h, A(),N,B(),M) !番号から順列パターンを生成する ※辞書式順序
DIM w(M)
MAT w=B !copy it
LET v=h
FOR i=1 TO N
FOR j=1 TO M !左端を1~Mとして
IF w(j)>0 THEN !その左端を除いた残りで最大の順列をつくる
LET w(j)=w(j)-1
!!!MAT PRINT w;
LET t=PermFactorialM(w,M) !その順列の番号を求める
IF v<t THEN EXIT FOR
LET v=v-t
LET w(j)=w(j)+1
END IF
NEXT j
LET A(i)=j !次へ
NEXT i
END SUB
> これは式で書けるのでしょうか?
円順列 数珠順列
異なるn個から
すべて (n-1)! (n-1)!/2
重複を許さず r個選ぶ comb(n,r)*(r-1)! comb(n,r)*(r-1)!/2
重複を許して r個選ぶ ? ? ← 問題2
同じものがp個、q個、…、r個ずつから
すべて ? ? ← 問題1
重複を許さず r個選ぶ ? ?
問題1は、メビウス関数、オイラー関数を使って表現できたと思います。