{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_HADDOCK show-extensions #-}

{- |
Module      :  Aftovolio.UniquenessPeriodsG
Copyright   :  (c) OleksandrZhabenko 2020-2023
License     :  MIT
Stability   :  Experimental
Maintainer  :  oleksandr.zhabenko@yahoo.com

Generalization of the uniqueness-periods and uniqueness-periods-general
packages functionality for small 'F.Foldable' data structures. Uses less dependencies.
-}
module Aftovolio.UniquenessPeriodsG (
    -- * List functions
    uniquenessPeriodsGG,
    uniquenessPeriodsG,
    uniquenessPeriodsGI8,
    diverse2GGL,
    diverse2GL,
    diverse2GLInt8,
) where

import qualified Data.Foldable as F
import Data.List hiding (foldr)
import Data.Maybe (mapMaybe)
import Data.Tuple
import GHC.Base
import GHC.Int
import GHC.Num ((-))

-- | A generalization of the uniquenessPeriods function of the @uniqueness-periods@ package.
uniquenessPeriodsGG ::
    (F.Foldable t1, F.Foldable t2, F.Foldable t3, Ord a) =>
    t3 a ->
    t1 a ->
    t2 a ->
    [Int16]
uniquenessPeriodsGG :: forall (t1 :: * -> *) (t2 :: * -> *) (t3 :: * -> *) a.
(Foldable t1, Foldable t2, Foldable t3, Ord a) =>
t3 a -> t1 a -> t2 a -> [Int16]
uniquenessPeriodsGG t3 a
sels t1 a
whspss t2 a
ws
    | t2 a -> Bool
forall a. t2 a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
F.null t2 a
ws = []
    | Bool
otherwise = (([Int16], a) -> Maybe Int16) -> [([Int16], a)] -> [Int16]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (t3 a -> ([Int16] -> Int16) -> t1 a -> ([Int16], a) -> Maybe Int16
forall a (t1 :: * -> *) (t2 :: * -> *) (t3 :: * -> *) b.
(Eq a, Foldable t1, Foldable t2, Foldable t3) =>
t3 a -> (t1 b -> b) -> t2 a -> (t1 b, a) -> Maybe b
helpGSel t3 a
sels [Int16] -> Int16
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
F.sum t1 a
whspss) ([([Int16], a)] -> [Int16])
-> ([(Int16, a)] -> [([Int16], a)]) -> [(Int16, a)] -> [Int16]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([(Int16, a)] -> Maybe (([Int16], a), [(Int16, a)]))
-> [(Int16, a)] -> [([Int16], a)]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr [(Int16, a)] -> Maybe (([Int16], a), [(Int16, a)])
forall {a}.
Eq a =>
[(Int16, a)] -> Maybe (([Int16], a), [(Int16, a)])
f ([(Int16, a)] -> [Int16]) -> [(Int16, a)] -> [Int16]
forall a b. (a -> b) -> a -> b
$ [(Int16, a)]
ks
  where
    !ks :: [(Int16, a)]
ks = t2 a -> [(Int16, a)]
forall (t :: * -> *) b. Foldable t => t b -> [(Int16, b)]
indexedL t2 a
ws
    !vs :: [Int16]
vs = ((Int16, a) -> Maybe Int16) -> [(Int16, a)] -> [Int16]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (Int16, a) -> Maybe Int16
forall {a}. (a, a) -> Maybe a
g [(Int16, a)]
ks
    g :: (a, a) -> Maybe a
g (a
x, a
y)
        | a
y a -> t1 a -> Bool
forall a. Eq a => a -> t1 a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`F.elem` t1 a
whspss = a -> Maybe a
forall a. a -> Maybe a
Just a
x
        | Bool
otherwise = Maybe a
forall a. Maybe a
Nothing
    {-# INLINE g #-}
    f :: [(Int16, a)] -> Maybe (([Int16], a), [(Int16, a)])
f ys :: [(Int16, a)]
ys@((Int16, a)
y : [(Int16, a)]
_) =
        let !idX0 :: a
idX0 = (Int16, a) -> a
forall a b. (a, b) -> b
snd (Int16, a)
y
         in (([Int16], a), [(Int16, a)]) -> Maybe (([Int16], a), [(Int16, a)])
forall a. a -> Maybe a
Just
                ((([Int16], a), [(Int16, a)])
 -> Maybe (([Int16], a), [(Int16, a)]))
-> ([(Int16, a)] -> (([Int16], a), [(Int16, a)]))
-> [(Int16, a)]
-> Maybe (([Int16], a), [(Int16, a)])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ( \([(Int16, a)]
v2, [(Int16, a)]
v3) ->
                        (
                            ( [Int16] -> [Int16] -> [Int16] -> [Int16]
helpUPV3 [Int16]
vs []
                                ([Int16] -> [Int16])
-> ([(Int16, a)] -> [Int16]) -> [(Int16, a)] -> [Int16]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int16, a) -> Int16) -> [(Int16, a)] -> [Int16]
forall a b. (a -> b) -> [a] -> [b]
map (Int16, a) -> Int16
forall a b. (a, b) -> a
fst
                                ([(Int16, a)] -> [Int16]) -> [(Int16, a)] -> [Int16]
forall a b. (a -> b) -> a -> b
$ [(Int16, a)]
v2
                            , (Int16, a) -> a
forall a b. (a, b) -> b
snd ((Int16, a) -> a)
-> ([(Int16, a)] -> (Int16, a)) -> [(Int16, a)] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Int16, a)] -> (Int16, a)
forall a. HasCallStack => [a] -> a
head ([(Int16, a)] -> a) -> [(Int16, a)] -> a
forall a b. (a -> b) -> a -> b
$ [(Int16, a)]
v2
                            )
                        , [(Int16, a)]
v3
                        )
                  )
                (([(Int16, a)], [(Int16, a)]) -> (([Int16], a), [(Int16, a)]))
-> ([(Int16, a)] -> ([(Int16, a)], [(Int16, a)]))
-> [(Int16, a)]
-> (([Int16], a), [(Int16, a)])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int16, a) -> Bool)
-> [(Int16, a)] -> ([(Int16, a)], [(Int16, a)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (\(Int16
_, a
xs) -> a
xs a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
idX0)
                ([(Int16, a)] -> Maybe (([Int16], a), [(Int16, a)]))
-> [(Int16, a)] -> Maybe (([Int16], a), [(Int16, a)])
forall a b. (a -> b) -> a -> b
$ [(Int16, a)]
ys
    f [(Int16, a)]
_ = Maybe (([Int16], a), [(Int16, a)])
forall a. Maybe a
Nothing
{-# INLINE uniquenessPeriodsGG #-}

-- | A general variant of the diversity property. Use it in general case.
diverse2GGL ::
    (F.Foldable t1, F.Foldable t2, F.Foldable t3, Ord a) =>
    t3 a ->
    t1 a ->
    t2 a ->
    Int16
diverse2GGL :: forall (t1 :: * -> *) (t2 :: * -> *) (t3 :: * -> *) a.
(Foldable t1, Foldable t2, Foldable t3, Ord a) =>
t3 a -> t1 a -> t2 a -> Int16
diverse2GGL t3 a
sels t1 a
whspss = [Int16] -> Int16
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int16] -> Int16) -> (t2 a -> [Int16]) -> t2 a -> Int16
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t3 a -> t1 a -> t2 a -> [Int16]
forall (t1 :: * -> *) (t2 :: * -> *) (t3 :: * -> *) a.
(Foldable t1, Foldable t2, Foldable t3, Ord a) =>
t3 a -> t1 a -> t2 a -> [Int16]
uniquenessPeriodsGG t3 a
sels t1 a
whspss
{-# INLINE diverse2GGL #-}

-- | A variant of the 'diverse2GGL' function for 'Char'.
diverse2GL :: (F.Foldable t1, F.Foldable t2) => t1 Char -> t2 Char -> Int16
diverse2GL :: forall (t1 :: * -> *) (t2 :: * -> *).
(Foldable t1, Foldable t2) =>
t1 Char -> t2 Char -> Int16
diverse2GL = [Char] -> t1 Char -> t2 Char -> Int16
forall (t1 :: * -> *) (t2 :: * -> *) (t3 :: * -> *) a.
(Foldable t1, Foldable t2, Foldable t3, Ord a) =>
t3 a -> t1 a -> t2 a -> Int16
diverse2GGL []
{-# INLINE diverse2GL #-}

--

-- | A variant for the 'uniquenessPeriodsGG' function for 'Char'.
uniquenessPeriodsG ::
    (F.Foldable t1, F.Foldable t2) => t1 Char -> t2 Char -> [Int16]
uniquenessPeriodsG :: forall (t1 :: * -> *) (t2 :: * -> *).
(Foldable t1, Foldable t2) =>
t1 Char -> t2 Char -> [Int16]
uniquenessPeriodsG = [Char] -> t1 Char -> t2 Char -> [Int16]
forall (t1 :: * -> *) (t2 :: * -> *) (t3 :: * -> *) a.
(Foldable t1, Foldable t2, Foldable t3, Ord a) =>
t3 a -> t1 a -> t2 a -> [Int16]
uniquenessPeriodsGG []
{-# INLINE uniquenessPeriodsG #-}

-- | A variant of the 'diverse2GGL' function for 'Int8'.
diverse2GLInt8 :: (F.Foldable t1, F.Foldable t2) => t1 Int8 -> t2 Int8 -> Int16
diverse2GLInt8 :: forall (t1 :: * -> *) (t2 :: * -> *).
(Foldable t1, Foldable t2) =>
t1 Int8 -> t2 Int8 -> Int16
diverse2GLInt8 = [Int8] -> t1 Int8 -> t2 Int8 -> Int16
forall (t1 :: * -> *) (t2 :: * -> *) (t3 :: * -> *) a.
(Foldable t1, Foldable t2, Foldable t3, Ord a) =>
t3 a -> t1 a -> t2 a -> Int16
diverse2GGL []
{-# INLINE diverse2GLInt8 #-}

-- | A variant for the 'uniquenessPeriodsGG' function for 'Int8'.
uniquenessPeriodsGI8 ::
    (F.Foldable t1, F.Foldable t2) => t1 Int8 -> t2 Int8 -> [Int16]
uniquenessPeriodsGI8 :: forall (t1 :: * -> *) (t2 :: * -> *).
(Foldable t1, Foldable t2) =>
t1 Int8 -> t2 Int8 -> [Int16]
uniquenessPeriodsGI8 = [Int8] -> t1 Int8 -> t2 Int8 -> [Int16]
forall (t1 :: * -> *) (t2 :: * -> *) (t3 :: * -> *) a.
(Foldable t1, Foldable t2, Foldable t3, Ord a) =>
t3 a -> t1 a -> t2 a -> [Int16]
uniquenessPeriodsGG []
{-# INLINE uniquenessPeriodsGI8 #-}

-- | The first and the third list arguments of numbers (if not empty) must be sorted in the ascending order.
helpUPV3 :: [Int16] -> [Int16] -> [Int16] -> [Int16]
helpUPV3 :: [Int16] -> [Int16] -> [Int16] -> [Int16]
helpUPV3 ks :: [Int16]
ks@(!Int16
z : [Int16]
zs) ![Int16]
acc ps :: [Int16]
ps@(!Int16
x : qs :: [Int16]
qs@(!Int16
y : [Int16]
_))
    | Int16
z Int16 -> Int16 -> Bool
forall a. Ord a => a -> a -> Bool
< Int16
y Bool -> Bool -> Bool
&& Int16
z Int16 -> Int16 -> Bool
forall a. Ord a => a -> a -> Bool
> Int16
x = [Int16] -> [Int16] -> [Int16] -> [Int16]
helpUPV3 [Int16]
zs ((Int16
y Int16 -> Int16 -> Int16
forall a. Num a => a -> a -> a
- Int16
x) Int16 -> [Int16] -> [Int16]
forall a. a -> [a] -> [a]
: [Int16]
acc) [Int16]
qs
    | Int16
z Int16 -> Int16 -> Bool
forall a. Ord a => a -> a -> Bool
< Int16
y = [Int16] -> [Int16] -> [Int16] -> [Int16]
helpUPV3 [Int16]
zs [Int16]
acc [Int16]
ps
    | Bool
otherwise = [Int16] -> [Int16] -> [Int16] -> [Int16]
helpUPV3 [Int16]
ks [Int16]
acc [Int16]
qs
helpUPV3 [Int16]
_ ![Int16]
acc [Int16]
_ = [Int16]
acc

indexedL :: (F.Foldable t) => t b -> [(Int16, b)]
indexedL :: forall (t :: * -> *) b. Foldable t => t b -> [(Int16, b)]
indexedL = (b -> [(Int16, b)] -> [(Int16, b)])
-> [(Int16, b)] -> t b -> [(Int16, b)]
forall a b. (a -> b -> b) -> b -> t a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
F.foldr b -> [(Int16, b)] -> [(Int16, b)]
forall {a} {b}. Num a => b -> [(a, b)] -> [(a, b)]
f []
  where
    f :: b -> [(a, b)] -> [(a, b)]
f b
x ((a
j, b
z) : [(a, b)]
ys) = (a
j a -> a -> a
forall a. Num a => a -> a -> a
- a
1, b
x) (a, b) -> [(a, b)] -> [(a, b)]
forall a. a -> [a] -> [a]
: (a
j, b
z) (a, b) -> [(a, b)] -> [(a, b)]
forall a. a -> [a] -> [a]
: [(a, b)]
ys
    f b
x [(a, b)]
_ = [(a
1, b
x)]

helpG ::
    (Eq a, F.Foldable t1, F.Foldable t2) =>
    (t1 b -> b) ->
    t2 a ->
    (t1 b, a) ->
    Maybe b
helpG :: forall a (t1 :: * -> *) (t2 :: * -> *) b.
(Eq a, Foldable t1, Foldable t2) =>
(t1 b -> b) -> t2 a -> (t1 b, a) -> Maybe b
helpG t1 b -> b
h t2 a
xs (t1 b
ts, a
x)
    | t1 b -> Bool
forall a. t1 a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
F.null t1 b
ts = Maybe b
forall a. Maybe a
Nothing
    | a
x a -> t2 a -> Bool
forall a. Eq a => a -> t2 a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`F.elem` t2 a
xs = Maybe b
forall a. Maybe a
Nothing
    | Bool
otherwise = b -> Maybe b
forall a. a -> Maybe a
Just (t1 b -> b
h t1 b
ts)
{-# INLINE helpG #-}

helpGSel ::
    (Eq a, F.Foldable t1, F.Foldable t2, F.Foldable t3) =>
    t3 a ->
    (t1 b -> b) ->
    t2 a ->
    (t1 b, a) ->
    Maybe b
helpGSel :: forall a (t1 :: * -> *) (t2 :: * -> *) (t3 :: * -> *) b.
(Eq a, Foldable t1, Foldable t2, Foldable t3) =>
t3 a -> (t1 b -> b) -> t2 a -> (t1 b, a) -> Maybe b
helpGSel t3 a
sels t1 b -> b
h t2 a
xs (t1 b
ts, a
x)
    | t3 a -> Bool
forall a. t3 a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
F.null t3 a
sels = (t1 b -> b) -> t2 a -> (t1 b, a) -> Maybe b
forall a (t1 :: * -> *) (t2 :: * -> *) b.
(Eq a, Foldable t1, Foldable t2) =>
(t1 b -> b) -> t2 a -> (t1 b, a) -> Maybe b
helpG t1 b -> b
h t2 a
xs (t1 b
ts, a
x)
    | t1 b -> Bool
forall a. t1 a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
F.null t1 b
ts = Maybe b
forall a. Maybe a
Nothing
    | a
x a -> t2 a -> Bool
forall a. Eq a => a -> t2 a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`F.elem` t2 a
xs = Maybe b
forall a. Maybe a
Nothing
    | a
x a -> t3 a -> Bool
forall a. Eq a => a -> t3 a -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`F.elem` t3 a
sels = b -> Maybe b
forall a. a -> Maybe a
Just (t1 b -> b
h t1 b
ts)
    | Bool
otherwise = Maybe b
forall a. Maybe a
Nothing
{-# INLINE helpGSel #-}