如何创建一个有理元素的列表 [英] How to create a list with rational elements
问题描述
我尝试以下。函数 cant :: Int - > Rational应给出类型Rational列表的第n个元素。
特别是,列表从元素1/1开始,并具有以下属性:(可以说a / b是分数,并且构造我使用模块Data.Ratio中的运算符%的有理数因此对于a / b,是写一个%b,而gcd是给我最大公约数的函数)
if(ab)== 0 then a %(a + b)
if(ab)<0&& (a-b)> 0&< a + 1 / = b + (gcd ab = a || b)then(ab)%(a + b)
例如,正如我所说的:当我以a / b = 1/1开始时,因为1-1 = 0,那么列表的第二个元素将是1/2。
然后我会取第二个元素1/2。因为1-2 = -1< 0 和<1> + 1 / = 2 + 1,那么列表的第三个元素将是2/1。
然后我会拿2/1,等等...
因此,我的想法是构建一个以1%1开始的列表,所以就像
[(1%1)..]
并且取第一个元素(1%1),并使用上面的条件创建第二个元素,但是[(1%1)..]不行。
(我是如何来到[(1%1)..]:在一些网站上,我看到了[1,2,3,4等]的符号[1 ..],并且我教了[(1%1)..]它会是一样的)
我还没有找到其他想法。有人能为我提供另一种策略吗?请不要代码,因为我想学习它,所以只有你的想法(S)将是完美的... ... xD
编辑:
你好,谢谢你为你的答案。 Collatz的例子帮了我很多。但是对于我使用其他想法的解决方案。现在,我写了以下内容:
$ p $ import Data.Ratio
list :: [Rational]
list = initial:map calculate下一个列表
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 ab == a || b)=(ab)%(a + b)
initial :: Rational
initial =(1%1)
但编译器说:
calculate.hs:8:1:模式中的分析错误:calculateNext
我认为它无法理解,我试图用参数%b来表达...?我对吗?
如果是的话,怎么解决这个问题才能理解它?
您可能会喜欢此博客文章和你可以查看 positiveRationals
函数由宇宙包。 (给定(+++)
辅助函数 here 。)
正好 你问什么,我建议看看 iterate
函数。把你提出的算法写成一个只需一步的函数,然后将该函数传递给 iterate
,它将为你运行所有的步骤。下面是一个类似算法的例子,可以让你了解我的意思。而不是合理的,我们会做Collatz序列 - 它是相似的,但不同的是它不包含破坏者。
Collatz序列如下所示:下一步,如果数目是偶数,除以二;否则,三倍并添加一个。在代码中,
collatzStep n
|即使n = n`div` 2
|否则= 3 * n + 1
collatz n =迭代collatzStep n
你可以通过在ghci中运行这个命令来看到从30开始的Collatz序列:
* Main>以10(collatz 30)
[30,15,46,23,70,35,106,53,160,80]
i try the following. The function cant :: Int -> Rational should give the n-th element of the list of the type Rational.
Especially, the list begins with the element 1/1 and has the following properties: (lets say a/b is the fraction, and to construct rationals i use the operator % from the module Data.Ratio. So for a/b, is write a%b. And gcd is the function which gives me greatest common divisor)
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)
so, for example, as i said: when i start with a / b = 1 / 1 .Because of 1-1 = 0 , then the second element of the list would be 1 /2. Then i would take the second element 1 / 2. Because 1-2= -1 < 0 and 1+1 /= 2+1, then the 3rd element of the list would be 2/1. And then i would take 2/1, and so on...
So, my idea was to construct a list beginning with 1%1 , so something like
[(1%1)..]
and take the first element which is indeed (1%1) and create with it the second elemnt using the conditions above, but [(1%1)..] does not work. (how i come to [(1%1)..] : on some sites i see the notation [1 ..] for [1,2,3,4, and so on], and i taught with [(1%1)..] it would be the same)
and i have no other idea found yet. Can someone offer me another strategy? Please not the code, because i want to learn it, so only your idea(s) would be perfect...xD
edit: hello, thank you for your answers. The Collatz example helped me a lot. But for the solution i use the other idea. And now, I write the following:
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)
But the compiler says:
calculate.hs: 8:1:Parse error in pattern: calculateNext
I think it can not understand, what i try to express with the argument a%b...? Am I right? If yes, how could it be solved such that it understand it ?
You might like this blog post, and you can view an implementation of the ideas given there in the positiveRationals
function provided by the universe package. (The definition of the (+++)
helper function is given here.)
To do exactly what you ask, I suggest looking into the iterate
function. Write the algorithm you proposed as a function which takes a single step, then pass that function to iterate
and it will run all the steps for you. Here is an example of a similar algorithm to give you an idea of what I mean. Instead of the rationals, we'll do the Collatz sequence -- it's similar, but different enough that it contains no spoilers.
The Collatz sequence goes like this: to get the next step, if the number is even, divide by two; otherwise, triple it and add one. In code,
collatzStep n
| even n = n `div` 2
| otherwise = 3 * n + 1
collatz n = iterate collatzStep n
You can see the Collatz sequence starting from, say, 30, by running this in ghci:
*Main> take 10 (collatz 30)
[30,15,46,23,70,35,106,53,160,80]
这篇关于如何创建一个有理元素的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!