recursive repetition of a string - haskell

I am trying to write a function that will take 2 strings, p and k. It will check the lengths of p and k and repeat the letters in p consecutively until the result word is of the length of k. ex: Let p = 123 and k = 45678. Then result word = 12312, because length of k is 5. So the chars of p are consecutively repeated until end word reaches length of k. My code below does not work as I want it to:
repString::[Char]->[Char]->[Char]
repString [] (y:ys) =[]
repString (x:xs) [] =[]
repString (x:xs) (y:ys)
|length(x:xs)<length(y:ys) =(x:xs)++x:repString (xs) []
main = do
print $ repString "123" "45678"
I am not sure how to make this work, because every time it reaches the end of x:xs, it will see an empty string and then it will fulfill the appropriate base case and terminate. I don't know how to make it go back to the beginning of (x:xs) and start printing again.

What you're trying to write is something like:
repString :: [Char] -> [Char] -> [Char]
repString [] k = []
repString p [] = []
repString p k
| length p <= n = p ++ repString p (drop (length p) k)
| otherwise = take n p
where n = length k
But would be better written as:
repString :: [Char] -> [Char] -> [Char]
repString p k = take (length k) (cycle p)

Related

haskell: Implementation of elementAt' function with guards for list with index from 1 to n

I'm solving some problem on https://wiki.haskell.org/99_questions/1_to_10.
I attempts to implements a second solution to problem 3 using guards. My goals is to wrap a guard in order to implement error manangement.
The code is this:
elementAt' :: [a] -> Int -> a
elementAt' xs k = if k < 1 || k > length xs then error "IndexOutOfbound" else elem xs K
where elem xs k
| k == 1 = x
| k > 1 = elem (tail xs) k
The error is this:
parse error (possibly incorrect indentation or mismatched brackets)
|
11 | | k == 1 = x
| ^
I tried to work with indentation, but I didn't succeed
The indentation is indeed wrong, you need to move it at least one column more to the right than the start of elem, so:
elementAt' :: [a] -> Int -> a
elementAt' xs k = if k < 1 || k > length xs then error "IndexOutOfbound" else elem xs K
where elem xs k
| k == 1 = x
| k > 1 = elem (tail xs) k
But this is not sufficient to make this compile. You furthermore wrote K instead of k at the definition of elementAt' xs k = …, furthermore x is not defined, so you can use head, finally you should decrement k in the recursive call:
elementAt' :: [a] -> Int -> a
elementAt' xs k = if k < 1 || k > length xs then error "IndexOutOfbound" else elem xs k
where elem xs k
| k == 1 = head xs
| k > 1 = elem (tail xs) (k-1)
Now it compiles but still it is not very idiomatic Haskell. You make use of length for example, which runs in linear time with the length of the list. If the list has infinite length, it will get stuck, furthermore you make use of head and tail, and these are non-total functions. Yes, we know that this will always work on a cons, since otherwise k > length would be triggered, but regardless it is often batter to use pattern matching over non-total functions.
Therefore a more idiomatic approach is likely:
elementAt' :: [a] -> Int -> a
elementAt' xs k
| k < 1 = error "IndexOutOfBound"
| otherwise = go xs k
where go [] _ = error "IndexOutOfBound"
go (x:xs) i
| i <= 1 = x
| otherwise = go xs (i-1)
Here we know that k is larger than the length if the list is exhausted, so in the go [] case.
Of course indexing should start at zero, as is documented in EWD831 :).

Idiomatic Haskell for transforming a vector into a 2D matrix?

I have a vector of Integers that I'd like to convert into an two-dimensional matrix. The input is guaranteed to be divisible by the row size. What's the most idiomatic way to do this in Haskell?
In Python I would do this:
# Taken from itertools docs.
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return itertools.izip_longest(fillvalue=fillvalue, *args)
m = list(grouper(v, n))
Assuming you mean turning a "vector" represented as a Haskell list into a "matrix" represented as a list of lists, then an idiomatic solution is likely to use splitAt to break off each row, building the list of rows EITHER using straightforward pattern matching and recursion:
chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n xs =
let (row, rest) = splitAt n xs
in row : chunksOf n rest
possibly with a guard to avoid embarrassing endless loops:
chunksOf :: Int -> [a] -> [[a]]
chunksOf n | n > 0 = chunks
where
chunks [] = []
chunks xs =
let (row, rest) = splitAt n xs
in row : chunks rest
OR ELSE using unfoldr:
import Data.List
chunksOf :: Int -> [a] -> [[a]]
chunksOf n | n > 0 = unfoldr chunk
where
chunk [] = Nothing
chunk xs = Just (splitAt n xs)
If the length is not a multiple of the row length, the final row will be shorter than the rest. To allow a fill character for the final incomplete row, you might write:
import Data.List
chunksOfWithFill :: Int -> a -> [a] -> [[a]]
chunksOfWithFill n filler | n > 0 = unfoldr chunk
where
chunk xs = case splitAt n xs of
([],[]) -> Nothing
(xs,[]) -> Just (fill xs, [])
result -> Just result
fill xs = take n (xs ++ repeat filler)
As #Will Ness notes in the comments, chunksOf is already available in the Data.List.Split module of the split package.

Explaining Haskell Code [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I was given this code and told to explain its logic, does anyone know what is going on, new to Haskell.
cpfx :: [[Char]] -> [Char]
cpfx [] = []
cpfx [x] = x
cpfx (x:xs) = cpfx' (x:xs) 0
cpfx' :: [[Char]] -> Int -> [Char]
cpfx' [x] _ = []
cpfx' (x:xs) n
| ifMatch (x:xs) n = x!!n : cpfx' (x:xs) (n+1)
| otherwise = []
ifMatch :: [[Char]] -> Int -> Bool
ifMatch [x] _ = True
ifMatch [x,y] n = x!!n == y!!n
ifMatch (x:y:xs) n
| x!!n == y!!n = ifMatch xs n
| otherwise = False
I am having trouble understand what cpfx,cpfx' and ifMatch are doing.
Take each function directly and look at it. Let's start from the bottom up, since they each use each other.
ifMatch :: [[Char]] -> Int -> Bool
so ifMatch takes a list of lists of Chars (or a list of Strings) and an Int, and gives you back a true/false value. Now let's look at the pattern matches
[x] _ = True -- one element list and any number is True
[x, y] n = x!!n == y!!n {- two element list is true if the character at index
#n# is the same in both lists -}
(x:y:xs) n -- three+ element list guards against...
| x!!n == y!n -- if the characters at index #n# are equal...
= ifMatch xs n -- ... then recurse
| otherwise = False -- otherwise, give me a False.
Taken together, you can see that ifMatch is supposed to check that all strings passed to it have the same letter at index n. It is equivalent to:
ifMatch [] _ = True
ifMatch xs n = let c = head xs !! n in
foldr ((&&) . (==c) . (!!n)) True xs
Though it actually appears to have a slight bug. It only checks if each pair of strings has identical letters at index n, so
ifMatch ["This", "That", "In", "Onward"] 1 == True
-- (^ == ^) && (^ == ^)
cpfx' :: [[Char]] -> Int -> [Char]
so cpfx' takes a list of list of Chars (or a list of Strings) and an Int and gives you back a list of Chars (or a String). Let's look at pattern matches here:
cpfx' [x] _ = [] -- one element list and any number is the empty list
cpfx' (x:xs) n -- multiple element list guards against...
| ifMatch (x:xs) n -- if all #x:xs# share an element at #n#...
= x!!n : -- ...add x!!n and...
cpfx' (x:xs) (n+1) -- ...recurse to the next index
| otherwise = [] -- otherwise, empty list.
So this grabs a character from x until the characters no longer match among all the strings in x:xs, and returns that prefix string.
cpfx :: [[Char]] -> [Char]
From a list of list of Chars (or a list of Strings) to a list of Chars (or a String).
cpfx [] = [] -- empty string gives empty string
cpfx [x] = x -- one-element list gives its only element
cpfx (x:xs) = cpfx' (x:xs) 0 {- anything else gives the shared prefix starting
at index zero -}
All in all, we've got three functions that work together to give you the longest substring of the head of a list of strings that exists at the beginning of all strings in that list.
import Data.Maybe (mapMaybe)
safeIndex :: [a] -> Int -> Maybe a
safeIndex xs n | length xs > n = Just $ xs !! n
| otherwise = Nothing
allEq :: Eq a => [a] -> Bool
allEq [] = True
allEq [_] = True
allEq (x:xs) = all (==x) xs
prefix :: [String] -> String
prefix xss#(x:_) = map snd $ takeWhile pred $ zip [0..] x where
pred :: (Int, Char) -> Bool
pred (n, _) = (allEq . mapMaybe (flip safeIndex n)) xss
testData :: [String]
testData = ["Hello", "Hello, World!", "Hello, Universe!", "Hello everybody!", "Hell's to you, then!"]
main :: IO ()
main = do
let p = prefix testData
putStrLn "Should be \"Hell\""
putStrLn p
or much easier with transpose
import Data.List (transpose)
prefix' :: [String] -> String
prefix' xss#(x:_) = take (length $ takeWhile allEq transposed) x where
transposed = transpose xss
or slightly more efficient
lengthWhile :: (a -> Bool) -> [a] -> Int
lengthWhile _ [] = 0
lengthWhile pred (x:xs) | pred x = 1 + lengthWhile pred xs
| otherwise = 0
prefix'' :: [String] -> String
prefix'' xss#(x:_) = take (lengthWhile allEq transposed) x where
transposed = transpose xss

Haskell - error in find/replace function

i'm making a function that takes three string values w1, w2 and s, and returns s but with all occurrences of the string w1 replaced by w2.
i have finished it, but there is an error. if w1 is only in the string s once, it works fine. but if it occurs multiple times, it doesn't work. eg:
Main> swapwords "turtles" "goats" "more turtles are becoming blind"
"more goats are becoming blind"
swapwords "turtles" "goats" "the blue turtles, dislike the green turtles"
"the blue turtles, dislike the green goats"
here is the current code:
split :: String -> Char -> String -> [String]
split "" _ "" = []
split "" _ r = [r]
split (x:xs) c ""
| x == c = [[c]] ++ split xs c ""
| otherwise = split xs c [x]
split (x:xs) c r
| x == c = r : [[c]] ++ split xs c ""
| otherwise = split xs c (r ++ [x])
swap :: String -> String -> [String] -> [String]
swap a b [] = []
swap a b (x:xs)
|x==a = [b] ++ xs
|x/=a = [x] ++ swap a b (xs)
join :: [String] -> String
join [] = ""
join (x:xs) = x ++ join (xs)
swapwords :: String -> String -> String -> String
swapwords a b "" = []
swapwords a b c = join (swap a b d)
where d = split c ' ' []
if anybody knows the solution it would help me loads. thanks
Your error is here:
swap :: String -> String -> [String] -> [String]
swap a b [] = []
swap a b (x:xs)
|x==a = [b] ++ xs -- <<< here
|x/=a = [x] ++ swap a b (xs)
When you find the word ayou are replacing it with b, but then you want to continue swapping on the remainder of the list.

Remove every nth element from string

How can you remove every nth element of a string?
I'm guessing you would use the drop function in some kind of way.
Like this drops the first n, how can you change this so only drops the nth, and then the nth after that, and so on, rather than all?
dropthem n xs = drop n xs
Simple. Take (n-1) elements, then skip 1, rinse and repeat.
dropEvery _ [] = []
dropEvery n xs = take (n-1) xs ++ dropEvery n (drop n xs)
Or in showS style for efficiency's sake
dropEvery n xs = dropEvery' n xs $ []
where dropEvery' n [] = id
dropEvery' n xs = (take (n-1) xs ++) . dropEvery n (drop n xs)
-- groups is a pretty useful function on its own!
groups :: Int -> [a] -> [[a]]
groups n = map (take n) . takeWhile (not . null) . iterate (drop n)
removeEveryNth :: Int -> [a] -> [a]
removeEveryNth n = concatMap (take (n-1)) . groups n
remove_every_nth :: Int -> [a] -> [a]
remove_every_nth n = foldr step [] . zip [1..]
where step (i,x) acc = if (i `mod` n) == 0 then acc else x:acc
Here's what the function does:
zip [1..] is used to index all items in the list, so e.g. zip [1..] "foo" becomes [(1,'f'), (2,'o'), (3,'o')].
The indexed list is then processed with a right fold which accumulates every element whose index is not divisible by n.
Here's a slightly longer version that does essentially the same thing, but avoids the extra memory allocations from zip [1..] and doesn't need to calculate modulus.
remove_every_nth :: Int -> [a] -> [a]
remove_every_nth = recur 1
where recur _ _ [] = []
recur i n (x:xs) = if i == n
then recur 1 n xs
else x:recur (i+1) n xs
Try to combine take and drop to achieve this.
take 3 "hello world" = "hel"
drop 4 "hello world" = "o world"
I like the following solution:
del_every_nth :: Int -> [a] -> [a]
del_every_nth n = concat . map init . group n
You just have to define a function group which groups a list in portions of length n. But that's quite easy:
group :: Int -> [a] -> [[a]]
group n [] = []
group n xs = take n xs : group n (drop n xs)

Resources