{- |
Description: Direct run-length encoding of a list
Copyright: Copyright (C) 2021 Yoo Chung
License: GPL-3.0-or-later
Maintainer: dev@chungyc.org

Some solutions to "Problems.P13" of Ninety-Nine Haskell "Problems".
-}
module Solutions.P13 (encodeDirect) where

import           Problems.Lists

-- | Implement the so-called run-length encoding data compression method directly.
-- I.e., do not explicitly create the sublists containing the duplicates,
-- as with 'Problems.P09.pack', but only count them.
--
-- As with 'Problems.P11.encodeModified',
-- simplify the result list by replacing the singletons @('Multiple' 1 x)@ by @('Single' x)@.
encodeDirect :: Eq a => [a] -> [Encoding a]
encodeDirect :: forall a. Eq a => [a] -> [Encoding a]
encodeDirect [] = []
encodeDirect (a
x:[a]
xs) = Int -> a -> Encoding a
forall a. Int -> a -> Encoding a
encode (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) a
x Encoding a -> [Encoding a] -> [Encoding a]
forall a. a -> [a] -> [a]
: [a] -> [Encoding a]
forall a. Eq a => [a] -> [Encoding a]
encodeDirect [a]
r
  where (Int
n, [a]
r) = a -> [a] -> (Int, [a])
forall a. Eq a => a -> [a] -> (Int, [a])
consume a
x [a]
xs

-- | Count and remove the elemement consecutively from the front of the list.
consume :: Eq a => a -> [a] -> (Int, [a])
consume :: forall a. Eq a => a -> [a] -> (Int, [a])
consume a
_ [] = (Int
0, [])
consume a
x l :: [a]
l@(a
y:[a]
ys)
  | a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
y = let (Int
n, [a]
zs) = a -> [a] -> (Int, [a])
forall a. Eq a => a -> [a] -> (Int, [a])
consume a
x [a]
ys in (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1, [a]
zs)
  | Bool
otherwise = (Int
0, [a]
l)

encode :: Int -> a -> Encoding a
encode :: forall a. Int -> a -> Encoding a
encode Int
1 a
x = a -> Encoding a
forall a. a -> Encoding a
Single a
x
encode Int
n a
x = Int -> a -> Encoding a
forall a. Int -> a -> Encoding a
Multiple Int
n a
x