• Nenhum resultado encontrado

Resolução Algorítmica de Problemas Exercício 1.

3. Lógica de Predicados

4.2. Resolução Algorítmica de Problemas Exercício 1.

A avaliação da expressão 3 + 4 == 4 + 3 resulta em: ( ) 7 ( ) 1 ( ) 0 ( x ) True ( ) False

Exercício 4.2.2.

Seja a seguinte definição de função: f :: Integer −> Integer −> Integer f x y = if x < y then x else y Desta forma, f a (f b c) vale ( ) a. ( ) b. ( ) c. ( ) maior entre a, b e c. ( x ) menor entre a, b e c.

Exercício 4.2.3.

A avaliação da expressão 3 + 4 /= 4 + 3 resulta em: ( ) 7 ( ) 1 ( ) 0 ( ) True ( x ) False

Exercício 4.2.4.

Se f é uma função tal que f 0 é igual a 10 e g é outra tal que g 0 é igual a 10, conclui-se que f (g 10) ( ) vale 0.

( ) vale 10. ( ) vale -10. ( ) vale 100.

Exercício 4.2.5.

Seja a seguinte definição de função: f :: Integer −> Integer f x = if x < 3 then x else f (x – 1) A avaliação de f 2 resulta em ( ) 0 ( ) 1 ( x ) 2 ( ) 3 ( ) 4

Exercício 4.2.6.

Quanto vale f (f 10) para f definida por f x = x ? ( ) 0 ( x ) 10 ( ) 12 ( ) 20 ( ) 22

Exercício 4.2.7.

Se o tipo de f é String −> String, qual o tipo de [ f x | x <− xs ] ? ( ) String −> String ( ) String ( x ) [ String ] ( ) Char ( ) [ Char ]

Exercício 4.2.8.

Seja g x = [x] : g (tail x). Pode-se afirmar que ( x ) g não pode ser definida pois há erro de tipo. ( ) g só funciona para argumentos que sejam listas.

( ) g tem tipo [a] −> [a], sendo a um dos tios válidos de Haskell.

( ) g só funciona para argumentos que sejam listas com pelo menos 1 elemento. ( ) nenhuma das opções acima está correta.

Exercício 4.2.9.

Sendo a um dos tipos válidos em Haskell, qual das funções abaixo possui o tipo [ a ] −> b −> a ? ( x ) f x y = head x

( ) f x y = y ( ) f x y = head y : x ( ) f x y = tail y

( ) Nenhuma das opções acima.

Exercício 4.2.10.

A expressão takeWhile even [ 10 , 8 .. 1 ] resulta em ( ) [ ] ( ) [ 10 ] ( ) [ 10 , 9 ] ( ) [ 9 , 7 , 5 , 3 , 1 ] ( x ) [ 10 , 8 , 6 , 4 , 2 ]

Exercício 4.2.11.

Considere a seguinte função g :: Integer −> Integer −> Integer

g n m = if n == m then n – m else g (n – 1) m

e admita, também, que ela seja chamada sempre com valores n maiores do que m. Marque a resposta mais precisa.

( ) A função sempre produz n-m como resultado. ( ) A função pode entrar em um loop infinito. ( ) A função sempre produz n-1 como resultado. ( x ) A função sempre produz 0 como resultado. ( ) Nenhuma das opções acima.

Exercício 4.2.12.

Marque V caso a sentença seja verdadeira e F caso seja falsa. ( F ) A expressão 3+4 < div 9 3 é inválida em Haskell.

( V ) Em Haskell sempre que utilizamos um condicional, há a necessidade de associar um else ao then. ( F ) [ [ ] ] é uma lista vazia.

( F ) Se f n = f (n + 1), sendo n :: Integer, então f 10 = 11.

( V ) Se f é uma função de inteiros para inteiros, então (f a) – (f a), sendo a um inteiro, sempre produzirá 0 como resultado.

( V ) É possível que, dependendo de uma função f que mapeia inteiros em inteiros, f 9 produza 3 como resultado.

( F ) Não importa qual seja a função f mapeando inteiros em inteiros que sempre teremos f 0 retornando 0 como resultado.

( F ) Se f e g são funções de inteiros para inteiros e a é inteira, então f (g a) é igual a g (f a).

( V ) Se x é um inteiro de dois dígitos, então (mod x 10) * 10 + div x 10 fornece um número que tem os dois dígitos de x na ordem inversa.

( V ) A expressão a + 1 = 2, sendo a :: Integer, contém um erro. ( F ) Um tipo é um conjunto de valores inteiros.

( V ) Quaisquer que sejam as funções de inteiros para inteiros f e g, sempre teremos f 10 + g 3 sendo igual a g 3 + f 10, pois a adição é comutativa em Haskell.

( F ) f :: (Integer, Integer) −> Integer é a assinatura de uma função que possui dois argumentos inteiros de entrada.

( F ) Se td é uma função que determina quantos dígitos tem um número inteiro, então div n (td n) fornece o dígito mais significativo de n, ou seja, aquele que ocorre mais à esquerda em n.

( F ) As listas em Haskell são bastante flexíveis com relação a como os seus elementos são calculados, desde que nenhum deles seja obtido a partir de uma expressão condicional pois, neste caso, um erro de tipo é imediatamente enviado.

Exercício 4.2.13.

Seja a seguinte definição de função: f :: Integer −> Integer f x = if x < 3 then x else f (x – 1) A avaliação de f 30 resulta em ( ) 0 ( ) 1 ( x ) 2 ( ) 3 ( ) 30

Exercício 4.2.14.

Dentre os seguintes identificadores, quantos podem ser nomes de variáveis ou funções: soma_2, 2soma, Soma, soma? ( ) um ( x ) dois ( ) três ( ) quatro

Exercício 4.2.15.

Sendo a um dos tipos válidos de Haskell, a −> a −> (a,a) é o tipo de funções que ( ) geram listas com dois elementos.

( ) têm dois argumentos repetidos e geram um par contendo a repetição destes valores. ( x ) têm argumentos de mesmo tipo e geram pares com componentes deste mesmo tipo. ( ) geram uma função cujos argumentos possuem o mesmo tipo do argumento de entrada.

Exercício 4.2.16.

Qual das funções abaixo não está em loop infinito? ( ) f x = f x + 1 ( ) f x = x + f 1 ( ) f x = f (x + 1) ( x ) f x = x + 1 ( ) f x = x : f x

Exercício 4.2.17.

Seja a seguinte definição de função: f :: Integer −> Integer

f [ ] = 1 f (x : xs) = x - f xs Então pode-se afirmar que:

( ) f determina o total de elementos da lista de entrada ( ) f determina a soma dos elementos da lista de entrada ( ) f retorna 0 qualquer que seja a lista de inteiros de entrada ( ) f possui um erro de tipo

( x ) Nenhuma das respostas acima

Exercício 4.2.18.

Crie uma função que imprima os termos de uma PG, sendo fornecidos: o primeiro termo, ( a1 ), a razão ( q ) e

o número de termos ( n ). Solução:

Sendo o termo geral da PG igual a: : an = a0. q( n – 1 )., podemos construir a função:

pg :: Integer −−−>−>>> Integer −−−−>>>> Integer −−−−>>>> [ Integer ]

pg a0 q n = [a0 * q ^ ( i – 1 ) | i <<<<−−−− [ 1 .. n ] ]

Exercício 4.2.19.

Escreva uma função que retorne a multiplicação de todos os dígitos de um número inteiro de entrada.

Solução:

Dado um determinado número, digamos, 123, a função deve retornar 6, resultante de: 1 x 2 x 3. Devemos multiplicar o dígito menos significativo com uma chamada recursiva à função, passando o restante dos dígitos, até que o argumento seja nulo, quando então a função deve retornar 1 (elemento nulo da multiplicação):

f :: Integer −−−>−>>> Integer

f 0 = 1

f num = num `mod` 10 * f (num `div` 10)

Observe que a chamada à função com argumento nulo vem antes da chamada à função com argumento não nulo! Isto é necessário, pois do contrário a função continuria indefinidamente sua chamada, num loop infinito.

Exercício 4.2.20.

O que produz a função f, definida como f [ ] = [ ]

f (x:xs) = if x == [ ] then f [ ] else f ( [ x ] : xs )

Solução:

Suponha que haja uma chamada á função passando-se a lista [1,2,3] como argumento. Então, f (x:xs) é o mesmo f (1:[2,3]), x é 1 e xs é [2,3], donde:

f (1:[2,3]) => x == [ ] é falso => chamada à f ( [ 1 ] : xs )

Porém, f ( [ 1 ] : xs ) é um erro de tipo, pois para [ 1 ] : xs ser sintaticamente correta, xs deveria ser uma lista de lista, o que não é verdade, pois no início passamos a lista [1,2,3] e não a lista [ [ 1 ] , [ 2 ] , [ 3 ] ].

Ou seja, ocorre um erro de tipo.

Exercício 4.2.21.

Escreva uma função para determinar se a soma do dígito mais significativo de um número com o seu dígito menos significativo é um número ímpar.

Solução:

Este problema será divido em sub-problemas:

1°- Determinação do dígito mais significativo de um número (digMais) 2°- Determinação do dígito menos significativo de um número (digMenos) 3°- Soma de dois números (soma)

Implementando as funções:

1°- Função para determinar o dígito mais significativo de um número

Aqui, devemos ir dividindo o número enquanto esta divisão (inteira) não resultar nula, quando então o dígito mais significativo do número foi encontrado:

digMais :: Integer −−−−>>>> Integer

digMais num = if num `div` 10 == 0 then num else digMais (num `div` 10)

2°- Função para determinar o dígito menos significativo de um número Aqui devemos simplesmente obter o resto da divisão do número por 10:

digMenos :: Integer −−−>−>>> Integer

digMenos num = num `mod` 10

3°- Soma de dois números

soma :: Integer −−−−>>>> Integer −−−−>>>> Integer

soma a b = a + b

4°- Verificar se um número é ímpar

Podemos utilizar a função Haskell odd (por exemplo, odd 13 retorna True) ou podemos impar criar nossa própria função, sabendo-se que o resto da divisão (inteira) de um número ímpar por 2 é sempre 1:

impar :: Integer −−−−>>>> Bool

impar num = num `mod` 2 == 1

Juntando tudo, temos que: se impar ( soma (digMais num) (digMenos num) ) é verdade então a soma do dígito mais significativo de um número com o seu dígito menos significativo é um número ímpar:

f :: Integer −−−−>>>> Bool

f num = impar ( soma (digMais num) (digMenos num) )

Exercício 4.2.22.

Escreva uma função para determinar o dobro do quadrado de um número inteiro.

dobro :: Integer −−−−>>>> Integer

dobro n = n * 2

quadrado :: Integer −−−>−>>> Integer

quadrado n = n * n

Utilizando composição de funções, temos:

f :: Integer −−−>−>>> Integer

Compor funções é o ato de utilizar a saída de uma função como entrada de uma outra função, ou seja, dadas duas funções f e g tem-se que:

( . ) :: (a -> b) −> (c -> a) −> (c -> b) ( f . g ) x = f ( g x )

onde: a, b e c são tipos válidos em Haskell.

Note que foi utilizado o ponto ( . ) em substituição ao símbolo matemático ( o ) de composição de funções: ( f o g ) x . Note também, que x tem que ter tipo c, o mesmo tipo do argumento de g.

Composições em Haskell são associativas, logo: f . ( g . h ) = ( f . g ) . h implica em: realize h, depois realize g e, por último, realize f .

Exercício 4.2.23.

Escreva uma função para determinar se o maior divisor de um número, exceto ele próprio, é um número primo.

Solução:

- Dividindo o problema em sub-problemas: 1°- Determinar os divisores do número (divisores) 2°- Encontrar o maior dos divisores (maiorDiv) 3°- Verificar se um número é primo (primo) - Implementando cada uma das funções:

1°- Determinar os divisores do número (divisores)

Dada a lista geradora [1..n], construa uma sub-lista com todos os valores i vindos daquela lista que sejam múltiplos de n (n `mod` i == 0):

divisores :: Integer −−−−>>>> [Integer]

divisores n = [ i | i <<<<−−−− [1..n] , n `mod` i == 0] 2°- Encontrar o maior dos divisores (maiorDiv)

Utilizando composição de funções (consulte as funções last e init na tabela 5):

maiorDiv n = ( last . init . divisores ) n

3°- Verificar se um número é primo (primo)

primo :: Integer −−−−>>>> Bool

primo n = [1,n] == (divisores n)

Resolvendo (novamente utilizando composição de funções):

f :: Integer −−−−>>>> Bool

Exercício 4.2.24.

Um número é dito Juareziano se o seu dígito menos significativo for um número par, se a soma dos seus dígitos for um número ímpar e se, além de ser divisível pela soma de seus dígitos, for um múltiplo de 7. Escreva um programa funcional para determinar se um número n é Juareziano.

Solução:

- Dividindo o problema em sub-problemas: Um número é Juareziano se o seu

dígito menos significativo for um número par, se a soma dos seus dígitos

for um número ímpar e se, além de ser divisível pela soma de seus dígitos, for um múltiplo de 7.

Ou seja:

J: número é Juareziano (juareziano) D: dígito menos significativo (dms) P: for um número par (par) S: soma dos seus dígitos (sd)

I: for um número ímpar (impar) , o mesmo que: ¬P V: divisível por (divide)

M: múltiplo de 7 (multi7) E:

J(n) <=> P.D(n) ∧ ¬P.S(n) ∧ V(n S(n)) ∧ M(n) :

- Implementando cada uma das funções: D: dígito menos significativo (dms)

dms :: Integer −−−>−>>> Integer dms n = n `mod` 10

P: for um número par (par)

par :: Integer −−−>−>>> Bool par n = n `mod` 2 == 0

S: soma dos seus dígitos (sd)

sd :: Integer −−−>−>>> Integer

sd n = if n < 10 then n else (dms n) + sd (n `div` 10)

I: for um número ímpar (impar)

impar :: Integer −−−−>>>> Bool impar n = not (par n)

V: divisível por (divide)

divide :: Integer −−−−>>>> Integer −−−>−>>> Bool

divide n m = m `mod` n == 0

M: múltiplo de 7 (multi7)

multi7 :: Integer −−−−>>>> Bool

multi7 n = n `mod` 7 == 0

Resolvendo J(n) <=> P.D(n) ∧ ¬P.S(n) ∧ V(n S(n)) ∧ M(n) :

juareziano :: Integer −−−−>>>> Bool

juareziano n = par (dms n) && not (par (sd n)) && divide n (sd n) && multi7 n

Obs.: Pode-se resolver J(n) utilizando composição de funções:

juareziano :: Integer −−−−>>>> Bool

juareziano n = (par . dms) n && (not . par . sd) n && divide n (sd n) && multi7 n

Exercício 4.2.25.

Defina uma expressão em Haskell para listar todos os números perfeitos entre dois inteiros m e n, com m < n. Um número é dito perfeito quando é igual à soma de seus divisores, exceto ele próprio. Por exemplo, 28 é perfeito pois os seus divisores são 1, 2, 4, 7 e 14 e 1 + 2 + 4 + 7 + 14 é igual a 28.

Solução:

- Dividindo o problema em sub-problemas: 1°- Criar uma lista com os divisores do número

2°- Somar os elementos da lista (com exceção do último):

2.1- Obter uma sub-lista com todos os elementos de uma lista com exceção do último elemento 2.2- Obter a soma de todos os elementos da sub-lista obtida em 2.1

3°- Verificar se um número é perfeito

- Implementando cada uma das funções:

1°- Criar uma lista com os divisores do número (divisores)

Dada a lista geradora [1..n], construa uma sub-lista com todos os valores i vindos daquela lista que sejam múltiplos de n (n `mod` i == 0):

divisores :: Integer −−−−>>>> [Integer]

2°- Somar os elementos da lista (com exceção do último)

2.1- Obter uma sub-lista com todos os elementos de uma lista com exceção do último elemento:

sublista :: [Integer] −−−−>>>> [Integer] sublista lista = init lista

2.2- Obter a soma de todos os elementos de uma lista (neste caso, da sub-lista obtida em 2.1):

soma :: [Integer] −−−−>>>> Integer

soma lista = sum lista

3°- Verificar se um número é perfeito, ou seja, comparar o número com a soma dos seus divisores:

perfeito :: Integer −−−>−>>> Bool

Bibliografia:

Alencar Filho, Edgard de. Iniciação à lógica matemática. São Paulo: Nobel, 2002.

Bezerra, Manoel J. Questões de matemática. São Paulo: Companhia Editora Nacional, 1977.

Bird, Richard. Introduction to functional programming using Haskell. 2ª ed. Harlow: Prentice Hall, 1998. Cunha, Celso, Cintra, Luís F. L. Nova gramática do português contemporâneo. Rio de Janeiro: Nova Fronteira, 1985.

Fethi, Rabhi, Lapalme, Guy. Algorithms: a functional programming approach. 2ª ed. Harlow: Addison- Wesley, 1999.

Gersting, Judith L. Fundamentos matemáticos para a ciência da computação. Rio de Janeiro: LTC, 2001. Hall, Cordelia, O'Donell, John. Discrete mathematics using a computer. Londres: Springer, 2000. Hegenberg, Leônidas. Lógica: o cálculo de predicados. São Paulo: Herder, 1973.

Iezzi, Gelson, Murakami, Carlos. Fundamentos de matemática elementar, 1: conjuntos, funções. 7ª ed. São Paulo: Atual, 1993.

Scheinerman, Edward R. Matemática Discreta: uma introdução. São Paulo: Pioneira Thomson Learning, 2003.

Souza, João Nunes de. Lógica para ciência da computação: fundamentos da linguagem, semântica e sistemas de dedução. Rio de Janeiro: Campus, 2002.

Thompson, Simon. Haskell: the craft of functional programming. 2ª ed. Harlow: Addison-Wesley Longman, 1999.

Documentos relacionados