module AAIPExamples where

data Peano = Z | S Peano deriving (Show)

add :: Peano -> Peano -> Peano
add Z Z = Z
add (S Z) Z = (S Z)
add Z (S Z) = (S Z)
add (S Z) (S Z) = S (S Z)
add Z (S (S Z)) = S (S Z)
add (S (S Z)) Z = S (S Z)
add (S Z) (S (S Z)) = S (S (S Z))
add (S (S Z)) (S Z) = S (S (S Z))
add (S (S (S Z))) Z = S (S (S Z))
add Z (S (S (S Z))) = S (S (S Z))

appenD  :: [a] -> [a] -> [a]
appenD [][] = []
appenD [a][] = [a]
appenD [][c] = [c]
appenD [a][c] = [a,c]
appenD [a,b][] = [a,b]
appenD [][c,d] = [c,d]
appenD [a,b][c] = [a,b,c]
appenD [a][c,d] = [a,c,d]
appenD [a,b][c,d] = [a,b,c,d]

droP :: Peano -> [a] -> [a]
droP Z x = x
--droP (S Z)         []      = []
droP (S Z)         [a]     = []
droP (S Z)         [a,b]   = [b]
droP (S Z)         [a,b,c] = [b,c]
--droP (S (S Z))     []      = []
--droP (S (S Z))     [a]     = []
droP (S (S Z))     [a,b]   = []
droP (S (S Z))     [a,b,c] = [c]
--droP (S (S (S Z))) []      = []
--droP (S (S (S Z))) [a]     = []
--droP (S (S (S Z))) [a,b]   = []
droP (S (S (S Z))) [a,b,c] = []

eveN :: Peano -> Bool
eveN Z                     = True
eveN (S Z)                 = False
eveN (S (S Z))             = True
eveN (S (S (S Z)))         = False
eveN (S (S (S (S Z))))     = True
eveN (S (S (S (S (S Z))))) = False

evenpos :: [a] -> [a]
evenpos [] = []
evenpos [a] = []
evenpos [a,b] = [b]
evenpos [a,b,c] = [b]
evenpos [a,b,c,d] = [b,d]
evenpos [a,b,c,d,e] = [b,d]
--evenpos [a,b,c,d,e,f] = [b,d,f]

eq :: Peano -> Peano -> Bool
eq Z Z = True
eq Z (S Z) = False
eq Z (S (S Z)) = False
eq (S Z) Z = False
eq (S Z) (S Z) = True
eq (S Z) (S (S Z)) = False
eq (S (S Z)) Z = False
eq (S (S Z)) (S Z) = False
eq (S (S Z)) (S (S Z)) = True

iniT :: [a] -> [a]
iniT [a] = []
iniT [a,b] = [a]
iniT [a,b,c] = [a,b]
iniT [a,b,c,d] = [a,b,c]

-- BK for sort only, does not work alone
insert :: Peano -> [Peano] -> [Peano]
--insert Z [] = [Z]
--insert (S Z) [] = [S Z]
--insert (S(S Z)) = [S(S Z)]
insert x [] = [x]	
insert Z [S Z] = [Z,S Z]
insert Z [S(S Z)] = [Z,S(S Z)]
--insert Z [S Z, S(S Z)] = [Z, S(S Z)]
--insert Z (x:xs) = (Z:x:xs)
insert (S Z) [Z] = [Z,(S Z)]
insert (S Z) [S(S Z)] = [S Z, S(S Z)]
insert (S(S Z)) [Z] = [Z, S(S Z)]
insert (S(S Z)) [S Z] = [S Z, S(S Z)]	
insert Z [S Z, S(S Z)] = [Z, S Z, S(S Z)]
insert (S Z) [Z,S(S Z)] = [Z, S Z, S(S Z)]
insert (S(S Z)) [Z, S Z] = [Z, S Z, S(S Z)]

lasT :: [a] -> a
lasT [a] = a 
lasT [a,b] = b
lasT [a,b,c] = c
lasT [a,b,c,d] = d

lasts :: [[a]] -> [a]
lasts [] = []
lasts [[a]] = [a]
lasts [[a,b]] = [b]
lasts [[a,b,c]] = [c]
lasts [[b],[a]] = [b,a]
lasts [[c],[a,b]] = [c,b]
lasts [[a,b],[c,d]] = [b,d]
lasts [[c,d],[b]] = [d,b]
lasts [[c],[d,e],[f]] = [c,e,f]
lasts [[c,d],[e,f],[g]] = [d,f,g]

lengtH :: [a] -> Peano
lengtH [] = Z
lengtH [a] = S Z
lengtH [a,b] = S(S Z)
lengtH [a,b,c] = S(S(S Z))

odD :: Peano -> Bool
odD Z                     = False
odD (S Z)                 = True
odD (S (S Z))             = False
odD (S (S (S Z)))         = True
odD (S (S (S (S Z))))     = False
odD (S (S (S (S (S Z))))) = True

oddpos :: [a] -> [a]
oddpos [] = []
oddpos [a] = [a]
oddpos [a,b] = [a]
oddpos [a,b,c] = [a,c]
oddpos [a,b,c,d] = [a,c]
oddpos [a,b,c,d,e] = [a,c,e]
oddpos [a,b,c,d,e,f] = [a,c,e]

repeatfirst :: [a] -> [a]
repeatfirst [a] = [a]
repeatfirst [a,b] = [a,a]
repeatfirst [a,b,c] = [a,a,a]
repeatfirst [a,b,c,d] = [a,a,a,a]

repeatlast :: [a] -> [a]
repeatlast [] = []
repeatlast [a] = [a]
repeatlast [a,b] = [b,b]
repeatlast [a,b,c] = [c,c,c]
repeatlast [a,b,c,d] = [d,d,d,d]

reversE :: [a] -> [a]
reversE [] = []
reversE [a] =[a]
reversE [a,b] = [b,a]
reversE [a,b,c] = [c,b,a]
reversE [a,b,c,d] = [d,c,b,a]
--reversE [a,b,c,d,e] = [e,d,c,b,a]
--reversE [a,b,c,d,e,f] = [f,e,d,c,b,a]

shiftl :: [a] -> [a]
shiftl [] = []
shiftl [a] = [a]
shiftl [a,b] = [b,a]
shiftl [a,b,c] = [b,c,a]
shiftl [a,b,c,d] = [b,c,d,a]

shiftr :: [a] -> [a]
shiftr [] = []
shiftr [a] = [a]
shiftr [a,b] = [b,a]
shiftr [a,b,c] = [c,a,b]
shiftr [a,b,c,d] = [d,a,b,c]
-- shiftr [a,b,c,d,e] = [e,a,b,c,d]

snoc :: a -> [a] -> [a]
snoc a []            = [a]
snoc b [a]           = [a,b]
snoc c [a,b]         = [a,b,c]
snoc d [a,b,c]       = [a,b,c,d]
--snoc e [a,b,c,d]   = [a,b,c,d,e]
--snoc f [a,b,c,d,e] = [a,b,c,d,e,f]

sort :: [Peano] -> [Peano]
sort [] = []
sort [Z]        = [Z]
sort [S Z]      = [S Z]
--sort [S(S Z)]   = [S(S Z)]	
sort [Z,S Z]        = [Z,S Z]
--sort [Z,S(S Z)]     = [Z,S(S Z)]
sort [S Z, Z]       = [Z,S Z]
--sort [S Z,S(S Z)]   = [S Z,S(S Z)]
--sort [S(S Z), Z]    = [Z,S(S Z)]
--sort [S(S Z),S Z]   = [S Z,S(S Z)]	
--sort [Z,S Z,S(S Z)] = [Z,S Z,S(S Z)]
--sort [Z,S(S Z),S Z] = [Z,S Z,S(S Z)]
--sort [S Z,Z,S(S Z)] = [Z,S Z,S(S Z)]
--sort [S Z,S(S Z),Z] = [Z,S Z,S(S Z)]
--sort [S(S Z),Z,S Z] = [Z,S Z,S(S Z)]
sort [S(S Z),S Z,Z] = [Z,S Z,S(S Z)]

swap:: [a] -> [a]
swap [] = []
swap [a] = [a]
swap [a,b] = [b,a]
swap [a,b,c] = [b,a,c]
swap [a,b,c,d] = [b,a,d,c]
swap [a,b,c,d,e] = [b,a,d,c,e]
--swap [a,b,c,d,e,f] = [b,a,d,c,f,e]

switch :: [a] -> [a]
switch [] = []
switch [a] = [a]
switch [a,b] = [b,a]
switch [a,b,c] = [c,b,a]
switch [a,b,c,d] = [d,b,c,a]
switch [a,b,c,d,e] = [e,b,c,d,a]
--switch [a,b,c,d,e,f] = [f,b,c,d,e,a]

taiL :: [a] -> [a]
taiL [a] = []
taiL [a,b] = [b]
taiL [a,b,c] = [b,c]
taiL [a,b,c,d] = [b,c,d]

takE :: Peano -> [a] -> [a]
takE Z             []      = []
takE Z             [a]     = []
takE Z             [a,b]   = []
--takE Z             [a,b,c] = []
takE (S Z)         []      = []
takE (S Z)         [a]     = [a]
takE (S Z)         [a,b]   = [a]
--takE (S Z)         [a,b,c] = [a]
takE (S (S Z))     []      = []
takE (S (S Z))     [a]     = [a]
takE (S (S Z))     [a,b]   = [a,b]
--takE (S (S Z))     [a,b,c] = [a,b]
--takE (S (S (S Z))) []      = []
--takE (S (S (S Z))) [a]     = [a]
--takE (S (S (S Z))) [a,b]   = [a,b]
--takE (S (S (S Z))) [a,b,c] = [a,b,c]

weave :: [a] -> [a] -> [a]
weave [] [] = []
weave [a][] = [a]
weave [][c] = [c]
weave [a][c] = [a,c]
weave [a,b][] = [a,b]
weave [][c,d] = [c,d]
weave [a,b][c] = [a,c,b]
weave [a][c,d] = [a,c,d]
weave [a,b][c,d] = [a,c,b,d]

