Haskell将点列表转换为字符串
我正在做作业,我需要一些帮助。这是最后一部分,但我真的很挣扎,不知道如何处理。问题是: 添加一个函数render,该函数获取图像并返回一个字符串, 如果打印,将给出图像的图示,如下所示 如下图所示(确保包括周围的一点边界 图像的所有侧面)。例如,render t应该返回Haskell将点列表转换为字符串,haskell,functional-programming,Haskell,Functional Programming,我正在做作业,我需要一些帮助。这是最后一部分,但我真的很挣扎,不知道如何处理。问题是: 添加一个函数render,该函数获取图像并返回一个字符串, 如果打印,将给出图像的图示,如下所示 如下图所示(确保包括周围的一点边界 图像的所有侧面)。例如,render t应该返回 ".|...\n.xxx.\n-+x--\n.|...\n" (图像中的点表示为“x”,原点表示为 “+”,水平轴和垂直轴表示为“-”和“|” 分别): (我们通过render t函数生成的字符串可以通过putStr打印出来
".|...\n.xxx.\n-+x--\n.|...\n"
(图像中的点表示为“x”,原点表示为
“+”,水平轴和垂直轴表示为“-”和“|”
分别):
(我们通过render t函数生成的字符串可以通过putStr打印出来
(渲染t)以实现上述结果)
图像和t就是这样:
type Point = (Int,Int)
type Image = [Point]
t :: Image
t=[(0,1),(1,0),(1,1),(2,1)]
首先,我需要另一个函数,因为它不能全部在渲染中完成。我知道要看y和x的最大/最小值来得到边界,我有一个函数。我还有一个函数,它将在每n个字符后向字符串中插入换行符。因此您有一个函数来获取尺寸:
dimensions :: Image -> (Point, Point)
返回左上角和右下角。然后,我将按顺序获得分数:
sortImage :: Image -> Image
它首先按最大的y
和最小的x
进行排序(提示:Data.List.sortBy
是您的朋友)。这实际上不是必要的,但它可以让以后的事情变得更容易。然后您可以创建一个空白图像(即仅轴和。
,或者您可以使用空格以获得更清晰的外观)
超出你的范围。一定要返回一个行列表,以后可以使用新行连接,但现在要使其更易于使用。现在,[String]=[[Char]]
,这样就有了一个2D字符数组。您有一个指示坐标的点列表,但您必须移动它们,以便您的左上角坐标现在是(0,0)
。这样我们就可以在数组上使用普通索引来设置点。幸运的是,我们已经计算了维度中的偏移值
然后您需要一个函数,该函数获取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
函数插入
将在[String]
中加入新行,将其变成一个大字符串
我从你的评论中看到,你是哈斯克尔的新手,所以我想说,如果你需要更多的帮助,我会给你更多的提示,但你最好先自己解决这个问题。如果您遇到困难,请发表评论,我将编辑我的答案以帮助您克服障碍。以下是一些需要思考的问题:
- 从功能上讲,什么是图像?现在忽略边界,图像是从坐标到该坐标上显示的任何对象的函数。尝试为图像创建一个类型签名。如果您使用
类型
将其称为FImage
,则可获得额外积分。将这些函数视为主要对象(记住,函数是一等公民)
- 执行轴,如图所示。请注意,您不需要任何边界。那不是很棒吗
- 执行一个函数,获取一个
FImage
和一个点
,并生成一个FImage
,其x
位置正确
- 从点列表中找出边界。像往常一样,总是先想一想:这是什么类型的签名
- 给定一个
FImage
和边界,生成最终的字符串。您可能需要在此处使用列表理解
- 把它们放在一起。这里隐藏着一个褶皱!它的一个论点是点列表。其他参数是什么(基本情况和组合函数)。在Haskell的这一专业水平上,不用太担心它是
foldl
还是foldr
,两者都可以工作(如果类型匹配)
- 完成:-)
学习愉快
(这以前是这个问题的一个重要部分。)Haskel可以让你头脑清醒一点,特别是当你刚刚开始的时候。只是为了澄清一下,您需要一个函数来将t=[(0,1),(1,0),(1,1),(2,1)]
转换为。|…\n.xxx。\n-+x--\n.|…\n“
对于图像的大小是否有任何定义的限制,或者我们的函数是否需要自行确定?我的意思是更像点的位置。如果其中一点是(11000)
我们的形象将变得非常大。这是我所知道的haskell最好的资源,我现在正在工作,但我会尽力帮助你找到合适的答案,当我有机会的时候。即使回想起来你对这个问题不满意,编辑掉这个问题也无济于事。请放回原处。您可能应该使用unlines
而不是interlate“\n”
,因为示例的末尾(在最后一行之后)也有一个换行符。这取决于用例。我个人更喜欢interlate
,因为它的行为类似于Python中的string.join
,Python是我的主要语言。如果有人想更改为“\r\n”
,这很容易解决。但实际上,它们本质上是等价的方法,差别很小。
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