{- Problema urmărește analiza numerelor naturale din punct de vedere al factorilor lor primi. Factorii primi ai unui număr sunt numere care prin înmulțirea lor produc numărul. Unii factori pot apărea în înmulțire de mai multe ori. De exemplu, numărul 15 este factorizat ca 3*5; numărul 144 este factorizat ca 2*2*2*2*3*3 = 2^4 * 3^2; numărul 150 este factorizat ca 2 * 3 * 5^2. -} {- 1. (4p) Definiți tipul de date factoring care descrie un număr împreună cu factorii săi. Deosebim între trei tipuri de numere: numărul 1, numerele prime (nu au factori) și numerele ne-prime, care au factori, fiecare factor având o putere la care trebuie ridicat. O valoare de tip Factoring trebuie să înglobeze informații despre: - numărul factorizat - tipul numărului (unu, prim, neprim) - factorii numărului și puterile la care trebuie ridicați, pentru numerele neprime. Faceți ca Factoring să derive clasa Show. Vom considera că toate numerele cu care lucrăm sunt de tipul Integer. -} --data Factoring = Undefined data Factoring = One | Prime Integer | Factoring Integer [(Integer, Integer)] deriving Show {- 2. (1p) Implementați funcția divisors, care dă lista de divizori (proprii, fără 1 și fără n) a unui număr n. Exemplu: divisors 144 = [2,3,4,6,8,9,12,16,18,24,36,48,72] -} divisors :: Integer -> [Integer] --divisors = undefined divisors n = [x | x <- [2..n-1], mod n x == 0] {- 3. (10p) Implementați funcția primeFactors, care întoarce lista de factori ai unui număr care sunt numere prime. Exemplu: primeFactors 150 = [2,3,5] -} primeFactors :: Integer -> [Integer] --primeFactors = undefined primeFactors n = [p | p <- divisors n, divisors p == []] {- sau primeFactors = filter (null . divisors) . divisors -- sau primeFactors n = fact $ divisors n where fact [] = [] fact (n:rest) = n : fact [d | d <- rest, mod d n /= 0] -} {- 4. (10p) Implementați funcția factoring, care întoarce valoarea de tip Factoring caracteristică unui număr natural. -} factoring :: Integer -> Factoring --factoring = undefined factoring n | n == 1 = One | primeFactors n == [] = Prime n | otherwise = Factoring n [(fact, pp n fact) | fact <- primeFactors n] where pp n f | mod n f == 0 = 1 + pp (div n f) f | otherwise = 0 {- 1b. (5p) Definiți fluxul de valori de tip Factoring corespunzătoare numerelor cu cel puțin 3 factori diferiți (primele sunt 30=2*3*5, 42=2*3*7, 60=2^2*3*5). -} complexFactors :: [Factoring] --complexFactors = undefined complexFactors = [f | f <- map factoring [1..], check f] where check f = case f of One -> False Prime _ -> False Factoring _ l -> length l > 2 {- sau complexFactors = [factoring x | x <- [2, 3..], length (primeFactors x) >= 3] -} {- Barem 1. 1p: Folosirea corectă a lui data 1p: diferențiere corectă a celor 3 tipuri 1p: integrare coerentă a informațiilor despre număr și despre factori 1p: deriving Show 2. 1p. implementare corectă a divizorilor. 3. 5p. Identificare numere prime 5p. Filtrarea numerelor prime dintre lista de divizori 4. 3p. Identificare corectă a tipurilor de numere 5p. Calcul corect al puterii unui factor; 2p pentru terminare; 3p pentru ciclu 2p. Coerență per total 5. 3p. Factorizare a tuturor numerelor 2p. Identificare corectă a numerelor cu mai mult de 2 factori -}