【发布时间】:2014-06-04 21:10:58
【问题描述】:
关于优化,我需要您的帮助。问题来了:
结合常用算术运算符,用数字 3 的 10 倍无法得到的最小(严格正数)自然数是多少?
这是我的解决方案:
import Ratio
num x 1 = [x]
num x n = num'' $ concat $ [ num' a b | i <- [1..n`quot`2], a <- num x i, b <- num x (n-i) ]
where num' a b | a==0 = [b]
| b==0 = [a]
| otherwise = [a+b,abs(a-b),a*b,a/b,b/a]
num'' (x:r) = x : num'' (filter (x/=) r)
num'' _ = []
cint x = map numerator . filter ((1==) . denominator) . num x
firstNumber x n = take 1 [ i | i <- [1..], i `notElem` (cint x n) ]
但是效率太低了。例如,当我调用 firstNumber 3 7 时,需要将近 30 秒才能看到结果。但是,firstNumber 3 10的结果我等了好久都没有看到。我该如何优化它?
【问题讨论】:
-
你编译过优化吗?另外,你能再解释一下这个问题吗? “使用 3 的 10 次无法获得的第一个数字”是什么意思?具体来说,我不明白“10 乘以 3”是什么意思。
-
一个提示:你有
num''(不是一个很好的函数名IMO),它基本上可以确保你的列表中没有重复。为什么不使用Data.Set?这是对唯一元素的无序集合的更有效实现,因为在内部它是作为二叉树实现的。您可能仅使用num'' = Data.Set.toList . Data.Set.fromList就可以节省大量时间,除非num''旨在接受无限流。由于看起来您的搜索空间有限,因此应该是安全的。 -
您将使用 3,3,3,3,3,3,3,3,3,3(3 的 10 次)。以及每个 3 之间的四个操作数(+、-、*、/)。考虑所有可能性。例如,当你调用 firstNumber 3 6 时,你得到 1,2,3,...31 但不是 32。现在明白了吗?
-
好的,我正在尝试。谢谢。
-
您不是在寻找最小的数字吗?那么得到正确的“第一个”的顺序是什么?除了您的列表理解定义遵循该顺序。那么,你的目标不是什么?
标签: haskell optimization