【问题标题】:Haskell: How to "know" if point is inside shape?Haskell:如何“知道”点是否在内部形状?
【发布时间】:2020-03-20 03:56:48
【问题描述】:

我目前正在为我的 Haskell 课程做一个 h家庭作业,我似乎遇到了死胡同。
我有这个字符串列表
["....................", "....................", "....#####...........", "...##...##..........", "..##.....##.........", "..#.......#.........", "..#...############..", "..#...#...#......#..", "..##..#..##......#..", "...##.#.##.......#..", "....#####........#..", "......#..........#..", "......############..", "....................", "...................."]

而且我必须替换每个'.'带有“*”并忽略“.”,它们是内部形状。
我目前这样做:

  1. 将该字符串列表转换为 元组列表,格式为 - (Row, Col, Char)
  2. ma​​p 应用到这个新列表并使用成功替换的字符创建新列表

地图函数看起来像这样
fillTuple tupleList = map(\(row, col, char) -> if notCharInShape tupleList (row,col) && char /= '#' then (row,col,'*') else (row,col,char)) tupleList
notCharInShape(暂时)看起来像这样
notCharInShape tupleList (row,col) = True
我现在很难找到一种方法来“知道”给定点是否在形状内。我尝试用谷歌搜索判断给定点是在圆内还是在矩形内的数学方程,但我首先必须知道圆心的 x,y 点和圆的半径,而我不知道。

我是否遗漏了什么,或者真的没有办法判断点是否在形状内部,如果形状中心,半径是未知的?

【问题讨论】:

  • 我猜你可以假设该区域的外边缘在所有形状之外并从那里开始。 (它需要一个比地图更复杂的算法。)
  • 您要求一种洪水填充算法。首先将 List 转换为 Matrix 或 2D Vector 或 Array 类型可能是明智之举...如果您 google Haskell flood fill 可以找到几篇文章。

标签: list haskell replace find tuples


【解决方案1】:

map 函数可能还不够,因为该函数不知道它迭代过的先前值的任何信息。

想想你将如何用 Python 这样的语言来做到这一点。您可能会有一些变量来跟踪您是否处于某个形状中的状态,然后决定是否应该将 . 转换为 * 或保持原样。

我认为foldl 功能会对您有所帮助。它使您可以访问可以随时间更改的初始值。

我将举一个稍微相关的例子。只要您还没有看到零或者它是零,就将一个添加到列表中的所有内容。

> snd $ foldl (\(seenZero,xs) a -> (if seenZero then True else a == 0, if seenZero || a == 0 then xs++[a] else xs++[a+1])) (False,[]) [1,2,3,4,0,1,2]
[2,3,4,5,0,1,2]

这里有一些参考资料。

【讨论】:

  • @NonAlcoholicVodka 如果 foldl 示例有意义并且您需要更多资源来理解 fold,请告诉我。
  • 谢谢,foldl 在 Haskell 中确实丰富了我,但我想不出在我的最终解决方案中使用它的方法:/
【解决方案2】:

我认为一般情况下无法做到这一点,至少在没有更多关于现有形状的信息或假设的情况下是无法做到的。如果允许任意形状,你怎么知道你在看重叠

      #####      ############
     ##   ##     #          #
    ##     ##    #          #
    #       #    #          #
    #       #    #          #
    ##     ##    #          #
     ##   ##     ############
      #####

而不是不重叠

      #####          ########
     ##   ##         #      #
    ##     ##       ##      #
    #   #####      ##       #
    #   #        ###        #
    ##  #        #          #
     ## #        ############
      ###

这两种解释会导致交叉口的颜色不同。但是,对于应该选择哪种解释,我们似乎没有规定。

作业是否指定总是有两种形状,一种是正方形,一种是圆形,或者类似的东西?

【讨论】:

  • 家庭作业只指定了一个输入,所以从技术上讲,我可以手动创建一个必须在该形状内的点列表,但我认为这不是正确的解决方案:D
【解决方案3】:

感谢大家的宝贵时间,我昨天睡着了,就在我入睡前我想到了解决办法,今天我试了一下,它成功了。
它不考虑两个形状之间存在间隙,但输入将保持不变,所以我不会为此烦恼。
我创建了新函数,它返回元组列表 (row,col) -> 这些点在某个形状内。
我在 fillTuple 中使用这些点,而不是我删除的 notCharInShape 函数。

我会在此处粘贴该函数的代码,以供可能遇到类似问题的任何人使用。 calculateNotFilledPositions _ [] = [] calculateNotFilledPositions row (xs:input) = [(row, col) | col <- [(fromMaybe (-1) (elemIndex '#' xs))..(length xs - (fromMaybe (-1) (elemIndex '#' (reverse xs)))) - 1], elem '#' xs] ++ calculateNotFilledPositions (row + 1) input

这个函数的作用是它基本上遍历输入的每一行并找到'#'的第一个索引和'#'的最后一个索引,并说不能填充之间的所有内容。
这可能并不理想,我是 Haskell 和函数式编程的初学者,所以如果有人想指出任何事情,请随意,我一直在努力变得更好:)

【讨论】:

    【解决方案4】:

    当你从一个给定的点上、下、左、右走,你会在每一边遇到一个#...这个点是一个形状。

    [ "                    ",
      "                    ",
      "    #####           ",
      "   ##   ##          ",
      "  ##     ##         ",
      "  #       #         ",
      "  #   X   #         ",
      "  #       #         ",
      "  ##     ##         ",
      "   ##   ##          ",
      "    #####           ",
      "                    ",
    

    您现在知道给定点的 x 和 y 坐标,因此您可以检查之前和之后的所有线,以检查 y 是否在形状“内部”。并且检查 x 之前和之后的每个字符都在形状“内部”。如果所有条件都为真,那么您的观点就在形状中。

    [ "                    ",
      "                    ",
      "    #(#)#           ",
      "   ##   ##          ",
      "  ##     ##         ",
      "  #       #         ",
      " (#)  X  (#)        ",
      "  #       #         ",
      "  ##     ##         ",
      "   ##   ##          ",
      "    #(#)#           ",
      "                    ",
    

    ["                    ",
    "                    ",
    "    #####           ",
    "   ##   ##          ",
    "  ##     ##         ",
    "  #       #         ",
    "  #   #(#)########  ",
    "  #  (#)X(#)     #  ",
    "  ##  #  ##      #  ",
    "   ## #(#)       #  ",
    "    #####        #  ",
    "      #          #  ",
    "      ############  ",
    "                    ",
    "                    "]
    

    【讨论】:

    • 好吧,这个解决方案可能有一些形状不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-20
    • 1970-01-01
    • 2016-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多