我不确定我是否在编写 scala 代码时犯了一些错误。
问题是:
The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832.
73167176531330624919225119674426574742355349194934 96983520312774506326239578318016984801869478851843 85861560789112949495459501737958331952853208805511 12540698747158523863050715693290963295227443043557 66896648950445244523161731856403098711121722383113 62229893423380308135336276614282806444486645238749 30358907296290491560440772390713810515859307960866 70172427121883998797908792274921901699720888093776 65727333001053367881220235421809751254540594752243 52584907711670556013604839586446706324415722155397 53697817977846174064955149290862569321978468622482 83972241375657056057490261407972968652414535100474 82166370484403199890008895243450658541227588666881 16427171479924442928230863465674813919123162824586 17866458359124566529476545682848912883142607690042 24219022671055626321111109370544217506941658960408 07198403850962455444362981230987879927244284909188 84580156166097919133875499200524063689912560717606 05886116467109405077541002256983155200055935729725 71636269561882670428252483600823257530420752963450
Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?
博主(http://www.ituring.com.cn/article/111574)说他用haskell
写的代码只需要6ms
:
import Data.List
import Data.Char
main = do
a <- readFile "008.txt"
print . maximum . map (product . take 13) . tails $ map digitToInt $ filter isDigit a
所以我尝试使用scala
:
object Main {
def main(args: Array[String]): Unit = {
val begin: Long = System.currentTimeMillis()
val content = Source.fromFile("file/text").filter(_.isDigit).map(_.toInt - '0').toList
val lists =
for (i <- 0 to content.size - 13)
yield content.drop(i).take(13)
println(lists.maxBy(_.reduce(_ * _)))
val end: Long = System.currentTimeMillis()
println(end - begin)
}
}
但平均需要 120ms
。我以为是 I/O 问题,但我发现它只花了 10ms
(我尝试使用 FileChannel
而不是 Source
,但节省的时间并不多。map
和 flatmap(for)
操作占用的时间最多的时间。
然后我尝试用java看看是不是JVM的原因。不出所料,Java 版本运行得更快。只用了大约 20ms
:
public static void main(String[] args) throws IOException {
long begin = System.currentTimeMillis();
byte[] bytes = Files.readAllBytes(Paths.get("file/text"));
List<Integer> list=new ArrayList<>();
for(int i=0;i<bytes.length;i++){
if(bytes[i]-'0'>=0&&bytes[i]-'0'<=9) list.add(bytes[i]-'0');
}
int max=-1;
List<Integer> maxList=new ArrayList<>();
List<Integer> temp=new ArrayList<>();
for(int i=0;i<=list.size()-13;i++){
int value=1;
for(int j=i;j<i+13;j++){
temp.add(list.get(j));
value*=list.get(j);
}
if(value > max) {
max = value;
maxList.clear();
maxList.addAll(temp);
}
temp.clear();
}
System.out.println(maxList);
long end = System.currentTimeMillis();
System.out.println(end - begin);
}
我的问题是为什么scala版本的代码运行这么慢?
最佳答案
正如@etherous 提到的:您在 Java 版本中使用可变状态,而您的 Scala 版本是完全不可变的,而且编写效率也更低。它们只是不同而已。
您可以尝试避免 maxBy
并尝试在一次迭代中保存已计算的结果。这个应该更接近您的 Java 版本。
val content = Source.fromFile("file/text").filter(_.isDigit).map(_.toLong - '0').toList
val result = (0 to content.size - 13).foldLeft((List.empty[Long], -1l)){case (current @(_, curMax), next) => {
val temp = content.drop(next).take(13)
val tempVal = temp.reduce(_*_)
if(tempVal > curMax) (temp, tempVal) else current
}
}
result
在这里是一个元组,包含 13 个数字的列表作为 _1
并且它的产品作为 _2
,就像你想要的那样两者。
奖金
现在想想。有一种叫做sliding
的方法正好可以解决这个问题。但我猜它运行得和你的 scala 代码一样慢。至少这会很短 :)。
content.sliding(13).maxBy(_.reduce(_*_))
关于java - 为什么scala写的代码比java慢6倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23965737/