---
# System prepended metadata

title: PFL_TP1_G05_09

---

# PFL_TP1_G05_09
Primeiro Projeto de Programação Funcional e Lógica (PFL) 


## Como correr o código

Tendo já instalada uma versão do interpretador de ghc, para correr o código e ter acesso a todas as suas funcionalidades, basta utilizar os seguintes comandos:

> ghci
> :l main.hs 
> main

Caso estes comandos não estejam a funcionar, será necessário correr o seguinte comando:

> :l main.hs polynomial.hs

Para correr os testes criados com recurso ao quickCheck:

Ubuntu:
> cabal update 
> cabal install quickcheck

Windows:
>cabal install --lib --package-env . QuickCheck


## Representação dos Polinomios

### Estrutura e justificação

Com o objetivo de escolher uma representação adequada para um polinómio, pensamos em duas alternativas diferentes: criar um data type específico ou utilizar apenas types já existentes. De modo a simplificar a solução ao problema proposto, foi escolhida a segunda opção.

Assim sendo, foram feitas as seguintes definições:
type Polynomial = [Monomial]
type Monomial = (Int, [Literal])
type Literal = (Char, Int)


O polinómio é representado por uma lista de monómios e um monómio é por sua vez um tuplo constituído por um Int, o coeficiente e uma lista de elementos do type Literal que corresponde à parte literal do monómio. O type Literal é definido por um tuplo (Char, Int) onde o caracter simboliza a variável e o int o seu expoente.


## Funcionalidades

### Parse de um polinómio

Para possibiltar o input como uma string, foi desenvolvida a função parsePolynomial. Esta recebe como parametro uma String e retorna um elemento do type Polynomial. Recorrendo à recursão, foi criada a função auxiliar parsePolynomialAux, que por sua vez chama parseMonomial onde irá ser criado cada monómio com as diferentes partes da String inicial. 


### Normalizar polinómios

Para normalizar um polinómio foi desenvolvida a função normalizePolynomial. Esta recebe e retorna um parâmetro do type Polynomial. 
No âmbito de dividir os processos, foi feita a composição de três funções diferentes:
reducePolynomial- soma monómios do polinómio com a mesma parte literal e remove os monómios com coeficiente igual a zero. 
reduceLiteralsPolynomial - remove do polinómio monómios com coeficientes igual a zero,
remove da parte literal de cada monómio do polinómio variáveis elevadas a zero e junta literais do mesmo monómio com a mesma variável.
sortPolynomial - ordena os monómios do polinómio por ordem crescente consoante o grau e coeficiente.

### Adicionar polinómios

Para somar dois polinómios foi implementada a função sum2Polynomials. Esta recebe dois parametros do type Polynomial e retorna apenas um. A função recorre à normalização da concatenação de duas listas que representam os polinómios.


### Multiplicar polinómios

Para multiplicar dois polinómios foi implementada a função prod2Polynomials. Esta recebe dois parametros do type Polynomial e retorna apenas um. A função recorre à normalização de uma lista, sendo esta formada pela multiplicação entre todos os elementos do primeiro polinómio e do segundo. Para a criação de cada monómio é chamada a função prod2Monomials.

### Derivada de um polinómio

Para derivar dois polinómios foi implementada a função derivPolynomial. Esta recebe como parametros um elemento do type Polynomial e um caracter e retorna um elemento do type Polynomial. A função recorre à normalização de uma lista, sendo esta formada pela derivação entre todos os elementos do polinómio em função do caracter. Para a criação de cada monómio é chamada a função derivMonomial.

### Output de um polinómio

Para dar output de um polinómio, foi desenvolvida a função outPolynomial.Esta recebe como parametro um elemento do type Polynomial e retorna uma String.
A função coloca em formato String todos os monómios do polinómio através de chamadas à função outMonomial e por fim, junta-os.

## Exemplos

Correndo os comandos : 

* **test1** : irá ser disponibilizado um exemplo de cada uma das funcionalidades (normalização, soma, multiplicação, derivação), onde é mostrado os diferentes operadores e o respetivo resultado com recurso às funções de parse e de outputting do programa;
* **test2** : irá ser disponibilizado um exemplo de cada uma das funcionalidades (normalização, soma, multiplicação, derivação), onde é  mostrado os diferentes operadores e o respetivo resultado com a representação interna do programa;


### **Parse**
>parsePolynomial "5000 + 100 + 2" 
>**Result :** [(5000,[]),(100,[]),(2,[])]

>parsePolynomial "x^5y + y^2 + 0x^6 + o^3"
>**Result :**  [(1,[('x',5),('y',1)]),(1,[('y',2)]),(0,[('x',6)]),(1,[('o',3)])]

>parsePolynomial "x^20z^30p^12" 
>**Result :** [(1,[('x',20),('z',30),('p',12)])]

### **Normalize**

> normalizePolynomial [(9,[('x',2), ('x',3)]),(2,[('x',1)]),(5,[('x',1)])] 
> **Result :** [(9,[('x',5)]),(7,[('x',1)])]

> normalizePolynomial [(0,[('x',2)]),(2,[('x',0)]),(8,[('u',1),('i',0)])] 
> **Result :** [(8,[('u',1)]),(2,[])]

> normalizePolynomial [(-2,[('x',2)]),(2,[('x',2)]),(8,[('u',1),('i',0)]),(8,[('u',1)]) ]
> **Result :** [(16, [('u',1)])]


### **Sum**
> sum2Polynomials [(-2,[('x',3),('x',1)])] [(2,[('x',2),('x',2)])]
>**Result :** []

> sum2Polynomials [(9,[('x',2)]),(2,[('x',1)]),(5,[('x',1)])] [(2,[('x',1),('p',1)])]
>**Result :**  [(2,[('p',1),('x',1)]),(9,[('x',2)]),(7,[('x',1)])]

> sum2Polynomials [(8,[]),(2,[('x',1),('e',0)]),(5,[('x',1),('r',0)])] [(2,[('x',1),('p',0)]),(-4,[])] 
> **Result :** [(9,[('x',1)]),(4,[])]


### **Multiplication**
> prod2Polynomials [(2,[('x',1),('p',0)]),(-4,[])] [(2,[]),(-4,[])] 
> **Result :** [(-4,[('x',1)]),(8,[])]

> prod2Polynomials [(5,[('t',1), ('p',9), ('t',1) ])] [(-1,[('f',0)])] 
>**Result :** [(-5,[('t',2),('p',9)])]

> prod2Polynomials [(2,[('x',1),('p',0),('k',6)]),(-4,[])] [(2,[('x',0),('l',2)])]
> **Result :**  [(4,[('k',6),('l',2),('x',1)]),(-8,[('l',2)])]

### **Derivation**
> derivPolynomial 'x' [(2,[('x',0),('p',1)]),(-4,[('x',0)]),(2,[]),(-4,[('i',19)])] 
>**Result :** []

> derivPolynomial 'o' [(1,[('o',0),('c',1)]),(-4,[('o',1)]),(2,[('o',3),('r',3)]),(-4,[('o',6)])] 
>**Result :** [(-24,[('o',5)]),(6,[('o',2),('r',3)]),(-4,[])]

> derivPolynomial 'y' [(2,[('y',3)]),(-4,[('y',3)]),(9,[('y',3)]),(7,[('y',3)])]
> **Result :** [(42,[('y',2)])]

### **Output**
>outPolynomial [(5000,[]),(100,[]),(2,[])] 
>**Result :** "5000 + 100 + 2"

>outPolynomial [(1,[('x',5),('y',1)]),(1,[('y',2)]),(0,[('x',6)]),(1,[('o',3)])] 
>**Result :** "x^5y + y^2 + 0x^6 + o^3"  

>outPolynomial [(1,[('x',20),('z',30),('p',12)])] 
>**Result :** "x^20 z^30 p^12" 

### **Tests**

De modo a a testar o programa, como foi sugestionado, utilizou-se a biblioteca quickCheck. Para as funcionalidades: normalização, soma, multiplicação e derivação foram desenvolvidas funções que permitiam garantir o bom funcionamento das mesmas. Estes testes foram colocados num ficheiro à parte chamado *test.hs*. É ainda de referir que para cada funcionalidade foram criados dois tipos de testes diferentes, testes de propriedades e testes unitários.







 
