;
f=
g
ij=f
a =hi
hi = g
hij= ij
g ' ' =0
g '"' =0;
g '$' =0;
g '&' =0-0
g '(' =0-0-0
g '*' =0-0-0;
g ',' =0-0-0;
g '.' =0-0-0-0
g '0' =0-0-0-0-0
g '2' =0-0-0-0-0;
g '4' =0-0-0-0-0;
g '6' =0; g '8' =0
g ':' =0; g '<' =0-0
g '>' =0; g '@' =0-0;
g 'B' =0; g 'D' =0-0;
g 'F' =0; g 'H' =0-0-0
g 'J' =0; g 'L' =0-0-0-0
g 'N' =0; g 'P' =0-0-0-0;
g 'R' =0; g 'T' =0-0-0-0;
g 'V' =0; g 'X' =0-0-0-0-0
g 'Z' =0; g '^' =0; g '`' =0
g 'b' =0; g 'd' =0; g 'f' =0;
g 'h' =0; g 'j' =0; g 'l' =0;
g 'n' =0; g 'p' =0; g 'r' =0-0
g 't' =0; g 'v' =0; g 'x' =0-0-0
g 'z' =0; g '\92' =0-0; g '|' =0;
g '~' =0; g y = 1 ;z=0; i(-0)z=z;
i m('\10':y ) ="y"; ; ; ; ; ; ; ;
i m(mnmnmnmnm:y ) = i(m - 1 ) y ; ;
i k m ="y"; ; k i [ ] =01<1010101010;
k m('\10':y ) = k(m + 1 )(i m y ) ; ;
k m y =01>10; m o = k 1$'\10':o ; ; ;
o i('\10':y ) = o i y ; ; ; ; ; ; ; ; ;
o i(k:y )|g k<i = o(1 - i ) y ; ; ; ; ; ;
o i(k:y )|g k>i = o(1 - i ) y ; ; ; ; ; ;
o i [ ] =01<10; o i y =01>10;v=01>10101010
s y|o 1 y = m y|o(-0) y = m y ; s y =v; ; ;
在线尝试!
说明
对于Haskell来说,这是非常有趣的任务。
平价
首先,我们需要某种确定字符是否具有偶数或奇数代码点的方法。这样做的通常方法是获取代码点并将其修改为2。但是,正如人们可能知道的那样,获取字符的代码点需要导入,由于源代码的限制,它不能被导入。用过的。经验更丰富的Haskeller会考虑使用递归。 Char
是Enum
类型类的一部分,因此我们可以获取它们的前任和后继。但是pred
,succ
它们也不可用,因为它们不交替字节奇偶校验。
因此,这使我们陷入困境,我们几乎无法对char进行任何操作。解决方案是对所有内容进行硬编码。我们可以将(大多数)偶数字符表示为文字,我们遇到的'
奇数是麻烦的,因为它是奇数,因此它不能与char本身相邻,从而使文字无法表达大多数奇数字符。因此,我们对所有偶数字节进行硬编码,然后在最后添加所有奇数字节的catch。
问题字节
您可能会注意到,有些偶数字节无法通过将其用单引号引起来来产生字面量。它们是不可打印的内容,换行符和\
。我们不需要担心不可打印的东西,因为只要我们不使用任何不需要打印的东西就可以进行验证。实际上,我们仍然可以使用奇数不可打印的东西,例如制表符,我只是最终不需要这样做。可以明智地忽略换行符,因为无论如何都会从程序中删除换行符。(我们可以包括换行符,因为它的代码点相当方便,但我们不需要这样做)。这留下了\
,现在\
有代码点92,它方便地是一个奇数后跟一个偶数,因此\92
在偶数和奇数之间交替,因此文字'\92'
是完全有效的。稍后,当我们确实需要代表换行符时,我们会注意到它很幸运具有相同的属性'\10'
。
间距问题
现在,为了开始编写实际代码,我们需要能够在一行上放置大量字符。为了做到这一点,我写了上限:
;
f=
g
ij=f
a =hi
hi = g
hij= ij
除有效的Haskell外,封顶不会执行任何操作。最初,我曾希望做出一些定义,以在以后的代码中为我们提供帮助,但事实并非如此。还有一些更简单的方法来制作上限,例如,空格和分号,但是它们不会以这种方式保存字节,因此我不必费心去更改它。
硬编码器
因此,现在我在一行上有足够的空间,我开始对值进行硬编码。这通常很无聊,但是有一些有趣的事情。一旦行开始变得更长,我们就可以;
在一行上放置多个声明,这可以为我们节省大量的字节。
第二个原因是,由于我们不能总是g
如此频繁地开始一行,因此我们不得不稍微缩进一行。现在,Haskell真的很关心缩进,因此它将对此抱怨。但是,如果缩进行之前的最后一行以分号结尾,则将允许它。为什么?我没有最微弱的人,但是可以。因此,我们只需要记住将分号放在行尾。
功能构建块
硬编码器完成后,就可以顺利运行到程序结尾。我们需要构建一些简单的功能。首先,我建立一个drop
名为的版本i
。 i
与drop
我们的不同之处在于,如果我们尝试删除字符串的末尾,它只会返回"y"
。i
与drop的不同之处还在于,如果尝试删除换行符,它将返回"y"
,这将很有用,因为稍后当我们验证程序是三角形时,这将允许我们False
在最后一行未完成时或在一条线早点结束。
k
k
ñssTrue
ñk
n + 1False
然后k
,我们为命名m
。m
仅仅是k
与1
在第一个参数,和一个换行前置到第二个参数。
接下来我们有o
。 o
需要一个数字和一个字符串。它确定字符串字节(忽略换行符)是否g
以输入数字开头的奇偶校验(使用)交替出现。
最后,我们有s
它运行o
既1
和0
,如果成功,要么推迟它来m
。如果两者均失败,则仅返回False
。这是我们想要的功能。它确定输入是三角形且交替的。