Rで集合操作を色々やっておく

id:witchmakersと集合位相の勉強会をやっているわけですが、直積とかべき集合とか毎回書き出すのは面倒です。人間のやるべきことではありません。そういうわけで、自分用の集合を生成する関数をRで書いたりしました。

直積

こんな感じで直積を書き出せるようなのを書いてみました。

> write.direct.product(1:3,4:6)
[1] "{(1,4),(2,4),(3,4),(1,5),(2,5),(3,5),(1,6),(2,6),(3,6)}"

関数定義はこんなの。expand.gridのおかげで簡単。

write.direct.product <- function(x,y){
  e <- expand.grid(x,y)
  m <- mapply(function(x,y){paste("(",x,",",y,")",sep="")},e[,1],e[,2])
  return(paste("{",paste(m,collapse=","),"}",sep=""))
}

直積を引数にするような関数とかはこんな感じで書けますね。

> apply(expand.grid(1:3,4:6),1,function(x){x[1]*x[2]})
[1]  4  8 12  5 10 15  6 12 18
> apply(expand.grid(letters[1:3],1:3),1,function(d){Reduce(function(x,init){paste(init,x,sep="")},rep(d[1],d[2]),init="")})
[1] "a"   "b"   "c"   "aa"  "bb"  "cc"  "aaa" "bbb" "ccc"

冪集合

冪集合を生成するようなコードは昔この辺に書いたりしました。

が、もっと簡単にできるはず。ということで書きました。combn関数とかapplyとかがあるから楽すぎた。

powerset <- function(list){
  c(NA,unlist(lapply(seq(length(list)),function(x){apply(combn(list,x),2,function(y){y})}),recursive=FALSE))
}

とりあえず、こんなことができる。

> powerset(list("a","b","c"))
[[1]]
[1] NA

[[2]]
[[2]][[1]]
[1] "a"


[[3]]
[[3]][[1]]
[1] "b"


[[4]]
[[4]][[1]]
[1] "c"


[[5]]
[[5]][[1]]
[1] "a"

[[5]][[2]]
[1] "b"


[[6]]
[[6]][[1]]
[1] "a"

[[6]][[2]]
[1] "c"


[[7]]
[[7]][[1]]
[1] "b"

[[7]][[2]]
[1] "c"


[[8]]
[[8]][[1]]
[1] "a"

[[8]][[2]]
[1] "b"

[[8]][[3]]
[1] "c"

これだと見ずらいので、lapplyを使えば大丈夫。

> lapply(powerset(list("a","b","c")),unlist)
[[1]]
[1] NA

[[2]]
[1] "a"

[[3]]
[1] "b"

[[4]]
[1] "c"

[[5]]
[1] "a" "b"

[[6]]
[1] "a" "c"

[[7]]
[1] "b" "c"

[[8]]
[1] "a" "b" "c"

これを集合っぽく書きたいよね!!ということで書きました。というかskypeとかで簡単にはれるから(ry。

write.list <- function(list){
  write.vector <- function(vector){
    return(paste("{",paste(vector,collapse=","),"}",sep=""))
  }
  write.list.intern <- function(list){
    ifelse(is.list(list),Reduce(function(init,x){paste(init,write.list.intern(x),sep="")},list,""),write.vector(list))
  }
  gsub("NA","",paste("{",gsub("\\}\\{","\\},\\{",write.list.intern(list)),"}",sep=""))
}

これでおk。

> write.list(list("a","b","c","d",list(1:10,list(1,2))))
[1] "{{a},{b},{c},{d},{1,2,3,4,5,6,7,8,9,10},{1},{2}}"
> write.list(lapply(powerset(list("a","b","c","d")),unlist))
[1] "{{},{a},{b},{c},{d},{a,b},{a,c},{a,d},{b,c},{b,d},{c,d},{a,b,c},{a,b,d},{a,c,d},{b,c,d},{a,b,c,d}}"

その他もうちょち書いたんだけど、この辺に書きすてておく。