<commit_before>--------------------------------------------------------------------------------
-- |
-- Module      : Projekt.Core.Polynomials
-- Note        : Allgemeine implementierung von Polynomen in einer Variablen
--
--
--
--------------------------------------------------------------------------------
module Projekt.Core.Polynomials
  ( Polynom (..)
  , fromMonomialsP
  -- getter
  , getDegrees, getLcP
  -- Operationen auf Polynomen
  , aggP, degP, uDegP, prodOfCoeffsP
  -- unär
  , moniP, reziprokP, deriveP
  -- binär
  , divP, (@/), modByP, ggTP, eekP
  -- weiteres
  , evalP
  , getAllP, getAllByDegP
  ) where
import Data.List
import qualified Control.Arrow as A
import Data.Maybe

import Projekt.Core.ShowTex

--import Debug.Trace

--------------------------------------------------------------------------------
--  Data Definition

-- |Polynome sind Listen von Monomen, welche durch Paare (Integer,a)
-- dargestellt werden. In der ersten Stelle steht der Grad, in der zweiten der
-- Koeffizient.
data Polynom a = P {unP :: [a]} deriving ()

instance (Eq a, Num a) => Eq (Polynom a) where
  {-f == g = unP (aggP f) == unP (aggP g)-}
  f == g = eqP f g

eqP (P ms) (P ns) = eqP' ms ns
  where eqP' [] ns = nullP' ns
        eqP' ms [] = nullP' ms
        eqP' (m:ms) (n:ns) = m==n && eqP' ms ns

nullP (P ms) = nullP' ms
nullP' []     = True
nullP' (m:ms) | m /= 0     = False
              | otherwise = nullP' ms


if' :: Bool -> a -> a -> a
if' True  x _ = x
if' False _ y = y

-- |Polonoe aus einer Liste von Monomen (dargestellt als Tuppel) erzeugen.
fromMonomialsP :: (Num a, Eq a) => [(Int,a)] -> Polynom a
fromMonomialsP []         = P[]
fromMonomialsP ((i,m):ms) = P ([0 | j <- [1..i]] ++ [m]) + fromMonomialsP ms

instance (Show a, Eq a, Num a) => Show (Polynom a) where
  show (P []) = "0"
  show (P ms) = intercalate "+" $
                (\ss -> [s | s <- reverse ss , s /= ""]) $
                zipWith (curry show') ms [0..]
    where show' :: (Show a, Eq a, Num a) => (a,Int) -> String
          show' (0,_) = ""
          show' (m,i) = show m ++ showExp i
          showExp :: Int -> String
          showExp 0 = ""
          showExp 1 = "·\x1B[04mX\x1B[24m"
          showExp i = "·\x1B[04mX" ++ showExp' (show i) ++ "\x1B[24m"
          showExp' :: String -> String
          showExp' ""     = []
          showExp' (c:cs) = newC : showExp' cs
            where newC | c == '0' = '⁰'
                       | c == '1' = '¹'
                       | c == '2' = '²'
                       | c == '3' = '³'
                       | c == '4' = '⁴'
                       | c == '5' = '⁵'
                       | c == '6' = '⁶'
                       | c == '7' = '⁷'
                       | c == '8' = '⁸'
                       | c == '9' = '⁹'

instance (ShowTex a, Num a, Eq a) => ShowTex (Polynom a) where
  showTex (P []) = "0"
  showTex (P ms) = intercalate "+" $
                   (\ss -> [s | s <- reverse ss , s /= ""]) $
                   zipWith (curry showTex') ms [0..]
    where showTex' :: (ShowTex a, Eq a, Num a) => (a,Int) -> String
          showTex' (0,_) = ""
          showTex' (m,i) = showTex m ++ showExp i
          showExp :: Int -> String
          showExp 0 = ""
          showExp 1 = "\\cdot{}X"
          showExp i = "\\cdot{}X^{" ++ show i ++ "}"

instance (Num a, Eq a) => Num (Polynom a) where
  (P ms) + (P ns) = P $ addP ms ns
  (P ms) * (P ns) = P $ multP' ms ns
  fromInteger i   = P [fromInteger i]
  abs _           = error "Prelude.Num.abs: inappropriate abstraction"
  signum (P ms)   = P $ map signum ms
  negate (P ms)   = P $ map negate ms

addP [] gs          = gs
addP fs []          = fs
addP (f:fs) (g:gs)  = f+g : addP fs gs

multP (f:fs) (g:gs) = f*g : addP (multP [f] gs) (multP fs(g:gs))
multP _ _           = []

multP' f []             = []
multP' [] f             = []
multP' f g  | n >= m    = foldl1' addP [ multMonom f i a | (i,a) <- gz]
            | otherwise = multP' g f
  where n  = length f
        m  = length g
        gz = zip [0..] g

-- |Multipliziert f mit a*x^i
multMonom :: Num a => [a] -> Int -> a -> [a]
multMonom f i a  = [0 | i <- [1..i]] ++ map (a*) f

multMonomP :: Num a => Polynom a -> Int -> a -> Polynom a
multMonomP (P f) i a  = P $ multMonom f i a

-- |Entfernt trailing zeros
aggP :: (Num a, Eq a) => Polynom a -> Polynom a
aggP (P ms) = P $ aggP' ms []
  where aggP' [] ns     = []
        aggP' (m:ms) ns | m /= 0     = ns ++ [m] ++ aggP' ms []
                        | otherwise = aggP' ms (ns ++ [m])
{-
 - Alt:
aggP :: (Num a, Eq a) => Polynom a -> Polynom a
aggP (P ms) = P $ take l ms
  where l = maximum $ 0:[i+1 | i <- [0..(length ms - 1)] , ms!!i /= 0]
 -}

getLcP :: (Num a, Eq a) => Polynom a -> a
getLcP (P[]) = 0
getLcP f     = (last . unP . aggP) f

-- |Nimmt ein Polynom und gibt eine liste der Gräder zurrück.
getDegrees :: (Num a, Eq a) => Polynom a -> [Int]
getDegrees (P ms) = [i | i <- [0..(length ms - 1)] , ms!!i /= 0]

-- |Gibt zu einem Polynom den Grad
degP :: (Num a, Eq a) => Polynom a -> Maybe Int
degP f | deg >= 0   = Just deg
       | otherwise = Nothing
  where deg = (length . unP . aggP) f - 1

uDegP :: (Num a, Eq a) => Polynom a -> Int
uDegP = fromJust . degP

-- |Gibt zu einem Polynom das Produkt der Koeffizient
prodOfCoeffsP :: Num a => Polynom a -> a
prodOfCoeffsP = product . unP<commit_msg>besseres gelDegreesP<commit_after>--------------------------------------------------------------------------------
-- |
-- Module      : Projekt.Core.Polynomials
-- Note        : Allgemeine implementierung von Polynomen in einer Variablen
--
--
--
--------------------------------------------------------------------------------
module Projekt.Core.Polynomials
  ( Polynom (..)
  , fromMonomialsP
  -- getter
  , getDegrees, getLcP
  -- Operationen auf Polynomen
  , aggP, degP, uDegP, prodOfCoeffsP
  -- unär
  , moniP, reziprokP, deriveP
  -- binär
  , divP, (@/), modByP, ggTP, eekP
  -- weiteres
  , evalP
  , getAllP, getAllByDegP
  ) where
import Data.List
import qualified Control.Arrow as A
import Data.Maybe

import Projekt.Core.ShowTex

--import Debug.Trace

--------------------------------------------------------------------------------
--  Data Definition

-- |Polynome sind Listen von Monomen, welche durch Paare (Integer,a)
-- dargestellt werden. In der ersten Stelle steht der Grad, in der zweiten der
-- Koeffizient.
data Polynom a = P {unP :: [a]} deriving ()

instance (Eq a, Num a) => Eq (Polynom a) where
  {-f == g = unP (aggP f) == unP (aggP g)-}
  f == g = eqP f g

eqP (P ms) (P ns) = eqP' ms ns
  where eqP' [] ns = nullP' ns
        eqP' ms [] = nullP' ms
        eqP' (m:ms) (n:ns) = m==n && eqP' ms ns

nullP (P ms) = nullP' ms
nullP' []     = True
nullP' (m:ms) | m /= 0     = False
              | otherwise = nullP' ms


if' :: Bool -> a -> a -> a
if' True  x _ = x
if' False _ y = y

-- |Polonoe aus einer Liste von Monomen (dargestellt als Tuppel) erzeugen.
fromMonomialsP :: (Num a, Eq a) => [(Int,a)] -> Polynom a
fromMonomialsP []         = P[]
fromMonomialsP ((i,m):ms) = P ([0 | j <- [1..i]] ++ [m]) + fromMonomialsP ms

instance (Show a, Eq a, Num a) => Show (Polynom a) where
  show (P []) = "0"
  show (P ms) = intercalate "+" $
                (\ss -> [s | s <- reverse ss , s /= ""]) $
                zipWith (curry show') ms [0..]
    where show' :: (Show a, Eq a, Num a) => (a,Int) -> String
          show' (0,_) = ""
          show' (m,i) = show m ++ showExp i
          showExp :: Int -> String
          showExp 0 = ""
          showExp 1 = "·\x1B[04mX\x1B[24m"
          showExp i = "·\x1B[04mX" ++ showExp' (show i) ++ "\x1B[24m"
          showExp' :: String -> String
          showExp' ""     = []
          showExp' (c:cs) = newC : showExp' cs
            where newC | c == '0' = '⁰'
                       | c == '1' = '¹'
                       | c == '2' = '²'
                       | c == '3' = '³'
                       | c == '4' = '⁴'
                       | c == '5' = '⁵'
                       | c == '6' = '⁶'
                       | c == '7' = '⁷'
                       | c == '8' = '⁸'
                       | c == '9' = '⁹'

instance (ShowTex a, Num a, Eq a) => ShowTex (Polynom a) where
  showTex (P []) = "0"
  showTex (P ms) = intercalate "+" $
                   (\ss -> [s | s <- reverse ss , s /= ""]) $
                   zipWith (curry showTex') ms [0..]
    where showTex' :: (ShowTex a, Eq a, Num a) => (a,Int) -> String
          showTex' (0,_) = ""
          showTex' (m,i) = showTex m ++ showExp i
          showExp :: Int -> String
          showExp 0 = ""
          showExp 1 = "\\cdot{}X"
          showExp i = "\\cdot{}X^{" ++ show i ++ "}"

instance (Num a, Eq a) => Num (Polynom a) where
  (P ms) + (P ns) = P $ addP ms ns
  (P ms) * (P ns) = P $ multP' ms ns
  fromInteger i   = P [fromInteger i]
  abs _           = error "Prelude.Num.abs: inappropriate abstraction"
  signum (P ms)   = P $ map signum ms
  negate (P ms)   = P $ map negate ms

addP [] gs          = gs
addP fs []          = fs
addP (f:fs) (g:gs)  = f+g : addP fs gs

multP (f:fs) (g:gs) = f*g : addP (multP [f] gs) (multP fs(g:gs))
multP _ _           = []

multP' f []             = []
multP' [] f             = []
multP' f g  | n >= m    = foldl1' addP [ multMonom f i a | (i,a) <- gz]
            | otherwise = multP' g f
  where n  = length f
        m  = length g
        gz = zip [0..] g

-- |Multipliziert f mit a*x^i
multMonom :: Num a => [a] -> Int -> a -> [a]
multMonom f i a  = [0 | i <- [1..i]] ++ map (a*) f

multMonomP :: Num a => Polynom a -> Int -> a -> Polynom a
multMonomP (P f) i a  = P $ multMonom f i a

-- |Entfernt trailing zeros
aggP :: (Num a, Eq a) => Polynom a -> Polynom a
aggP (P ms) = P $ aggP' ms []
  where aggP' [] ns     = []
        aggP' (m:ms) ns | m /= 0     = ns ++ [m] ++ aggP' ms []
                        | otherwise = aggP' ms (ns ++ [m])
{-
 - Alt:
aggP :: (Num a, Eq a) => Polynom a -> Polynom a
aggP (P ms) = P $ take l ms
  where l = maximum $ 0:[i+1 | i <- [0..(length ms - 1)] , ms!!i /= 0]
 -}

getLcP :: (Num a, Eq a) => Polynom a -> a
getLcP (P[]) = 0
getLcP f     = (last . unP . aggP) f

-- |Nimmt ein Polynom und gibt eine liste der Gräder zurrück.
getDegrees :: (Num a, Eq a) => Polynom a -> [Int]
getDegrees (P ms) = [snd m | m <- (zip ms [0..]), fst m /= 0]
{-getDegrees (P ms) = [i | i <- [0..(length ms - 1)] , ms!!i /= 0]-}

-- |Gibt zu einem Polynom den Grad
degP :: (Num a, Eq a) => Polynom a -> Maybe Int
degP f | deg >= 0   = Just deg
       | otherwise = Nothing
  where deg = (length . unP . aggP) f - 1

uDegP :: (Num a, Eq a) => Polynom a -> Int
uDegP = fromJust . degP

-- |Gibt zu einem Polynom das Produkt der Koeffizient
prodOfCoeffsP :: Num a => Polynom a -> a
prodOfCoeffsP = product . unP
{'fraction_non_alphanumeric': 0.20978956150922407, 'fraction_numerical': 0.009641234819690368, 'mean_word_length': 1.5576102418207682, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '645153', 'n_tokens_mistral': 4165, 'n_tokens_neox': 4027, 'n_words': 1332}