【问题标题】:Haskell converting list of points into stringHaskell将点列表转换为字符串
【发布时间】:2013-12-12 01:11:10
【问题描述】:

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

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

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

(其中图像中的点表示为'x',原点表示 '+',横轴和纵轴分别用'-'和'|'表示 分别):

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

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

image 和 t 就是这样:

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

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

【问题讨论】:

  • Haskel 可能会让您有所了解,尤其是在您刚开始的时候。只是为了澄清您需要一个将t=[(0,1),(1,0),(1,1),(2,1)] 转换为".|...\n.xxx.\n-+x--\n.|...\n" 的函数
  • 对于图像的大小是否有任何已定义的限制,或者我们的函数是否需要自行确定?
  • 我的意思更像是点的位置。如果其中一个点是(1,1000),我们的图像将会变得非常大。
  • 这是我所知道的 Haskell 的最佳资源,我目前正在工作,但当我有机会时,我会尽力为您提供适当的答案。 learnyouahaskell.com
  • 编辑掉这个问题并没有帮助,即使你回想起来对这个问题不满意。请放回去。

标签: haskell functional-programming


【解决方案1】:

所以你有一个函数来获取你的尺寸:

dimensions :: Image -> (Point, Point)

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

sortImage :: Image -> Image

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

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

超出您的尺寸。请务必返回行列表,您可以稍后加入新行,但现在让它更易于使用。现在,[String] = [[Char]],所以你有一个二维字符数组。你有一个Points 的列表表示坐标,但是你必须改变它们,这样你的左上角坐标现在是(0, 0)。这样我们就可以在数组上使用普通索引来设置我们的点。幸运的是,我们已经计算了dimensions 中的偏移值。

然后你需要一个函数,它接受blankImage 的输出并使用你现在的偏移量Image 中的值替换字符。由于Points 现在是您的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],将它变成一个大字符串。


我从您的 cmets 看到您是 Haskell 的新手,所以我会说如果您需要更多帮助,我会提供更多提示,但您最好尝试完成这个自己先。如果您遇到困难,请发表评论,我将编辑我的答案以帮助您克服障碍。

【讨论】:

  • 您应该使用unlines 而不是intercalate "\n",因为该示例的末尾(最后一行之后)也有一个换行符。
  • 这取决于用例。我个人更喜欢intercalate,因为它就像我的主要语言 Python 中的string.join。如果有人想更改为"\r\n",这很容易解决。但实际上它们本质上是等效的方法,差异很小。
【解决方案2】:

这里有一些事情需要考虑:

  • 从功能上讲,什么是图像?现在忽略边界,图像是从坐标到该坐标上显示的任何内容的函数。尝试为图像提出类型签名。如果您使用type 将其称为FImage,则会获得奖励积分。将此类函数视为您的主要对象(请记住,函数是一等公民)。
  • 实现轴,如FImage。请注意,您不需要任何界限。这不是很好吗?
  • 实现一个接受FImagePoint 的函数,并生成一个FImage,其中x 在正确的位置。
  • 从点列表中找出边界。与往常一样,始终首先考虑:this 的类型签名是什么?
  • 给定FImage 和边界,生成最终的String。您可能想在此处使用列表推导式。
  • 把它们放在一起。这里隐藏着一个褶皱!它的论点之一将是点列表。其他参数是什么(基本情况和组合函数)。在此级别的 Haskell 专业知识中,不要太担心是 foldl 还是 foldr,两者都可以工作(如果类型匹配)。
  • 完成:-)

学习愉快!

(之前是这个问题的answer to a duplicate。)

【讨论】:

    猜你喜欢
    • 2021-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 2017-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多