Problem 118

1 から 9 の全ての数字を使い、自由につなげることで 10 進数の数字を作り、複数の集合を作ることができる。集合 {2,5,47,89,631} は面白いことに全ての要素が素数である。
1 から 9 の数字をちょうど 1 個ずつ含み、素数の要素しか含まない集合はいくつあるか?

見るからに組み合わせが爆発しそうな問題.並び替え×分割パターンなのでそれはそれは大変なことに.
どうにかこうにか調べる組み合わせを減らして30秒.Rの割によく頑張ったと思う.でも多分まだもうちょっと短縮できる.
今回はgmpの他にcombinatパッケージを使った.順列を列挙するpermn関数などが使えるのでこれもPE進めるのに便利なパッケージだ.

library(combinat)
library(gmp)

v2dig <- function(v) as.numeric(paste(v, collapse=""))
permn2dig <- function(x){
  if(length(x) == 1) return(x)
  unlist(lapply(permn(x), v2dig))
}
  
f <- function(d, last = 0){
  n <- length(d)
  if(n <= 2) return(0)
  ans <- 0
  for(i in 1:(n/2)){
    subs <- combn(d, i)
    coln <- ifelse(i == n/2, ncol(subs)/2, ncol(subs))
    for(j in 1:coln){
      if(last >= v2dig(subs[, j])) next # 小さいものは先に調べているはず
      t <- sum(isprime(permn2dig(subs[, j])) != 0)
      if(t == 0) next
      nextd <- setdiff(d, subs[, j])
      last <- v2dig(subs[, j])
      ans <- ans + t * (sum(isprime(permn2dig(nextd)) != 0) + 
                        Recall(nextd, last))
    }
  }
  return(ans)
}

system.time(f(1:9))