module HGeometry.List.Util where
import           Data.Bifunctor
import qualified Data.Foldable as F
import qualified Data.List as List
import           Data.List.NonEmpty (NonEmpty(..))
import qualified Data.List.NonEmpty as NonEmpty
import           Data.Maybe
import           Data.Ord (comparing)
import           HGeometry.Ext
import           HGeometry.List.Zipper (allNonEmptyNexts, extractNext)
import qualified HGeometry.List.Zipper as Zipper
import qualified HGeometry.NonEmpty.Util as NonEmptyUtil
leaveOutOne    :: [a] -> [(a,[a])]
leaveOutOne :: forall a. [a] -> [(a, [a])]
leaveOutOne [a]
xs = (Zipper a -> [a]) -> (a, Zipper a) -> (a, [a])
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second Zipper a -> [a]
forall a. Zipper a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList ((a, Zipper a) -> (a, [a]))
-> (Zipper a -> (a, Zipper a)) -> Zipper a -> (a, [a])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (a, Zipper a) -> (a, Zipper a)
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (a, Zipper a) -> (a, Zipper a))
-> (Zipper a -> Maybe (a, Zipper a)) -> Zipper a -> (a, Zipper a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Zipper a -> Maybe (a, Zipper a)
forall a. Zipper a -> Maybe (a, Zipper a)
extractNext
              (Zipper a -> (a, [a])) -> [Zipper a] -> [(a, [a])]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Zipper a -> [Zipper a]
forall a. Zipper a -> [Zipper a]
allNonEmptyNexts ([a] -> Zipper a
forall a. [a] -> Zipper a
Zipper.fromList [a]
xs)
minimumMaybe :: Ord a => [a] -> Maybe a
minimumMaybe :: forall a. Ord a => [a] -> Maybe a
minimumMaybe = (a -> a -> Ordering) -> [a] -> Maybe a
forall a. (a -> a -> Ordering) -> [a] -> Maybe a
minimumMaybeBy a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare
maximumMaybe :: Ord a => [a] -> Maybe a
maximumMaybe :: forall a. Ord a => [a] -> Maybe a
maximumMaybe = (a -> a -> Ordering) -> [a] -> Maybe a
forall a. (a -> a -> Ordering) -> [a] -> Maybe a
minimumMaybeBy ((a -> a -> Ordering) -> a -> a -> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare)
minimumMaybeBy     :: (a -> a -> Ordering) -> [a] -> Maybe a
minimumMaybeBy :: forall a. (a -> a -> Ordering) -> [a] -> Maybe a
minimumMaybeBy a -> a -> Ordering
cmp = \case
  [] -> Maybe a
forall a. Maybe a
Nothing
  [a]
xs -> a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$ (a -> a -> Ordering) -> [a] -> a
forall (t :: * -> *) a.
Foldable t =>
(a -> a -> Ordering) -> t a -> a
List.minimumBy a -> a -> Ordering
cmp [a]
xs
minimaOn   :: Ord b => (a -> b) -> [a] -> [a]
minimaOn :: forall b a. Ord b => (a -> b) -> [a] -> [a]
minimaOn a -> b
f = (a -> a -> Ordering) -> [a] -> [a]
forall a. (a -> a -> Ordering) -> [a] -> [a]
minimaBy ((a -> b) -> a -> a -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing a -> b
f)
minimaBy     :: (a -> a -> Ordering) -> [a] -> [a]
minimaBy :: forall a. (a -> a -> Ordering) -> [a] -> [a]
minimaBy a -> a -> Ordering
cmp = \case
  []     -> []
  (a
x:[a]
xs) -> NonEmpty a -> [a]
forall a. NonEmpty a -> [a]
NonEmpty.toList (NonEmpty a -> [a]) -> NonEmpty a -> [a]
forall a b. (a -> b) -> a -> b
$ (NonEmpty a -> a -> NonEmpty a) -> NonEmpty a -> [a] -> NonEmpty a
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' (\mins :: NonEmpty a
mins@(a
m:|[a]
_) a
y -> case a
m a -> a -> Ordering
`cmp` a
y of
                                                               Ordering
LT -> NonEmpty a
mins
                                                               Ordering
EQ -> a
y a -> NonEmpty a -> NonEmpty a
forall a. a -> NonEmpty a -> NonEmpty a
NonEmpty.<| NonEmpty a
mins
                                                               Ordering
GT -> a
ya -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:|[]
                                          ) (a
xa -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:|[]) [a]
xs
extractMinimaBy        :: (a -> a -> Ordering) -> [a] -> [a] :+ [a]
 a -> a -> Ordering
cmp [a]
xs = case [a] -> Maybe (NonEmpty a)
forall a. [a] -> Maybe (NonEmpty a)
NonEmpty.nonEmpty [a]
xs of
    Maybe (NonEmpty a)
Nothing  -> [] [a] -> [a] -> [a] :+ [a]
forall core extra. core -> extra -> core :+ extra
:+ []
    Just NonEmpty a
xs' -> (NonEmpty a -> [a]) -> (NonEmpty a :+ [a]) -> [a] :+ [a]
forall a b c. (a -> b) -> (a :+ c) -> b :+ c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first NonEmpty a -> [a]
forall a. NonEmpty a -> [a]
NonEmpty.toList ((NonEmpty a :+ [a]) -> [a] :+ [a])
-> (NonEmpty a :+ [a]) -> [a] :+ [a]
forall a b. (a -> b) -> a -> b
$ (a -> a -> Ordering) -> NonEmpty a -> NonEmpty a :+ [a]
forall a. (a -> a -> Ordering) -> NonEmpty a -> NonEmpty a :+ [a]
NonEmptyUtil.extractMinimaBy a -> a -> Ordering
cmp NonEmpty a
xs'
  
  
  
  
  
  
partition3   :: Foldable f => (a -> Ordering) -> f a -> ([a],[a],[a])
partition3 :: forall (f :: * -> *) a.
Foldable f =>
(a -> Ordering) -> f a -> ([a], [a], [a])
partition3 a -> Ordering
f = (a -> ([a], [a], [a]) -> ([a], [a], [a]))
-> ([a], [a], [a]) -> f a -> ([a], [a], [a])
forall a b. (a -> b -> b) -> b -> f a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> ([a], [a], [a]) -> ([a], [a], [a])
g ([],[],[])
  where
    g :: a -> ([a], [a], [a]) -> ([a], [a], [a])
g a
x ([a]
lts,[a]
eqs,[a]
gts) = case a -> Ordering
f a
x of
                          Ordering
LT -> (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
lts,   [a]
eqs,  [a]
gts)
                          Ordering
EQ -> (  [a]
lts, a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
eqs,  [a]
gts)
                          Ordering
GT -> (  [a]
lts,   [a]
eqs,a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
gts)
groupBy'     :: (a -> a -> Ordering) -> [a] -> [NonEmpty a]
groupBy' :: forall a. (a -> a -> Ordering) -> [a] -> [NonEmpty a]
groupBy' a -> a -> Ordering
cmp = [a] -> [NonEmpty a]
go
  where
    go :: [a] -> [NonEmpty a]
go = \case
      []       -> []
      (a
x:[a]
xs)   -> let ([a]
pref,[a]
rest) = (a -> Bool) -> [a] -> ([a], [a])
forall a. (a -> Bool) -> [a] -> ([a], [a])
List.span (\a
y -> a
x a -> a -> Ordering
`cmp` a
y Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
EQ) [a]
xs
                  in (a
x a -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:| [a]
pref) NonEmpty a -> [NonEmpty a] -> [NonEmpty a]
forall a. a -> [a] -> [a]
: [a] -> [NonEmpty a]
go [a]
rest