如何创建一个有理元素的列表 [英] How to create a list with rational elements

查看:151
本文介绍了如何创建一个有理元素的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试以下。函数 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



编辑:
你好,谢谢你为你的答案。 Collat​​z的例子帮了我很多。但是对于我使用其他想法的解决方案。现在,我写了以下内容:

$ 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 ,它将为你运行所有的步骤。下面是一个类似算法的例子,可以让你了解我的意思。而不是合理的,我们会做Collat​​z序列 - 它是相似的,但不同的是它不包含破坏者。



Collat​​z序列如下所示:下一步,如果数目是偶数,除以二;否则,三倍并添加一个。在代码中,

  collat​​zStep n 
|即使n = n`div` 2
|否则= 3 * n + 1

collat​​z n =迭代collat​​zStep n

你可以通过在ghci中运行这个命令来看到从30开始的Collat​​z序列:

  * Main>以10(collat​​z 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆