本帖最后由 xioaxu790 于 2014-7-4 15:49 编辑
问题导读:
1、如何编写for循环、和自定义函数?
2、什么是sapply函数?
经历了前面两个小挑战,你应该对R有点理解了。我们继续推进,今天的问题有点点复杂,复杂的不是R,而是一个数学概念:质数和质因子。任何一个合数都可以被几个质数所分解,这个性质很重要,我们将用它来解决Project Euler的第三个问题。还是和之前一样的,你需要自己在R控制台中敲打下面这些命令,根据结果自行揣摩其用处。
- # 预备练习,学习for循环、建立自定义函数和其它一些函数
- for (n in 1:10) {
- print(sqrt(n))}
- x <- c('hello','world','I','love','R')
- for (n in x) {
- print(n)}
- x <- seq(from=1,to=10,by=1)
- print(x)
- x <- seq(from=1,to=10,by=2)
- print(x)
- x <- seq(from=1,to=2,length.out=10)
- print(x)round(x)
- x > 1.5
- all(x>1.5)
- any(x>1.5)
- # 如何自定义一个求圆面积的函数
- myfunc <- function(r) {
- area <- pi*r^2
- return(area)
- }
- print(myfunc(4))
- # 同时求四个不同半径圆的面积
- r <- c(2,2,4,3)
- sapply(X=r,FUN=myfunc)
- # Project Euler 3
- # 找到600851475143这个数的最大质因子
- # 先建立一个函数以判断某个数是否为质数
- findprime <- function(x) {
- if (x %in% c(2,3,5,7)) return(TRUE)
- if (x%%2 == 0 | x==1) return(FALSE)
- xsqrt <- round(sqrt(x))
- xseq <- seq(from=3,to=xsqrt,by=2)
- if (all(x %% xseq !=0)) return(TRUE)
- else return(FALSE)
- }
- # 列出1到100的质数,看函数对不对
- x = 1:100
- x[sapply(x,findprime)]
- # 寻找最大的质因子
- n <- 600851475143
- for (i in seq(from=3, to=round(sqrt(n)), by=2)) {
- if (findprime(i) & n %% i == 0) {
- n <- n / i
- prime.factor <- i
- if (i >= n)
- break
- }
- }
- print(prime.factor)
-
复制代码
最后的结果是6857。本例中除了使用for循环外,还见到了sapply函数,这是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反转后判断。
下一篇:笨办法学R编程(三)
|