Daniel Bo
Daniel Bo

Reputation: 2518

Haskell Split list into Sublist using pattern recognition

I am trying to split a Array containing I and Os, if a certain pattern occurs.

lets assume i have an input, looking like this:

data Bit = O | I  deriving (Eq, Show)    
let b = [I,I,O,O,O,O,O,I,I,O,O,O,I,O]

that is what i am generating, when encoding [[Bool]] -> [Bit] corresponding input to my encode function would be let a = [[True, False, False, True],[False, False],[False]]

Now my objective is to decode what ive generated,so i need a function that gets me from b to a.

But i can't come up with a way to split b list into 3 sublists, every time it reads either I,O or I,I. Every Odd letter stands for following member or starting array member. I am basically copying utf unicode encoding.

So i am trying to build a function that would get me from b to a. After some time i came up with this:

split :: [Bit] -> [[Bit]]
split (x1:x2:xs) = if (x1 == I)
                    then [x2 : split xs]
                    else x2 : split xs

And i cant figure out, how to split the list into sublist. Any kind of advice/help/code is greatly appreciated

EDIT:

split :: [Bit] ->[[Bit]]
split [] = []
split xs = case foo xs of (ys,I,x2) -> -- generate new subarray like [...,[x2]]
                    (ys,O,x2) -> -- append existing subarray with value x2 [.....,[previous values]++x2]

foo :: [a] -> ([a],x1,x2)
foo x1:x2:input =  (input,x1,x2)

those 2 comments are the last thing i need to figure out. after that im done :)

if feeding b into function split, i want this ouput: [[I,O,O,I],[O,O],[O]] final step would be to get from b to [[True, False, False, True],[False, False],[False]]

Upvotes: 1

Views: 379

Answers (2)

vek
vek

Reputation: 1543

If I got it right, you need something like:

split [] = []
split xs = case foo xs of (ys,r) -> r : split ys

foo :: [a] -> ([a],r)
foo = undefined

In foo, the list should get partially consumed and returns the rest of the list and the value to collect.

EDIT:

data Bit = O | I deriving (Eq, Show)    

sampleA = [[True, False, False, True],[False, False],[False]]
sampleB = [I,I,O,O,O,O,O,I,I,O,O,O,I,O]

type TwoBit = (Bit,Bit)

twobit (x:y:xs) = (x,y) : twobit xs
twobit _ = []

split :: [TwoBit] -> [[Bool]]
split [] = []
split xs = case spli xs of (ys,r) -> r : split ys
    where
        spli :: [TwoBit] -> ([TwoBit],[Bool])
        spli (x:xs) = case span (not . pterm) xs of 
            (ys,zs) -> (zs, map ptrue $ x:ys)

        pterm x = (I,O) == x || (I,I) == x
        ptrue x = (O,I) == x || (I,I) == x

splitTB = split . twobit

main = print $ splitTB sampleB == sampleA

PS Functions that look like s -> (s,a) could also be represented as State monad.

Upvotes: 1

Mulan
Mulan

Reputation: 135406

I would start with if (x1 == 1) ...

If x1 is a Bit that can be either I or O, why are you comparing its equality against a Num, 1?

Upvotes: 2

Related Questions