Function 如何创建Prouhet–;图埃–;哈斯克尔的莫尔斯序列?

Function 如何创建Prouhet–;图埃–;哈斯克尔的莫尔斯序列?,function,haskell,recursion,Function,Haskell,Recursion,我是Haskell的noob,但对ActionScript3.0面向对象有一些经验。因此,我们正在进行一次重大的编程转换。我读过哈斯克尔的基本知识,比如算术。我可以编写简单的函数 作为一项实际作业,我必须在哈斯克尔用计算机生成所谓的tms1。所以它应该是这样的: >tms1 0 0 >tms1 1 1 >tms1 2 10 >tms1 3 1001 >tms1 4 10010110 等等。。。根据维基百科,我应该使用这个公式 t0 = 0 t2n = tn t2n

我是Haskell的noob,但对ActionScript3.0面向对象有一些经验。因此,我们正在进行一次重大的编程转换。我读过哈斯克尔的基本知识,比如算术。我可以编写简单的函数

作为一项实际作业,我必须在哈斯克尔用计算机生成所谓的tms1。所以它应该是这样的:

>tms1 0
0
>tms1 1
1
>tms1 2
10
>tms1 3
1001
>tms1 4
10010110
等等。。。根据维基百科,我应该使用这个公式

t0 = 0
t2n = tn
t2n + 1 = 1 − tn
我不知道如何在Haskell中实现这个公式。你能指导我创建一个吗? 到目前为止,我得到的是:

module ThueMorse where
tms1 :: Int -> Int
tms1 0 = 0
tms1 1 = 1
tms1 2 = 10
tms1 3 = 1001
tms1 x = tms1 ((x-1)) --if x = 4 the output will be 1001, i don't know how to make this in a recursion function
我在互联网上做了一些研究,发现了这个代码

资料来源:

代码:


但是这段代码没有给出期望的结果。非常感谢您的帮助。

我建议您在代码中使用布尔值列表;然后,不需要显式地转换数字。我使用如下定义的序列:

0
01
0110
01101001
0110100110010110
01101001100101101001011001101001
...
>concatMap show $ lookupMorseAlternate 4
"10010110"
>map (concatMap show) $ take 5 morseAlternate
["0", "1", "10", "1001", "10010110"]
invertList :: [Integer] -> [Integer]
invertList [] = []
invertList (h:t) 
    |h == 1 = 0:invertList t
    |h == 0 = 1:invertList t
    |otherwise = error "Wrong Parameters: Should be 0 or 1"

thueMorse :: Integer -> [Integer]
thueMorse 1 = [0]
thueMorse n = thueMorse (n - 1) ++ invertList (thueMorse (n - 1))
请注意,前导零非常重要

递归定义现在很容易:

morse = [False] : map step morse where step a = a ++ map not a
这是因为我们从不访问尚未定义的元素。打印列表留给读者作为练习

下面是另一个定义,使用这样一个事实,即可以通过将
1
替换为
10
,将
0
替换为
01
,来实现下一步:

morse = [False] : map (concatMap step) morse where step x = [x,not x]
编辑 以下是sdcvvc使用函数
iterate
进行的更简单的定义
iterate f x
返回重复应用程序列表,从无应用程序开始,将
f
返回到
x

iterate f x = [x,f x,f (f x),f (f (f x)),...]
以下是定义:

morse = iterate (\a -> a ++ map not a) [False]
morse = iterate (>>= \x -> [x,not x]) [False]

您对序列的定义似乎是位序列的序列:

0  1  10 1001 10010110 ... etc.
t0 t1 t2 t3   t4
但维基百科页面将其定义为一个单位序列:

0  1  1  0  1  ... etc
t0 t1 t2 t3 t4
lookupMorse :: Int -> Int
lookupMorse 0 = 0;
lookupMorse n | even n    =     lookupMorse (div  n    2)
              | otherwise = 1 - lookupMorse (div (n-1) 2)
>concatMap show $ take 10 morse
"0110100110"
这是维基百科中的定义所指的公式。有了这些知识,您提到的递归关系的定义更容易理解:

t0 = 0
t2n = tn
t2n + 1 = 1 − tn
在英语中,这可以表述为:

  • 第0位为零
  • 对于偶数非零索引,该位与索引一半处的位相同
  • 对于奇数索引,位是1减去索引一半处的位(减1)
棘手的部分是从下标2n和2n+1到奇数和偶数,并理解n在每种情况下的含义。一旦完成,就可以直接编写一个函数来计算序列的*n*th位:

0  1  1  0  1  ... etc
t0 t1 t2 t3 t4
lookupMorse :: Int -> Int
lookupMorse 0 = 0;
lookupMorse n | even n    =     lookupMorse (div  n    2)
              | otherwise = 1 - lookupMorse (div (n-1) 2)
>concatMap show $ take 10 morse
"0110100110"
如果需要整个序列,请将lookupMorse映射到非负整数上:

morse :: [Int]
morse = map lookupMorse [0..]
这是无限的Thue-Morse序列。要显示它,
获取其中的一些,将它们转换为字符串,并连接生成的序列:

0  1  1  0  1  ... etc
t0 t1 t2 t3 t4
lookupMorse :: Int -> Int
lookupMorse 0 = 0;
lookupMorse n | even n    =     lookupMorse (div  n    2)
              | otherwise = 1 - lookupMorse (div (n-1) 2)
>concatMap show $ take 10 morse
"0110100110"
最后,如果要使用“位序列序列序列”定义,首先需要从序列中删除一些位,然后再获取一些位。除零索引情况外,要删除的数字与要获取的数字相同:

lookupMorseAlternate :: Int -> [Int]
lookupMorseAlternate 0 = take 1 morse
lookupMorseAlternate n = take len $ drop len morse
    where
        len = 2 ^ (n-1)
这就产生了替代序列定义:

morseAlternate :: [[Int]]
morseAlternate = map lookupMorseAlternate [0..]
您可以这样使用:

0
01
0110
01101001
0110100110010110
01101001100101101001011001101001
...
>concatMap show $ lookupMorseAlternate 4
"10010110"
>map (concatMap show) $ take 5 morseAlternate
["0", "1", "10", "1001", "10010110"]
invertList :: [Integer] -> [Integer]
invertList [] = []
invertList (h:t) 
    |h == 1 = 0:invertList t
    |h == 0 = 1:invertList t
    |otherwise = error "Wrong Parameters: Should be 0 or 1"

thueMorse :: Integer -> [Integer]
thueMorse 1 = [0]
thueMorse n = thueMorse (n - 1) ++ invertList (thueMorse (n - 1))
像这样简单:

0
01
0110
01101001
0110100110010110
01101001100101101001011001101001
...
>concatMap show $ lookupMorseAlternate 4
"10010110"
>map (concatMap show) $ take 5 morseAlternate
["0", "1", "10", "1001", "10010110"]
invertList :: [Integer] -> [Integer]
invertList [] = []
invertList (h:t) 
    |h == 1 = 0:invertList t
    |h == 0 = 1:invertList t
    |otherwise = error "Wrong Parameters: Should be 0 or 1"

thueMorse :: Integer -> [Integer]
thueMorse 1 = [0]
thueMorse n = thueMorse (n - 1) ++ invertList (thueMorse (n - 1))

问题似乎是,您丢弃了前导零。使用列表而不是数字也可以避免反复转换数字。我总是想:如果我用大量代码解决一个小问题,我就做错了。你可以这样写:
a`rem`2==0
/
1
作为
偶数a
奇数a
custinv x
可以定义
map(\a->1-a)x
,甚至
custinv=map(1-
amountTrue x=sum(fromnum x)
amountTrue x=length(filter id x)
。使用迭代:第一个定义:
morse=iterate(\a->a++map not a)[False]
第二个定义:
morse=iterate(>=\x->[x,not x])[False]
我认为这里的所有结果都是一步一步得出的。如果将thueMorse 1=[0]更改为thueMorse 0=[0],则此操作有效。