分享

笨办法学R编程(二)

本帖最后由 xioaxu790 于 2014-7-4 15:49 编辑
问题导读:
1、如何编写for循环、和自定义函数?
2、什么是sapply函数?




经历了前面两个小挑战,你应该对R有点理解了。我们继续推进,今天的问题有点点复杂,复杂的不是R,而是一个数学概念:质数和质因子。任何一个合数都可以被几个质数所分解,这个性质很重要,我们将用它来解决Project Euler的第三个问题。还是和之前一样的,你需要自己在R控制台中敲打下面这些命令,根据结果自行揣摩其用处。
  1. # 预备练习,学习for循环、建立自定义函数和其它一些函数
  2. for (n in 1:10) {
  3. print(sqrt(n))}
  4. x <- c('hello','world','I','love','R')
  5. for (n in x) {
  6. print(n)}
  7. x <- seq(from=1,to=10,by=1)
  8. print(x)
  9. x <- seq(from=1,to=10,by=2)
  10. print(x)
  11. x <- seq(from=1,to=2,length.out=10)
  12. print(x)round(x)
  13. x > 1.5
  14. all(x>1.5)
  15. any(x>1.5)
  16. # 如何自定义一个求圆面积的函数
  17. myfunc <- function(r) {
  18. area <- pi*r^2
  19. return(area)
  20. }
  21. print(myfunc(4))
  22. # 同时求四个不同半径圆的面积
  23. r <- c(2,2,4,3)
  24. sapply(X=r,FUN=myfunc)
  25. # Project Euler 3
  26. # 找到600851475143这个数的最大质因子
  27. # 先建立一个函数以判断某个数是否为质数
  28. findprime <- function(x) {
  29. if (x %in% c(2,3,5,7)) return(TRUE)
  30. if (x%%2 == 0 | x==1) return(FALSE)
  31. xsqrt <- round(sqrt(x))
  32. xseq <- seq(from=3,to=xsqrt,by=2)
  33. if (all(x %% xseq !=0)) return(TRUE)
  34. else return(FALSE)
  35. }
  36. # 列出1到100的质数,看函数对不对
  37. x = 1:100
  38. x[sapply(x,findprime)]
  39. # 寻找最大的质因子
  40. n <- 600851475143
  41. for (i in seq(from=3, to=round(sqrt(n)), by=2)) {
  42. if (findprime(i) & n %% i == 0) {
  43. n <- n / i
  44. prime.factor <- i
  45. if (i >= n)
  46. break
  47. }
  48. }
  49. print(prime.factor)
复制代码

最后的结果是6857。本例中除了使用for循环外,还见到了sapply函数,这是R语言中非常重要的一类向量化计算函数。求质数的方法可以参考这个文章,本例使用的是其中的境界4。实际上根据质因子的性质,本例不一定非要建立判断质数的函数,不过这个函数我们在后面会用到的。另外如果你想用其它软件找这个数字的质因子,也可以看看这里。


看到各位对“笨办法系列”的东西还比较感兴趣,我也很乐意继续写下去。今天的示例将会用到数据框(data.frame)这种数据类型,并学习如何组合计算两个向量,以及如何排序。我们将用所学的东西来解决Project Euler的第四个问题,就是找出一个集合中最大的回文数。回文数是指一个像1534351这样“对称”的数,如果将这个数的数字按相反的顺序重新排列后,所得到的数和原来的数一样。开始啦!
  1. # 预备练习
  2. x <- y <- 1:9
  3. data <- expand.grid(x=x,y=y)
  4. print(data)
  5. z<- data$x * data$y
  6. # 一个九九乘法表
  7. z <- matrix(z,ncol=9)
  8. set.seed(1)
  9. x <- round(runif(10),2)
  10. print(x)
  11. order(x)
  12. x[order(x)[1]]
  13. which.min(x)
  14. x[which.min(x)]
  15. x[order(x)]
  16. y <- 1:10
  17. data <- data.frame(x,y)
  18. class(data)
  19. head(data)
  20. data[1,]
  21. data[,1]
  22. data$x
  23. data[order(data$x),]
  24. # Project Euler 4
  25. # 在两个三位数字的乘积中,找出最大的回文数
  26. # 先建立一个将数字顺序进行反转的函数
  27. reverse <- function(n) {
  28. reversed <- 0
  29. while (n > 0) {
  30. reversed <- 10 * reversed + n %% 10
  31. n <- n%/%10
  32. }
  33. return(reversed)
  34. }
  35. # 从大到小搜索回文数
  36. x <- y <- 999:100
  37. data <- expand.grid(x=x,y=y)
  38. data$prod <- data$x * data$y
  39. data <- data[order(data$prod,decreasing=T),]
  40. head(data)
  41. 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反转后判断。


下一篇:笨办法学R编程(三)

没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条