-- |
-- Module      :  Phladiprelio.Halfsplit
-- Copyright   :  (c) OleksandrZhabenko 2023
-- License     :  MIT
-- Stability   :  Experimental
-- Maintainer  :  oleksandr.zhabenko@yahoo.com
--

{-# LANGUAGE NoImplicitPrelude #-}

{-# OPTIONS_HADDOCK -show-extensions #-}

module Phladiprelio.Halfsplit where

import GHC.Base
import GHC.Enum (fromEnum)
import GHC.Real (quot,quotRem)
import GHC.Num ((+),(-),abs)
import Data.List hiding (foldr)
import GHC.Int (Int8)
import Text.Show (Show(..))
import System.IO (putStrLn,getLine,putStr)
import Data.Tuple (fst)

-- | Converts the data that is an instance of 'Show' typeclass to be printed in two-column way.
halfsplit 
  :: (Show a, Eq b) 
  => (a -> b)
  -> Int8 
  -> [a] 
  -> String
halfsplit :: forall a b. (Show a, Eq b) => (a -> b) -> Int8 -> [a] -> [Char]
halfsplit a -> b
g = forall a b.
(Show a, Eq b) =>
(a -> b) -> [Char] -> Int8 -> [a] -> [Char]
halfsplit1G a -> b
g [Char]
"" 
{-# INLINE halfsplit #-}

-- | Converts the data that is an instance of 'Show' typeclass to be printed in two-column way with
-- customizable ending of each line.
halfsplit1G 
  :: (Show a, Eq b) 
  => (a -> b)
  -> String -- ^ Additional 'String' added to every line before the \"\\n\" character.
  -> Int8 
  -> [a] 
  -> String
halfsplit1G :: forall a b.
(Show a, Eq b) =>
(a -> b) -> [Char] -> Int8 -> [a] -> [Char]
halfsplit1G a -> b
g [Char]
appendstr Int8
m [a]
xs 
 | forall (t :: * -> *) a. Foldable t => t a -> Bool
null [a]
xs = []
 | Bool
otherwise = 
    let (Int
n, Int
rr2) = forall a. Integral a => a -> a -> (a, a)
quotRem (forall a. Enum a => a -> Int
fromEnum Int8
m) (if Int8
m forall a. Ord a => a -> a -> Bool
< Int8
0 then -Int
10 else Int
10)
        r :: ([[Char]], [[Char]])
r = 
          case forall a. Num a => a -> a
abs Int
rr2 of
           Int
1 -> let us :: [a]
us = forall a. [a] -> [a]
reverse [a]
ts in (if Int
rrr forall a. Eq a => a -> a -> Bool
== Int
0 then forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> [Char]
show [a]
ys else forall a. Int -> a -> [a]
replicate Int
l0 Char
' 'forall a. a -> [a] -> [a]
:forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> [Char]
show [a]
ys, forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> [Char]
show [a]
us)
           Int
2 -> let us :: [[[Char]]]
us = (forall a. Int -> a -> [a]
replicate (Int
lt1 forall a. Num a => a -> a -> a
- Int
ly1) [forall a. Int -> a -> [a]
replicate Int
l0 Char
' ']) forall a. Monoid a => a -> a -> a
`mappend` forall a. [a] -> [a]
reverse (forall a b. (a -> b) -> [a] -> [b]
map forall a. [a] -> [a]
reverse [[[Char]]]
y1s) in (forall a. Monoid a => [a] -> a
mconcat [[[Char]]]
us, forall a. Monoid a => [a] -> a
mconcat [[[Char]]]
t1s)
           Int
3 -> let us :: [[[Char]]]
us = (forall a. Int -> a -> [a]
replicate (Int
lt1 forall a. Num a => a -> a -> a
- Int
ly1) [forall a. Int -> a -> [a]
replicate Int
l0 Char
' ']) forall a. Monoid a => a -> a -> a
`mappend` [[[Char]]]
y1s
                    ks :: [[[Char]]]
ks = forall a. [a] -> [a]
reverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ [[[Char]]]
t1s in (forall a. Monoid a => [a] -> a
mconcat [[[Char]]]
us, forall a. Monoid a => [a] -> a
mconcat [[[Char]]]
ks)
           Int
4 -> let us :: [[[Char]]]
us = (forall a. Int -> a -> [a]
replicate (Int
lt2 forall a. Num a => a -> a -> a
- Int
ly2) [forall a. Int -> a -> [a]
replicate Int
l0 Char
' ']) forall a. Monoid a => a -> a -> a
`mappend` forall a. [a] -> [a]
reverse (forall a b. (a -> b) -> [a] -> [b]
map forall a. [a] -> [a]
reverse [[[Char]]]
y2s) in (forall a. Monoid a => [a] -> a
mconcat [[[Char]]]
us, forall a. Monoid a => [a] -> a
mconcat [[[Char]]]
t2s)
           Int
5 -> let us :: [[[Char]]]
us = (forall a. Int -> a -> [a]
replicate (Int
lt2 forall a. Num a => a -> a -> a
- Int
ly2) [forall a. Int -> a -> [a]
replicate Int
l0 Char
' ']) forall a. Monoid a => a -> a -> a
`mappend` [[[Char]]]
y2s
                    ks :: [[[Char]]]
ks = forall a. [a] -> [a]
reverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ [[[Char]]]
t2s in (forall a. Monoid a => [a] -> a
mconcat [[[Char]]]
us, forall a. Monoid a => [a] -> a
mconcat [[[Char]]]
ks)
           Int
_ -> let us :: [a]
us = forall a. [a] -> [a]
reverse [a]
ys in (if Int
rrr forall a. Eq a => a -> a -> Bool
== Int
0 then forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> [Char]
show [a]
us else forall a. Int -> a -> [a]
replicate Int
l0 Char
' 'forall a. a -> [a] -> [a]
:forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> [Char]
show [a]
us, forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> [Char]
show [a]
ts) in ((\([[Char]]
rs, [[Char]]
qs) -> Int -> [Char] -> [[Char]] -> [[Char]] -> [Char]
mergePartsLine Int
n ([Char]
appendstr forall a. Monoid a => a -> a -> a
`mappend` [Char]
"\n") [[Char]]
rs [[Char]]
qs) ([[Char]], [[Char]])
r) forall a. Monoid a => a -> a -> a
`mappend` [Char]
appendstr
              where ([a]
ys,[a]
ts) = forall a. Int -> [a] -> ([a], [a])
splitAt Int
l [a]
xs 
                    (Int
l,Int
rrr) = forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs forall a. Integral a => a -> a -> (a, a)
`quotRem` Int
2
                    l0 :: Int
l0 = forall (t :: * -> *) a. Foldable t => t a -> Int
length forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> [Char]
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> a
head forall a b. (a -> b) -> a -> b
$ [a]
xs 
                    rss :: [[[Char]]]
rss = forall a b. (a -> b) -> [a] -> [b]
map (forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> [Char]
show) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy (\a
x a
y ->  a -> b
g a
x forall a. Eq a => a -> a -> Bool
== a -> b
g a
y) forall a b. (a -> b) -> a -> b
$ [a]
xs
                    r1ss :: [[[Char]]]
r1ss = forall a. a -> [a] -> [a]
intersperse [forall a. Int -> a -> [a]
replicate Int
l0 Char
' '] [[[Char]]]
rss
                    l2 :: Int
l2 = (forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ [[[Char]]]
rss) forall a. Integral a => a -> a -> a
`quot` Int
2
                    l3 :: Int
l3 = (forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ [[[Char]]]
r1ss) forall a. Integral a => a -> a -> a
`quot` Int
2
                    ([[[Char]]]
y1s,[[[Char]]]
t1s,Int
_) = forall a. Int -> [[a]] -> ([[a]], [[a]], Int)
splitGroups Int
l2 [[[Char]]]
rss
                    ly1 :: Int
ly1 = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ [[[Char]]]
y1s
                    lt1 :: Int
lt1 = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ [[[Char]]]
t1s
                    ([[[Char]]]
y2s,[[[Char]]]
t2s,Int
_) = forall a. Int -> [[a]] -> ([[a]], [[a]], Int)
splitGroups Int
l3 [[[Char]]]
r1ss
                    ly2 :: Int
ly2 = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ [[[Char]]]
y2s
                    lt2 :: Int
lt2 = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ [[[Char]]]
t2s

-- | A generalized version of 'halfsplit1G' with the possibility to prepend and append strings to it.
halfsplit2G 
  :: (Show a, Eq b) 
  => (a -> b)
  -> String -- ^ Additional 'String' added to every line before the \"\\n\" character.
  -> String -- ^ A 'String' that is prepended to the 'halfsplit1G' result.
  -> String -- ^ A 'String' that is appended to the 'halfsplit1G' result.
  -> Int8 
  -> [a] 
  -> String
halfsplit2G :: forall a b.
(Show a, Eq b) =>
(a -> b) -> [Char] -> [Char] -> [Char] -> Int8 -> [a] -> [Char]
halfsplit2G a -> b
g [Char]
appendstr [Char]
prestr [Char]
poststr Int8
m [a]
xs = [Char]
prestr forall a. Monoid a => a -> a -> a
`mappend` forall a b.
(Show a, Eq b) =>
(a -> b) -> [Char] -> Int8 -> [a] -> [Char]
halfsplit1G a -> b
g [Char]
appendstr Int8
m [a]
xs forall a. Monoid a => a -> a -> a
`mappend` [Char]
poststr
{-# INLINABLE halfsplit2G #-}

mergePartsLine :: Int -> String -> [String] -> [String] -> String
mergePartsLine :: Int -> [Char] -> [[Char]] -> [[Char]] -> [Char]
mergePartsLine Int
n [Char]
newlined [[Char]]
xs [[Char]]
ys = forall a. [a] -> [[a]] -> [a]
intercalate [Char]
newlined forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\[Char]
x [Char]
y -> [Char]
x forall a. Monoid a => a -> a -> a
`mappend` (forall a. Int -> a -> [a]
replicate Int
n (if Int
n forall a. Ord a => a -> a -> Bool
< Int
0 then Char
'\t' else Char
' ')) forall a. Monoid a => a -> a -> a
`mappend` [Char]
y) [[Char]]
xs forall a b. (a -> b) -> a -> b
$ [[Char]]
ys

splitGroups :: Int -> [[a]] -> ([[a]], [[a]], Int)
splitGroups :: forall a. Int -> [[a]] -> ([[a]], [[a]], Int)
splitGroups Int
l [[a]]
tss = forall a b. (a -> b -> b) -> b -> [a] -> b
foldr forall {t :: * -> *} {a}.
Foldable t =>
t a -> ([t a], [t a], Int) -> ([t a], [t a], Int)
h ([],[],Int
0) [[a]]
tss
   where h :: t a -> ([t a], [t a], Int) -> ([t a], [t a], Int)
h t a
js ([t a]
rss,[t a]
mss,Int
k)
            | Int
k forall a. Ord a => a -> a -> Bool
< Int
l = ([t a]
rss, t a
jsforall a. a -> [a] -> [a]
:[t a]
mss, Int
k forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. Foldable t => t a -> Int
length t a
js)
            | Bool
otherwise = (t a
js forall a. a -> [a] -> [a]
: [t a]
rss, [t a]
mss, Int
k forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. Foldable t => t a -> Int
length t a
js)

showWithSpaces :: (Show a) => Int -> a -> String
showWithSpaces :: forall a. Show a => Int -> a -> [Char]
showWithSpaces Int
n a
x 
 | Int
l forall a. Ord a => a -> a -> Bool
< Int
n = [Char]
xs forall a. Monoid a => a -> a -> a
`mappend` forall a. Int -> a -> [a]
replicate (Int
n forall a. Num a => a -> a -> a
- Int
l) Char
' '
 | Bool
otherwise = [Char]
xs
    where xs :: [Char]
xs = forall a. Show a => a -> [Char]
show a
x
          l :: Int
l = forall (t :: * -> *) a. Foldable t => t a -> Int
length [Char]
xs

print23 :: String -> String -> Int -> [String] -> IO ()
print23 :: [Char] -> [Char] -> Int -> [[Char]] -> IO ()
print23 [Char]
prestr [Char]
poststr Int
n [[Char]]
xss = do
  [Char] -> IO ()
putStrLn [Char]
prestr
  let linez :: [([Char], Int)]
linez = forall a b. [a] -> [b] -> [(a, b)]
zip [[Char]]
xss [Int
1..]
  if Int
n forall a. Ord a => a -> a -> Bool
>= Int
2 Bool -> Bool -> Bool
&& Int
n forall a. Ord a => a -> a -> Bool
<= Int
l forall a. Num a => a -> a -> a
- Int
1
      then do
          let linez3 :: [[Char]]
linez3 = (\([Char]
x:[Char]
y:[Char]
t:[[Char]]
xs) -> [Char]
xforall a. a -> [a] -> [a]
:(Char
' 'forall a. a -> [a] -> [a]
:[Char]
y)forall a. a -> [a] -> [a]
:(Char
' 'forall a. a -> [a] -> [a]
:Char
' 'forall a. a -> [a] -> [a]
:[Char]
t)forall a. a -> [a] -> [a]
:[[Char]]
xs) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter (\([Char]
ts,Int
m) -> Int
m forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int
n forall a. Num a => a -> a -> a
- Int
1..Int
n forall a. Num a => a -> a -> a
+ Int
1]) forall a b. (a -> b) -> a -> b
$ [([Char], Int)]
linez
          forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM ([Char] -> IO ()
putStrLn) [[Char]]
linez3 forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [Char] -> IO ()
putStrLn [Char]
poststr
      else (case Int
n of
             Int
1 -> [Char] -> IO ()
putStr [Char]
" " forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM [Char] -> IO ()
putStrLn (forall a. Int -> [a] -> [a]
take Int
2 [[Char]]
xss)
             Int
m -> if Int
m forall a. Eq a => a -> a -> Bool
== Int
l then forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM [Char] -> IO ()
putStrLn ((\([Char]
x:[Char]
y:[[Char]]
xs) -> [Char]
xforall a. a -> [a] -> [a]
:(Char
' 'forall a. a -> [a] -> [a]
:[Char]
y)forall a. a -> [a] -> [a]
:[[Char]]
xs) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop (Int
l forall a. Num a => a -> a -> a
- Int
2) forall a b. (a -> b) -> a -> b
$ [[Char]]
xss) else forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM [Char] -> IO ()
putStrLn []) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [Char] -> IO ()
putStrLn [Char]
poststr
         where l :: Int
l = forall (t :: * -> *) a. Foldable t => t a -> Int
length [[Char]]
xss