
I want to split a string into 5 parts of equal length, with the last fifth padded if necessary, but can't get it right - here's what I've got -
fifths :: String -> String fifths s = fifths' "" 0 s where l = (length s) `div` 5 [... snip ...] Any thoughts? Thanks! This isn't homework BTW, I'm having a go at the ruby quiz puzzles in haskell, which seems to be a nice way to learn.
Cool idea! Can you post a link for the puzzles? As for this one, don't you want the first multiple of five larger than the length of the string? You should be able to make things simpler if you auto-pad the string from the get-go (forgive any syntax errors, as I'm just composing in a browser here...): prepad :: Integer -> String -> String prepad n s | (length s) `mod` n == 0 = s prepad n s = prepad n (s ++ ' ') And now you can be sneaky: nths :: Integer -> String -> String nths n s = [first_nth n s] ++ nths (n-1) (after_first_nth n s) nths 1 s = s Where first takes the first n chars (e.g., take ((length s) `div` n)) and after_first_nth returns the tail of the list.. -- paulrbrown@gmail.com http://mult.ifario.us/ -- paulrbrown@gmail.com http://mult.ifario.us/

Paul Brown-4 wrote:
Cool idea! Can you post a link for the puzzles?
Thankyou! It's http://www.rubyquiz.com - They are mostly well suited to haskell, lot of mazes etc. I've done 5 or 6 with varying degrees of success but have learned a lot. This thing about strings in fifths is from #1, the solitaire cipher.
As for this one, don't you want the first multiple of five larger than the length of the string? You should be able to make things simpler if you auto-pad the string from the get-go (forgive any syntax errors, as I'm just composing in a browser here...):
[snip]
Good plan! I will play with that. -- View this message in context: http://www.nabble.com/split-string-into-n-parts-tf2496941.html#a6961186 Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

jim burton
Paul Brown-4 wrote:
Cool idea! Can you post a link for the puzzles?
Thankyou! It's http://www.rubyquiz.com - They are mostly well suited to haskell, lot of mazes etc. I've done 5 or 6 with varying degrees of success but have learned a lot. This thing about strings in fifths is from #1, the solitaire cipher.
At a quick glance I can't see which bit needs it. The only mention of five is where it asks to split the string into groups of five characters (not into five equal parts), padded with Xs. You can do that like this: splitAtMb n l = let p = splitAt n l in if null $ fst p then Nothing else Just p in_fives l = unfoldr (splitAtMb 5) (l ++ replicate (length l `mod` 5) 'X') To break a string into five equal parts with the last padded with Xs, try this: fifths l = let len = length l part_length = (len+4)`div`5 pad_length = 5*part_length - len in unfoldr (splitAtMb part_length) (l ++ replicate pad_length 'X') I haven't checked these at all carefully, but at least they illustrate the use of unfoldr. [aside: One might argue that the prelude ought to provide splitAtMb rather than splitAt.] -- Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk

Jón Fairbairn-2 wrote:
At a quick glance I can't see which bit needs it. The only mention of five is where it asks to split the string into groups of five characters (not into five equal parts), padded with Xs.
Oh dear, you're right. Sorry, I read in a rush. Thanks for the solution too. Jón Fairbairn-2 wrote:
You can do that like this:
splitAtMb n l = let p = splitAt n l in if null $ fst p then Nothing else Just p
in_fives l = unfoldr (splitAtMb 5) (l ++ replicate (length l `mod` 5) 'X')
To break a string into five equal parts with the last padded with Xs, try this:
fifths l = let len = length l part_length = (len+4)`div`5 pad_length = 5*part_length - len in unfoldr (splitAtMb part_length) (l ++ replicate pad_length 'X')
I haven't checked these at all carefully, but at least they illustrate the use of unfoldr. [aside: One might argue that the prelude ought to provide splitAtMb rather than splitAt.]
-- Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- View this message in context: http://www.nabble.com/split-string-into-n-parts-tf2496941.html#a6961825 Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

tweak to in_fives
in_fives l = unfoldr (splitAtMb 5) (l ++ replicate (5 - length l `mod` 5) 'X')
-- View this message in context: http://www.nabble.com/split-string-into-n-parts-tf2496941.html#a6961912 Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

jim burton
tweak to in_fives
in_fives l = unfoldr (splitAtMb 5) (l ++ replicate (5 - length l `mod` 5) 'X')
Whoops! Yes. And a slapped wrist for me for writing a constant three times. Serves me right for not writing groups_of n l = unfolder (splitAtMb n) ... in_fives = groups_of 5 :-) -- Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk

I wrote:
jim burton
wrote: Thankyou! It's http://www.rubyquiz.com - They are mostly well suited to haskell, lot of mazes etc. I've done 5 or 6 with varying degrees of success but have learned a lot. This thing about strings in fifths is from #1, the solitaire cipher.
At a quick glance I can't see which bit needs it. The only mention of five is where it asks to split the string into groups of five characters (not into five equal parts), padded with Xs.
You can do that like this:
splitAtMb n l = let p = splitAt n l in if null $ fst p then Nothing else Just p
Gah! Brain AWOL. I'm surprised no-one picked me up on that. Why didn't I use: splitAtMb n [] = Nothing splitAtMb n l = Just $ splitAt n l ?
in_fives l = unfoldr (splitAtMb 5) (l ++ replicate (length l `mod` 5) 'X')
And using length makes this over-strict. maybe something like groups_of n = unfoldr (splitPad 5) where splitPad [] = Nothing splitPad l = Just $ mapFst (padwith 'X') (splitAt n l) padwith c l = take n $ l ++ replicate n c mapFst f (a,b) = (f a, b) -- in Data.Graph.Inductive.Query.Monad which is a little bit inefficient, but less clunky than checking for the end of list in order to apply padwith just once. -- Jón Fairbairn Jon.Fairbairn@cl.cam.ac.uk

Gah! Brain AWOL. I'm surprised no-one picked me up on that. Why didn't I use:
splitAtMb n [] = Nothing splitAtMb n l = Just $ splitAt n l
Actually, I've some code lying around doing exactly this (but without the padding ;)), written with the coalgebra inlined: split n = unfoldr $ \xs -> case xs of [] -> Nothing _ -> Just (splitAt n xs) Cheers, Stefan
participants (4)
-
jim burton
-
Jón Fairbairn
-
Paul Brown
-
Stefan Holdermans