【问题标题】:Caesar Shift function in Haskell?Haskell中的Caesar Shift函数?
【发布时间】:2020-05-16 17:08:59
【问题描述】:

我必须编写一个移位函数,从“表”(列表)中搜索元素对。如果元素不在给定的列表中,它必须给出一个 '#' az 结果。

例子:

shift [('b', 'g'), ('c', 'h'), ('a', 'f')] 'a' == 'f'
shift [('b', 'g'), ('c', 'h'), ('a', 'f')] 'b' == 'g'
shift [('b', 'g'), ('c', 'h'), ('a', 'f')] 'b' == 'g'
shift [('b', 'g'), ('c', 'h'), ('a', 'f')] 'x' == '#'

我的代码:

shift :: [(Char,Char)] -> Char -> Char
shift z c = [b |(a,b)<-z,a==c]!!0

它有效,但不适用于例外情况。我似乎无法让它适用于不在列表中的元素。 我试过了:

shift z c 
    | c `elem` z =[b |(a,b)<-z,a==c]!!0
    | otherwise ='#'

还有一个辅助函数:

isgood z c
    | c `elem` z = (shift z c)
    | otherwise = '#'

但它们不起作用。如何解决?

【问题讨论】:

  • 提示:看看ordchr
  • 这可能是 Map 对象的工作。如果是这样,您可能会发现函数 findWithDefault 很有用。
  • 最直接的库函数是lookup。你可以使用 fromMaybe 来获得结果,或者如果你愿意,可以自己进行模式匹配。

标签: list function haskell shift caesar-cipher


【解决方案1】:

您可以通过多种方式来编写本文,它们基本上都在做同样的事情。

一种方法只是对您之前的尝试之一进行轻微修改,即“有效,但不适用于例外”:

shift :: [(Char,Char)] -> Char -> Char
shift z c = [b |(a,b)<-z,a==c]!!0

我相信您已经观察到,唯一的问题是程序在您找不到字符时崩溃,而不是函数根据需要为您提供“#”。这是因为(!! 0)head(它等价)一样,在应用于空列表时会失败并出现丑陋的运行时错误。因此,您需要做的就是检查列表是否为空,然后取第一个元素或给出默认答案。在我看来,最简洁的方法是在 case 表达式中进行模式匹配:

shift :: [(Char,Char)] -> Char -> Char
shift z c = case [b |(a,b)<-z,a==c] of
    [] -> '#'
    (c:_) -> c

但是这种以成对列表的形式在“查找表”中查找内容的概念是如此标准,以至于 Haskell Prelude 已经有了一个函数,自然而然地称为lookup。它返回一个Maybe 类型作为处理失败的安全方式,如果你愿意,你可以用与以前版本类似的方式对结果进行模式匹配:

shift z c = case (lookup c z) of
    Nothing -> '#'
    Just c -> c

这可以使用另一个标准库函数fromMaybe 进一步简化:

shift z c = fromMaybe '#' (lookup c z)

还有两点要完成:

  • 使用对列表作为类似于字典的数据结构,虽然对于简单的情况是可以的,但效率不是很高。最好使用专门的结构,例如 Map
  • shift 是这个函数的一个奇怪名称,因为它需要一个任意对的查找表。对于真正的 Caesar 移位密码,该表隐含在移位编号中,您需要一个 Int -&gt; Char -&gt; Char 类型的函数,它的实现方式将完全不同。

【讨论】:

  • 如果你是一个无意义的恋物癖者,你也可以这样做 shift = fromMaybe '#' ... lookup 并定义 (...) = (.) . (.) 没人关心。
  • 您还需要使用flip lookup 而不仅仅是lookup 才能工作:)。但是,是的,我故意避免提出类似的建议,甚至使用 $ 运算符而不是括号,以避免混淆问题或引入需要对 Haskell 新手解释的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
  • 2019-08-29
  • 1970-01-01
相关资源
最近更新 更多