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))) "*")
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 "*"
" *"
some example inputs with expected outputs:
makeStr [1,2,3] ""
" ***"
makeStr [0,2,3] ""
"* **"
makeStr [1,2,3,4] ""
" ****"
makeStr [0,9] ""
"* *"
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 " ****"
" ** * *"
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))
A possible solution could follow these steps.
x:xs
, check x
.
x==0
, then emit a '*'
, and recurse with xs
where each number has been decrementedx/=0
, then emit a ' '
, and recurse with x:xs
where each number has been decrementedE.g.
f [1,3]
= ' ' : f [0,2]
= ' ' : '*' : f [1]
= ' ' : '*' : ' ' : f [0]
= ' ' : '*' : ' ' : '*' : f []
= ' ' : '*' : ' ' : '*' : []
= " * *"
The above is not efficient as it could be. One can improve the efficiency keeping a second "offset" integer argument, and incrementing that instead of decrementing the whole list.
@chi solution, but without the need to decrement every element of the list at every recursive step.
makeStr = f 0
f _ [] = ""
f i (x:xs)
| x - i == 0 = '*' : f (i+1) xs
| otherwise = ' ' : f (i+1) (x:xs)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With