• 软件
  • 看到一个有意思的题目:a~z,0:9,所有3位的密码组合

这样想的:8种情况:

Letter代表字母,Num代表数字:

1:LLL

2:LLN

3:LNL等等

<br />
Letter=letters<br />
Num=0:9<br />
LLL=outer(outer(Letter,Letter,"paste"),Letter,"paste")<br />
等等:<br />
NNN=outer(outer(Num,Num,"paste"),Num,"paste")<br />


算法有点暴力,期待更好的算法!
</p>

<br />
result=array(NA,dim=c(36,36,36))<br />
str=c(letters,0:9)<br />
for(i in 1:36){<br />
  for(j in 1:36){<br />
    for(k in 1:36){<br />
      result[i,j,k]=outer(outer(str[i],str[j],"paste"),str[k],"paste")<br />
    }<br />
  }<br />
}<br />


这种方法仍然很暴力,期待更好的算法。
</p>

抱歉,1楼,2楼算法太过脑残:

<br />
str=c(letters,0:9)<br />
result=outer(outer(str,str,"paste"),str,"paste")<br />
</p>

是的 要避免使用循环,尽可能使用R内置的向量化运算函数.outer应该就是.

如何把 result [36x36x36 的一个超大矩阵.] 按元素 取出来 按行写入到文本文件呢 ?

回复 第4楼 的 simbabest:outer应该不是向量化运算函数。至于怎样写入文本文件,还没有想到。

回复 第7楼 的 simbabest:

确实

另外,既然是生成密码,那么你的例子里面用paste0函数,比paste函数更好。

显然 这里要求可以重复的 .

比如取 aaa ,aab ,abb,aba,bbb 都是可以的

combn 是排列组合 ,不放回的取样.

弄个小点的样本说明问题

<br />
> combn(c('a','b','c','d','e'),3)<br />
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]<br />
[1,] "a"  "a"  "a"  "a"  "a"  "a"  "b"  "b"  "b"  "c"<br />
[2,] "b"  "b"  "b"  "c"  "c"  "d"  "c"  "c"  "d"  "d"<br />
[3,] "c"  "d"  "e"  "d"  "e"  "e"  "d"  "e"  "e"  "e"<br />
</p>

回复 第5楼 的 zjgslxh:

outer 函数:

<br />
function (X, Y, FUN = "*", ...)<br />
{<br />
    if (is.array(X)) {<br />
        dX <- dim(X)<br />
        nx <- dimnames(X)<br />
        no.nx <- is.null(nx)<br />
    }<br />
    else {<br />
        dX <- length(X)<br />
        no.nx <- is.null(names(X))<br />
        if (!no.nx)<br />
            nx <- list(names(X))<br />
    }<br />
    if (is.array(Y)) {<br />
        dY <- dim(Y)<br />
        ny <- dimnames(Y)<br />
        no.ny <- is.null(ny)<br />
    }<br />
    else {<br />
        dY <- length(Y)<br />
        no.ny <- is.null(names(Y))<br />
        if (!no.ny)<br />
            ny <- list(names(Y))<br />
    }<br />
    if (is.character(FUN) && FUN == "*") {<br />
        robj <- as.vector(X) %*% t(as.vector(Y))<br />
        dim(robj) <- c(dX, dY)<br />
    }<br />
    else {<br />
        FUN <- match.fun(FUN)<br />
        Y <- rep(Y, rep.int(length(X), length(Y)))<br />
        if (length(X))<br />
            X <- rep(X, times = ceiling(length(Y)/length(X)))<br />
        robj <- FUN(X, Y, ...)<br />
        dim(robj) <- c(dX, dY)<br />
    }<br />
    if (no.nx)<br />
        nx <- vector("list", length(dX))<br />
    else if (no.ny)<br />
        ny <- vector("list", length(dY))<br />
    if (!(no.nx && no.ny))<br />
        dimnames(robj) <- c(nx, ny)<br />
    robj<br />
}<br />
<bytecode: 0x07f2d728><br />
<environment: namespace:base><br />


不好意思,知识浅薄 我也看不粗来 它是不是向量化运算.
</p>

回复 第6楼 的 doctorjxd:

combn(rep(mystr,3), 3)会将重复的三个1,当成三个不同的字符处理。

题中要求的结果是36^3个,而combn(rep...)之后结果的个数为choose(36*3, 3)个。

x = c(letters, 0:9)
do.call(paste0, expand.grid(x, x, x))

回复 第9楼 的 namgalsip:

确实,会造成很多重复的。

还是肖版的方法简捷。

苹果楠童鞋 call然后拿来do 果然高端大气上档次!

回复 第12楼 的 zjgslxh:

买苹果吧,买了以后你也能写出来 [s:11]

回复 第13楼 的 肖楠:

[s:15]为什么我用苹果也写不出来……

回复 第14楼 的 yanlinlin82:[s:11]说明您不是用5s,果断换。[s:13]

回复 第14楼 的 yanlinlin82:

要用最新的顶配版,这样灵感才够足 [s:17]

回复 第10楼 的 肖楠:

大神的世界 好难懂 [s:12]

求解释 ,直接调用paste0 和do.call 调用 居然不一样:

<br />
> z<-expand.grid(c(1,2,3),c(1,2))<br />
> z<br />
  Var1 Var2<br />
1    1    1<br />
2    2    1<br />
3    3    1<br />
4    1    2<br />
5    2    2<br />
6    3    2<br />
> paste0(z)<br />
[1] "c(1, 2, 3, 1, 2, 3)" "c(1, 1, 1, 2, 2, 2)"<br />
> do.call(paste0,z)<br />
[1] "11" "21" "31" "12" "22" "32"<br />


另外 ,追问一句 outer函数 到底是向量化运算不?上面贴了代码 但我看不出来..
</p>

如果l=list(a=c(1:4),b=c(2:3))

那么第一个子表个数为4,第二个子表的个数为2,则对各子表按照下面这样来组合,应该怎么实现呢?

do.call(paste0, expand.grid(l[[1]], l[[1]], l[[1]], l[[1]] ))

do.call(paste0, expand.grid(l[[2]], l[[2]]))

回复 第17楼 的 simbabest:

do.call(paste0, z) 的目的是把列表中的值,分别作为参数,传递给目标函数。

相当于 paste0(z$Var1, z$Var2)

你直接paste0(z),那么就只有z一个参数。

怎么感觉这个情境跟我的两篇日志有关(肖帮主当时还帮我纠正了一个错误):

http://yihui.name/en/2013/01/find-out-available-usernames-with-r/

http://yihui.name/en/2012/08/stupid-iastate-password-rules/