星期三, 八月 22, 2012

笨办法学R编程(4)

看到各位对“笨办法系列”的东西还比较感兴趣,我也很乐意继续写下去。今天的示例将会用到数据框(data.frame)这种数据类型,并学习如何组合计算两个向量,以及如何排序。我们将用所学的东西来解决Project Euler的第四个问题,就是找出一个集合中最大的回文数。回文数是指一个像1534351这样“对称”的数,如果将这个数的数字按相反的顺序重新排列后,所得到的数和原来的数一样。开始啦!
# 预备练习
 
x <- y <- 1:9
data <- expand.grid(x=x,y=y)
print(data)
z <- data$x * data$y
# 一个九九乘法表
z <- matrix(z,ncol=9)
 
set.seed(1)
x <- round(runif(10),2)
print(x)
order(x)
x[order(x)[1]]
which.min(x)
x[which.min(x)]
x[order(x)] 
y <- 1:10
data <- data.frame(x,y)
class(data)
head(data)
data[1,]
data[,1]
data$x
data[order(data$x),]
 
# Project Euler 4
# 在两个三位数字的乘积中,找出最大的回文数
# 先建立一个将数字顺序进行反转的函数
reverse <- function(n) {
    reversed <- 0
    while (n > 0) {
        reversed <- 10 * reversed + n %% 10
        n <- n%/%10
    }
    return(reversed)
}
 
# 从大到小搜索回文数
x <- y <- 999:100
data <- expand.grid(x=x,y=y)
data$prod <- data$x * data$y
data <- data[order(data$prod,decreasing=T),]
head(data)
value <- data$prod for (i in 1:length(value)) { isequal <- (value[i] == reverse(value[i])) if (isequal) { print(data[i,]) break } }

得到的结果是906609,本例是先将乘积排序后再判断是否回文数,找到的第一个就是答案,所以速度会快一点。如果不用expand.grid函数的话,可以利用嵌套for来组合计算。另外还有一种作法是利用R本身的rev函数,先将数字转为字符,再切开成一串向量,用rev反转后判断。

10 条评论:

  1. 看不明白reverse function是怎么work的。我是用了个笨法子,好在数不是很多:
    a<-c()
    for(n in 999:100){
    for(m in 999:100){
    aa=m*n
    aa=as.character(aa)
    aa=unlist(strsplit(aa,""))
    bb=paste(aa,collapse="")
    cc=paste(rev(aa),collapse="")
    if(bb==cc) a<-c(a, m*n)
    }
    }
    max(a)

    回复删除
    回复
    1. 这个法子是可以的,转成字符嘛。例子中的reverse函数是用求余数的方法将个位上的数字提取,然后转到十位上去,十位上的数字用整除变成个位数,如此循环。

      删除
  2. 我写了个投机取巧的计算方法。把100-999的所有三位数作为两个向量x和y,然后把x和y每一项的乘积作为一个矩阵,再把矩阵转化为一个向量,从大到小验证向量的所有值,找出其中最大的一个回文数。

    x = 100:999
    y = t(100:999)
    mat = x %*% y
    vec = as.vector(sort(mat))
    i = 810000
    while (i > 0){
    product = as.character(vec[i])
    reverse = paste(rev(strsplit(product,'')[[1]]),collapse='')
    if (reverse == product) break
    i = i - 1
    }
    print(product)

    回复删除
    回复
    1. 这样做也蛮好,但就是没法知道是哪两个数字相乘得到的最终结果。

      删除
  3. 请指教:
    data <- data[order(data$prod,decreasing=T),]
    head(data) // 这句是用来检测 order 的结果的吗?


    value <- data$prod

    回复删除
  4. 最后一个搜索回文数的程序 我运行了好久都没运行出来 请问一下博主该程序的运行时间大概是多久?

    回复删除
  5. 可能是我电脑昨天有问题了 今天再运行就很快 ~

    回复删除