项目欧拉#22,关闭158,055

时间:2014-05-21 15:06:34

标签: r splitstackshape

我目前正在通过Project Euler problem 22进行以下挑战:

使用names.txt(右键单击并将“保存链接/目标为...”),一个包含超过五千个名字的46K文本文件,首先按字母顺序排序。然后计算每个名称的字母值,将该值乘以列表中的字母位置以获得名称分数。

例如,当列表按字母顺序排序时,值为3 + 15 + 12 + 9 + 14 = 53的COLIN是列表中的第938个名称。因此,COLIN将获得938×53 = 49714的分数。

文件中所有名称分数的总和是多少?

可以使用上面的链接下载该文件。我写了下面的代码来解决问题:

rm(list=ls())
library(splitstackshape)

#read in data from http://projecteuler.net/problem=22
names=sort(t(read.table("names.txt",sep=",")))

#letters to numbers conversion vectors
from=LETTERS[seq(1,26)]
to=as.character(seq(1,26))

#function to replace all letters with corresponding numbers
gsub2 = function(pattern, replacement, x, ...){
  for(i in 1:length(pattern))
    x = gsub(pattern[i],paste(replacement[i]," ",sep=""), x, ...)
  x
}

#create df, run function, create row number var for later calculation
df=data.frame(names=names)
df$name.num = gsub2(from,to,df$names)
df$rownum=seq(1,nrow(df))

#split letter values, add across rows, multiply by row number to get name score and sum 
df=concat.split(df,"name.num"," ")
df$name.sum=rowSums(df[,4:15],na.rm=TRUE)
df$name.score=df$name.sum*df$rownum
print(sum(df$name.score,na.rm=TRUE))

我的结果似乎是关闭了158,055(我得到871040227应该是871198282)。我发现了它的部分内容,看起来名称列表排序正确,名称得分正确编译(例如,我也得到COLIN=49174)。我还在SO上阅读了解决这个问题的其他线程,但它们主要是在Python中,问题似乎与我的不同。我怀疑是names.txt文件在某种程度上没有被正确读取,或者我正在使用的方法(concat.split包中的splitstackshape)来分割{{1} }是不正确的,虽然它似乎工作正常。

有什么想法吗?

此外,欢迎任何有关如何改进/简化我的代码的建议!

2 个答案:

答案 0 :(得分:6)

我过去常常在R中处理Euler问题。这是我对22的解决方案。

namesscore<-function(name) {
    score<-0;
    for(s in 1:nchar(name)) {
        score<-score + which(substr(name,s,s)==LETTERS[1:26])
    }
    score
}
names<-scan("prob022.txt", "character", sep=",", quote="\"", na.strings="")
name.pos <- rank(names)
name.val <- sapply(names,namesscore)
sum(name.pos*name.val)
# [1] 871198282

有一个名字&#34; NA&#34;列表中可能会给您带来问题。

答案 1 :(得分:3)

正如@MrFlick指出的那样,名单中有一个'NA',所以你需要对它进行处理。

x = sort(scan('http://projecteuler.net/project/names.txt', what = '', sep =',', na.strings = ""))
s = sapply(x, function(w){
    match(w, x) * sum(match(strsplit(w, '')[[1]], LETTERS))
 })
print(sum(s))

# 871198282