-- | This module provides functions for creating Supersort variants for
--   adjudicating between 3 sorting algorithms.
module Data.Tensort.Subalgorithms.Supersort
  ( supersort,
    mundaneSuperStrat,
    magicSuperStrat,
  )
where

import Data.Tensort.Utils.Types
  ( SortAlg,
    Sortable (..),
    SupersortStrat,
  )

-- | Used for creating a Supersort algorithm that adjudicates between 3 sorting
--   algorithms.
--
--   Takes 3 sorting algorithms and a SuperStrat and returns a SortAlg that
--   adjudicates between the 3 sorting algorithms using the provided
--   SuperStrat.

-- | ==== __Examples__
-- >>> import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)
-- >>> import Data.Tensort.Subalgorithms.Permutationsort (permutationsort)
-- >>> import Data.Tensort.OtherSorts.Mergesort (mergesort)
--
-- >>> supersort (mergesort, bubblesort, permutationsort, mundaneSuperStrat) (SortBit [16, 23, 4, 8, 15, 42])
-- SortBit [4,8,15,16,23,42]
--
-- >>> supersort (mergesort, bubblesort, permutationsort, mundaneSuperStrat) (SortRec [(16, 23), (4, 8), (15, 42)])
-- SortRec [(4,8),(16,23),(15,42)]
supersort ::
  (SortAlg, SortAlg, SortAlg, SupersortStrat) ->
  Sortable ->
  Sortable
supersort :: (SortAlg, SortAlg, SortAlg, SupersortStrat) -> SortAlg
supersort (SortAlg
subAlg1, SortAlg
subAlg2, SortAlg
subAlg3, SupersortStrat
superStrat) Sortable
xs = do
  let result1 :: Sortable
result1 = SortAlg
subAlg1 Sortable
xs
  let result2 :: Sortable
result2 = SortAlg
subAlg2 Sortable
xs
  if Sortable
result1 Sortable -> Sortable -> Bool
forall a. Eq a => a -> a -> Bool
== Sortable
result2
    then Sortable
result1
    else SupersortStrat
superStrat (Sortable
result1, Sortable
result2, SortAlg
subAlg3 Sortable
xs)

-- | Takes 3 SortAlgs and adjudicates between them to find a common result.
--   Optimized for use in Mundane Robustsort variants.

-- | ==== __Examples__
-- >>> import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)
-- >>> import Data.Tensort.OtherSorts.Mergesort (mergesort)
-- >>> import Data.Tensort.Subalgorithms.Permutationsort (permutationsort)
--
-- >>> supersort (mergesort, bubblesort, permutationsort, mundaneSuperStrat) (SortBit [16, 23, 4, 8, 15, 42])
-- SortBit [4,8,15,16,23,42]
--
-- >>> supersort (mergesort, bubblesort, permutationsort, mundaneSuperStrat) (SortRec [(16, 23), (4, 8), (15, 42)])
-- SortRec [(4,8),(16,23),(15,42)]
mundaneSuperStrat :: SupersortStrat
mundaneSuperStrat :: SupersortStrat
mundaneSuperStrat (Sortable
result1, Sortable
result2, Sortable
result3) = if Sortable
result2 Sortable -> Sortable -> Bool
forall a. Eq a => a -> a -> Bool
== Sortable
result3 then Sortable
result2 else Sortable
result1

-- | Takes 3 SortAlgs and adjudicates between them to find a common result.
--   Optimized for use in Magic Robustsort variants.
--
--   Previously we used different SuperStrats for Mundane and Magic Supersorts.
--   Currently there is no need to differentiate, but we keep this here for
--   backwards compatibility and in case this changes again in the future.

-- | ==== __Examples__
-- >>> import Data.Tensort.Subalgorithms.Bubblesort (bubblesort)
-- >>> import Data.Tensort.OtherSorts.Mergesort (mergesort)
-- >>> import Data.Tensort.Subalgorithms.Permutationsort (permutationsort)
--
-- >>> supersort (mergesort, bubblesort, permutationsort, magicSuperStrat) (SortBit [16, 23, 4, 8, 15, 42])
-- SortBit [4,8,15,16,23,42]
--
-- >>> supersort (mergesort, bubblesort, permutationsort, magicSuperStrat) (SortRec [(16, 23), (4, 8), (15, 42)])
-- SortRec [(4,8),(16,23),(15,42)]
magicSuperStrat :: SupersortStrat
magicSuperStrat :: SupersortStrat
magicSuperStrat = SupersortStrat
mundaneSuperStrat