-- |
-- Module      :  DobutokO.Poetry
-- Copyright   :  (c) OleksandrZhabenko 2020
-- License     :  MIT
-- Stability   :  Experimental
-- Maintainer  :  olexandr543@yahoo.com
--
-- Helps to order the 7 or less Ukrainian words (or their concatenations) 
-- to obtain (to some extent) suitable for poetry or music text. The main 
-- module in the library that imports all other ones except Main.

{-# LANGUAGE BangPatterns #-}

module DobutokO.Poetry (
  -- * Uniqueness type synonym
  Uniqueness
  -- * Main functions
  , uniq10Poetical4
  , uniq10Poetical5
  , uniq10PoeticalG
  , uniqNPoeticalG
  , uniqNPoeticalGN
  , uniqNPoetical
  , uniqNPoeticalN
  , uniqNPoeticalV
  , uniqNPoeticalVN
  , uniqNPoeticalVG
  , uniqNPoeticalVGN
  -- * Additional functions
  , uniquenessVariantsG
  , uniquenessVariantsGN
  , uniquenessVariants3
  , uniquenessVariants4
  , uniqMaxPoeticalG
  , uniqMaxPoeticalGN
  , uniqMaxPoeticalGNV
  , uniqInMaxPoetical
  , uniqInMaxPoeticalN
  -- * Generalized variants
  -- ** Main ones
  , uniqNPoetical2GN
  , uniqNPoetical2VGN
  , uniqNPoeticalUGN_
  , uniqNPoeticalUGN
  , uniqNPoeticalUGN51_
  , uniqNPoeticalUGN51
  -- ** Additional functions
  , uniquenessVariants2GN
  , uniqMaxPoetical2GN
  -- * On one line output
  , uniqInMaxPoeticalNLine
  , uniqNPoeticalNLine
  , uniqNPoetical2GNLine
) where

import Data.Char (isPunctuation)
import qualified Data.Vector as V
import Data.List ((\\))
import MMSyn7s
import DobutokO.Poetry.Norms
import DobutokO.Poetry.Auxiliary
import DobutokO.Poetry.UniquenessPeriodsG

type Uniqueness = ([Int],V.Vector Int,String)

-- | A variant of 'uniquesessVariantsG' with the norm being 'norm3'.
uniquenessVariants3 :: String -> V.Vector ([Int],Int,Int,Int,String)
uniquenessVariants3 = uniquenessVariantsG norm3

-- | A variant of 'uniquesessVariantsG' with the norm being 'norm4'.
uniquenessVariants4 :: String -> V.Vector ([Int],Int,Int,Int,String)
uniquenessVariants4 = uniquenessVariantsG norm4

-- | Given a 'String' consisting of no more than 7 Ukrainian words [some of them can be created by concatenation with preserving the Ukrainian 
-- pronunciation of the parts, e. g. \"так як\" (actually two correct Ukrainian words and a single conjunction) can be written \"такйак\" 
-- (one phonetical Ukrainian word transformed literally with preserving phonetical structure), if you would not like to treat them separately], 
-- it returns a 'V.Vector' of possible combinations without repeating of the words in different order and for each of them appends also 
-- the information about 'uniquenessPeriods' to it and finds out three different metrics -- named \"norms\". 
-- 
-- Afterwards, depending on these norms it can be specified some phonetical properties of the words that 
-- allow to use them poetically or to create a varied melody with them. Some variants of this generalized function are 'uniquesessVariants3' and 
-- 'uniquesessVariants4' with the predefined norms.
uniquenessVariantsG :: ([Int] -> Int) -> String -> V.Vector ([Int],Int,Int,Int,String)
uniquenessVariantsG g xs
  | null xs = V.empty
  | otherwise =
     case V.length . V.fromList . take 7 . words $ xs of
      7 ->
       V.fromList . map ((\vs -> let !rs = uniquenessPeriods vs in (rs, norm1 rs, norm2 rs, g rs, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $
         ([V.fromList [x1,x2,x3,x4,x5,x6,x7] | !x1 <- [0..6], !x2 <- [0..6] \\ [x1], !x3 <- [0..6] \\ [x1,x2], !x4 <- [0..6] \\ [x1,x2,x3],
           !x5 <- [0..6] \\ [x1,x2,x3,x4], !x6 <- [0..6] \\ [x1,x2,x3,x4,x5], !x7 <- [0..6] \\ [x1,x2,x3,x4,x5,x6]]::[V.Vector Int])
      6 ->
       V.fromList . map ((\vs -> let rs = uniquenessPeriods vs in (rs, norm1 rs, norm2 rs, g rs, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $
         ([V.fromList [x1,x2,x3,x4,x5,x6] | !x1 <- [0..5], !x2 <- [0..5] \\ [x1], !x3 <- [0..5] \\ [x1,x2], !x4 <- [0..5] \\ [x1,x2,x3],
           !x5 <- [0..5] \\ [x1,x2,x3,x4], !x6 <- [0..5] \\ [x1,x2,x3,x4,x5]]::[V.Vector Int])
      5 ->
       V.fromList . map ((\vs -> let rs = uniquenessPeriods vs in (rs, norm1 rs, norm2 rs, g rs, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $
         ([V.fromList [x1,x2,x3,x4,x5] | !x1 <- [0..4], !x2 <- [0..4] \\ [x1], !x3 <- [0..4] \\ [x1,x2], !x4 <- [0..4] \\ [x1,x2,x3],
            !x5 <- [0..4] \\ [x1,x2,x3,x4]]::[V.Vector Int])
      4 ->
       V.fromList . map ((\vs -> let rs = uniquenessPeriods vs in (rs, norm1 rs, norm2 rs, g rs, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $
         ([V.fromList [x1,x2,x3,x4] | !x1 <- [0..3], !x2 <- [0..3] \\ [x1], !x3 <- [0..3] \\ [x1,x2], !x4 <- [0..3] \\ [x1,x2,x3]]::[V.Vector Int])
      3 ->
       V.fromList . map ((\vs -> let rs = uniquenessPeriods vs in (rs, norm1 rs, norm2 rs, g rs, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $ ([V.fromList [x1,x2,x3] | !x1 <- [0..2], !x2 <- [0..2] \\ [x1],
          !x3 <- [0..2] \\ [x1,x2]]::[V.Vector Int])
      2 ->
       V.fromList . map ((\vs -> let rs = uniquenessPeriods vs in (rs, norm1 rs, norm2 rs, g rs, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $ ([V.fromList [x1,x2] | !x1 <- [0,1], !x2 <- [0,1] \\ [x1]]::[V.Vector Int])
      _ -> V.empty

-- | Generalization of the 'uniquenessVariantsG' with usage of several norms (instead of one). They constitute a 'V.Vector' of functions 
-- @norm :: [Int] -> Int@. So the inner vector in the each resulting 'Uniqueness' has the same length as the vector of norms.
uniquenessVariantsGN :: V.Vector ([Int] -> Int) -> String -> V.Vector Uniqueness
uniquenessVariantsGN vN = uniquenessVariants2GN vN (uniquenessPeriods)

-- | Given a norm and a Ukrainian 'String' consisting of no more than 7 words (see also the information for 'uniquenessVariantG'), returns the maximum by the
-- specified norm element of the 'uniquenessVariantsG' applied to the same arguments.
uniqMaxPoeticalG :: ([Int] -> Int) ->  String -> ([Int],Int,Int,Int,String)
uniqMaxPoeticalG g = V.maximumBy (\(_,_,_,x30,_) (_,_,_,x31,_) -> compare x30 x31) . uniquenessVariantsG g

-- | Generalized variant of the 'uniqMaxPoeticalG' with the several norms given as a 'V.Vector' of functions and an 'Int' parameter. The function evaluates 
-- the generated 'V.Vector' of 'Uniqueness' elements to retrieve the possibly maximum element in it with respect to the order and significance (principality) 
-- of the norms being evaluated. The most significant and principal is the norm, which index in the 'V.Vector' of them is the 'Int' argument of the function 
-- minus 1, then less significant is the next to the left norm and so on.
uniqMaxPoeticalGN :: Int -> V.Vector ([Int] -> Int) ->  String -> Uniqueness
uniqMaxPoeticalGN k vN = uniqMaxPoetical2GN k vN (uniquenessPeriods)

-- | Similar to 'uniqMaxPoeticalG' but instead of resulting in a maximum element, outputs it by parts and returns the rest of the 'V.Vector' without this 
-- maximum element.
uniqInMaxPoetical :: V.Vector ([Int],Int,Int,Int,String) -> IO (V.Vector ([Int],Int,Int,Int,String))
uniqInMaxPoetical v = do
  let !uniq = V.maximumBy (\(_,_,_,x30,_) (_,_,_,x31,_) -> compare x30 x31) v
  putStrLn (filter (not . isPunctuation) . lastFrom5 $ uniq) >> print (fourFrom5 uniq) >> putStrLn ""
  return . V.filter (/= uniq) $ v

-- | Generalized variant of the 'uniqInMaxPoetical' with usage of the several norms. 
uniqInMaxPoeticalN :: Int -> V.Vector ([Int] -> Int) -> V.Vector Uniqueness -> IO (V.Vector Uniqueness)
uniqInMaxPoeticalN k vN v = do
  let !uniq = uniqMaxPoeticalGNV k vN v
  putStrLn (filter (not . isPunctuation) . lastFrom3 $ uniq) >> print (twoFrom3 uniq) >> putStrLn ""
  return . V.filter (/= uniq) $ v

-- | Generalized variant of the 'uniqInMaxPoetical' with usage of the several norms and all the information is printed on the same line. 
uniqInMaxPoeticalNLine :: Int -> V.Vector ([Int] -> Int) -> V.Vector Uniqueness -> IO (V.Vector Uniqueness)
uniqInMaxPoeticalNLine k vN v = do
  let !uniq = uniqMaxPoeticalGNV k vN v
  putStr (filter (not . isPunctuation) . lastFrom3 $ uniq) >> putStr " "
  return . V.filter (/= uniq) $ v

-- | A variant of the 'uniqNPoeticalG' function with the @n@ equal to 10.
uniq10PoeticalG :: ([Int] -> Int) -> String -> IO ()
uniq10PoeticalG = uniqNPoeticalG 10

-- | A variant of 'uniq10PoeticalG' with the 'norm4' applied. The list is (according to some model, not universal, but a reasonable one in the most cases) the 
-- most suitable for intonation changing and, therefore, for the accompaniment of the highly changable or variative melody.
uniq10Poetical4 :: String -> IO ()
uniq10Poetical4 = uniq10PoeticalG norm4

-- | A variant of 'uniq10PoeticalG' with the 'norm5' applied. The list is (according to some model, not universal, but a reasonable one in the most cases) the 
-- most suitable for rhythmic speech and two-syllabilistic-based poetry. Therefore, it can be used to create a poetic composition or to emphasize some 
-- thoughts.
uniq10Poetical5 :: String -> IO ()
uniq10Poetical5 = uniq10PoeticalG norm5

-- | Recursive @n :: Int@ times application of the 'uniqInMaxPoetical' function. Prints @n@ (or less if there are less of them) maximum elements starting from 
-- the first and further to the rest. The norm given defines the way, in which the elements are considered the \"maximum\" ones.
uniqNPoetical :: Int -> V.Vector ([Int],Int,Int,Int,String) -> IO ()
uniqNPoetical n v
 | n == 0 = return ()
 | compare (V.length v) n == LT = V.mapM_ (\x -> putStrLn (filter (not . isPunctuation) . lastFrom5 $ x) >> print (fourFrom5 x) >> putStrLn "" ) v
 | otherwise = (uniqInMaxPoetical v >>= uniqNPoetical (n - 1))

-- | Generalized variant of the 'uniqNPoetical' with usage of several norms. 
uniqNPoeticalN :: Int -> Int -> V.Vector ([Int] -> Int) -> V.Vector Uniqueness -> IO ()
uniqNPoeticalN n k vN v
 | n == 0 = return ()
 | compare (V.length v) n == LT = V.mapM_ (\x -> putStrLn (filter (not . isPunctuation) . lastFrom3 $ x) >> print (twoFrom3 x) >> putStrLn "" ) v
 | otherwise = (uniqInMaxPoeticalN k vN v >>= uniqNPoeticalN (n - 1) k vN)

-- | Generalized variant of the 'uniqNPoetical' with usage of several norms but prints it output on the one line. 
uniqNPoeticalNLine :: Int -> Int -> V.Vector ([Int] -> Int) -> V.Vector Uniqueness -> IO ()
uniqNPoeticalNLine n k vN v
 | n == 0 = putStrLn ""
 | compare (V.length v) n == LT = V.mapM_ (\x -> putStr (filter (not . isPunctuation) . lastFrom3 $ x) >> putStr " " ) v  >> putStrLn ""
 | otherwise = (uniqInMaxPoeticalNLine k vN v >>= uniqNPoeticalNLine (n - 1) k vN)

-- | The result of the recursive @n :: Int@ times application of the 'uniqInMaxPoetical' function. The norm given defines the way, in which the elements 
-- are considered the \"maximum\" ones.
uniqNPoeticalV :: Int -> V.Vector ([Int],Int,Int,Int,String) -> IO (V.Vector ([Int],Int,Int,Int,String))
uniqNPoeticalV n v
 | n == 0 || compare (V.length v) n == LT = return v
 | otherwise = (uniqInMaxPoetical v >>= uniqNPoeticalV (n - 1))

-- | Generalized variant of the 'uniqNPoeticalV' with usage of several norms. 
uniqNPoeticalVN :: Int -> Int -> V.Vector ([Int] -> Int) -> V.Vector Uniqueness -> IO (V.Vector Uniqueness)
uniqNPoeticalVN n k vN v
 | n == 0 || compare (V.length v) n == LT = return v
 | otherwise = (uniqInMaxPoeticalN k vN v >>= uniqNPoeticalVN (n - 1) k vN)

-- | Recursive @n :: Int@ times application of the 'uniqInMaxPoetical' function after the 'uniquenessVariantsG' application to the 'String'. 
-- Prints @n@ (or less if there are less of them) maximum elements starting from the first and further to the rest. The norm given defines the way, 
-- in which the elements are considered the \"maximum\" ones.
uniqNPoeticalG :: Int -> ([Int] -> Int) -> String -> IO ()
uniqNPoeticalG n g xs
 | n == 0 = return ()
 | otherwise = do
   let v = uniquenessVariantsG g xs
   if compare (V.length v) n == LT
     then V.mapM_ (\x -> putStrLn (filter (not . isPunctuation) . lastFrom5 $ x) >> print (fourFrom5 x) >> putStrLn "" ) v
     else (uniqInMaxPoetical v >>= uniqNPoetical (n - 1))

-- | Generalized variant of the 'uniqNPoeticalG' with usage of several norms. 
uniqNPoeticalGN :: Int -> Int -> V.Vector ([Int] -> Int) -> String -> IO ()
uniqNPoeticalGN n k vN = uniqNPoetical2GN n k vN (uniquenessPeriods)

-- | The result of the recursive @n :: Int@ times application of the 'uniqInMaxPoetical' function after the 'uniquenessVariantsG' application to the 'String'. 
-- The norm given defines the way, in which the elements are considered the \"maximum\" ones.
uniqNPoeticalVG :: Int -> ([Int] -> Int) -> String -> IO (V.Vector ([Int],Int,Int,Int,String))
uniqNPoeticalVG n g xs
 | n == 0 = return V.empty
 | otherwise = do
   let v = uniquenessVariantsG g xs
   if compare (V.length v) n == LT then return v else uniqNPoeticalV n v

-- | Generalized variant of the 'uniqNPoeticalVG' with usage of several norms. 
uniqNPoeticalVGN :: Int -> Int -> V.Vector ([Int] -> Int) -> String -> IO (V.Vector Uniqueness)
uniqNPoeticalVGN n k vN = uniqNPoetical2VGN n k vN (uniquenessPeriods)

-- | Generalization of the 'uniquenessVariantsG' with usage of several norms (instead of one). They constitute a 'V.Vector' of functions 
-- @norm :: [Int] -> Int@. So the inner vector in the each resulting 'Uniqueness' has the same length as the vector of norms.
uniquenessVariants2GN :: V.Vector ([Int] -> Int) -> (String -> [Int]) -> String -> V.Vector Uniqueness
uniquenessVariants2GN vN g xs
  | null xs = V.empty
  | otherwise =
     case V.length . V.fromList . take 7 . words $ xs of
      7 ->
       V.fromList . map ((\vs -> let !rs = g vs in (rs, V.map (\f -> f rs) vN, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $
         ([V.fromList [x1,x2,x3,x4,x5,x6,x7] | !x1 <- [0..6], !x2 <- [0..6] \\ [x1], !x3 <- [0..6] \\ [x1,x2], !x4 <- [0..6] \\ [x1,x2,x3],
           !x5 <- [0..6] \\ [x1,x2,x3,x4], !x6 <- [0..6] \\ [x1,x2,x3,x4,x5], !x7 <- [0..6] \\ [x1,x2,x3,x4,x5,x6]]::[V.Vector Int])
      6 ->
       V.fromList . map ((\vs -> let rs = g vs in (rs, V.map (\f -> f rs) vN, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $
         ([V.fromList [x1,x2,x3,x4,x5,x6] | !x1 <- [0..5], !x2 <- [0..5] \\ [x1], !x3 <- [0..5] \\ [x1,x2], !x4 <- [0..5] \\ [x1,x2,x3],
           !x5 <- [0..5] \\ [x1,x2,x3,x4], !x6 <- [0..5] \\ [x1,x2,x3,x4,x5]]::[V.Vector Int])
      5 ->
       V.fromList . map ((\vs -> let rs = g vs in (rs, V.map (\f -> f rs) vN, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $
         ([V.fromList [x1,x2,x3,x4,x5] | !x1 <- [0..4], !x2 <- [0..4] \\ [x1], !x3 <- [0..4] \\ [x1,x2], !x4 <- [0..4] \\ [x1,x2,x3],
            !x5 <- [0..4] \\ [x1,x2,x3,x4]]::[V.Vector Int])
      4 ->
       V.fromList . map ((\vs -> let rs = g vs in (rs, V.map (\f -> f rs) vN, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $
         ([V.fromList [x1,x2,x3,x4] | !x1 <- [0..3], !x2 <- [0..3] \\ [x1], !x3 <- [0..3] \\ [x1,x2], !x4 <- [0..3] \\ [x1,x2,x3]]::[V.Vector Int])
      3 ->
       V.fromList . map ((\vs -> let rs = g vs in (rs, V.map (\f -> f rs) vN, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $ ([V.fromList [x1,x2,x3] | !x1 <- [0..2], !x2 <- [0..2] \\ [x1],
          !x3 <- [0..2] \\ [x1,x2]]::[V.Vector Int])
      2 ->
       V.fromList . map ((\vs -> let rs = g vs in (rs, V.map (\f -> f rs) vN, vs)) . unwords . V.toList .
        V.backpermute (V.fromList . take 7 . words $ xs)) $ ([V.fromList [x1,x2] | !x1 <- [0,1], !x2 <- [0,1] \\ [x1]]::[V.Vector Int])
      _ -> V.empty

-- | Generalized variant of the 'uniqMaxPoeticalG' with the several norms given as a 'V.Vector' of functions and an 'Int' parameter. The function evaluates 
-- the generated 'V.Vector' of 'Uniqueness' elements to retrieve the possibly maximum element in it with respect to the order and significance (principality) 
-- of the norms being evaluated. The most significant and principal is the norm, which index in the 'V.Vector' of them is the 'Int' argument of the function 
-- minus 1, then less significant is the next to the left norm and so on.
uniqMaxPoetical2GN :: Int -> V.Vector ([Int] -> Int) ->  (String -> [Int]) -> String -> Uniqueness
uniqMaxPoetical2GN k vN g xs
 | compare k (V.length vN) == GT = error "DobutokO.Poetry.uniqMaxPoetical2GN: undefined for that amount of norms. "
 | compare k 0 == GT =
   let vM = uniquenessVariants2GN vN g xs
       maxK = V.maximumBy (\(_,vN0,_) (_,vN1,_) -> compare (V.unsafeIndex vN0 (k - 1)) (V.unsafeIndex vN1 (k - 1))) vM
       vK = V.filter (\(_,vN2,_) -> V.unsafeIndex vN2 (k - 1) == ((\(_,vNk,_) -> V.unsafeIndex vNk (k - 1)) maxK)) vM in
         uniqMaxPoeticalGNV (k - 1) (V.unsafeSlice 0 (V.length vN - 1) vN) vK
 | otherwise = V.maximumBy (\(_,vN0,_) (_,vN1,_) -> compare (V.unsafeIndex vN0 0) (V.unsafeIndex vN1 0)) . uniquenessVariantsGN vN $ xs

-- | The same as 'uniqMaxPoetical2GN' but applied to the other last argument. Is used inside the former one.
uniqMaxPoeticalGNV :: Int -> V.Vector ([Int] -> Int) ->  V.Vector Uniqueness -> Uniqueness
uniqMaxPoeticalGNV k vN vM
 | compare k (V.length vN) == GT = error "DobutokO.Poetry.uniqMaxPoeticalGNV: undefined for that amount of norms. "
 | compare k 0 == GT =
   let maxK = V.maximumBy (\(_,vN0,_) (_,vN1,_) -> compare (V.unsafeIndex vN0 (k - 1)) (V.unsafeIndex vN1 (k - 1))) vM
       vK = V.filter (\(_,vN2,_) -> V.unsafeIndex vN2 (k - 1) == ((\(_,vNk,_) -> V.unsafeIndex vNk (k - 1)) maxK)) vM in
         uniqMaxPoeticalGNV (k - 1) (V.unsafeSlice 0 (V.length vN - 1) vN) vK
 | otherwise = V.maximumBy (\(_,vN0,_) (_,vN1,_) -> compare (V.unsafeIndex vN0 0) (V.unsafeIndex vN1 0)) vM

-- | Generalized variant of the 'uniqNPoeticalG' with usage of the several norms. 
uniqNPoetical2GN :: Int -> Int -> V.Vector ([Int] -> Int) -> (String -> [Int]) -> String -> IO ()
uniqNPoetical2GN n k vN g xs
 | n == 0 = return ()
 | otherwise = do
   let v = uniquenessVariants2GN vN g xs
   if compare (V.length v) n == LT
     then V.mapM_ (\x -> putStrLn ((filter (not . isPunctuation) . lastFrom3 $ x)) >> print (twoFrom3 x) >> putStrLn "" ) v
     else (uniqInMaxPoeticalN k vN v >>= uniqNPoeticalN (n - 1) k vN)

-- | Generalized variant of the 'uniqNPoeticalG' with usage of the several norms, but prints its output on the same line. 
uniqNPoetical2GNLine :: Int -> Int -> V.Vector ([Int] -> Int) -> (String -> [Int]) -> String -> IO ()
uniqNPoetical2GNLine n k vN g xs
 | n == 0 = putStrLn ""
 | otherwise = do
   let v = uniquenessVariants2GN vN g xs
   if compare (V.length v) n == LT
     then V.mapM_ (\x -> putStr ((filter (not . isPunctuation) . lastFrom3 $ x)) >> putStr " " ) v >> putStrLn ""
     else (uniqInMaxPoeticalNLine k vN v >>= uniqNPoeticalNLine (n - 1) k vN)

-- | Generalized variant of the 'uniqNPoeticalVG' with usage of the several norms. 
uniqNPoetical2VGN :: Int -> Int -> V.Vector ([Int] -> Int) -> (String -> [Int]) -> String -> IO (V.Vector Uniqueness)
uniqNPoetical2VGN n k vN g xs
 | n == 0 = return V.empty
 | otherwise = do
   let v = uniquenessVariants2GN vN g xs
   if compare (V.length v) n == LT then return v else uniqNPoeticalVN n k vN v

-- | Variant of the 'uniqNPoetical2GN', which uses as a function 'uniquenessPeriods2' with the first argument equal to the first 'Int' argument.
uniqNPoeticalUGN_ :: Int -> Int -> Int -> V.Vector ([Int] -> Int) -> String -> IO ()
uniqNPoeticalUGN_ x n k vN = uniqNPoetical2GN n k vN (uniquenessPeriods2 x)

-- | Variant of the 'uniqNPoetical2VGN', which uses as a function 'uniquenessPeriods2' with the first argument equal to the first 'Int' argument.
uniqNPoeticalUGN :: Int -> Int -> Int -> V.Vector ([Int] -> Int) -> String -> IO (V.Vector Uniqueness)
uniqNPoeticalUGN x n k vN = uniqNPoetical2VGN n k vN (uniquenessPeriods2 x)

-- | Variant of the 'uniqNPoeticalUGN_', which uses as a single norm 'norm51'.
uniqNPoeticalUGN51_ :: Int -> Int -> String -> IO ()
uniqNPoeticalUGN51_ x n = uniqNPoeticalUGN_ x n 1 (V.singleton norm51)

-- | Variant of the 'uniqNPoeticalUGN', which uses as a single norm 'norm51'.
uniqNPoeticalUGN51 :: Int -> Int -> String -> IO (V.Vector Uniqueness)
uniqNPoeticalUGN51 x n = uniqNPoeticalUGN x n 1 (V.singleton norm51)