从点列表中确定最小和最大x和y

时间:2017-03-25 00:49:07

标签: haskell

我对这种语言还很陌生,所以我很难找到解决问题的最佳方法。我想获取Point的列表,例如[(1,0),(2,3),(4,6)],并确定最小和最大xy值,因为我需要使用它们构建网格。

这是我的代码:

type Point a = (a,a)

-- The main program: read points from stdin, write an SVG file to stdout. 
main :: IO ()
main = do
  str <- getContents
  let points = toPoints str
  let minXY = [(x,y) | x <- points, y <- points, x1 <- points, y1 <- points, x < x1, y < y1]
  mapM_ (mapM_ print) minXY

3 个答案:

答案 0 :(得分:2)

您可以使用x函数将点列表分区为yunzip坐标列表,该函数将对列表转换为一对列表:

unzip :: [(a, b)] -> ([a], [b])
points = [(1,0),(2,3),(4,6)]
unzip points = ([1,2,4],[0,3,6])

然后,您可以使用minimummaximum函数直接计算每个列表的最小值和最大值:

bounds :: [Point Int] -> ((Int, Int), (Int, Int))
bounds points = ((minimum xs, maximum xs), (minimum ys, maximum ys))
  where (xs, ys) = unzip points

只是为了好玩,这是一个更先进的解决方案,只能在坐标上进行一次传递:

import Control.Arrow
import Data.Semigroup

bounds = unzip >>> minmax *** minmax
  where minmax = foldMap (Min &&& Max) >>> getMin *** getMax

它使用了Control.Arrow中的一些便捷操作符:

-- Apply two functions to a single value, returning both results.
(f &&& g) x = (f x, g x)

-- Apply two functions to the elements of a pair.
(f *** g) (x, y) = (f x, g y)

-- Left-to-right function composition.
(f >>> g) x = g (f x)

以及来自Min的{​​{1}}和Max幺半群:

Data.Semigroup

答案 1 :(得分:1)

您可以使用前奏中的minimummaximum来计算数字列表的最小值和最大值。在调用之前,我们需要使用fst将元组列表映射到数字列表中,fst获取元组或snd的第一项以获取元组的第二项。

获取x

的最大值
maximum $ fst <$> [(1,0),(2,3),(4,6)]

同样的事情,y使用snd代替fst

答案 2 :(得分:1)

@gabesoft解决方案是这样做的一种方式。以下将计算每轴单次通过的最小值和最大值。 让我们定义一个函数,它接受一个表示当前结果的元组(累加器或最小值和最大值),一个值为a,并将新结果作为元组返回。

minMax :: (Ord a) => (a, a) -> a -> (a, a)
minMax (minAcc, maxAcc) val = (min minAcc val, max maxAcc val)

我们现在可以在折叠中使用此功能:

points = [(1,2), (3, 4), (-1, -3)] :: [(Int, Int)]
foldl minMax (maxBound, minBound) points

我们使用maxBound / minBound来获取Int的最小/最大边界作为起始值。 但是,这不适用于元组列表。要使它在元组上工作,您可以执行以下操作:

foldl minMax (maxBound::Int, minBound::Int) $ fst <$> points
foldl minMax (maxBound::Int, minBound::Int) $ snd <$> points

<$>运算符为fmap。因此,我们首先在点上运行fst以提取第一个元组值,并使用折叠将minMax函数应用于此。