我正试图在屏幕上画一些东西。
我的函数接收一个int by参数列表(例如[0,0,0,5,5,5,3,3,3,2,4,4,0])并且我要迭代几个来自最大数字的时间([0,0,0,5,5,5,3,3,3,2,4,4,0]) - > 5)直到0
在每次迭代中,我都要检查整个列表,并生成一个String(连接“”,“ - ”和“\ n”)。编写结果假设是这样的:
***
*** **
****** **
*********
*********
-------------
我的功能是:
generateSTR (x:xs) = daux (x:xs) (maximum (x:xs)) (x:xs) ""
where daux (h:hs) mh (y:ys) strdib
| mh /= 0 && length(h:hs) == 0 = daux (y:ys) (mh-1) (y:ys) "\n" ++ strdib
| mh > h && mh > 0 && (h:hs) /= [] = daux hs mh (y:ys) "" ++ strdib
| mh <= h && mh > 0 && (h:hs) /= [] = daux hs mh (y:ys) "*" ++ strdib
| mh == 0 && length(h:hs) > 0 = daux hs mh hs "-" ++ strdib
daux [] 0 [] strdib = strdib
daux [] _ _ strdib = strdib
问题在于我只是在抽奖中获得第一行(b是空白“”)。
bbb***bbbbbbb
第一行是好的,但我不知道为什么我的程序会停止。当我试图恢复原始列表(函数中的第三个参数)时,我肯定做错了什么。
第三个参数是假设“保存”原始列表,在使用整个列表后,连接“\ n”并恢复原始列表,继续下一次迭代,直到0。
我做错了什么?
提前谢谢。
答案 0 :(得分:4)
如果您的代码变得如此毛茸茸以至于无法对其进行调试,那么退一步尝试一种新方法来解决问题是件好事。优选地,一个构建较小的可测试组件。
在这种情况下,您尝试生成一个给定高度列表的垂直条形图。正如您所发现的,这样做是 hard 。但是我们可以轻松生成一个水平条,对吗?这只是n
字符的重复*
。
bar :: Int -> String
bar n = replicate n '*'
-- bar 5 = "*****"
下一个棘手的问题是旋转它以使其垂直。那看起来像Haskell的价值是什么?我们不是一个简单的String
,而是一个String
列表,每个列表代表一行。因此,如果我们将[replicate n '*']
作为单行长度n,我们想要的是replicate n ['*']
,或n行长度为1.我们可以直接使用该定义,但事实证明此操作只是转置由函数Data.List.transpose
提供的矩阵。
verticalBar :: Int -> [String]
verticalBar n = transpose [bar n]
-- verticalBar 5 = ["*","*","*","*","*"]
这应该指出我们如何将水平条列表转换为垂直图形。
transpose . map bar
但这不是很正确,因为我们丢失了一些元素而且图表看起来是颠倒的!我们需要填充每一行,以便在我们转置它之前,我们的水平布局图形不会很粗糙。
graph :: [Int] -> String
graph heights = unlines . transpose . map draw $ heights
where
maxHeight = maximum heights
draw height = replicate (maxHeight - height) ' ' ++ replicate height '*' ++ "-"
现在我们有了图表!
λ putStrLn $ graph [0,0,0,5,5,5,3,3,3,2,4,4,0]
***
*** **
****** **
*********
*********
-------------