Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Haskell中测试四个点是否形成正方形_Haskell - Fatal编程技术网

在Haskell中测试四个点是否形成正方形

在Haskell中测试四个点是否形成正方形,haskell,Haskell,在一个网站上,我发现了以下挑战,被抓住了,我不知道如何解决它。我们需要定义以下函数: isSquare::(数a,词a)=>(a,a)->(a,a)->(a,a)->(a,a)->Bool 这样,当点是正方形的顶点时返回True,当点不是正方形的顶点时返回False isSquare (1,1) (1,1) (1,1) (1,1) == True isSquare (0,0) (0,2) (3,2) (3,0) == False isSquare (0,0) (3,4) (8,4)

在一个网站上,我发现了以下挑战,被抓住了,我不知道如何解决它。我们需要定义以下函数:

isSquare::(数a,词a)=>(a,a)->(a,a)->(a,a)->(a,a)->Bool

这样,当点是正方形的顶点时返回True,当点不是正方形的顶点时返回False

isSquare (1,1) (1,1) (1,1) (1,1)    == True
isSquare (0,0) (0,2) (3,2) (3,0)    == False
isSquare (0,0) (3,4) (8,4) (5,0)    == False
isSquare (0,0) (0,0) (1,1) (0,0)    == False
我试过这个:

  • 定义计算点之间距离的函数

  • 将距离映射到由点构成的列表

  • 如果距离相等,则
    True


  • 如果有点p1、p2、p3和p4,则计算距离d1=| p1 p2 |,d2=|p1 p3 |,d3=| p1 p4 |,d4=| p2 p3 |,d5=| p2,p4 |,d6=| p3 p4 |。(您还可以计算距离的平方…)

    看看你得到了多少不同的距离值。如果只有两个不同的值,则一个用于4条边的长度,另一个用于2条对角线的长度,并且有一个正方形

    如果有两个以上的不同值,则它不是正方形


    实现提示:创建一个距离列表,然后查看列表函数。

    如果有点p1、p2、p3和p4,则计算距离d1=| p1 p2 |,d2=| p1 p3 |,d3=| p1 p4 |,d4=| p2 p3 |,d5=| p2,p4 |,d6=| p3 |。(您还可以计算距离的平方…)

    看看你得到了多少不同的距离值。如果只有两个不同的值,则一个用于4条边的长度,另一个用于2条对角线的长度,并且有一个正方形

    如果有两个以上的不同值,则它不是正方形


    实现提示:创建一个距离列表,然后查看列表函数。

    我确信有很多方法可以解决这个问题,但这是我第一次想到的方法

    import Data.Functor
    import Data.Maybe
    import Control.Applicative
    import Control.Monad
    
    首先,让我们为二维向量定义一个类型,并对其进行一些基本操作。我们需要能够加和减,并使用点积来测试正交性

    data V2 a = V2 a a
      deriving Eq
    
    (^+), (^-) :: Num a => V2 a -> V2 a -> V2 a
    V2 x y ^+ V2 x' y' = V2 (x + x') (y + y')
    V2 x y ^- V2 x' y' = V2 (x - x') (y - y')
    infixl 6 ^+, ^-
    
    dotProduct :: (Num a) => V2 a -> V2 a -> a
    dotProduct (V2 x y) (V2 x' y') = (x * x') + (y * y')
    
    orthogonal :: (Eq a, Num a) => V2 a -> V2 a -> Bool
    orthogonal a b = dotProduct a b == 0
    
    我们还将定义一条线段:

    data LineSegment a = LineSegment (V2 a) (V2 a)
    
    isSquare
    函数将首先获取前三个点,并查看它们是否形成直角三角形。让我们定义一个直角三角形类型,以及一个函数,如果三个点之间有直角,则将它们转换为直角三角形

    data RightTriangle a =
      RightTriangle
        (V2 a)          -- Point at the right angle
        (LineSegment a) -- Hypotenuse
    
    rightTriangleMaybe :: (Eq a, Num a)
      => V2 a -> LineSegment a -> Maybe (RightTriangle a)
    rightTriangleMaybe x hyp@(LineSegment a b) =
      guard (orthogonal (x ^- a) (x ^- b)) $> RightTriangle x hyp
    
    rightTriangleMaybe' :: (Eq a, Num a)
      => V2 a -> V2 a -> V2 a -> Maybe (RightTriangle a)
    rightTriangleMaybe' a b c =
      rightTriangleMaybe a (LineSegment b c) <|>
      rightTriangleMaybe b (LineSegment a c) <|>
      rightTriangleMaybe c (LineSegment a b)
    

    我相信有很多方法可以解决这个问题,但这是我第一次想到的

    import Data.Functor
    import Data.Maybe
    import Control.Applicative
    import Control.Monad
    
    首先,让我们为二维向量定义一个类型,并对其进行一些基本操作。我们需要能够加和减,并使用点积来测试正交性

    data V2 a = V2 a a
      deriving Eq
    
    (^+), (^-) :: Num a => V2 a -> V2 a -> V2 a
    V2 x y ^+ V2 x' y' = V2 (x + x') (y + y')
    V2 x y ^- V2 x' y' = V2 (x - x') (y - y')
    infixl 6 ^+, ^-
    
    dotProduct :: (Num a) => V2 a -> V2 a -> a
    dotProduct (V2 x y) (V2 x' y') = (x * x') + (y * y')
    
    orthogonal :: (Eq a, Num a) => V2 a -> V2 a -> Bool
    orthogonal a b = dotProduct a b == 0
    
    我们还将定义一条线段:

    data LineSegment a = LineSegment (V2 a) (V2 a)
    
    isSquare
    函数将首先获取前三个点,并查看它们是否形成直角三角形。让我们定义一个直角三角形类型,以及一个函数,如果三个点之间有直角,则将它们转换为直角三角形

    data RightTriangle a =
      RightTriangle
        (V2 a)          -- Point at the right angle
        (LineSegment a) -- Hypotenuse
    
    rightTriangleMaybe :: (Eq a, Num a)
      => V2 a -> LineSegment a -> Maybe (RightTriangle a)
    rightTriangleMaybe x hyp@(LineSegment a b) =
      guard (orthogonal (x ^- a) (x ^- b)) $> RightTriangle x hyp
    
    rightTriangleMaybe' :: (Eq a, Num a)
      => V2 a -> V2 a -> V2 a -> Maybe (RightTriangle a)
    rightTriangleMaybe' a b c =
      rightTriangleMaybe a (LineSegment b c) <|>
      rightTriangleMaybe b (LineSegment a c) <|>
      rightTriangleMaybe c (LineSegment a b)
    

    我们创建一个函数,返回两点之间的笛卡尔距离:

    dist (x1, y1) (x2, y2) = sqrt $ (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)
    
    我们可以从每个点计算到其他三个点的距离

    对于正方形,这些距离对于每个点都是相同的,其形式为
    [a,a,sqrt(2*a^2)]
    。可以测试以下各项,以确定给定的点集形成正方形:

    • 所有的距离列表都是相同的
    • 较短的两个距离相等
    • 最长距离=sqrt(2*a^2),其中a是短距离
    实际上,我们不需要为所有的点建立上述条件,所以您可以从下面的函数中切掉几行

    这里d1、d2、d3和d4是每个点的排序距离列表

    例如:

    对于点
    (0,0)(0,1)(1,1)(1,0)

    点(0,0)的排序距离列表为
    [1,1,1.414]

    * distance to (0,1) = 1
    * distance to (1,0) = 1
    * distance to (1,1) = sqrt(2) ~ 1.414
    
    同样,所有其他点的距离列表为
    [1,1,1.414]

    * distance to (0,1) = 1
    * distance to (1,0) = 1
    * distance to (1,1) = sqrt(2) ~ 1.414
    
    我们通过映射列表上的部分距离函数来计算距离,然后进行排序,以确保较短的距离位于头部

    然后我们可以查看距离列表,确保前两个元素相等

    d1!!0 == d1!!1
    
    对角线距离等于两条边距离平方和的平方根

    sqrt((d1!!0)^2+(d1!!1)^2) == d1!!2
    
    您可以将最后一个条件等效为

    (d1!!0)^2+(d1!!1)^2 == (d1!!2)^2 
    
    实际上,正如user@dfeuer所指出的,我们可以使用平方距离来建立一组点,即一个正方形。然后,这些函数可以写成

    dist (x1, y1) (x2, y2) = (x2-x1)^2 + (y2-y1)^2
    
    isSquare (x1,y1) (x2,y2) (x3,y3) (x4,y4) =
      let m1 = dist (x1,y1)
          m2 = dist (x2,y2)
          m3 = dist (x3,y3)
          m4 = dist (x4,y4)
          d1 = sort $ map m1 [(x2,y2),(x3,y3),(x4,y4)]
          d2 = sort $ map m2 [(x1,y1),(x3,y3),(x4,y4)]
          d3 = sort $ map m3 [(x1,y1),(x2,y2),(x4,y4)]
          d4 = sort $ map m4 [(x1,y1),(x2,y2),(x3,y3)]
      in d1 == d2 && d2 == d3 && d3 == d4 && d1!!0 == d1!!1 && 2*d1!!0 == d1!!2
    

    我们创建一个函数,返回两点之间的笛卡尔距离:

    dist (x1, y1) (x2, y2) = sqrt $ (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)
    
    我们可以从每个点计算到其他三个点的距离

    对于正方形,这些距离对于每个点都是相同的,其形式为
    [a,a,sqrt(2*a^2)]
    。可以测试以下各项,以确定给定的点集形成正方形:

    • 所有的距离列表都是相同的
    • 较短的两个距离相等
    • 最长距离=sqrt(2*a^2),其中a是短距离
    实际上,我们不需要为所有的点建立上述条件,所以您可以从下面的函数中切掉几行

    这里d1、d2、d3和d4是每个点的排序距离列表

    例如:

    对于点
    (0,0)(0,1)(1,1)(1,0)

    点(0,0)的排序距离列表为
    [1,1,1.414]

    * distance to (0,1) = 1
    * distance to (1,0) = 1
    * distance to (1,1) = sqrt(2) ~ 1.414
    
    同样,所有其他点的距离列表为
    [1,1,1.414]

    * distance to (0,1) = 1
    * distance to (1,0) = 1
    * distance to (1,1) = sqrt(2) ~ 1.414
    
    我们通过映射列表上的部分距离函数来计算距离,然后进行排序,以确保较短的距离位于头部

    然后我们可以查看距离列表并确保