2013-12-12 24 views
4

我正在完成这项任务,我需要一些帮助。这是最后一部分,但我真的很困难,不知道如何处理。这里的问题:Haskell将点列表转换为字符串

添加的功能使这需要的图像,并返回一个字符串, 如果打印出来,会给下图所示的图像作为 的图示(并确保周围有一个点的边界 图像的各个方面)。作为一个例子,使吨应返回

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

(其中图像中的点被表示为“X”,原点表示 “+”,水平轴和垂直轴被表示为“ - ”和“ |” 分别地):

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

(字符串我们产生由渲染吨功能可以通过执行putStr 印刷(渲染吨),以实现上述的结果)。

图像和T只是这样的:

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

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

+1

哈斯克尔可有点让你的头部周围,特别是如果你刚刚开始。只是为了澄清你需要一个函数将't = [(0,1),(1,0),(1,1),(2,1)]'变成'“。| ... \ n.xxx 。\ n- + x - \ n。| ... \ n“' – Paperwaste

+0

对于图像大小还有任何已定义的限制,或者我们的功能是否需要自行确定? – Paperwaste

+0

我的意思是更像点的位置。如果其中一点是'(1,1000)',我们的形象将变得非常大。 – Paperwaste

回答

6

让您拥有一个功能,让你的尺寸:

dimensions :: Image -> (Point, Point) 

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

sortImage :: Image -> Image 

,列出各种各样的最大y和最小x第一(提示:Data.List.sortBy是你的朋友)。这实际上并非必要,但它可以让事情稍后变得容易。然后,你可以创建一个空白图像(即只轴和'.',或者您可以使用空格了简洁的外观)

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

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

然后,您需要一个函数,它将输出blankImage并使用您现在的偏移量Image中的值替换字符。由于Point s为现在指数在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看到,所以我会说,如果你需要更多的帮助,我会提供一些更多的提示,但是它会为你更好首先尝试自己解决这个问题。如果您遇到困难,请发表评论,我会编辑我的答案以帮助您解决问题。

+0

+1令人惊叹的答案 – Paperwaste

+1

你应该使用'unlines'而不是'intercalate“\ n”',因为这个例子在最后(在最后一行之后)有一个换行符。 – raymonad

+0

这取决于用例。我个人比较喜欢'intercalate',因为它在Python中是'string.join',它是我的主要语言。如果有人想改变为“\ r \ n”',这是一个简单的修复。但实际上它们本质上是等效的方法,差异很小。 – bheklilr

0

这里有一些事情要考虑:

  • 什么是形象,从功能上来讲?现在忽略边界,图像是从坐标到该坐标上显示的任何值的函数。试着想出一个图像的类型签名。如果您使用type称此为FImage,则为奖励积分。想想你的主要对象这样的功能(记住,功能是一等公民)。
  • 执行轴,如FImage。请注意,您不需要任何界限。这不是很好吗?
  • 执行一个函数,该函数采用FImagePoint,并生成处于正确位置的FImage
  • 从点列表中找出边界。与往常一样,总是首先想想:这是什么类型的签名?
  • 鉴于FImage和界限,产生最终String。你可能想在这里使用List comprehensions。
  • 把它放在一起。有一个隐藏在这里的折叠!其中一个论点将成为点的列表。其他参数是什么(基本情况和组合函数)。在Haskell专业知识水平下,不要太担心它是否为foldlfoldr,两者都可以工作(如果类型匹配)。
  • 完成:-)

快乐学习!

(这是以前这个问题的answer to a duplicate