Haskell将点列表转换为字符串

时间:2013-12-12 01:11:10

标签: haskell functional-programming

我正在完成任务,我需要一些帮助。这是最后一部分,但我真的很挣扎,不知道如何接近。这是问题所在:

  

添加一个函数渲染,它接受一个图像并返回一个字符串,   如果打印,将给出图像的图解表示   如下所示(确保包括一个点边界   图像的各个方面)。例如,渲染t应返回

".|...\n.xxx.\n-+x--\n.|...\n"
     

(图像中的点表示为'x',原点表示   '+',水平和垂直轴表示' - '和'|'   分别地):

.|...
.xxx.
-+x--
.|...
     

(我们通过render t函数生成的字符串可以通过执行putStr来打印   (渲染t)以达到上述结果)。

     

image和t就是这样:

type Point = (Int,Int)
type Image = [Point]
t :: Image
t=[(0,1),(1,0),(1,1),(2,1)]

首先,我需要另一个功能,因为它不能全部在渲染中完成。我知道要查看y和x的最大/最小值来获得边界,我有一个函数。我还有一个函数,它会在每n个字符后在字符串中插入换行符。

2 个答案:

答案 0 :(得分:6)

所以你有一个功能来获得你的尺寸:

dimensions :: Image -> (Point, Point)

返回左上角和右下角。然后我会按排序顺序获得积分:

sortImage :: Image -> Image

首先列出最大y和最小x的排序(提示:Data.List.sortBy是您的朋友)。这实际上不是必需的,但它可以使以后更容易。然后你可以创建一个空白图像(即只有轴和'.',或者你可以使用空格来获得更清晰的外观)

blankImage :: (Point, Point) -> [String]

超出您的尺寸。请务必返回行列表,稍后可以使用新行加入,但现在可以更轻松地使用它们。现在,[String] = [[Char]],所以你有一个2D数组的字符。您有Point s列表指示坐标,但您必须移动它们,以便左上角坐标现在为(0, 0)。这样我们就可以在数组上使用常规索引来设置我们的点。幸运的是,我们已经计算了dimensions中的偏移值。

然后你需要一个获取blankImage输出的函数,并使用你现在偏移的Image中的值替换字符。由于Point现在是blankImage中的索引,因此这应该非常简单。

fillImage :: Image -> [String] -> [String]

所以过程是:

import Data.List

showImage :: Image -> String
showImage img = intercalate "\n" filled
    where
        sortedImg = sorteImage img
        (upperL, lowerR) = dimensions sortedImg
        blank = blankImage (upperL, lowerR)
        offsetImg = offsetImage upperL sortedImg
        filled = fillImage offsetImg blank
    putStrLn $ intercalate "\n" filled

函数intercalate会将您的[String]加入新行,将其转换为一个大字符串。


我从你的评论中看到你是Haskell的新手,所以我会说,如果你需要更多的帮助,我会提供一些更多的提示,但是你尝试通过它会更好这是你自己。如果你遇到困难,请发表评论,我会编辑我的答案以帮助你克服障碍。

答案 1 :(得分:0)

以下是需要考虑的一些事项:

  • 从功能上讲,什么是图像?暂时忽略边界,图像是从坐标到此坐标上显示的任何函数的函数。尝试为图像提供类型签名。如果您使用type将其称为FImage,则可获得积分。把这些功能想象成你的主要对象(记住,功能是一等公民)。
  • 实施轴,FImage。请注意,您不需要任何界限。那不是很好吗?
  • 实施一个带有FImagePoint的函数,并生成一个FImage,其x位于正确的位置。
  • 从点列表中找出界限。一如既往,始终先思考:这是什么类型的签名?
  • 给定FImage和界限,产生最终String。您可能希望在此处使用列表推导。
  • 把它们放在一起。这里隐藏着一个折叠!其中一个论点是点数列表。什么是其他参数(基本情况和组合函数)。在Haskell专业知识的这个级别,不要过于担心它是foldl还是foldr,两者都有效(如果类型匹配)。
  • 完成: - )

快乐学习!

(以前是此问题的answer to a duplicate。)