我是斯卡拉新手,刚开始学习这门语言.
我从Project Euler页面解决了问题8.
代码看起来像这样(我删除了读取输入文件所需的所有代码):
def max(n1: Int, n2: Int): Int = Math.max(n1, n2)
def max_product(digits: List[Int], num: Int): Int = {
def max_core(lst: List[Int], curr_max: Int): Int = lst match {
case a if lst.length >= num =>
max_core(a.tail, max(lst.slice(0, num).reduceLeft(_*_), curr_max))
case _ => curr_max
}
max_core(digits, 0)
}
println(max_product(1::2::3::4::2::3::Nil, 2))
它工作正常,结果是正确的.但是,我对这个解决方案并不完全满意.我不喜欢max_core子功能,并且感觉它可以改进.我对FP的理解是,你应该迭代一个列表,切片似乎不是这里的方式.
问题是:如何?
首先,我不会重新发明轮子...方法max已定义RichInt,所以你可以写a max b,for a和b整数.
此外,,而不是slice已被弃用,因此lst.slice(0, num)我会用lst.take(num).当Scala 2.8启动时,不推荐使用的方法可能会消失.
编辑:事实上,正如丹尼尔指出的那样,slice(Int, Int)并没有被弃用.当我最初写这篇文章的时候我很匆忙,而我正在思考slice(Int),这相当于drop(Int).我仍然觉得lst.take(num)比lst.slice(0, num):) 更清楚.
(nitpick)你的最后一行也没有编译,因为你忘了添加Nil到你的序列的结尾.1::2::3::4,最终会调用::一个Int没有这个方法的.这就是为什么你需要添加Nil到结束(调用::上Nil).
此外,您使用的算法乍一看并不明显.我写这个的方式如下:
val numbers = /*"--the string of numbers--"*/.map(_.asDigit).toList
def sliding[A](xs: List[A], w: Int): List[List[A]] = {
for(n <- List.range(0, xs.size - w))
yield xs drop n take w
}
def product(xs: List[Int]): Int = (1 /: xs) (_ * _)
sliding(numbers, 5).map(product).sort(_ > _).head
Run Code Online (Sandbox Code Playgroud)
我觉得最后一行解释得很好什么的算法,应该做的事-以列表的滑动窗口,计算产品在滑动窗口,然后得到最大的计算出产品的(我已经实现了最大的功能sort(_ > _).head出懒惰,我可以做一些O(n)而不是O(n log(n)),如果性能是关键的......它仍然在一秒钟内运行).
请注意,滑动函数将位于Scala 2.8库中(请参阅Daniel的文章,从中我开始编写此滑动定义的灵感来源).
编辑:哎呀...抱歉/:.我只是喜欢它的简洁性以及折叠的初始元素出现在列表之前的事实.您可以等效地写product为以下内容,以便更明确:
def product(xs: List[Int]): Int = xs.foldLeft(1)(_ * _)
Run Code Online (Sandbox Code Playgroud)
-- Flaviu Cipcigan
| 归档时间: |
|
| 查看次数: |
560 次 |
| 最近记录: |