如何返回 Haskell 中的中间数字

发布于 2024-11-10 02:48:10 字数 153 浏览 2 评论 0原文

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

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

I have the following beginning of a function, and am unsure as to how I should return Middle Number (i.e. the number that is neither the largest nor smallest):

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

撩发小公举 2024-11-17 02:48:10

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

I would recommend you break the function into two steps: First, sort the three numbers. Then, take the middle element. For the first step, also consider if you can take it one step at a time; each step bringing it a bit closer to being fully sorted, then tail-recursing back to bring it even closer.

小姐丶请自重 2024-11-17 02:48:10

“中间的数字”比其中一个数字大,但比另一个数字小。而且中间只有一个数字。解决此问题的最机械方法是首先通过

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

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

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

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

当然还有更好的方法来编写函数,但出于理解目的,最好能够手动且系统地分解所有可能的情况,并确定在每种情况下要做什么。 如何设计程序是一本很棒的书,可以帮助您学习如何以这种方式系统化。

The "middle number" is larger than one of the numbers, but smaller than the other number. And there is only one middle number. The most mechanical way to solve this would be to start off

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

Check if a is the middle number by being less than b but greater than c.

Now what if a is the middle number, but it's actually greater than b and less than c? There's another guard. What if b is the middle number? There's another 2 guards. What if c is the middle number? There's 2 more guards, for a total of 6 different cases.

(btw, the expression | a < b && a > c = a is referred to as a guard. If you don't have a firm grasp yet of what guards are, then I recommend LYAH # Guards)

Of course there are better ways to write the function, but for understanding purposes it's good to be able to manually and systematically break down all of the possible situations, and determine what to do in each situation. How To Design Programs is a great book for learning how to be systematic in this way.

看海 2024-11-17 02:48:10

强制性的 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)] 

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

The obligatory Rube-Goldberg-answer:

import Control.Applicative

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

[Edit]

Here is another version:

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

I'm sure we could translate this to arrow syntax for further obfuscation, but I leave that task to the interested reader.

小帐篷 2024-11-17 02:48:10

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

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

Expanding on Dan Burton's answer with guards, I evaluate a, b, c cases each in its own guard. However, what happens when 2 of the numbers are equal? Then the middle number should be one of the duplicated ones.

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
听,心雨的声音 2024-11-17 02:48:10

您可以利用守卫和 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

You can leverage guards and where to obtain the same result in simple way:

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

If you don't have access to the built-in max. you can easily write your own.

max' :: Int -> Int -> Int
max' x y
  | x > y = x
  | otherwise = y
如梦初醒的夏天 2024-11-17 02:48:10

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

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

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

I did a quick brute force method but this is most certainly not the best solution

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

Obviously this is an awful idea as it explicitly relies on there being 3 items in the list, but it does the job

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文