【问题标题】:Converting from one representation of a "Shape" to another从“形状”的一种表示转换为另一种
【发布时间】:2019-01-03 23:27:04
【问题描述】:

以下定义表示由网格上特定坐标处的彩色方块组成的形状:

type AltShape = [Point]
data Point = P Colour (Int,Int)  deriving Eq
data Colour = Black | Red | Green | Blue  deriving Eq

我应该假设坐标总是正数,坐标(0,0)指的是图片的左上角,y坐标向下增长

红色的 L 形可以表示为

lShape = [P Red (0,0), P Red (0,1), P Red (0,2), P Red (1,2)]

表示这种形状的另一种方法是列表列表,每行一个列表:

type Shape = [Row] 
type Row   = [Square]
type Square = Maybe Colour

例如,上面的红色 L 形将由以下 Shape 类型的值表示:

lShape2 = [[x,o]
          ,[x,o]
          ,[x,x]] where x = Just Red
                        o = Nothing

我的任务是定义一个函数toShape :: AltShape -> Shape,它将AltShape 转换为Shape。我有另一个任务来定义一个函数fromShape :: Shape -> AltShape,但是data Shape = S [Row] 在哪里。我发现这很简单,并这样写:

    fromShape :: Shape -> AltShape
    fromShape (S rows) = [ P c (x,y) | (y,row) <- index rows, (x,Just c) <- index row]
     where index = zip [0..]

但是,我在这个问题上遇到了更多麻烦。我从创建函数开始

colourAndCoords :: Point -> (Colour,(Int,Int))
colourAndCoords ( P c (x,y) ) = (c,(x,y))

然后我创建了一个函数

coords :: [Point] -> [(Int,Int)]
coords ps = map snd (map colourAndCoords ps)

我的想法是将这个列表与所有可能的协调的另一个列表进行比较,在有匹配的地方添加正确的颜色,在没有匹配的地方我会添加任何内容。但是,我的老师说我把它弄得太复杂了,我应该考虑另一种解决方案。但我很难想到一个。所以我想我的问题是更简单的方法是什么?我不是在寻求解决方案,只是朝着正确的方向轻推。

非常感谢花时间阅读本文并回复的任何人!

如果我想出一个解决方案,我会回来更新这个帖子。

【问题讨论】:

    标签: haskell


    【解决方案1】:

    如果您想要一个高效的解决方案,accumArray 函数几乎可以满足您的需求(在计算出适当的界限之后)。

    λ> arr = accumArray (const Just) Nothing ((0, 0), (2, 1)) [((y, x), c) | P c (x, y) <- lShape]
    λ> arr
    array ((0,0),(2,1)) [((0,0),Just Red),((0,1),Nothing),((1,0),Just Red),((1,1),Nothing),((2,0),Just Red),((2,1),Just Red)]
    λ> elems arr
    [Just Red,Nothing,Just Red,Nothing,Just Red,Just Red]
    

    现在问题简化为split elements into groups

    λ> chunksOf 2 (elems arr)
    [[Just Red,Nothing],[Just Red,Nothing],[Just Red,Just Red]]
    

    对于真正的应用程序,您可能希望将其保留为数组,因为数组索引速度很快 (O(1)) 而列表索引速度很慢 (O(n))。

    【讨论】:

    • 感谢您的回复,但我认为我不应该使用除基本库(Data.List、Char 等)之外的任何库。看起来不错:)
    • 使用哪个库由您决定,但为了记录,Data.Arraypart of the language specincluded in GHC
    【解决方案2】:

    如果不关心效率,您可以考虑这种方法:

    1. 找出最大的 x 坐标(称为 w)和最大的 y 坐标(称为 h)。
    2. 创建一个矩形列表,长度为 w x h,具有列表解析或类似功能。在每个位置,在整个点列表中查找具有匹配位置的点,如果找到,则使用其颜色(否则为Nothing)。

    如果效率是一个问题,您可以考虑一种更复杂的方法:

    1. 将您的[AltShape] 变成IntMap (IntMap Colour),例如使用 this technique,它将 y 和 x 映射到颜色。
    2. 使用toAscList 遍历占用的行;在每个中,使用toAscList 遍历占用的列。您需要手动使用[] 填充未占用的行,并使用Nothing 填充未占用的列。

    第二种方法的优势(或可能的劣势,取决于您的目标!)是它自然会产生“参差不齐的”Shapes,它会省略尾随的Nothings。

    【讨论】:

      猜你喜欢
      • 2021-10-08
      • 2015-01-26
      • 1970-01-01
      • 1970-01-01
      • 2015-05-11
      • 2020-11-21
      • 1970-01-01
      • 2021-05-13
      相关资源
      最近更新 更多