Wil*_*nes 4 haskell functional-programming
I am trying to create a function that combines strings given a list of Integers. For example, say the function was given [1,2,3], then the output would be " ***". Basically, each number represents a * with spaces before it. So the number 5 would be " *" which is 4 spaces followed by the *. However, I am given a list and I can't just ++ them all together because the strings mess up the order.
My idea was to start out by taking the first element in the list and send it back as the string recursively. So for [1,2,3] I would send back to the function [2,3] with String = " *". Next, for each element I check if the length of the string -1 is <= the next element (- 1 because 0 is included). In the list that I am giving the function, this will ALWAYS be the case (the list will always be a number from 0-9, increasing, and NO repeats). Then I would ++ the original string to the function call again to make the recursive statement. I did this till there was nothing left. Here is what I've done:
makeStr :: [Integer] -> String -> String
makeStr [] _ = ""
makeStr (x:xs) s
| null xs && s == "" = getStar ((fromIntegral x)) "*"
| null xs && s /= "" = s ++ getStar ((fromIntegral x) - (length s)) "*"
| s == "" = makeStr xs (getStar ((fromIntegral x) - ((length s))) "*")
| length s - 1 <= (fromIntegral x) = s ++ makeStr xs (getStar ((fromIntegral x) - ((length s))) "*")
Run Code Online (Sandbox Code Playgroud)
Note: getStar is a simple function that takes a number and "*" and returns the string with the correct amount of spaces. It has the declaration of getStar :: Int -> String -> String. This function works perfectly, I have tested it numerous times and I really do not believe it is the issue, hence why I did not include it.
An example of getStar function is:
getStar 3 "*"
" *"
Run Code Online (Sandbox Code Playgroud)
some example inputs with expected outputs:
makeStr [1,2,3] ""
" ***"
makeStr [0,2,3] ""
"* **"
makeStr [1,2,3,4] ""
" ****"
makeStr [0,9] ""
"* *"
Run Code Online (Sandbox Code Playgroud)
The output of my program is incorrect for any list over 2 elements.
makeStr [0,1] "" -- correct
"**"
makeStr [1,2,3] "" -- incorrect, should be " ***"
" ** *"
makeStr [1,2,3,4] "" -- incorrect, should be " ****"
" ** * *"
Run Code Online (Sandbox Code Playgroud)
I can't figure out why it is correct for the first 2 elements, then incorrect for anything after. I've traced through it multiple times but it all seems like it should work fine.
Edit Solution:
makeStr :: [Integer] -> String
makeStr [] = ""
makeStr (x:xs)
| x == 0 = "*" ++ makeStr (map (subtract 1) xs)
| x /= 0 = " " ++ makeStr (map (subtract 1) (x:xs))
Run Code Online (Sandbox Code Playgroud)
可能的解决方案可以按照以下步骤操作。
x:xs,请检查x。
x==0,则发出'*',然后递归xs递减每个数字的位置x/=0,则发出' ',然后递归x:xs递减每个数字的位置例如
f [1,3]
= ' ' : f [0,2]
= ' ' : '*' : f [1]
= ' ' : '*' : ' ' : f [0]
= ' ' : '*' : ' ' : '*' : f []
= ' ' : '*' : ' ' : '*' : []
= " * *"
Run Code Online (Sandbox Code Playgroud)
上面的效率可能不高。可以通过保留第二个“偏移”整数参数来提高效率,并增加它而不是减少整个列表。