条件付きの01文字列を列挙する

  • こちらの第2コメントの処理から
  • 0,1以外を文字変数にしようという話から派生している話題
  • 行数やリストの要素数も、神の数か、指定した数(こちらは文字変数で表す)ことにすると…
  • 処理自体は以下のようになるのかと思われる
  • 検算していない…
# 次のような文字列を作る
# 0と1とでできている
# 先頭が1である
# 連続する0の数はMax0concatとする
# Max0concat = 1,2,...
# 1はいくら連続してもよい
# distinctな文字列とする
# 繰り返し処理の上限Niterを与えて処理が有限となるようにする
# Niter = 1,2,...
Max0concat<-3 # ヒットの種類数は Max0concat+1
Niter<-3 # ヒット本数上限
  • 処理:ここから先は、数値は1しか出てこない、処理行数も1行だけ
Nh<-Max0concat+1 # ヒットの種類数 ※2以上であること
# 先頭が1で、0が0...Max0concat個後続する文字列リストを作る
as<-rep(list(c()),Nh)
for(i in 1:Nh){
	as[[i]]<-c(1,rep(0,i-1))
}
res<-as
for(i in 1:Niter){
	tmpres<-list()
	for(j in 1:Nh){
		tmpres<-append(tmpres,lapply(res,append,as[[j]],after=FALSE))
	}
	res<-append(res,tmpres)
}
res
  • 連続0数を振ってやり、繰り返し処理数を振った上で、得られる文字列数を調べてみる
Max0concats<-1:5 # Max0concatを1から5まで
Niters<-1:5 # 繰り返し処理数を1から5まで

MN<-expand.grid(Max0concats,Niters)

#numseqs<-rep(0,length(MN[,1]))
numseqs<-matrix(0,length(Max0concats),length(Niters))
for(x in 1:length(MN[,1])){
	Max0concat<-MN[x,1]
	Niter<-MN[x,2]

Nh<-Max0concat+1 # ヒットの種類数 ※2以上であること

# 先頭が1で、0が0...Max0concat個後続する文字列リストを作る
as<-rep(list(c()),Nh)
for(i in 1:Nh){
	as[[i]]<-c(1,rep(0,i-1))
}
res<-as
for(i in 1:Niter){
	tmpres<-list()
	for(j in 1:Nh){
		tmpres<-append(tmpres,lapply(res,append,as[[j]],after=FALSE))
	}
	res<-append(res,tmpres)
}
numseqs[Max0concat,Niter]<-length(res)


}
persp(log(numseqs))
  • 上の方法では本当にdistinctなのだろうか…
  • 指定人数までのヒットの連続パターンを知るだけならば、順列関数でできる
Nh<-4 # Nhを指定することにしよう
Niter<-3
Nb<-3 # ベース数
# ヒットの連続パターンは、1からNhまで
hits<-1:(Nh)
as<-rep(list(c()),Nh)
for(i in 1:Nh){
	as[[i]]<-c(1,rep(0,i-1))
}
library(gtools) # permutations()関数を使う
# リストにすべての順列(長さが1からNhまで)を格納
seqs<-NULL
for(i in 1:Niter){
	seqs<-append(seqs,list(permutations(n=Nh,i,repeats.allowed=TRUE)))
}
# 累積加算使用
# リストがベクトルを持っているので、lapply()の中でapply()を使う
cumsumseqs<-lapply(seqs,apply,1,cumsum)
# さて、ここで、Nb以下の数値の個数が残塁数、Nbより大の数値の個数が得点…
# それを簡単な関数で出すのがよくわからない
# と、思ったけれど…、ちょっと休憩して考え直す
# 残塁の人を負の数に、得点の人を正の数にする
cumsumseqs2<-lapply(cumsumseqs,"-",Nb+0.5)
# 正負判定をする(正なら1、負なら−1)
cumsumseqs3<-lapply(cumsumseqs2,sign)
# 正を2、負を0にして
cumsumseqs4<-lapply(cumsumseqs3,"+",1)
# 正を1、負を0にする
cumsumseqs5<-lapply(cumsumseqs4,"/",2)
# lpplay()の中でapply()を列に使おうとすると、人数が1のときに行列になっていないのでエラーが出る
# それを回避するために、行列の転地をして
cumsumseqs6<-lapply(cumsumseqs5,"t")
# 1の人数を足し合わせる
# これが各順列の得点
points<-lapply(cumsumseqs6,apply,1,sum)
# 各順列の生起確率はヒットタイプを表す数値をそれぞれのヒットタイプの生起確率の対数に変換して
# sum()して指数関数で戻す