我尝试以下方法。函数 cant :: Int - > Rational应该给出Rational类型列表的第n个元素。
特别是,列表以元素1/1开头,并具有以下属性: (假设a / b是分数,构造有理数我使用模块Data.Ratio中的运算符%。所以对于a / b,写一个%b。而gcd是给出最大公约数的函数)
if(a-b)==0 then a % (a+b)
if (a-b)<0 && a+1/= b+1 then (a+1) % (b-1)
if (a-b)>0 && (gcd a b = a || b) then (a-b) % (a+b)
所以,例如,正如我所说:当我以a / b = 1/1开始。因为1-1 = 0,那么列表的第二个元素将是1/2。 然后我将采用第二个元素1 / 2.因为1-2 = -1&lt; 0 和 1 + 1 / = 2 + 1,那么列表的第3个元素将是2/1。 然后我会采取2/1,依此类推......
所以,我的想法是构建一个以1%1开头的列表,所以像
[(1%1)..]
并取第一个确实是(1%1)的元素并使用上述条件创建第二个元素,但[(1%1)..]不起作用。 (我怎么来[(1%1)..]:在某些网站上,我看到[1,2,3,4等等]的符号[1 ..],我教[(1%) 1)..]它会是相同的)
我还没有找到其他想法。有人可以给我另一种策略吗?请不要代码,因为我想学习它,所以只有你的想法才会完美...... xD
编辑: 你好,谢谢你的回答。 Collatz的例子给了我很多帮助。但对于解决方案,我使用另一个想法。现在,我写下以下内容:
import Data.Ratio
list :: [Rational]
list = initial : map calculateNext list
calculateNext :: Rational -> Rational
calculateNext (a%b) | (a-b) == 0 = a % (a+b)
| (a-b)<0 && (a+1) /= (b-1) = (a+1)%(b-1)
| (a-b)>0 && (gcd a b == a || b) = (a-b)%(a+b)
initial :: Rational
initial = (1%1)
但是编译器说:
calculate.hs: 8:1:Parse error in pattern: calculateNext
我认为它无法理解,我试图用a%b的论点来表达...?我对吗? 如果是的话,怎么解决它才能理解呢?
答案 0 :(得分:4)
您可能希望this blog post,并且您可以在positiveRationals
function提供的universe package中查看相应提示的实现。 ((+++)
辅助函数的定义给出了here。)
要完全按 的要求,我建议您查看iterate
函数。将您建议的算法写为一个函数,只需一步,然后将该函数传递给iterate
,它将为您运行所有步骤。这是一个类似算法的例子,可以让您了解我的意思。而不是理性,我们将做Collatz序列 - 它类似,但足够不同,它不包含剧透。
Collatz序列如下:要进行下一步,如果数字是偶数,则除以2;否则,将它加倍并添加一个。在代码中,
collatzStep n
| even n = n `div` 2
| otherwise = 3 * n + 1
collatz n = iterate collatzStep n
你可以通过在ghci:
中运行来看到从30开始的Collatz序列*Main> take 10 (collatz 30)
[30,15,46,23,70,35,106,53,160,80]
答案 1 :(得分:3)
这可以通过简单的递归模式实现:
list = initial : map calculateNext list
在这种情况下,initial == 1 % 1
和calculateNext
将是您使用if
语句概述的代码。