【问题标题】:How do I return the middle number in Haskell如何在 Haskell 中返回中间数
【发布时间】:2023-03-17 02:27:01
【问题描述】:

我有一个函数的以下开头,我不确定我应该如何返回中间数(即既不是最大也不是最小的数字):

middleNumber :: Int -> Int -> Int -> Int
middleNumber a b c
    | ...

【问题讨论】:

    标签: haskell int guard


    【解决方案1】:

    我建议您将函数分为两个步骤:首先,对三个数字进行排序。然后,取中间元素。第一步,还要考虑是否可以一步一步来;每一步都使它更接近完全排序,然后尾递归返回以使其更接近。

    【讨论】:

    • 谢谢,我试试看:)
    【解决方案2】:

    “中间数字”大于其中一个数字,但小于另一个数字。而且只有一个中间数。解决这个问题最机械的方法是开始

    middleNumber a b c
        | a < b && a > c = a
    

    通过小于b 但大于c 来检查a 是否是中间数。

    现在如果a 是中间数,但它实际上大于b 并且小于c?还有一个守卫。如果b 是中间数字怎么办?还有2个守卫。如果c 是中间数字怎么办?还有 2 名警卫,总共有 6 种不同的情况。

    (顺便说一句,| a &lt; b &amp;&amp; a &gt; c = a这个表达式被称为守卫。如果你还没有牢牢掌握守卫是什么,那么我推荐LYAH # Guards

    当然有更好的方法来编写函数,但为了便于理解,最好能够手动系统地分解所有可能的情况,并确定在每种情况下要做什么。 How To Design Programs 是一本学习如何以这种方式系统化的好书。

    【讨论】:

      【解决方案3】:

      必选的 Rube-Goldberg-answer:

      import Control.Applicative
      
      middleNumber a b c = sum $ [sum, negate.minimum, negate.maximum] <*> [[a,b,c]]
      

      [编辑]

      这是另一个版本:

      middleNumber a b c = fst $ maximumBy (compare `on` abs.snd) [(a,b-c),(b,c-a),(c,a-b)] 
      

      我确信我们可以将其转换为箭头语法以进一步混淆,但我将这项任务留给感兴趣的读者。

      【讨论】:

      • 导入数据列表; middleNumber a b c = (sort [a,b,c]) !! 1
      • let l = [a,b,c] in delete (minimum l) . delete (maximum l) $ l ... :-)
      • 另一个:middleNumber a b c = minimum [max a b, max a c, max b c](反之亦然)
      • @all:很好!我认为玩弄是一种对语言有更好感觉的好方法,而教科书的答案很无聊。
      【解决方案4】:

      我做了一个快速的蛮力方法,但这肯定不是最好的解决方案

      import Data.List
      middleNum :: Int -> Int -> Int -> Int
      middleNum a b c = (\[_,m,_] -> m) $ sort $ a:b:c:[]
      

      显然这是一个糟糕的想法,因为它明确依赖于列表中有 3 个项目,但它确实可以完成工作

      【讨论】:

        【解决方案5】:

        扩展 Dan Burton 对警卫的回答,我评估了 a、b、c 案例,每个案例都有自己的警卫。但是,当两个数字相等时会发生什么?那么中间的数字应该是重复的数字之一。

        middleNumber :: Int -> Int -> Int -> Int
        middleNumber a b c
            | (a > b && a < c) || (a > c && a < b) = a
            | (b > a && b < c) || (b > c && b < a) = b
            | (c > a && c < b) || (c > b && c < a) = c
            | otherwise = if a == b then a else c
        

        【讨论】:

          【解决方案6】:

          您可以利用警卫和where 以简单的方式获得相同的结果:

          middleNumber :: Int -> Int -> Int -> Int
          middleNumber x y z
            | a == x = max y z
            | a == y = max x z
            | a == z = max x y
            where
              a = max x $ max y z
          

          如果您无权访问内置的max。您可以轻松编写自己的代码。

          max' :: Int -> Int -> Int
          max' x y
            | x > y = x
            | otherwise = y
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-09-22
            • 1970-01-01
            • 2012-12-19
            • 1970-01-01
            • 2023-02-26
            相关资源
            最近更新 更多