Você está na página 1de 182

Introduo Programao

uma Abordagem Funcional

Credin Silva de Menezes, Maria Claudia Silva Boeres, Maria Christina Valle Rauber, Thais Helena Castro, Alberto Nogueira de Castro Jnior, Cludia Galarda Varassin

Departamento de Informtica - UFES Departamento de Cincia da Computao UFAM 2008

ndice
1. CONCEITOS BSICOS.......................................................................4 1.1 Introduo...........................................................................................4 2. A LINGUAGEM DE PROGRAMAO HASKELL E O AMBIENTE HUGS .........................................................................................................................12 Exerccios...............................................................................................19 Kjnkln......................................................................................................19 Oinoi........................................................................................................19 oijpo.........................................................................................................19 3. A Arte de Resolver Problemas...........................................................20 3.4. Um pequeno exemplo:.................................................................22 4. ABSTRAO, GENERALIZAO, INSTANCIAO E MODULARIZAO .........................................................................................................................27 5. Tipos de Dados Numricos................................................................35 Descrio............................................................................................37 Program error: divide by zero ...........................................................38 >..............................................................................................................44 Exerccios...............................................................................................44 <<<< falta completar exerccios>>.........................................................44 6. EXPRESSES LGICAS E O TIPO BOOLEAN...............................45 P || Q && R.....................................................................................51 Exerccios...............................................................................................53 1..............................................................................................................53 <<<< falta exerccios >>>.......................................................................53 7. Definies Condicionais.....................................................................54 8. O TESTE DE PROGRAMAS..............................................................61 9. RESOLVENDO PROBLEMAS - OS MOVIMENTOS DO CAVALO...67 <<<<< inserir exerccios>>>...................................................................76 10. TUPLAS............................................................................................77 11. VALIDAO DE DADOS.................................................................82 1.Explique por que no existe o valor k que apie a definio da funo fx; .........................................................................................................................86 2.Jpojpoj..................................................................................................86 3.Pojpoj...................................................................................................86 4.Pojpoij..................................................................................................86 12. LISTAS..............................................................................................87 Exerccios: ...........................................................................................101 Kjoj........................................................................................................101 Ionopi....................................................................................................101 Oijoip.....................................................................................................101 Joij.........................................................................................................101 Oioi........................................................................................................101 Iojo........................................................................................................101 13. Resolvendo Problemas com Listas................................................102

3 14. Paradigma Aplicativo......................................................................106 15. Processamento de Cadeias de Caracteres primeiros passos....117 Exerccios.............................................................................................124 Kjbkj......................................................................................................124 Kjn.........................................................................................................124 Ono.......................................................................................................124 Onoi......................................................................................................124 16. O PARADIGMA RECURSIVO........................................................125 19. APLICAES.................................................................................161 20. ENTRADA E SAIDA DE DADOS...................................................179 20.1 Introduo: ..............................................................................179

4 1. CONCEITOS BSICOS 1.1 INTRODUO Neste curso o leitor estar se envolvendo com a aprendizagem de conceitos e mtodos bsicos para a construo de programas de computador. A abordagem que daremos est voltada para o envolvimento do aprendiz com a soluo de problemas ao invs da atitude passiva de ver o que os outros fizeram. Uma questo central que permeia o curso a de que construir programas uma tarefa de engenharia, e que, portanto produzir artefatos com os quais o ser humano ter de conviver. Artefatos estes que devem satisfazer requisitos de qualidade e serem, portanto, passveis de constatao. Optamos desenvolver a disciplina orientada descrio de funes, um formalismo bastante conhecido por todos os que chegam a este curso. Esperamos, com isso, atenuar algumas dificuldades tpicas do ensino introdutrio de programao. Nas sees seguintes apresentamos alguns conceitos bsicos que nos parecem importantes ter em mente antes de iniciarmos um curso de programao. 1.2. COMPUTADORES Denominamos computador uma mquina de processar dados, numricos ou simblicos, que funciona atravs da execuo de programas. Ao contrrio das inmeras mquinas que conhecemos, tais como mquina de lavar roupa, liquidificador, aspirador de p, e tantas outras, que realizam uma nica funo, o computador uma mquina multiuso. Podemos us-lo como uma mquina de escrever sofisticada, como uma mquina de fax, como uma prancheta de desenho sofisticada, como um fichrio eletrnico, como uma planilha de clculos e de tantas outras formas. exatamente como o nosso conhecido videogame: para mudar de jogo basta trocar o cartucho. No videogame, cada novo jogo determinado por um novo programa. Em linhas gerais podemos entender um computador como uma mquina capaz de: a) b) interpretar dados que lhe so fornecidos, produzindo resultados em forma de novos dados, usando para isso conceitos que lhe foram antecipadamente informados e, aceitar a descrio de novos conceitos e consider-los na interpretao de novas situaes.

Alguns exemplos de uso de um computador: 1) Descrever para uma mquina a relao mtrica que existe entre os lados de um tringulo retngulo. De posse desse conhecimento, a mquina poderia, por exemplo, determinar o valor de um dos lados quando conhecido o valor dos outros dois.

5 2) Informar a uma mquina as regras de conjugao de verbos. Com este conhecimento a mquina pode determinar a forma correta para um determinado tempo e pessoa de um verbo especfico. 3) Traduo de textos; 4) Classificao de textos quanto sua natureza: romance, poesia, documentrio, entrevista, artigo cientfico; 5) Manipulao de expresses algbricas, resoluo de integral indefinida, etc; 6) Programao automtica: dada uma certa especificao, gerar um programa eficiente; 7) Monitoramento de pacientes em um Centro de Tratamento Intensivo; 8) Identificao de tumores no crebro a partir da comparao de imagens com padres conhecidos de anormalidade; 9) Roteamento inteligente de mensagens; 10) Monitoramento de regies por satlite. 1.3. PROGRAMAO tarefa de identificar o conhecimento necessrio para a descrio de um conceito, organiz-lo e codific-lo de modo a ser entendido pela mquina damos o nome de programao de computadores. Ao conhecimento codificado, produto final da tarefa de programao d-se o nome de programa. A programao de computadores uma atividade que compreende vrias outras atividades, tais como: entendimento do problema a ser resolvido, planejamento de uma soluo, formalizao da soluo usando uma linguagem de programao, verificao da conformidade da soluo obtida com o problema proposto. 1.4. LINGUAGEM DE PROGRAMAO A descrio de conhecimento para um agente racional qualquer (seja uma mquina ou um humano) subentende a existncia de padres segundo os quais o agente possa interpretar o conhecimento informado. A esses padres, quando rigorosamente elaborados, damos o nome de formalismo. Um formalismo composto de dois aspectos: a sintaxe e a semntica. A sintaxe permite ao agente reconhecer quando uma "seqncia de smbolos" que lhe fornecida est de acordo com as regras de escrita e, portanto representa um programa. A semntica permite que o agente atribua um significado ao conhecimento descrito pela "seqncia de smbolos". Por exemplo, quando um agente humano (com

6 determinado grau de escolaridade) encontra a seguinte seqncia de smbolos {3, 4} U {5, 9, 15}, ele por certo reconhecer como uma expresso algbrica escrita corretamente e, se lembrar dos fundamentos da teoria dos conjuntos, associar esta cadeia como a descrio de um conjunto composto pela unio dos elementos de dois conjuntos menores. Eis aqui algumas observaes importantes sobre a necessidade de linguagens de programao: Ainda no possvel usar linguagem natural para ensinar o computador a realizar uma determinada tarefa. A linguagem natural, to simples para os humanos, possui ambigidades e redundncias que a inviabilizam como veculo de comunicao com os computadores. A linguagem nativa dos computadores muito difcil de ser usada, pois requer do programador a preocupao com muitos detalhes especficos da mquina, tirando pois ateno do problema. Para facilitar a tarefa de programao foram inventadas as linguagens de programao. Estas linguagens tm por objetivo se colocarem mais prximas do linguajar dos problemas do que do computador em si. Para que o programa que escrevemos possa ser entendido pelo computador, existem programas especiais que os traduzem (compiladores) ou os que interpretam (interpretadores) para a linguagem do computador. Podemos fazer um paralelo com o que ocorre quando queremos nos comunicar com uma pessoa de lngua estrangeira. Podemos escrever uma carta em nossa lngua e pedir a algum que a traduza para a lngua de nosso destinatrio ou se quisermos conversar pessoalmente, podemos usar um intrprete.

1.5. PROPRIEDADES DE UM PROGRAMA Fazemos programas com a inteno de dotar uma mquina da capacidade de resolver problemas. Neste sentido, um programa um produto bem definido, que para ser usado precisa que sejam garantidas algumas propriedades. Aqui fazemos referncias a duas delas: a correo e o desempenho. A correo pode ser entendida como a propriedade que assegura que o programa descreve corretamente o conhecimento que tnhamos inteno de descrever. O desempenho trata da propriedade que assegura que o programa usar de forma apropriada o tempo e os recursos da mquina considerada. Cabe aqui alertar aos principiantes que a tarefa de garantir que um programa foi desenvolvido corretamente to complexa quanto prpria construo do programa em si. Garantir que um programa funciona corretamente condio imprescindvel para o seu uso e, portanto estaremos dando maior nfase a esta propriedade. 1.6. PARADIGMAS DE LINGUAGENS DE PROGRAMAO

7 As regras que permitem a associao de significados s "seqncias de smbolos" obedecem a certos princpios. Existem vrias manifestaes destes princpios e a cada uma delas denominamos de paradigma. Um paradigma pode ser entendido informalmente como uma forma especfica de se "pensar" sobre programao. Existem trs grandes grupos de paradigmas para programao: o procedimental (ou procedural), o funcional e o lgico. Os dois ltimos so freqentemente referidos como sendo subparadigmas de um outro mais geral, o paradigma declarativo. O paradigma procedimental subentende a organizao do conhecimento como uma seqncia de tarefas para uma mquina especfica. O paradigma lgico requer o conhecimento de um formalismo matemtico denominado lgica matemtica. O paradigma funcional baseia-se no uso dos princpios das funes matemticas. De uma forma geral, os paradigmas declarativos enfatizam o aspecto correo e o procedimental os aspectos de desempenho. Vejam que falamos em "enfatizam", o que quer dizer que apresentam facilidades para descrio e verificao da propriedade considerada. Entretanto, em qualquer caso, o programador dever sempre garantir que os dois aspectos (correo e desempenho) sejam atendidos. 1.7. PROGRAMAO FUNCIONAL Para os fins que aqui nos interessam neste primeiro momento, podemos entender o computador, de uma forma simplificada, como uma mquina capaz de: a) avaliar expresses escritas segundo regras sintticas bem definidas, como a das expresses aritmticas que to bem conhecemos (ex. 3 + 5 - 8) obedecendo semntica das funes primitivas das quais ela dotada (por exemplo: as funes aritmticas bsicas como somar, subtrair, multiplicar e dividir); b) aceitar a definio de novas funes e posteriormente consider-las na avaliao de expresses submetidas sua avaliao. Por enquanto, denominaremos o computador de mquina funcional. Na Figura 1.1 apresentamos um exemplo de interao de um usurio com a nossa Mquina Funcional.
usurio: 3+5/2

Mquina funcional:: 5,5 usurio: f x y = (x + y) / 2

Mquina funcional: definio de f foi aceita usurio: (f 3 5) + (f 10 40)

Mquina funcional: 29

Figura 1.1

8 Na primeira interao podemos observar que o usurio descreveu uma expresso aritmtica e que a mquina funcional avaliou e informou o resultado. Na segunda interao o usurio descreve, atravs de uma equao, uma nova funo, que ele denominou de f e que a mquina funcional acatou a nova definio. Na terceira interao o usurio solicita a avaliao de uma nova expresso aritmtica usando o conceito recentemente definido e que a mquina funcional faz a avaliao usando corretamente o novo conceito. Desta forma, percebemos que a mquina funcional capaz de avaliar expresses aritmticas e funes e tambm aceitar definies de funes, usando para isso, ambientes distintos. 1.8. EXPRESSES ARITMTICAS A nossa mquina funcional hipottica entende a sintaxe das expresses aritmticas, com as quais todo aluno universitrio j bem familiarizado e capaz de avali-las usando as mesmas que regras que j conhecemos. Sintaxe - Todo operador aritmtico pode ser entendido, e aqui o ser, como uma funo que possui dois parmetros. A notao usual para as operaes aritmticas a infixada, ou seja, smbolo funcional colocado entre os dois operandos. Nada impede de pensarmos nelas escritas na forma prefixada, que a notao usual para funes com nmero de parmetros diferente de 2. Por exemplo, podemos escrever "+ 3 2" para descrever a soma do nmero 3 com o nmero 2. As funes definidas pelo programador devem ser escritas de forma prefixada, como no exemplo de interao apresentado na Figura 1.1. Combinando essas duas formas, infixada e prefixada, podemos escrever expresses bastante sofisticadas. Avaliao - As expresses aritmticas, como sabemos, so avaliadas de acordo com regras de avaliao bem definidas, efetuando as operaes de acordo com suas prioridades. Por exemplo, na expresso " 3 + 5 / 2" o primeiro operador a ser avaliado ser o de diviso (/) e posteriormente o de adio. Se desejarmos mudar essa ordem, podemos usar parnteses em qualquer quantidade, desde que balanceados e em posies apropriadas. Por exemplo, na expresso "(3 + 5) / 2", a utilizao de parnteses determina que a sub-expresso 3 + 5 ter prioridade na avaliao. 1.9. FUNES Podemos entender o conceito de funes como uma associao entre elementos de dois conjuntos A e B de tal forma que para cada elemento de A existe apenas um elemento de B associado. O conjunto A conhecido como o domnio da funo, ou ainda como o conjunto de entrada, e o conjunto B o contra-domnio ou conjunto de sada. Para ser mais preciso, podemos afirmar que uma funo f , que associa os elementos de um conjunto A aos elementos de um conjunto B, consiste em um conjunto de pares ordenados onde o primeiro elemento do par pertence a A o segundo a B. Exemplos:

9 a) Seja a funo T que associa as vogais do alfabeto com os cinco primeiros inteiros positivos. T = {(a,1), (e,2), (i,3), (o,4), (u,5)} b) Seja a funo Q, que associa a cada nmero natural o seu quadrado. Q = {(0,0), (1,1), (2,4), (3,9), (4,16), ...} Podemos observar que a funo T um conjunto finito e que a funo Q um conjunto infinito. 1.10. DESCRIES FUNCIONAIS Podemos descrever um conjunto, de duas formas: extensional, onde explicitamos todos os elementos que so membros do conjunto, como no caso do conjunto T apresentado anteriormente; ou na forma intencional, onde descrevemos um critrio de pertinncia dos membros do conjunto. Por exemplo, o conjunto Q acima apresentado poderia ser reescrito da seguinte forma: Q = {(x, y) | x natural e y = x.x} que pode ser lido da seguinte maneira: Q o conjunto dos pares ordenados (x, y) tal que x um nmero natural e y o produto de x por x. Quando descrevemos uma funo para fins computacionais, estamos interessados em explicitar como determinar o segundo elemento do par ordenado, conhecido o primeiro elemento do par. Em outras palavras, como determinar y conhecendo-se o valor de x. Normalmente dizemos que queremos determinar y em funo de x. Nesta forma de descrio, omitimos a varivel y e explicitamos o primeiro elemento que denominado ento de parmetro da funo. No caso acima teramos ento: Qx=x.x 1.11. POR QUE COMEAR A APRENDIZAGEM DE PROGRAMAO ATRAVS DO PARADIGMA FUNCIONAL? Tendo em vista a prtica vigente de comear o ensino de programao em cursos de computao utilizando o paradigma procedimental, apresentamos a seguir alguns elementos que baseiam nossa opo de comear o ensino de programao usando o paradigma funcional. 1) O aluno de graduao em Computao tem de 4 a 5 anos para aprender todos os detalhes da rea de computao, portanto no se justifica que tudo tenha que ser absorvido no primeiro semestre. O curso introdutrio apenas o primeiro passo e no visa formar completamente um programador. Este o momento de apresentarlhe os fundamentos e, alm disso, permitir que ele vislumbre a variedade de problemas que podem ser solucionados como o apoio do computador;

10 2) O paradigma procedimental requer que o aluno tenha um bom entendimento dos princpios de funcionamento de um computador real, pois eles se baseiam, como as mquinas reais, no conceito de mudana de estados (mquina de Von Neumann). O paradigma lgico, outro forte candidato, requer o conhecimento de lgica matemtica que o aluno ainda no domina adequadamente; O paradigma funcional baseado num conhecimento que o aluno j est familiarizado desde o ensino mdio (funes, mapeamento entre domnios) o qual ainda explorado em outras disciplinas do ciclo bsico, o que nos permite concentrar nossa ateno na elaborao de solues e na descrio formal destas; O elevado poder de expresso das linguagens funcionais permite que a abrangncia do uso do computador seja percebida mais rapidamente. Em outras palavras, podemos resolver problemas mais complexos j no primeiro curso; O poder computacional do paradigma funcional idntico ao dos outros paradigmas. Apesar disso, ele ainda no usado nas empresas, por vrios aspectos. Dentre os quais podemos citar: i) No passado, programas escritos em linguagens funcionais eram executados muito lentamente. Apesar disso no ser mais verdadeiro, ficou a fama; A cultura de linguagens procedimentais possui muitos adeptos no mundo inteiro, o que, inevitavelmente, cria uma barreira introduo de um novo paradigma. Afinal, temos medo do desconhecido e trememos quando temos que nos livrar de algo que j sabemos; H uma crena que linguagens funcionais so difceis de aprender e s servem para construir programas de inteligncia artificial.

3) 4)

5)

6)

ii)

iii)

7)

A ineficincia das linguagens funcionais em comparao s procedimentais tem se reduzido atravs de alguns mecanismos tais como: lazy evaluation, grafo de reduo, combinadores. Para fazer um programa que "funciona" (faz alguma coisa, embora no necessariamente o que desejamos) mais fcil faz-lo no paradigma procedimental. Para fazer um programa que funciona "corretamente" para resolver um determinado problema mais fcil no paradigma funcional, pois esse paradigma descreve "o que fazer" e no "como fazer". As linguagens funcionais so geralmente utilizadas para processamento simblico, ou seja, soluo de problemas no numricos. (Exemplo: integrao simblica X integrao numrica). Atualmente constata-se um crescimento acentuado do uso deste tipo de processamento.

8)

9)

11 10) A crescente difuso do uso do computador nas mais diversas reas do conhecimento gera um crescimento na demanda de produo de programas cada vez mais complexos. Os defensores da programao funcional acreditam que o uso deste paradigma seja uma boa resposta a este problema, visto que com linguagens funcionais podemos nos concentrar mais na soluo do problema do que nos detalhes de um computador especfico, o que aumenta a produtividade. Se mais nada justificar o aprendizado de uma linguagem funcional como primeira linguagem, resta a explicao didtica. Estamos dando um primeiro passo no entendimento de programao como um todo. , portanto, importante que este passo seja simplificado atravs do apoio em uma "mquina" j conhecida, como o caso das funes. Ainda um outro argumento: mesmo que tenhamos que usar posteriormente uma outra linguagem para ter uma implementao eficiente, podemos usar o paradigma funcional para formalizar a soluo. Sendo assim, a verso em linguagem funcional poderia servir como uma especificao do programa.

11)

12)

Exerccios: 1. Conceitue programao de computadores. 2. Quais os principais paradigmas de programao e o que os diferenciam. 3. Faa uma descrio intencional da funo: F = {1,3,5,7,...}. 4, Faa uma listagem de outros exemplos de programas de computador que so usados hoje em diferentes reas do conhecimento e por diferentes profissionais. 5. Apresente exemplo de outras linguagens tcnicas usadas pelo ser humano para descrever conhecimento. 6. Os conceitos de correo e de desempenho, se aplicam a qualquer artefato. Escolha 3 artefatos quaisquer e discuta os dois conceitos. 7. Apresente uma descrio informal da funo que conjuga os verbos regulares da 1a. conjugao.

2. A LINGUAGEM DE PROGRAMAO HASKELL E O AMBIENTE HUGS 2.1. INTRODUO Neste curso usaremos o ambiente HUGS, no qual utilizada uma implementao da linguagem de programao funcional Haskell. Essa linguagem por apresentar uma sintaxe simples e elegante, alm de oferecer operadores bastante expressivos, tem sido usada com bons resultados para a aprendizagem de fundamentos de programao. Podemos usar o HUGS como uma calculadora qualquer, qual submetemos expresses que ela avalia e nos informa o valor resultante. Vejamos por exemplo a interao a seguir. ?3+5*2 13 ? (3 + 5) * 2 16 ? Nas expresses acima importante destacar o uso do smbolo * (asterisco) que empregado para representar a multiplicao. Alm desse, outros smbolos usuais sero substitudos, como veremos logo mais. As operaes aritmticas so, como sabemos, funes. A notao utilizada em Haskell para as operaes aritmtica a usual, ou seja, infixada (o smbolo da operao fica entre os operandos). Uma outra forma que pode ser usada para escrever expresses usando o operador de forma prefixada. Por exemplo, div 15 6 , indica a diviso inteira do nmero 15 (dividendo) pelo nmero 6 (divisor). O smbolo de maior (>) usado pelo sistema para indicar que est preparado para avaliar uma nova expresso. Aps avaliar uma expresso o Haskell informa o resultado na linha seguinte e em seguida exibe uma nova interrogao, se disponibilizando para uma nova avaliao. Podemos explicar o seu funcionamento conforme o esquema da figura abaixo. Em outras palavras, o ambiente HUGS estabelece uma repetio para leitura de uma expresso, avaliao de uma expresso e exibio do resultado, conforme se ilustra no esquema a seguir..

1 3 Podemos usar o ambiente HUGS somente para isso, para escrever expresses e solicitar ao sistema que as avalie. Entretanto podemos ousar mais e usar o ambiente para descrever novas funes a partir das funes j oferecidas pelo ambiente. Podemos tambm utilizar nessas novas definies as prprias definies que tivermos construdo anteriomente. 2.2. DESCRIO DE FUNES: A forma de descrever funes similar ao que nos referimos anteriormente no captulo 1, ou seja, atravs de uma equao, onde no lado esquerdo da igualdade damos um nome funo e relacionamos os parmetros considerados na sua definio. No lado direito escrevemos uma expresso utilizando outras funes, primitivas ou no. Isto nos leva portanto a tomar conhecimento que a linguagem possui funes primitivas que j a acompanham e que portanto prescindem de definio. Por exemplo, para definir a funo que determina o espao percorrido por um mvel em movimento retilneo uniforme, conhecidos a sua velocidade e o tempo decorrido, podemos escrever: espaco v t = v * t No esquema a seguir fazemos uma identificao didtica dos vrios elementos da definio.O lado esquerdo da igualdade tambm chamado de inteface ou assinatura da funo e o lado direito o corpo da definio. espaco nome da funo v t parmetros = v*t expresso aritmtica que define a relao que h entre os parmetros corpo da definio

interface da funo

Para alimentar o HUGS com novas definies devemos criar um arquivo em disco no qual editaremos as definies desejadas. Cada arquivo pode ter uma ou mais definies. Normalmente agrupamos em um mesmo arquivo as definies relacionadas com a soluo de um problema especfico ou definies de propsito geral. No jargo de programao com a linguagem Haskell, um conjunto de definies denominado de script. A alimentao de novas definies indicada ao sistema atravs de um comando que usado no lugar de uma expresso, quando o sistema exibe o seu pedido de tarefa (o smbolo de interrogao. Para indicar que estaremos dando um comando usamos o smbolo " : " (dois pontos) seguido do nome do comando (existem vrios). Para a tarefa que temos neste instante utilizamos o comando load (oportunamente veremos outros). Por exemplo, podemos escrever um conjunto de definies em um arquivo denominado pf0001.hs. Para alimentar este arquivo no ambiente HUGS podemos escrever: > :load pf001.hs

1 4 A partir deste momento, todas as definies contidas no arquivo informado estaro disponveis para uso. Podemos entender isso como fazer uma extenso da mquina Haskell. Na figura 2.1 apresentamos um esquema de utilizao do ambionete HUGS e de um editor de textos para provimento de novas definies.

Editor de texto

Arquivo com definies

Interpretador HUGS programador

Figura 2.1 Interaes do Programador com o Ambiente de Programao

Vale aqui um pequeno lembrete, podemos estender a noo de funes para incorporar tambm as chamadas funes constantes, ou seja, aquelas que no possuem domnio, apenas contradomnio. Na nomenclatura de definies dizemos que temos definies paramtricas e definies no paramtricas. Por exemplo, podemos definir a constante pi, da seguinte maneira: pi = 3.1416

1 5 2.3. UM EXEMPLO: Considere que queremos descrever uma funo para determinar as razes de uma equao do segundo grau. Sabemos que pela nossa clssica frmula as razes so descritas genericamente por:

A soluo, como sabemos, formada por um par de valores. Por enquanto vamos descrever este fato por duas funes, uma para a primeira raiz e outra para a segunda. eq2g1 a b c = ((-b) + sqrt (b^2 - 4.0 * a * c )) / (2.0 * a) Vamos discutir alguns detalhes desta codificao: o termo -b precisa ser codificado entre parntesis pois nmeros negativos so obtidos por um operao unria que produz um nmero negativo a partir de um positivo; o smbolo da raiz quadrada foi substitudo pela funo sqrt; o numerador da frao precisa ser delitimado pelo uso de parntesis; o denominador tambm precisa ser delimitado por parntesis; o smbolo de multiplicao usual foi trocado pelo * (asterisco); o smbolo de potenciao foi substitudo pelo ^ (circunflexo). Podemos agora descrever a outra raiz de forma anloga: eq2g2 a b c = ((-b) - sqrt (b^2 - 4.0 * a * c )) / (2.0 * a) Visto que as duas possuem partes comuns, poderamos ter escrito abstraes auxiliares e produzir um conjunto de definies, tal como: quad x raizdelta a b c dobro x eq2g1 a b c eq2g2 a b c = = = = = x*x sqrt ( quad b - 4.0 * a * c ) 2.0 * x ((-b) + raizdelta a b c) / dobro a ((-b) - raizdelta a b c) / dobro a

Vejamos como ficaria uma interao com o HUGS, a partir de um arquivo de definies denominado eq2g.gs: > :l eq2g.gs Reading script file "eq2g.gs": Haskell session for: standard.prelude eq2g.gs

1 6 > eq2g1 2.0 5.0 2.0 -0.5 > eq2g2 2.0 5.0 2.0 -2.0 > eq2g1 3.0 4.0 5.0 Program error: {sqrt (-44.0)} Podemos observar que houve um problema com a avaliao da expresso eq2g1 3.0 4.0 5.0 Este um erro semntico, provocado pela tentativa de extrair a raiz quadrada de um nmero negativo. A funo que definimos portanto uma funo parcial, ou seja, ela no est definida para todo o domnio dos reais. Neste caso o sistema apenas acusa o problema ocorrido. 2.4. DEFINIES LOCAIS : As definies que discutimos anteriormente so globais, no sentido de que esto acessveis ao uso direto do usurio e tambm disponveis para uso em qualquer outra definio. Por exemplo, se temos o script: quad x = x * x hipo x y = sqrt ( quad x + quad y) Podemos utilizar a definio quad tanto externamente pelo usurio quanto internamente pela definio hipo. Se no entanto desejamos construir subdefinies para uso em uma definio especfica, podemos defini-las internamente, restringindo o seu contexto A maneira de introduzir definies locais utilizando a clusula where. Vamos modificar o script acima para que quad s possa ser usado no interior de hipo. hipo x y = sqrt ( quad x + quad y) where quad x = x * x

As definies internas tambm no precisam ser paramtricas. Veja este outro exemplo. hipo x y = sqrt ( k1 + k2) where k1 = x * x k2 = y * y

1 7 Note que apesar de x e y no serem parmetros de k1 e k2 eles foram utilizados em suas definies. Isto possvel porque x e y tm validade em todo o lado direito da definio. Temos que considerar ainda que nada impede que em uma definio local tenhamos uma outra definio local e dentro desta outra, e assim sucessivamente. hipo x y = sqrt k where k = quad x + quad y where quad x = x * x

2.5. MODELO DE AVALIAO DE EXPRESSES: Quando o avaliador do HUGS toma uma expresso contendo apenas constantes e operaes primitivas, ele apenas efetua as operaes obedecendo prioridade dos operadores e aquelas determinadas pelo uso de parntesis. Por exemplo, para avaliar a expresso 3 + 5 / 2, primeiro realizada a diviso 5/2, resultando em 2.5, o qual adicionado ao 3, finalmente obtendo 5.5. Podemos entender isso como uma seqncia de redues de uma expresso outra mais simples, at que se atinja um termo irredutvel. Veja os exemplos a seguir: 3 + 5 / 2 3 + 2.5 5.5 (3 + 5) / 2 8 / 2 4 3 + 5 + 2 8 + 2 10 As setas () so usadas para indicar um passo de reduo. Quando as expresses utilizam funes definidas pelo usurio, o processo anlogo. Cada referncia uma definio substituda por seu lado direito, at que se atinja uma expresso bsica, e prossegue como no caso anterior. Vejamos os exemplos abaixo, considerando a primeira definio de hipo e de quad apresentada anteriormente: ordem 1 2 3 4 5 6 7 expresso hipo 3 5 + hipo 4 4 sqrt ( quad 3 + quad 5) + hipo 4 4 sqrt ( 3 * 3 + quad 5) + hipo 4 4 sqrt (3 * 3 + 5 * 5) + hipo 4 4 sqrt (3 * 3 + 5 * 5) + sqrt (quad 4 + quad 4) sqrt (3 * 3 + 5 * 5) + sqrt (4 * 4 + quad 4) sqrt (3 * 3 + 5 * 5) + sqrt (4 * 4 + 4 * 4) reduo aplicada expresso inicial def de hipo def de quad def de quad def de hipo def de quad def de quad

1 8 8 9 10 11 12 13 14 15 16 sqrt (9 + 5 * 5) + sqrt (4 * 4 + 4 * 4) sqrt (9 + 25) + sqrt (4 * 4 + 4 * 4) sqrt 34 + sqrt (4 * 4 + 4 * 4) 5.83095 + sqrt (4 * 4 + 4 * 4) 5.83095 + sqrt (16 + 4 * 4) 5.83095 + sqrt (16 + 16) 5.83095 + sqrt (32) 5.83095 + 5.65685 11.4878 * * + sqrt * * + sqrt +

Para uma realizao especfica da linguagem, isso no precisa acontecer exatamente assim. Entretanto este modelo suficiente para nossos interesses. O nmero de redues necessrias para chegar forma irredutvel de uma expresso, tambm denominada de forma cannica ou ainda forma normal, pode ser usado como critrio para discutir o desempenho da mesma. Exerccios 1. Estabelea categorias para comparar duas definies; 2. Usando as categorias definidas no item 1 compare as duas definies apresentadas para as razes de uma equao do segundo grau; 3. Compare usando as suas categorias, as trs definies apresentadas para hipo; 4. Apresente uma explicao para o erro produzido pela avaliao da expresso eq2g1 3.0 4.0 5.0 5. Apresente uma seqncia de redues para a expresso: eq2g1 2.0 5.0 2.0 6. Apresente um conjunto de definies para a funo total para a determinao das razes de uma equao do segundo grau. 2.6. ASSINATURA DE FUNES E A NOTAO CURRY: Do estudo de funes sabemos que toda funo possui um domnio e um contradomnio. O domnio pode ser formado por zero ou mais conjuntos. Quando uma funo no possui domnio dizemos que uma funo constante. Para descrever este conhecimento sobre domnio e contradomnio usado o conceito de assinatura, do ingls signature. Por exemplo, na funo que determina a mdia aritmtica de 3 nmeros reais, temos que o domnio formado pelo produto cartesiano R x R X R e o contradomnio R. A assinatura desta funo a seguinte: ma3 :: R X R X R R Em Haskell poderamos ter a seguinte definio:

1 9 ma3 x y z = (x + y + z) / 3. usual tambm dizer R X R X R R o tipo da funo ma3. Para simplificar o trabalho com funes o matemtico Haskell Cury criou uma nova notao, que considera que qualquer funo tem sempre um nico parmetro de entrada. Segundo ele, o resultado de aplicar uma funo sobre um parmetro produz uma nova funo que pode ser aplicada a outro parmetro, e assim sucessivamente. Por exemplo, nesta notao, a funo ma3 teria a seguinte assinatura: ma3 :: R R R R Podemos ler da seguinte maneira: ma3 uma funo que mapeia um numero real em uma nova funo cuja assinatura : ma3 :: R R R. A funo ma3 por sua vez mapeia um nmero real em uma nova funo cuja assinatura : ma3 :: R R. A funo ma3 por sua vez mapeia um nmero real em uma nova funo cuja assinatura : ma3 :: R. Que uma funo constante. Em captulos posteriores veremos as vantagens desta notao introduzida por Haskell, conhecida por notao Curry. Por enquanto podemos afirmar que essa facilidade vem do fato que nesta notao as funes possuem propriedades equivalentes s dos dados. Exerccios Kjnkln Oinoi oijpo

2 0 3. A Arte de Resolver Problemas 3.1. INTRODUO: O grande objetivo deste curso criar oportunidades para que o estudante desenvolva suas habilidades como resolvedor de problemas. Mais especificamente estamos interessados na resoluo de problemas usando o computador, entretanto, temos certeza, que as idias so gerais o suficiente para ajudar a resolver qualquer problema. Embora muitas pessoas j tenham discutido sobre este assunto ao longo da histria, nosso principal referencial ser o professor George Polya, que escreveu um livro sobre este assunto, com o mesmo nome deste captulo, voltado para a resoluo de problemas de matemtica do ensino fundamental. Todos os alunos deste curso tero grande proveito se lerem este livro. As idias ali apresentadas com certeza se aplicam com muita propriedade resoluo de problemas com o computador. Na medida do possvel estaremos apresentando aqui algumas adaptaes que nos parecem apropriadas neste primeiro contato com a resoluo de problemas usando o computador. 3.2. DICAS INICIAIS: apresenta-se a seguir algumas orientaes: 3.2.1. S se aprende a resolver problemas atravs da experincia. Logo o aluno que est interessado em aprender deve trabalhar, buscando resolver por si mesmo, os problemas propostos antes de tentar o auxlio do professor ou de outro colega; 3.2.2. A ajuda do professor no deve vir atravs da apresentao pura e simples de uma soluo. A ajuda deve vir atravs do fornecimento de pistas que ajudem o aluno a descobrir a soluo por si mesmo; 3.2.3. muito importante no se conformar com uma nica soluo. Quanto mais solues encontrar, mais hbil o estudante ficar, e alm disso, poder comparar as vrias alternativas e escolher a que lhe parecer mais apropriada. A escolha dever sempre ser baseada em critrios objetivos. 3.2.4. Na busca pela soluo de um problema, nossa ferramenta principal o questionamento. Devemos buscar formular questes que nos ajudem a entender o problema e a elaborar a soluo. 3.2.5. Aprenda desde cedo a buscar um aprimoramento da sua tcnica para resolver problemas, crie uma sistematizao, evite chegar na frente de um problema como se nunca tivesse resolvido qualquer outro problema. Construa um processo individual e v aperfeioando-o cada vez que resolver um novo problema. 3.3 COMO RESOLVER UM PROBLEMA: O professor Polya descreve a resoluo de um problema como um processo complexo que se divide em quatro etapas, as quais apresentamos aqui, com alguma adaptao. Segundo nos recomenda Polya, em qualquer destas etapas devemos ter em mente trs questes sobre o andamento do nosso trabalho, que so: Por onde comear esta etapa? O que posso fazer com os elementos que disponho? Qual a vantagem de proceder da forma escolhida?

2 1 Etapa 1 - Compreenso do Problema impossvel resolver um problema sobre o qual no tenhamos um entendimento adequado. Portanto, antes de correr atrs de uma soluo, concentre-se um pouco em identificar os elementos do problema. Faa perguntas tais como: Quais so os dados de entrada? O que desejamos produzir como resultado? Qual a relao que existe entre os dados de entrada e o resultado a ser produzido? Quais so as propriedades importantes que os dados de entrada possuem? Etapa 2 - Planejamento Nesta fase devemos nos envolver com a busca de uma soluo para o problema proposto. Pode ser que j o tenhamos resolvido antes, para dados ligeiramente modificados. Se no o caso, pode ser que j tenhamos resolvido um problema parecido. Qual a relao que existe entre este problema que temos e um outro problema j conhecido? Ser que podemos quebrar o problema em problemas menores? Ser que generalizando o problema no chegaremos a um outro j conhecido? Conhecemos um problema parecido, embora mais simples, o qual quando generalizado se aproxima do que temos? Etapa 3 - Desenvolvimento Escolhida uma estratgia para atacar o problema, devemos ento caminhar para a construo da soluo. Nesta fase, devemos considerar os elementos da linguagem de programao que iremos usar, respeitando os elementos disponibilizados pela linguagem, tais como tipos, formas de definio, possibilidades de generalizao e uso de elementos anteriormente definidos. A seguir, devemos codificar cada pedao da soluo, e garantir que cada um esteja descrito de forma apropriada. Em outras palavras, no basta construir, temos que ser capazes de verificar se o resultado de nossa construo est correto. Isto pode ser realizado pela identificao de instncias tpicas, da determinao dos valores esperados por estas, da submisso dessas instncias ao avaliador e finalmente, da comparao dos resultados esperados com os resultados produzidos pela avaliao de nossas definies. Alm disso, devemos garantir que a definio principal tambm est correta. Em sntese, a fase de desenvolvimento compreende as seguintes subfases: 1. construo da soluo; 2. planejamento do teste; 3. teste com o computador de mesa; 4. codificao da soluo; 5. teste com o uso do computador. Etapa 4 - Avaliao do Processo e seus resultados O trabalho do resolvedor de problemas no pra quando uma soluo est pronta. Devemos avaliar a qualidade da soluo, o processo que realizamos e questionar as possibilidades de uso posterior da soluo obtida e tambm do prprio mtodo utilizado. Novamente devemos fazer perguntas: Este foi o melhor caminho que poderia ter sido usado? Ser que desdobrando a soluo no obtenho componentes que poderei usar mais facilmente no futuro? Se esta

2 2 soluo for generalizada possvel reus-la mais facilmente em outras situaes? Registre tudo, organize-se para a resoluo de outros problemas. Anote suas decises, enriquea a sua biblioteca de solues e mtodos. 3.4. UM PEQUENO EXEMPLO: Enunciado: Deseja-se escrever um programa que permita determinar a menor quantidade de cdulas necessrias para pagar uma dada quantia em Reais. Etapa 1 Compreenso Questo: Quais os dados de entrada? Resposta: A quantia a ser paga. Questo: Qual o resultado a ser obtido? Resposta: A menor quantidade de cdulas. Questo: Qual a relao que existe entre a entrada e a sada? Resposta: O somatrio dos valores de cada cdula utilizada deve ser igual quantia a ser paga. Questo: Existe algum elemento interno, ou seja, uma dado implcito? Resposta: Sim, os tipos de cdulas existentes.Considere que o Real possui apenas as seguintes cdulas: 1, 5, 10, 50 e 100. importante observar que qualquer cdula um mltiplo de qualquer uma das menores. Etapa 2 - Planejamento Conheo algum problema parecido? Existe um problema mais simples? Podemos entender como um problema mais simples um que busque determinar quantas cdulas de um dado valor so necessrias para pagar a quantia desejada. Por exemplo, para pagar R$ 289,00 poderamos usar 289 cdulas de R$ 1,00. Ou tambm poderamos usar 5 notas de R$ 50,00, mas neste caso ficariam ainda faltando R$ 39,00. Claro que no queremos que falte nem que sobre e, alm disso, desejamos que a quantidade seja mnima. Parece uma boa estratgia comear vendo o que d para pagar com a maior cdula e determinar quando falta pagar. O restante pode ser pago com uma cdula menor, e por a afora. Explorando a instncia do problema j mencionada, vamos fazer uma tabela com estes elementos. Expresso para determinar a Quantidade quantidade de cdulas cdulas de um determinado valor. 289 / 100 2

de

Quantia a Pagar

289,00 89,00

2 3 89/ 50 39/ 10 9/ 5 4/ 1 TOTAL Etapa 3 - Desenvolvimento Soluo 1 - Considerando a tabela acima descrita, codificando cada linha como uma subexpresso da definio. ncedulas q = (div q 100) + (div (mod q 100) 50) + (div (mod (mod q 100) 50) 10) + (div (mod (mod (mod q 100) 50) 10) 5)+ (div (mod (mod (mod (mod q 100) 50) 10) 5) 1) 1 3 1 4 11 39,00 9,00 4,00 0,00

Soluo 2 - Considerando uma propriedade das cdulas, ou seja, j que uma cdula qualquer mltiplo das menores, a determinao do resto no precisa considerar as cdulas maiores do que a cdula que estamos considerando em um dado ponto. ncedulas2 q = (div q 100) + (div (mod q 100) 50) + (div (mod q 50) 10) + (div (mod q 10) 5)+ (div (mod q 5) 1) Etapa 4 - Avaliao A soluo deixa de explicitar as abstraes referentes quantidade de cdulas de um determinado valor, assim como o resto correspondente. Podemos questionar, no seria melhor explicitar? Assim poderamos us-las de forma independente e alm disso, a soluo fica mais clara e portanto inteligvel. ncedulas q n100 q r100 q n50 q r50 q n10 q r10 q n5 q r5 q n1 q = = = = = = = = = = n100 q + n50 q + n10 q + n5 q + n1 q div q 100 mod q 100 div (r100 q) 50 mod (r100 q) 50 div (r50 q) 10 mod (r50 q) 10 div (r10 q) 5 mod (r10 q) 5 div (r10 q) 5

2 4 Supondo que no queremos generalizar todas as funes menores ainda poderamos escrever o programa usando definies locais.

ncedulas q

= n100 + n50 + n10 + n5 + n1 where n100 = div q 100 r100 = mod q 100 n50 = div r100 50 r50 = mod r100 50 n10 = div r50 10 r10 = mod r50 10 n5 = div r10 5 n1 = mod r10 5

Podemos ainda considerar que se houver uma troca no sistema, de modo a incluir uma nova cdula que no seja mltiplo de seus valores menores. Seria fcil mudar o programa para contemplar a mudana nas leis do mundo do problema. 3.5. PROVRBIOS: O professor Polya tambm nos sugere que a lembrana de alguns provrbios pode ajudar o aprendiz (e o resolvedor de problemas) a organizar o seu trabalho. Diz Polya que, apesar dos provrbios no se constiturem em fonte de sabedoria universalmente aplicvel, seria uma pena desprezar a descrio pitoresca dos mtodos heursticos que apresentam. Alguns so de ordem geral, tais como: O fim indica aos meios. Seus melhores amigos so O que, Por que, Onde, Quando e Como. pergunte O que, pergunte Por que, pergunte Onde, pergunte Quando e pergunte Como - e no pergunte a ningum quando precisar de conselho. No confie em coisa alguma, mas s duvide daquilo que merecer dvida. Olhe em torno quando encontrar o primeiro cogumelo ou fizer a primeira descoberta; ambos surgem em grupos. A seguir apresentamos uma lista deles, organizados pelas etapas s quais parecem mais relacionados. Etapa 1 : Compreenso do problema. Quem entende mal, mal responde. Pense no fim antes de comear. O tolo olha para o comeo, o sbio v o fim.

2 5 O sbio comea pelo fim, o tolo termina no comeo. Etapa 2 : Planejamento da soluo. A perseverana a me da boa sorte. No se derruba um carvalho com uma s machadada. Se no princpio no conseguir, continue tentando. Experimente todas as chaves do molho. Veleja-se conforme o vento. Faamos com pudermos se no pudermos fazer como queremos. O sbio muda de opinio, o tolo nunca. Mantenha duas cordas para um arco. Faa e refaa que o dia bastante longo. O objetivo da pescaria no lanar o anzol mas sim pegar o peixe. O sbio cria mais oportunidades do que as encontra. O sbio faz ferramentas daquilo que lhe cai s mos. Fique sempre de olho na grande ocasio. Etapa 3: Construo da soluo. Olhe antes de saltar. Prove antes de confiar. Uma demora prudente torna o caminho seguro. Quem quiser navegar sem risco, no se faa ao mar. Faa o que puder e espere pelo melhor. fcil acreditar naquilo que se deseja. Degrau a degrau sobe-se a escada. O que o tolo faz no fim, o sbio faz no princpio. Etapa 4: Avaliao da soluo. No pensa bem quem no repensa. mais seguro ancorar com dois ferros. Exerccios 1) Compare as duas definies para a funo que descreve o nmero mnimo de cdulas para pagar uma quantia q, ncedulas e ncedulas2; 2) Desenvolva a soluo para o problema da cdulas considerando o fato de que o Real possui notas de 2 e notas de 20. O que muda? 3) Apresente trs problemas semelhante ao das cdulas;

2 4) 6 Desenvolva uma soluo para o problema considerando que para cada tipo de cdula existe um quantidade limitada (maior ou igual a zero);

2 7 4. ABSTRAO, GENERALIZAO, INSTANCIAO E MODULARIZAO 4.1. INTRODUO: Na busca por resolver um problema podemos usar vrios princpios, cada um evidentemente ter uma utilidade para a resoluo do problema, ou para garantia de sua correo ou ainda para facilitar os usos posteriores da soluo que obtivermos. Apresentamos a seguir alguns deles. 4.2. ABSTRAO: Quando escrevemos uma expresso e no damos nome a ela, o seu uso fica limitado quele instante especfico. Por exemplo, suponha que desejamos determinar a hipotenusa de um tringulo retngulo com catetos 10 e 4. Como conhecemos o teorema de Pitgoras (a2 = b2 + c2), podemos usar diretamente nossa mquina funcional para avaliar a seguinte expresso: > sqrt ((10.0 * 10.0)+ (4.0 * 4.0)) 10.7703 > A expresso que codificamos serve apenas para esta vez. Se em algum outro instante precisarmos avalia-lateremos que codific-la novamente. Para evitar isso, que damos nomes s nossas expresses, para que possamos us-las repetidamente, apenas referenciando-as pelo seu nome. No caso acima, poderamos escrever a definio: hipotenusa = sqrt ((10.0 * 10.0)+ (4.0 * 4.0)) De posse dessa definio nossa mquina poder avaliar a expresso sempre que dela precisarmos., basta escreve-la: > hipotenusa 10.7703 Voc pode agora estar se perguntando, porque no trocamos a definio para usar diretamente o valor 10.7703? hipotenusa = 10.7703 Agindo assim a mquina no precisaria avaliar a expresso sqrt ((10.0 * 10.0)+ (4.0 * 4.0)) a cada uso. Por outro lado no ficaria registrada a origem do valor 10.7703., com o tempo perderamos esta informao. De qualquer forma, teramos criado uma abstrao qual denominamos hipotenusa. Outra pergunta pode estar rondando a sua cabea, por que escrever uma definio que sempre avaliada para o mesmo valor, por que no generaliza-la? Bom, este foi apenas um recurso didtico para separar os dois conceitos, a abstrao que acabamos de apresentar a generalizao que apresentaremos a seguir. No entanto convm lembrar que algumas definies so realmente constantes e que no so de grande utilidade, como o caso da seguinte definio:

2 8 pi = 3.1416 4.3. GENERALIZAO: Quando uma abstrao se aplica a vrios valores podemos generaliz-la. Assim, alm de us-la vrias vezes para os mesmos valores, podemos tambm us-la para valores diferentes. Esta ultima alternativa evidentemente facilita o seu reuso. Vamos apresentar duas formas para fazer isso. a) Elaborando a definio usando outras definies constantes. Por exemplo, no caso da definio acima para a hipotenusa, poderamos escrever as definies a seguir: b = 10.0 c = 4.0 hipotenusa = sqrt (( b * b) + ( c * c)) Aqui, hipo se aplica a dois valores quaisquer b e c, os quais so objetos de outras definies. b)Uma forma mais geral atravs do conceito de parametrizao. Esta consiste em indicar no cabealho da definio (lado esquerdo da igualdade) quais so os objetos da generalizao. Para o exemplo que estamos trabalhando, podemos escrever: hipotenusa b c = sqrt (( b * b) + ( c * c)) Temos ento descrito a funo paramtrica hipotenusa cujos parmetros so b e c. 4.3.1 INSTANCIAO: A parametrizao permite que usemos a mesma definio para diferentes instncias do problema. Por exemplo, suponha que desejamos determinar a hipotenusa de trs tringulos retngulos. O primeiro com catetos 10 e 4, o segundo com catetos 35 e 18 e o terceiro com catetos 9 e 12. Podemos instanciar a definio paramtrica para estabelecer a seguinte interao: > hipo 10.0 4.0 10.7703 (5 reductions, 42 cells) > hipo 35.0 18.0 39.3573 (5 reductions, 43 cells) > hipo 9.0 12.0 15.0 (5 reductions, 38 cells) >

2 9 4.4. MODULARIZAO: Em geral, nossos problemas no sero to simples e diretos quanto o exemplo acima. Quando nos deparamos com problemas maiores, um bom princpio : Divida para facilitar a conquista. Basicamente este princpio consiste em quebrar o problema inicial em problemas menores, elaborar a soluo para cada um dos problemas menores e depois combin-las para obter a soluo do problema inicial. A cada um dos subproblemas encontrados podemos reaplicar o mesmo princpio. Segundo Polya, esta uma heurstica muito importante qual ele denomina de Decomposio e Combinao. Antes de pensar em codificar a soluo em uma linguagem de programao especfica, podemos represent-la atravs de um esquema grfico denominado de estrutura modular do problema (veja a representao para o problema a seguir). 4.6. MODULARIZANDO: Considere o problema de descrever rea da figura Fig 4.1 abaixo.

Figura 4.1 Um polgono irregular para o qual desejamos determinar a sua rea Como podemos concluir por uma inspeo da figura, no existe uma frmula pronta para calcular sua rea. Precisamos dividir a figura em partes para as quais conheamos uma maneira de calcular a rea e que, alm disso, conheamos as dimenses necessrias.

3 0 Podemos fazer vrias tentativas, como por exemplo, as ilustradas nas figuras Fig. 4.2 a, Fig. 4.2 b e Fig. 4.2 c.

a b c Figura 4.2 Possveis subdivises do polgono apresentado na Figura 4.1.

Podemos tentar descrever a rea das figuras menores em cada uma das figuras apresentadas. Nas figuras 4.2. b e 4.2 c, parece que precisaremos subdividir novamente. Em 4.2 b a casinha em verde pode ser transformada em um retngulo e um tringulo. Em 4.2 c a casinha azul (meia-gua) que pode ser dividida em um retngulo e um tringulo, como na Figura 4.3. E a figura Fig. 4 a, que podemos dizer?

Figura 4.3 Subdiviso de uma sub-figura da Figura 4.3 c, Vamos partir para a nossa soluo a partir da figura Fig. 4.2 c. Podemos dizer que a rea total pode ser obtida pela soma das reas amarela, com rea vermelha e mais a rea azul. A rea azul pode ser subdividida em azul-claro e azul-escuro rea total rea azul = = rea amarela + rea vermelha + rea azul rea azulclaro + rea azulescuro

Quando escolhemos as reas acima citadas, no foi por acaso. A escolha foi baseada na simplicidade do subproblema. Podemos usar este conhecimento para chegar a um outro. Trs das reas que precisamos calcular so de forma

3 1 retangular. Ou seja, so especializaes de um conceito mais geral. A quarta rea, tambm pode ser obtida pela especializao do conceito de tringulo retngulo. Vamos agora aproximar nossas definies da linguagem de programao. Portanto podemos escrever:

a_retangulo x y = x * y
O

tringulo que temos retngulo e podemos descrever sua rea por:

a_t_retangulo x y = (x * y) / 2.0
A determinao da rea vermelha nos traz uma pequena dificuldade, no nos foi informado qual o comprimento da base do retngulo. E agora? Observando bem a figura podemos concluir que a base do retngulo igual hipotenusa do tringulo retngulo de catetos a e d. Podemos escrever ento: atotal a b c d e a_azul x y z hipo x y a_retangulo x y a_t_retangulo x y = = = = = a_retangulo a b + a_retangulo (hipo a d) e + a_azul a c d a_retangulo y z + a_t_retangulo x y sqrt ( x * x + y * y) x*y (x * y) / 2.0

A estrutura da soluo de um problema obtida pela modularizao pode ser representada por um diagrama denominado de rvore. Para o problema acima discutido a rvore da forma apresentada na Figura 4.5.

3 2

Figura 4.5 Representao em rvore da estrutura modular do problema clculo da rea do polgono irregular apresentado na Figura 4.1. 4.7. UM EXEMPLO DETALHADO : Escreva uma descrio funcional para o volume de cada uma das peas apresentadas nas Fguras 4.6 e 4.7.

Figura 4.6 Pea no. 1

Figuras 4.7 Pea no. 2

Soluo 1: Vamos comear pela Figura 4.6. Uma rpida anlise nos leva a identificar duas partes. Na parte inferior temos um paraleleppedo, sobre o qual se assenta um cilindro. Vamos supor que so macios. Chamemos de a, b e c as dimenses do paraleleppedo, de r o raio da base do cilindro e de h a sua altura. O volume total da pea pode ser determinado pela soma do volume das duas peas menores. Chamemos a funo de volfig46, e tentemos uma definio. volfig46 a b c r h = (a * b * c) + (3.1416 * r * r * h)

3 3 Vamos ento tratar da pea descrita na figura 4.7. Agora identificamos uma pea apenas. Um paraleleppedo com um furo no centro. Chamemos de a, b e c as dimenses do paraleleppedo, de r o raio do buraco. Para descrever o volume da pea devemos subtrair do volume do paraleleppedo o volume correspondente ao buraco. Chamemos a funo de volfig47, e tentemos uma definio. Volfig47 a b c r = (a * b * c) - (3.1416 * r * r * c) Soluo 2: A soluo 1, apesar de resolver o problema, deixa de contemplar algumas prticas importantes. No tratamento da primeira pea (Figura 4.6), apesar de identificadas duas peas menores, estas abstraes no foram descritas separadamente. Ou seja, deixamos de registrar formalmente a existncia de duas abstraes e com isso no pudemos modularizar a descrio da funo principal. Podemos tentar ento um outro caminho, contemplando as abstraes para o cilindro e para o paraleleppedo: volcil r h volpar a b c Volfig46 a b c r h = 3.1416 * r * r * h =a*b*c = volpar a b c + volcil r h

Voltemos ento para a segunda pea (Figura 4.7), e vejamos se podemos identificar similaridades. Aqui s temos uma pea, que como sabemos, guarda uma relao com o paraleleppedo da primeira e s. Como podemos encontrar similaridades? Aprofundando melhor nossa anlise podemos lembrar que o furo no paraleleppedo, na verdade corresponde a um cilindro que foi retirado. Assim considerando, podemos ento concluir que o volume da figura 4.7 pode ser obtido pela diferena entre o volume de um paraleleppedo e de um cilindro. Como j temos as definies para volume de cilindro e volume de paraleleppedo, s nos resta escrever a definio final do volume da figura 4.7: volfig47 a b c r = volpar a b c - volcil r c Analisando a soluo, podemos tirar algumas concluses: a) a soluo ficou mais clara, b) a soluo propiciou o reaproveitamento de definies. c) se precisarmos usar volume de cilindro e de paraleleppedo isoladamente ou em outras combinaes, j as temos disponveis. Consideraes complementares - assim como decidimos descrever isoladamente o volume de dois slidos, poderamos ter feito o mesmo para as figuras. As descries das reas de um retngulo e de uma circunferncia podem ser dadas isoladamente por: acir r = pi * r * r

3 4 aret a b = a * b Podemos reescrever o volume do cilindro e do paraleleppedo da seguinte maneira: volcil r h = acir r * h volpar a b c = aret a b * c Soluo 3: Se aprofundarmos a anlise podemos observar que as duas figuras podem ser abstradas como uma s! O cilindro que aparece na primeira, como um volume que deve ser acrescentado pode ser entendido como o mesmo cilindro que deve ser subtrado na segunda. Alm disso, podemos estender a soluo para furos que no vazem a pea, pois a altura do cilindro pode ser qualquer. volfig a b c r h = volpar a b c + volcil r h Podemos observar que esta a mesma definio apresentada anteriormente para a figura 4.6. O que muda o uso. Para calcular o volume da Figura 4.6 usamos um h positivo e para Figura 4.7 um h negativo. > volfig 6.0 8.0 2.0 2.0 5.0 158.832 > volfig 6.0 8.0 2.0 2.0 (-2.0) 70.8673 -- determinar o volume de uma instncia da figura Fig. 1, com um cilindro de raio 2 e altura 5. -- determinar o volume de uma instncia da figura Fig. 2, vasada por um furo de raio 2. -- neste caso fornecemos um valor negativo para a altura do cilindro com o mesmo valor da altura do paraleleppedo -- determinar o volume de uma instncia da figura Fig. 2, que tem um furo de raio 2 e profundidade 1.

> volfig 6.0 8.0 2.0 2.0 (-1.0) 83.4336 Exerccios: 1) 2) 3) 4) 5) 6)

Discuta o significado da expresso volfig 6.0 8.0 2.0 2.0 (-5.0). O que poderia ser feito para contornar este efeito indesejvel? Resolva o problema da Figura 4.1 usando a modularizao sugerida pela figura 4.2 b. Redesenhe a Figura 4.5 (rvore de modularizao) para a soluo apresentada ao exerccio 2. Apresente 3 problemas similares para calculo de rea de polgono irregular. Apresente 3 problemas similares para calculo de volume de objetos. Apresente 3 problemas similares em outros domnios de conhecimento.

3 5 5. Tipos de Dados Numricos 5.1. INTRODUO: Denominamos de Tipo de Dado a um conjunto de valores, munido de um conjunto de operaes sobre esses valores. Por exemplo, podemos denominar de T1 ao tipo de dados formado por um conjunto S de valores idntico aos nmeros naturais ( S = {0,1,2,3, ...]) e munido das operaes de adio ( a) e multiplicao (m). Cada operao possui uma tipo, indicando o domnio e o contradomnio. Por exemplo, para o tipo T1, o domnio de a S X S e o contradomnio S. A notao a seguir usualmente utilizada e em geral denominada de a assinatura da operao. a :: S X S S m :: S X S S Como visto no captulo 2, em Haskell escreveramos: a :: S S S m :: S S S Em Haskell, conhecendo-se o tipo dos valores de uma expresso podemos determinar o tipo do valor que dela resultar, ou seja, o seu contra-domnio. Em linguagens de programao isto equivale a dizer que a linguagem fortemente tipada. Dizemos ainda que os tipos so elementares ou estruturados. Os numricos so elementares, assim como tambm o so os tipos lgico e os caracteres. Neste captulo trataremos dos tipos numricos, os demais viro em captulos posteriores. Os nmeros formam um tipo de dados fundamental na computao. Aqui nos interessa subdividi-los em inteiros e reais. Antes de irmos alm, importante que se saiba que, sendo o computador composto de elementos finitos, algumas adaptaes e simplificaes precisam ser feitas para o tratamento de nmeros. Em HUGS, quando estamos submetendo expresses para avaliao, podemos desejar que o tipo do resultado seja exibido. Para que isso ocorra, podemos dar um comando ao HUGS. Para obtermos este comportamento do ambiente, podemos usar o comando :set, que ativa ou desativa parmetros do ambiente. Para ativiar um parmetro usamos uma letra correspondente ao parmetro, precedido do smbolo +. Para desativar usamos o smbolos -. Para saber sobre outros parametros, experimente submeter apenas o comando :set. A sequencia de interaes a seguir ilustra a ativao e desativao da exibio do tipo dos resultados. > :set +t > 2^20 1048576 :: Integer

3 6 > :set -t > 2^100 1267650600228229401496703205376

5.2. NMEROS INTEIROS: Para trabalhar com nmeros inteiros, a lingugem Haskell prov o tipo Integer, que pode produzir nmeros que podem ter uma quantidade ilimitada de algarismos, entretanto, como a memria do computador finita, qualquer que seja a mquina real que estivermos usando, inevitavelmente esbarraremos em limites. Na ilustrao a seguir podemos observar essa flexibilidade, quando obtemos o valor para a expresso 21000, um nmero de 302 algarismos. Claro, o limite pode estar bem longe e podemos no atingi-lo em nossas aplicaes. > 2^1000 107150860718626732094842504906000181056140481170553360744375038837 035105112493612249319837881569585812759467291755314682518714528569 231404359845775746985748039345677748242309854210746050623711418779 541821530464749835819412673987675591655439460770629145711964776865 42167660429831652624386837205668069376 Experimente com nmeros maiores! Por exemplo, 9999 9999 um nmero que tem por volta de 40 mil algarismos. provida ainda uma representao de inteiros mais restrita, denominada Int. Esta verso trabalha com um intervalo de valores fixo e reduzido e tem como vantagem economizar memria do computador e tempo de processamento, usando caractersticas especficas do computador. Para que um nmero seja representado nesta verso, devemos indicar explicitamente, como no exemplo a seguir. > 1234567890::Int 1234567890 :: Int > 12345678901::Int Program error: arithmetic overflow O exemplo a seguir ilustra a diferena entres as duas possibilidades. > 1089979879870979879 1089979879870979879 :: Integer > 1089979879870979879::Int Program error: arithmetic overflow

3 7 O conjunto de operaes associadas ao domnio pode variar, entretanto, em geral so fornecidas as seguintes operaes primitivas: Nome + * div ^ Adio Multiplicao Subtrao diviso inteira Potncia descreve o resto da diviso inteira entre dois inteiros Descrio Exemplos > 13 + 15 + 21 + 24 + 27 + 31 131 :: Integer > 20 * 10 * 98 19600 :: Integer > 1234 - 4321 -3087 :: Integer > div 12834 10 1283 :: Integer > 2^20 1048576 :: Integer > rem 12834 10 4 :: Integer > rem (12834 10) -4 :: Integer > mod 12834 10 4 :: Integer > mod (-12834) 10 6 :: Integer > abs 123 123 :: Integer > abs (-123) 123 :: Integer > signum (-3888876527829798) -1 :: Integer > signum 0 0 :: Integer > signum 3 1 :: Integer

rem

mod

Descreve o mdulo da diviso inteira entre dois inteiros

abs

valor absoluto

signum

produz -1, 0 ou 1, indicando quando o nmero negativo, zero ou positivo

Algumas observaes so importantes: a) As operaes podem ser combinadas para construir expresses mais complexas; > 5 + 12 * 3 41 :: Integer b) As operaes possuem precedncia, ou seja, existe uma ordem em que devem ser consideradas. No exemplo anterior, a multiplicao (*)

3 8 tem precedncia sobre a adio (+) e portanto realizada antes da adio. Esta precedncia pode ser modificada pelo uso de parntesis. > (5 + 12) * 3 51 :: Integer c) A operao div (diviso) parcial, ou seja, no se aplica quando o denominador nulo. Quando submetemos uma expresso com esta caracterstica, o HUGS no avalia a expreso e sinaliza que h um erro. > div 398 0 Program error: divide by zero

5.3. NMEROS REAIS: A denominao em Haskell para a adequao dos reais aos computadores, denominada de Float. Para este tipo no falaremos de uma lista de constantes. Ao invs disso falaremos aqui em magnitude e preciso de um nmero. Como na notao cientfica. A preciso nos diz quantos algarismos significativos so usados e a magnitude nos diz qual o maior expoente admitido. Por exemplo, uma determinada implementao pode utilizar 6 algarismos significativos. Nesta, o nmero 123456.789 seria representado pelo nmero 123457.0, onde o 6 foi arredondado para 7. A magnitude permite que nmeros bem pequenos e bem grandes sejam representados. Por exemplo, um nmero muito grande como 99999999999999999999999999999.0 poderia ser representado por 1.0e+29 e um nmero bem pequeno como 0.00000000009999999999999999999999999999, poderia ser representado por 1.0e-010. > 0.1234567890123456789012345678901234567890 0.123456789012346 :: Double A representao cientfica utilizada quando necessrio: > 1234567890123456789012345678.9 1.23456789012346e+027 :: Double A implementao denominada Double. Se uma quantidade menor explicitar que o nmero Float. corrente usa por default um verso estendida desejarmos, podemos representar os nmeros usando de algarismos significativos, para isso precisamos considerado deve ser representado na modalidade

> 0.1234567890123456789012345678901234567890::Float 0.1234568 :: Float

3 9 O conjunto de operaes aqui tambm pode variar, entretanto, em geral as listadas no quadro abaixo so providas. Nome pi + * / ^ sin cos tan sqrt log exp Descrio a constante 3.14159... Exemplos

> pi 3.14159265358979 :: Double > 2.5 + 3.3216 + 0.389458 Adio 6.211058 :: Double > 3.2 * 1.23 * 0.208 Multiplicao 0.818688 :: Double > 3.456789 - 1.344499089877 Subtrao 2.112289910123 :: Double > 9.345988 / 234569.34 Diviso 3.98431781408431e-005 :: Double potncia (o expoente tem que ser Int > 1.5324^10 e positivo) 71.4038177956654 :: Double > sin pi Seno 1.22460635382238e-016 :: Doubl > cos pi Coseno -1.0 :: Double > tan ( pi / 4.0) Tangente 1.0 :: Double > sqrt 8.5 raiz quadrada 2.91547594742265 :: Double > log 2.71828182845905 logaritmo na base e 1.0 :: Double > exp 1.0 potncia na base e 2.71828182845905 :: Double

Da mesma forma como ocorre nos nmeros inteiros, nos reais tambm podemos combinar operaes para construir operaes mais complexas. Tambm vale para os reais a precedncia de operadores, como nos inteiros podemos usar parntesis para controlar a ordem em que as operaes sero realizadas. 5.4. CONVERSO DE TIPOS: Em Haskell os inteiros so tratados como um subconjunto dos reais. Assim, quando temos nmeros reais misturados com nmeros inteiros em uma mesma expresso, os nmeros inteiros so automaticamente tratados como reais. >3+5 8 :: Integer > 3 + 5.0

4 0 8.0 :: Double Existem funes especficas para converso de tipos: a) a funo truncate converte um real x para o menor inteiro menor ou igual x. > truncate pi 3 :: Integer b) a funo round converte um real x para o inteiro mais prximo de x, ou seja: round x = truncate (x + 0.5) > round pi 3 :: Integer > round (exp 1) 3 :: Integer

5.5. PRECEDNCIA DOS OPERADORES: Quando aparecem vrios operadores juntos na mesma expresso, certas regras de precedncia so estabelecidas para resolver possveis ambigidades. A ordem em que os operadores so considerados a seguinte: 1) div, mod, abs, sqrt e qualquer outra funo 2) ^ 3) * / 4) +, Da mesma forma que na matemtica usual podemos usar os parntesis para forar uma ordem diferente de avaliao. Exemplos: >2+3*5 17 comentrio: o operador * tem precedncia sobre o operador +. Podemos escrever a expresso a seguir para denotar a seqncia de avaliaes: 2 + 3 * 5 2 + 15 17

4 1 > (2 + 3) * 5 25 comentrio: a ordem de avaliao foi alterada pelo uso dos parntesis. A seqncia de avaliao portanto: (2 + 3) * 5 5 * 5 25 > 3 * mod 10 4 + 5 11 comentrio: a primeira prioridade para avaliao do operador mod, seguida da avaliao do operador * e finalmente do operador +. Podemos escrever a seguinte seqncia de avaliao: 3 * mod 10 4 + 5 3 * 2 + 5 6 + 5 11 > 3 ^ mod 10 4 9 comentrio : A primeira avaliao do operador mod e em seguida avaliado o operador ^. A seqncia de avaliao : 3 ^ mod 10 4 3 ^ 2 9

> 4 ^ mod (div 20 4) 2 4 comentrio: A seqncia de avaliao : 4 ^ mod (div 20 4) 2 4 ^ mod 5 2 4 ^ 1 1

5.6. ORDEM DE ASSOCIAO: Quando h ocorrncia de operadores de mesma precedncia leva-se em considerao a ordem de associao que pode ser direita ou esquerda. 1. O operador de subtrao faz associao esquerda, 5 - 4 - 2 = (5 - 4) - 2 e no 5 - ( 4 - 2) 2. J o operador de exponenciao faz associao direita,

4 2 3 ^ 4 ^ 5 = 3 ^ ( 4 ^ 5 ) e no ( 3 ^ 4 ) ^5

O uso adequado das noes de precedncia e associao serve tambm para escrevermos expresses com economia de parntesis. Observaes: 1. O operador unrio - deve ser sempre representado entre parnteses quando utilizado junto com outro operador. 1. (- x)^y ou - (x^y) e nunca -x^y ou x^-y. 2. A exponenciao quando repetida em uma expresso avaliada da direita para a esquerda. 1. 2^3^3 = 2^(3^3). 3. Os demais operadores, na situao acima, so avaliados da esquerda para a direita. 1. 2 - 3 - 5 = (2 - 3) - 5 2. 2 + 3 + 3 = (2 + 3) + 3 Exemplos: >3 - 7 - 2 -6 >3*7+4 25 > 3 * ( 7 + 4) 33 > 3 ^ ( 1 + 3) 81 5.6. TIPOS DE NOVAS DEFINIES: Ao definir novas funes, o fazemos tomando por base os tipos de dados existentes na linguagem. O corpo dessas definies tem por base a composio das operaes fornecidas por estes tipos bsicos. Assim, o tipo do dado resultante da avaliao de uma aplicao desta nova funo, pode ser antecipado por um analisador de tipos, antes mesmo de avaliar a expresso. Observe as duas definies a seguir: media x y = (x + y) / 2 media' x y = truncate ((x + y) / 2)o tipo de dado resultante pela aplicao de media real, uma vez que a operao / (diviso), s se aplica a nmeros reais.

4 3 Da mesma forma, o tipo resultante pela aplicao da funo media inteiro, dado que a ultima operao a ser realizada, a truncate, converte reais para inteiros. Podemos conferir isso nas submisses de avaliao a seguir: > media 3 4 3.5 :: Double 5.6. HIERARQUIA DE NMEROS: At agora dissemos que a linguagem Haskell trabalha com dois tipos numricos, os reais e os inteiros. Isto uma verdade irrefutvel. Ao avaliar uma expresso numrica o resultado ser sempre um nmero real ou um nmero inteiro. Entretanto, para facilitar a construo de um sistema de tipos adequado para a avaliao do tipo de uma expresso, antes mesmo que ela seja avaliada, tornou-se necessrio a criao de uma hierarquia de tipos, conforme mostraremos agora.

<<< falta completar a explicao>>>>> Ao definir novas funes, o fazemos tomando por base os tipos de dados existentes na linguagem. O corpo dessas definies tem por base a composio das operaes fornecidas por estes tipos bsicos. Assim > media' 3 4 3 :: Integer

4 4 > Exerccios Qual o tipo resultante da avaliao da definio: media' x y = div (x + y) 2 O que ocorre na avaliao de uma expresso que usa a definio: media' x y = div (x + y) 2.0

<<<< falta completar exerccios>>

4 5 6. EXPRESSES LGICAS E O TIPO BOOLEAN

6.1. INTRODUO: Uma caracterstica fundamental dos agentes racionais a capacidade de tomar decises adequadas considerando as condies apresentadas pelo contexto onde est imerso. Uma mquina que sabe apenas fazer contas, ou seja, manusear as operaes aritmticas, ter sua utilidade fortemente reduzida e, portanto no despertar tantos interesses prticos. Os computadores que temos hoje so passveis de serem programados para tomada de deciso, ou seja, possvel escolher entre 2 ou mais aes, qual a que se deseja aplicar em um determinado instante. Em nosso paradigma de programao precisamos de dois elementos fundamentais: um tipo de dados para representar a satisfao ou no de uma condio e um mecanismo que use essas condies na escolha de uma definio. Neste captulo discutiremos a natureza das proposies lgicas, sua aplicabilidade na resoluo de problemas e introduziremos um novo tipo de dados, denominado de boolean. Satisfazendo logo de sada a curiosidade do leitor lembramos que o nome uma homenagem a George Boole que estudou e formalizou as operaes com estes tipos de valores. 6.2. PROPOSIES LGICAS: Revirando o ba das coisas estudadas no ensino fundamental, por certo encontraremos s sentenas matemticas. Lembraremos ento que elas so afirmaes sobre entes matemticos, tais como os exemplos a seguir: 1. vinte e dois maior que cinco 2. dois mais trs igual a oito 3. todo nmero primo impar O conceito de proposio lgica mais geral, aplicando-se s mais diversas situaes do cotidiano, como nos exemplo a seguir: 1. Maria namorada de Pedro 2. Jos apaixonado por Maria 3. Hoje domingo Analisando o significado da informao contida em uma proposio lgica podemos concluir que ela ser uma afirmao verdica, quando se referir a fatos que realmente acontecem em um determinado mundo. Quando isso no ocorre, conclumos que elas so inverdicas. Obviamente que isto ir requerer que possamos ter acesso ao mundo considerado para podermos avaliar uma dada proposio. Sentenas Fechadas: as sentenas acima possuem uma caracterstica importante: todos os seus componentes esto devidamente explicitados. Denominamos estas sentenas de sentenas fechadas. Uma sentena fechada

4 6 pode ser avaliada imediatamente, conferindo o que elas afirmam com o mundo sobre o qual elas se referem. Sentenas Abertas: Um outro tipo de proposio importante so as sentenas abertas. Nestas, alguns personagens no esto devidamente explicitados e, portanto a sentena no pode ser avaliada. Quando tratamos sentenas abertas, antes necessrio instanci-las para algum valor. Por exemplo, a sentena matemtica, x + 5 > 10 nem sempre verdadeira, depende do valor que atribuirmos varivel x. Quando atribumos valores s variveis de uma sentena dizemos que estamos instanciando a sentena. No caso acima, podemos instanciar a sentena para os valores 3 e 10, entre outros, obtendo as seguintes instncias: 1. 3 + 5 > 10 2. 10 + 5 > 10 Agora podemos avali-las e concluir que a segunda verdica e a primeira no. O mesmo poderia ocorrer com afirmaes de outra natureza, como por exemplo:

Se substituirmos Um certo cidado por Bill Gates, podemos concluir que a sentena verdica. O mesmo no se pode concluir se a substituirmos pelo nome de inmeras pessoas que arrancam os cabelos todos os dias, prejudicados que ficam com o mau funcionamento do citado programa. Sentenas Compostas: O discurso do cotidiano e at o discurso matemtico, pode ser escrito como uma lista de proposies simples. Como por exemplo: 1. Hoje domingo 2. Aos domingos tem futebol 3. Quando meu time joga, eu assisto Nem sempre isto desejvel ou suficiente. Para resolver a questo, podemos contar com as sentenas compostas. Como por exemplo:: a) Trs menor que cinco e o quatro tambm.; b) Domingo irei ao futebol ou escreverei notas de aula; c) Esperanto no uma linguagem de programao. Observamos ento, o surgimento de trs palavras para criar essas sentenas e que essas palavras ( e, ou, no) no se referem a coisas, propriedades ou

4 7 fenmenos de um determinado universo. Elas so denominadas de palavras lgicas, visto que a sua funo na linguagem possibilitar a articulao entre as proposies do discurso. A composio de uma proposio pode envolver vrias palavras lgicas, como nos exemplos a seguir: 1. Dois menor que trs e maior que um mas no maior que a soma de trs com dois; 2. Maria gosta de Pedro e de Joana mas no gosta de Antonio. Avaliao de Sentenas Compostas: Para avaliar sentenas simples, vimos que bastava inspecionar o mundo ao qual ela se refere e verificar se a situao expressa pela sentena ocorre ou no. E como proceder para as sentenas compostas? Um caminho que parece confivel apoiar essa avaliao no papel representado por cada uma das palavras lgicas. Assim, quando ao considerarmos a proposio: Hoje fui ao cinema e ao teatro, s poderemos dizer que ela verdica se tanto a proposio Hoje fui ao cinema quanto a proposio Hoje fui ao teatro forem avaliadas como verdicas. Para a proposio composta Maria foi a missa ou ao cinema, devemos consider-la como verdica se uma das duas proposies: 1. Maria foi a missa 2. Maria foi ao cinema forem avaliadas como verdica. E se as duas forem avaliadas como verdicas? No discurso cotidiano tendemos a pensar nesta situao como inverdica visto que queramos uma ou outra. A linguagem natural no estabelece se devemos ou no explicitar que no estamos falando do caso em que ambas podem ser constatadas. Podemos assumir, portanto, que a nossa sentena composta usando ou ser avaliada como verdica quando pelo menos uma das duas proposies que a compe for avaliada com verdica. No caso da sentena composta usando a palavra lgica no, como em Hoje no choveu diremos que ela ser avaliada como verdica quando a proposio Hoje choveu no puder ser constatada e como inverdica no caso oposto.

4 8 6.3. O TIPO DE DADOS BOOLEAN: Podemos agora discutir sobre a natureza do valor resultante da avaliao de uma sentena. A avaliao de natureza funcional, ou seja, dada uma sentena s ela ser mapeada em um de dois valores distintos. Ento, o contradomnio de uma avaliao um conjunto com apenas dois valores, um para associar com avaliaes verdicas e outras com as inverdicas. Podemos escolher um nome para esses valores. Historicamente, as linguagens de programao os tem denominado de True e False. O primeiro para associar com as proposies que podem ser constatadas no mundo considerado e a segunda com as no constatveis. O tratamento das proposies compostas pode tambm receber um tratamento formal. Cada uma das palavras lgicas associamos uma funo matemtica cujo domnio e contradomnio ser o conjunto que acabamos de definir com as constantes True e False. aval :: <sentena> {True, False} Em Hugs nossos operadores so representados por:

Palavra lgica e ou no

Smbolo em Hugs && || not

Vamos ento formalizar a avaliao de sentenas compostas. Sejam s1 e s2 duas proposies lgicas, 1. O valor lgico da sentena s1 && s2 True se e somente se o valor lgico de s1 True e o valor lgico de s2 True e False em caso contrrio. 2. O valor lgico da sentena s1 || s2 False se e somente se o valor lgico de s1 False e o valor lgico de s2 False e True em caso contrrio. 3. O valor lgico da sentena not s1 True se e somente se o valor lgico de s1 False e False em caso contrrio

4 9

Tabela Verdade: Estas definies tambm podem ser representadas atravs de uma enumerao de suas associaes, formando o que se costuma chamar de Tabelas Verdade as quais apresentamos a seguir. s1 True True False False s2 s1 && s2 True True False False True False False False s1 True True False False s2 s1 || s2 True True False True True True False False

s1 not s1 True False False True

6.4. OPERADORES RELACIONAIS: Quando falamos de proposies lgicas no discurso matemtico, ou seja, sentenas matemticas, usamos termos tais como: menor do que, menor ou igual, diferente, entre outros. Estes termos so fundamentais para a nossa inteno de prover os computadores com a capacidade de deciso. Denominamos estes elementos de operadores relacionais, pois estabelecem uma relao de comparao entre valores de um mesmo domnio. O contradomnio deles do tipo Boolean. A tabela a seguir apresenta esses operadores, seus significados e exemplos de uso. significado operador == igualdade /= Diferena < Menor <= Menor ou igual > Maior >= Maior ou igual exemplo (2 + 3) == (8 3) 5 /= (4 * 2 -3) (2 + 3) < 6 (2 * 3) <= 6 (4 + 2) > (2 * 3) (8 3 * 2) >= (15 div 3) resultado True False True True False False

Podemos usar estes operadores para construir novas definies ou simplesmente, em uma sesso de Hugs para solicitar a avaliao de uma expresso, como apresentado nos exemplos a seguir.

5 0 > 5 > 4 True :: Bool > 4 /= (5 + 3) True :: Bool > (mod 5 2) == (rem 5 2) True :: Bool > (mod (-5) 2) == (rem (-5) 2) False :: Bool > (div 5 2) <= truncate(5.0 / 2.0) True :: Bool

6.5. EXPRESSES E DEFINIES: Agora que temos um novo tipo de dados, ou seja, um par composto de constantes e funes, podemos p-lo a nosso servio, escrevendo expresses, de forma to natural quanto aquela que usamos para escrever expresses aritmticas. Usando essas expresses podemos ento construir definies cujo tipo resultante seja booleano. Os ingredientes bsicos para construir essas expresses so os operadores relacionais. Expresses simples : Por exemplo, para construir uma definio que avalie se um nmero par, podemos usar a seguinte definio:

par x = (mod x 2) == 0 Vejamos alguns exemplos ilustrados abaixo:

> par 5 False > par 148 True > par 0 True > par (truncate ((5 + 2) / 2)) False

5 1 Outros exemplos de definies: Verificar se a mltiplo de b Verificar se a divisor de b Verificar se uma distncia d igual diagonal de um quadrado de lado a Verificar se um nmero um quadrado perfeito Verificar se dois nmeros a e b so termos consecutivos de uma P.A. de razo r multiplo a b = (mod a b) == 0 divisor a b = multiplo b a

diag d a = (a * sqrt 2.0) == d

quadp n = (sqrt n)^2 == n

spa a b r = (a + r) == b

Expresses compostas : Podemos usar agora os operadores lgicos para construir expresses compostas. Como nos exemplos a seguir: Verificar se 3 nmeros esto em ordem decrescente Verificar se um nmero x est no intervalo fechado definido por a e b ordc a b c = (a > b) && (b > c) pert x a b = (x >= a) && (x <= b) ou pert x a b = not ((x < a) || (x > b))

Verificar se um determinado ponto do pquad x y = (x > 0) && (y > 0) espao cartesiano est no primeiro quadrante Verificar se 3 nmeros a, b e c, so lados de um tringulo retngulo tret a b c = ((a^2 + b^2) = = c^2) || ((a^2 + c^2) = = b^2) || ((b^2 + c^2) = =a^2)

Quando nossas expresses possuem mais de um operador lgico devemos observar a precedncia de um sobre o outro. Por exemplo, na expresso: P || Q && R onde P, Q e R so expresses lgicas, o operador && ser avaliado primeiro pois tem precedncia sobre o ||, portanto a expresso ser avaliada para True se P for avaliado para True ou se a sub-expresso (Q && R) for avaliada para True.

5 2 Podemos modificar esta ordem utilizando parntesis como nas expresses aritmticas. A expresso acima poderia ser reescrita como: (P || Q) && R E agora, para que ela seja avaliada para verdadeira preciso que R seja avaliada para verdadeira. Vejamos mais um exemplo de definio: Verificar se x est fora do intervalo definido por fxab = ((x <=a) || (x >= b)) && (a <= b) a e b e a e b esto em ordem no decrescente Verificar se x menor que a ou se x maior g x a b = (x <=a) || (x >= b) && (a <= b) que b e a e b esto em ordem no decrescente

6.6. RESOLVENDO UM PROBLEMA: Desejamos verificar se um determinado ponto do espao cartesiano est dentro ou fora de um retngulo paralelo aos eixos, conhecidos o ponto, o canto superior esquerdo e o canto inferior direito do retngulo. Etapa 1 [Entendendo o problema] O ponto pode estar em qualquer quadrante? E o retngulo, pode estar em qualquer quadrante? Basta ter os dois cantos para definir o retngulo? Em que ordem sero informados os cantos? Como se descreve um canto? Um ponto que esteja sobre um dos lados, est dentro ou fora do retngulo? Vamos assumir ento as seguintes decises: discutiremos inicialmente apenas sobre pontos e retngulos localizados no primeiro quadrante. A ordem em que os dados sero informados ser: primeiro o ponto, depois o canto superior esquerdo e por ultimo o canto inferior direito. Para cada ponto sero informadas as duas coordenadas, primeiro a abscissa e depois a ordenada. Os pontos na borda so considerados pertencentes ao retngulo. Etapa 2 [Planejando a Soluo]: Conheo algum problema parecido? Posso decompor este problema em problemas mais simples? Sei resolver um problema mais geral em que este um caso particular? Bom, j nos envolvemos com o problema para verificar se um ponto estava num intervalo linear, este tambm se refere a intervalo. Verificar se um ponto pertence a uma regio qualquer do espao n-dimensional mais geral, se eu conhecesse uma definio para este problema geral, bastaria instanci-la. Ser que posso decompor o problema na verificao de dois espaos lineares, um definido pelos lados paralelos ao eixo das ordenadas e outro paralelo ao eixo das abscissas? Se afirmativo, como combino as duas solues?

5 3 Para que um ponto esteja dentro do retngulo necessrio que sua ordenada esteja entre as ordenadas dos dois cantos. Sabemos tambm que a abscissa precisa estar entre as abscissas dos dois cantos. Isso basta? Para combinar as solues percebemos que suficiente que as duas primeiras estejam satisfeitas. Etapa 3 [Construindo a Soluo] Construindo a soluo - Anteriormente j elaboramos a definio de pertinncia a um intervalo linear, vamos us-la aqui. pert x a b = (x>=a) && (x <= b) pertinncia linear pertinncia de pertsup x y x1 y1 x2 y2 = (pert x x1 x2) && (pert y y2 y1) superfcie E o teste, para que valores interessam testar? Etapa 4 [Analisando a Soluo]: Existem outras maneiras de resolver o problema? Esta soluo se aplica as outras dimenses?

Exerccios 1.

<<<< falta exerccios >>>

5 4 7. Definies Condicionais

7.1. INTRODUO: Sabemos de nosso conhecimento matemtico que algumas funes no so contnuas em um domnio e que, portanto, possuem vrias definies. Em muitos casos, o domnio D de uma funo est dividido em regies disjuntas que se complementam e, para cada uma dessas regies, existe uma expresso que define o seu mapeamento no contra-domnio. Podemos representar esta situao pela figura abaixo:

Exemplo 1 - Considere a funo que determina o valor da passagem area de um adulto, para um determinado trecho, por exemplo, Vitria-Manaus, considerando a sua idade. Pessoas com idade a partir de 60 anos possuem um desconto de 40% do valor. Considere ainda que a passagem para o trecho considerado custa R$ 600,00. Temos aqui duas formas de calcular o valor da passagem de uma pessoa, dividindo o domnio em dois subconjuntos. O dos adultos com menos de 60 e o dos demais. Podemos definir as duas funes: vpass1 = 600 vpass2 = vpass1 * 0.6 Para usar uma das definies, temos que explicitamente escolher a que se aplica ao nosso caso. Exemplo 2 - Considere a funo que associa com um determinado rendimento o Imposto de Renda a ser pago. At um determinado valor, o

5 5 contribuinte no paga imposto, e a partir de ento o rendimento dividido em faixas (intervalos), aos quais se aplicam diferentes taxas. Suponha a tabela hipottica abaixo.

Faixa inferior ou igual a 10.800 entre 10.801 e 20.000 entre 20.001 e 30.000 acima de 30.000

alquota 0 10 20 25

Desconto 0 1000 1500 1800

Para descrever as vrias definies e os correspondentes subdomnios, poderamos escrever separadamente cada definio, construindo portanto vrias funes, e deixar que o usurio escolha qual usar. Claro que isto traria muitos inconvenientes pois estaramos deixando uma escolha mecnica na mo do usurio, que alm de sobrecarreg-lo com tarefas desnecessrias, ainda estaria expondo-o ao erro por desateno. Mas vamos l construir as funes independentes. ir1 s = 0 ir2 s = s * 0.1 - 1000 ir3 s = s * 0.2 - 1500 ir4 s = s * 0.25 - 1800 Agora, para us-las, o usurio pega o seu salrio, olha a tabela e seleciona qual funo aplicar. A escolha de qual definio usar para uma dada situao, em si, um tipo de computao. Podemos descrever essa computao com expresses condicionais, vamos deixar que o computador escolha. Descrevemos cada subdomnio com a respectiva funo aplicvel e deixemos que ele escolha a definio a aplicar, dependendo do valor fornecido. Vejamos ento como isso pode ser feito nas sees subsequentes. 7.2. A ESTRUTURA IF: Uma expresso condicional construda com if possui a seguinte sintaxe: if <expresso lgica> then <expresso 1> else <expresso 2> onde:

5 6 Uma expresso descrevendo uma condio a ser satisfeita, envolvendo operadores relacionais e operadores lgicos. 1. Expresses descrevendo um valor a ser produzido como resposta entrada fornecida e, como a expresso total tem que ser de um nico tipo, as duas expresses devem ser do mesmo tipo. 2. Cada uma destas expresses pode ser inclusive uma outra condicional, dentro da qual pode haver outras e assim sucessivamente. 3. Quando a <expresso lgica> avaliada para True o valor resultante ser o que for obtido pela avaliao da <expresso 1> caso contrrio ser o obtido pela avaliao da <expresso 2>

<expresso lgica>

<expresso1> e <expresso2>

Para a funo que calcula o valor da passagem area podemos ento construir a seguinte definio: vpass x = if x < 60 then 600 else 360 rvore de deciso: Podemos representar as expresses condicionais atravs de uma notao grfica denominada de rvore de deciso. importante considerar que este tipo de representao uma ferramenta importantssima para estruturarmos a soluo de problemas que requerem expresses condicionais.

Exemplo 3 Definir a funo que determina o valor absoluto de um nmero. Sabemos que esta funo se define em dois subdomnios: subdomnio x<0 x >= 0 expresso -x x

5 7 Como s temos duas possibilidades, podemos codificar da seguinte maneira: absoluto x = if x < 0 then -x else x

Para concluir esta apresentao voltemos ao nosso exemplo 2 que definie a funo para calculo do Imposto de Renda. O domnio neste caso deve ser quebrado em quatro subdomnios e para cada um deles construiremos uma expresso. domnio s 10800 pert s 10801 20000 pert s 20001 30000 s > 30000 funo ir1 s ir2 s ir3 s ir4 s

Para codificar precisaremos ir quebrando sucessivamente o domnio da funo. Primeiro dividimos entre o primeiro intervalo e o resto, depois dividimos o resto entre o segundo intervalo e o resto e assim sucessivamente. A codificao final pode ser:

ir s = if s <= 10800 then ir1 else if pert s 10800 20000 then ir2 else if pert s 20001 30000 then ir3 else ir4 where ir1 = 0 ir2 = s * 0.1 - 1000 ir3 = s * 0.2 - 1500 ir4 = s * 0.25 - 1800 pert x a b = x>=a && x<=b

7.2.1 USANDO O IF EXEMPLO 1: Considere um mapeamento de valores numricos onde o domnio se divide em 4 regies, cada uma das quais possui diferentes formas de mapeamento. As regies so apresentadas na figura abaixo, numeradas da

5 8 esquerda para direita. Observe ainda que as extremidades so abertas. Considere ainda a seguinte tabela de associaes:

regio regio 1 regio 2 regio 3 regio 4

mapeamento desejado o dobro de x o sucessor de x o quadrado de x o simtrico do quadrado de x

Podemos analisar as regies atravs do seguinte diagrama:

X<0
True False

X < -15
True False

X > 10
True False

5 9 O que nos levar seguinte definio: f x = if x < 0 then if x then else else if x then else < 2 x < x (-15) * x + 1 10 ^2 (x ^ 2)

Exemplo 2: Dados 3 nmeros inteiros distintos, determinar o maior deles. Podemos explorar uma soluo da seguinte maneira. Considere um retngulo e divida-o horizontalmente em 2 partes, a parte de cima representa as situaes onde a > b e a de baixo aquelas onde b > a. Divida agora o retngulo verticalmente, em cada uma das regies anteriores surgiro 2 metades. Na de cima, representamos agora a relao entre a e c. Na de baixo, a relao entre b e c.

Explorando as relaes entre os Representando as relaes atravs de nmeros uma rvore de deciso Traduzindo a rvore de deciso para Hugs, chegamos seguinte definio: maior a b c = if a > b then if a > c then a else c else if b > c then b else c

6 0 7.3 DEFINIES PROTEGIDAS (guarded commands): A estrutura IF foi apresentada por primeiro por questes histricas, por tratar-se de uma forma pioneira de escrever definies condicionais. Entretanto, algumas vezes podemos lanar mo de estruturas mais simples e mais legveis. As definies protegidas, tambm conhecidas por guarded commands permitem que se escreva para uma mesma funo, vrias definies, cada uma delas protegida por uma expresso lgica.

<nome da funo> <parmetros> | <proteo 1> | <proteo 2> | <proteo 3> . . . | <proteo n> [ | otherwise

= <definio 1> = <definio 2> = <definio 3> = <definio n> = <definio n + 1> ]

A ltima clausula da definio opcional, por este motivo est apresentada dentro de colchetes. Vejamos como podemos reescrever a definio da nossa funo ir para clculo do imposto de renda.

ir' s | s<=10800 = ir1 | pert s 10800 20000 = ir2 | pert s 20001 30000 = ir3 |otherwise = ir4 where ir1 = 0 ir2 = s * 0.1 - 1000 ir3 = s * 0.2 - 1500 ir4 = s * 0.25 - 1800

Exerccios 1. Reescreva, usando definies protegidas. a definio da funo que determina o maior de 3 nmeros inteiros fornecidos.

<<< completar exerccios >>>>

6 1

8. O TESTE DE PROGRAMAS 8.1. INTRODUO: No basta desenvolver um programa para resolver um dado problema. preciso garantir que a soluo esteja correta. Muitos erros podem ocorrer durante o desenvolvimento de um programa e, portanto temos que garantir que o programa que ir ser executado est livre de todos eles. Ao conceber a soluo podemos nos equivocar e escolher caminhos errados, precisamos eliminar esses equvocos. Ao codificarmos a nossa soluo podemos cometer outros erros ao no traduzirmos corretamente nossa inteno. Esses erros podem ocorrer por um mau entendimento dos elementos da linguagem ou at mesmo por descuido, o certo que eles ocorrem. Uma estratgia muito til, mas no infalvel, o teste de programa. Em sua essncia, o teste de programa consiste em submeter um programa ao exerccio de algumas instncias do problema e comparar os resultados esperados com os resultados obtidos. 8.2. O PROCESSO DE TESTE: Em primeiro lugar devemos escolher as instncias apropriadas, no basta escolh-las aleatoriamente. A seguir devemos determinar, sem o uso do programa, qual o valor que deveria resultar quando o programa for alimentado com essas instncias. O passo seguinte consiste em submeter cada instncia ao programa e anotar o resultado produzido por ele. Finalmente devemos comparar cada valor esperado com o valor produzido e descrever qual o tipo de ocorrncia. Um exemplo: Considere o problema de identificar se um dado ponto est ou no localizado no primeiro quadrante do espao cartesiano. Considere ainda que concebemos a seguinte definio:

primquad x y

(x >= 0) && (y >= 0)

Precisamos agora verificar se ela atende nossa inteno. Para tanto devemos escolher algumas instncias, prever o resultado esperado e em seguida submeter ao HUGS, para ver o que acontece. Que pares de valores deveremos escolher? Bom, vamos escolher uns pares usando a seguinte estratgia: um par onde x maior que y, outro onde y seja maior que x e um terceiro em que os dois sejam iguais. Gerando uma planilha como apresentada a seguir.

6 2 resultado resultado diagnstico esperado obtido -2 False -5 False 5 True y

x -5 -2 5

Podemos agora submeter as instncias avaliao do sistema, obtendo a seguinte interao: ? primquad (-5) (-2) False ? primquad (-2) (-5) False ? primquad 5 5 True ? Podemos agora completar o preenchimento de nossa planilha, obtendo a tabela a seguir:

resultado resultado diagnstico esperado obtido -5 -2 False False sucesso -2 -5 False False sucesso 5 5 True True sucesso x y Verificando as diversas linhas da coluna Diagnstico, parece que nosso programa est correto. Veja que ele passou com sucesso em todos os testes! Que pena que no seja verdade. Apesar de passar em todos os testes a que foi submetido, ele no funciona corretamente. Tudo que podemos afirmar neste instante que para os valores usados, o programa funciona corretamente. E para os outros valores, ser que funciona corretamente? Outros valores? Quais? 8.3. PLANO DE TESTE: Para escolher os valores que usaremos, antes de mais nada devemos identificar as classes de valores que sero relevantes para o teste, em um segundo instante podemos ento escolher os representantes destas classes. Quando temos um parmetro, os possveis valores a serem usados so todas as constantes do domnio. Para o caso de um parmetro do tipo int, existem 65536 valores diferentes. Testar nosso programa para todos esses valores implicaria em determinar a mesma quantidade de resultados esperados e em

6 3 seguida digitar e submeter esta mesma quantidade de instncias do problema para o sistema e ainda depois conferir um a um os resultado obtidos com os esperados. Enfim, um trabalho imenso. Imagine agora se fossem dois parmetros? A quantidade de pares seria da ordem de 4.29497 x 10^09 (algo da ordem de quatro bilhes). E para 3 parmetros? E para n parmetros? Nmeros cada vez mais enormes. Por este caminho, testar programas seria invivel. Felizmente no precisamos de todos eles, basta identificar as classes distintas que importam para o problema, ou seja, as classes de equivalncia relevantes. Isto pode ser obtido analisando o enunciado estendido do problema. No caso de nosso exemplo anterior, analisando melhor a definio, podemos identificar que por definio espao cartesiano se divide em quatro regies. A primeira, onde ambos as coordenadas so positivas, denominamos de primeiro quadrante. A segunda, onde a coordenada x negativa e a y positiva, denominamos de segundo quadrante. O terceiro quadrante o espao onde ambas as coordenadas so negativas. Ainda temos o quarto quadrante onde a coordenada x positiva e a y negativa. E os pontos que ficam em um dos eixos ou na interseo destes, qual a classificao que eles tm? Bom, podemos convencionar que no esto em nenhum dos 4 quadrantes descritos. Resumindo, nosso plano de teste deve contemplar estas situaes, conforme ilustra-se na tabela a seguir. x positivo negativo negativo negativo nulo qualquer no nulo nulo y quadrante positivo primeiro positivo segundo negativo terceiro positivo quarto qualquer eixo das ordenadas no nulo nulo nulo eixo das abscessos origem

bom observar ainda que este plano pode e deve ser preparado antes mesmo de elaborar o programa, para faz-lo, precisamos apenas da especificao detalhada. Alm disso, este plano no precisa ser feito pelo programador responsvel pela elaborao da soluo, qualquer outro programador, de posse do enunciado detalhado, pode se encarregar da tarefa. Este tipo de plano serve para alimentar o teste denominado de caixa preta. Esta denominao se deve ao fato de no ser necessrio conhecermos a estrutura da soluo para elaborar o plano. Um outro aspecto positivo da elaborao do plano o mais cedo possvel que contribu para um melhor entendimento do problema.

6 4 Voltando ao nosso exemplo, podemos agora elaborar a nossa planilha de teste considerando as classes de equivalncia a serem definidas. Uma questo que surge como escolhemos o representante de uma classe? Existem melhores e piores? No nosso caso, como pode ser qualquer valor positivo ou negativo, podemos escolher valores de um dgito apenas, no mnimo escreveremos e digitaremos menos. x 2 -2 -2 2 0 0 2 -2 0 y 3 3 -3 -3 3 -3 0 0 0 resultado esperado True False False False False False False False False resultado obtido diagnstico

8.4. REALIZANDO O TESTE: Vejamos agora o resultado de nossa interao com o HUGS. ? primquad 2 3 True ? primquad (-2) 3 False ? primquad (-2) (-3) False ? primquad 2 (-3) False ? primquad 0 (-3) False ? primquad 0 3 True ? primquad 0 (-3) False ? primquad 2 0 True ? primquad (-2) 0 False ? primquad 0 0 True ?

6 5 Voltemos agora para nossa planilha e vamos preench-la na coluna de resultado obtido e diagnstico. x 2 -2 -2 2 0 0 2 -2 0 resultado resultado esperado obtido 3 True True 3 False False -3 False False -3 False False 3 False True -3 False False 0 False True 0 False False 0 False True y diagnstico sucesso sucesso sucesso sucesso falha sucesso falha sucesso falha

8.5. Depurao: Uma vez testado o programa e identificado que ocorreram instncias para as quais a nossa definio no est fazendo a associao correta, ou seja, o valor obtido diferente do esperado, devemos passar a uma nova fase. Depurar um programa um processo que consiste em buscar uma explicao para os motivos da falha e posteriormente corrigi-la. Obviamente isto tambm no um processo determinante e nem possumos uma frmula mgica. Ao longo de nossa formao de programadores iremos aos poucos incorporando heursticas que facilitem esta tarefa. Por enquanto muito cedo para falarmos mais do assunto e vamos concluir com um fechamento do problema anterior. Aps concluir as modificaes devemos testar o programa novamente. Depurando nossa soluo - Podemos concluir por simples inspeo da nossa ltima planilha (aquela com todas as colunas preenchidas) que nossa soluo est incorreta. Uma interpretao dos resultados nos leva hiptese de que a nossa soluo considera que quando o ponto se localiza na origem ou em um dos eixos positivos, a nossa definio est considerando que eles esto no primeiro quadrante. Passo seguinte, verificar se de fato nossa definio incorre neste erro. Em caso afirmativo, corrigi-la e a seguir resubmet-la aos testes. Observando a nossa definio inicial, podemos concluir que de fato nossa hiptese se confirma. primquad x y = (x >= 0) && (y >= 0)

Podemos ento modific-la para obter uma nova definio, que esperamos que esteja correta.

6 6 primquad x y = (x > 0) && (y > 0)

Agora submet-la novamente ao teste e ver o que acontece! 8.6. UMA SNTESE DO PROCESSO: O processo , como vimos, repetitivo e s se encerra quando no identificarmos mais erros. O diagrama ilustra o processo como um todo. Mas lembre-se, isto ainda no garante que seu programa esteja 100% correto! Quando no identificamos erro, apenas podemos concluir que para as instncias que usamos o nosso programa apresenta os resultados esperados.

<<<Inserir exerccios>>>

6 7 9. RESOLVENDO PROBLEMAS - OS MOVIMENTOS DO CAVALO

9.1. INTRODUO: Considere o jogo de xadrez, onde peas so movimentadas em um tabuleiro dividido em 8 linhas e oito colunas. Considere ainda os movimentos do cavalo, a partir de uma dada posio, conforme diagrama a seguir, onde cada possvel movimento designado por mi. No esquema, o cavalo localizado na posio (5, 4) pode fazer oito movimentos, onde o primeiro deles, m1, levaria o cavalo para a posio (7,5). 8 m3 7 6 5 4 3 2 1 1 m3 m3 m3 m3 m4 C m5 m6 2 3 4 5 m7 6 7 8 m8 m3 m3 m2 m1 m3 M3

9.2. PROBLEMA 1: Escreva uma funo que determina se, a partir de uma dada posio, o cavalo pode ou no realizar o primeiro movimento. Vamos cham-la de pmov, e denominar seus parmetros (a posio corrente), de x e y. Eis alguns exemplos de uso de nossa funo e os valores esperados: instncia pmov 5 4 pmov 8 1 pmov 1 1 pmov 1 8 resultado True False True False

9.2.1. Soluo - A soluo pode ser encontrada atravs da construo de uma expresso booleana que avalie se a nova posio, ou seja, aquela em que o cavalo seria posicionado pelo primeiro movimento, est dentro do tabuleiro. Como o cavalo, no primeiro movimento, anda duas casas para direita e uma para cima, basta verificar se as coordenadas da nova posio no ultrapassam a oitava fileira (linha ou coluna). Codificando em HUGS, temos ento: pmov x y = (x + 2 <= 8 ) && (y + 1 <= 8)

6 8 9.2.2. TESTANDO A SOLUO - Como j discutimos anteriormente, para verificar a correo de nossa soluo, devemos submet-la a um teste. Para tanto devemos escolher as classes de equivalncias relevantes e, a partir delas, produzir a nossa planilha de teste. Olhando para a especificao do problema, podemos identificar 4 conjuntos de valores que se equivalem para os fins do nosso programa, como podemos observar na figura abaixo: 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8

9.2.3. Estendendo o Problema - Podemos fazer o mesmo para todos os demais movimentos, obtendo com isso as seguintes definies: pmov x y smov x y tmov x y qmov x y qtmov x y sxmov x y stmov x y omov x y = = = = = = = = (x + 2 <= 8 ) && (y + 1 <= 8) (x + 1 <= 8 ) && (y + 2 <= 8) (x - 1 >= 1 ) && (y + 2 <= 8) (x - 2 >= 1 ) && (y + 1 <= 8) (x - 2 >=1 ) && (y - 1 >= 1) (x - 1 >= 1 ) && (y - 2 >= 1) (x + 1 <= 8 ) && (y - 2 >= 1) (x + 2 <= 8 ) && (y - 1 >= 1)

9.2.4. Identificando Abstraes - Podemos agora indagar, olhando para as oito definies, sobre a ocorrncia de algum conceito geral que permeie todas elas. Poderamos tambm ter feito isso antes. Como no o fizemos, faamo-lo agora. Podemos observar que todas elas avaliam duas expresses e que ambas testam fronteiras que podem ser margem direita, margem esquerda, margem superior ou margem inferior. Podemos observar ainda, que o par margem direita e margem superior testam o mesmo valor 8, assim como ocorre com as duas outras, que testam o valor 1. Com isso podemos definir duas novas funes, f e g, para testar estes limites. Agora, as nossas definies anteriores podem ser reescritas, usando as duas abstraes identificadas. pmov x y smov x y tmov x y = = = f (x + 2 ) && f( y + 1) f (x + 1) && f (y + 2) g (x - 1) && f (y + 2)

6 9 qmov x y qtmov x y sxmov x y stmov x y omov x y fw gw = = = = = = = g (x - 2) && f (y + 1) g (x - 2) && g (y 1) g (x - 1) && g (y 2) f (x + 1 ) && g (y 2) f (x + 2) && g (y 1) w <= 8 w >= 1

9.2.5. Anlise da Soluo - O que ser que ganhamos com esta nova forma de descrever a nossa soluo? Podemos indicar pelo menos trs indcios de vantagem na nova soluo: 1. Clareza - Na medida em que agora est explicitado, que todas as oito funes para verificar os movimentos possuem estrutura semelhante e que todas esto usando funes para verificar a ultrapassagem das bordas; 2. Manuteno - Se nosso tabuleiro mudasse, ou seja, passasse a ter 9 linhas por nove colunas, bastaria alterar a funo f e tudo estaria modificado, ao invs de termos que alterar as oito definies. 3. Reuso - As duas funes que testam as bordas poderiam ser usadas para construir funes para avaliar o movimento de outras peas do jogo de xadrez. 9.3. PROBLEMA 2: Sabemos que para cada posio alguns movimentos podem ser realizados e outros no. Como ordenamos os movimentos no sentido antihorrio, gostaramos de obter, para uma dada posio, dos movimentos que podem ser realizados, aquele que possui o menor ndice. Vejamos o esquema abaixo.

8 m4 m1 m3 m3 C1 7 C3 m5 6 m5 m8 m6 5 m6 m7 4 3 m2 m3 2 m1 m4 1 C4 C2 1 2 3 4 5 6 7 8 Podemos observar que o cavalo C1 s pode fazer os movimentos m5 e m6 e que o de menor ndice m5. J o cavalo C2 s pode fazer os movimentos m3 e m4 e que o de menor ndice o m3. Enquanto isso o cavalo C3 pode fazer os

7 0 movimentos m1, m4, m5, m6, m7 e m8. Para este caso o movimento de menor ndice o m1. Vamos chamar esta funo de qualmov e, como no problema anterior, os parmetros sero as coordenadas da posio atual do cavalo. Eis alguns exemplos de uso de nossa funo:

Instncia qualmov 8 1 qualmov 8 8 qualmov 3 7 qualmov 1 1

resultado 3 5 1 1

9.3.1. SOLUO - Bem, como j sabemos, para verificar se um dado movimento mi possvel, basta arranjar um meio de sair verificando um-a-um os movimentos, a partir do primeiro (m1) e encontrar o primeiro que pode ser realizado. Quando isso ocorrer podemos fornecer como resposta o seu ndice. Podemos construir para isso uma rvore de deciso. Na raiz da rvore estar a pergunta " possvel realizar o movimento m1"? Em caso afirmativo (brao esquerdo da rvore), mapeamos no valor 1 e em caso negativo (brao direito), o que devemos fazer? Bom, a podemos comear uma nova rvore (na verdade uma sub-rvore), cuja raiz ser: " possvel realizar o movimento m2"? E da prosseguimos at que todos os movimentos hajam sido considerados. A rvore resultante ser:

7 1

9.3.2. CODIFICANDO A SOLUO - Vamos ento explorar os recursos da linguagem para transformar nosso plano em um programa que de fato possa ser "entendido" pelo nosso sistema de programao (HUGS). Como podemos observar temos aqui o caso de uma funo que no contnua para o domnio do problema. Pelo que sabemos at ento, no d para expressar a soluo como uma nica expresso simples. Resta-nos o recurso das expresses condicionais. Para verificar se um dado movimento satisfeito podemos usar as funes que construmos anteriormente e com isso obtemos a seguinte definio: qualmov x y = if pmov x y then 1 else if smov x y then 2 else if tmov x y then 3 else if qmov x y then 4 else if qtmov x y then 5 else if sxmov x y then 6 else if stmov x y then 7 else if omov x y then 8 else 0

9.3.3. ANLISE DA SOLUO - EM PRIMEIRO LUGAR, INCLUMOS A RESPOSTA IGUAL A ZERO (0) QUANDO O MOVIMENTO M8, O LTIMO A SER AVALIADO, RESULTA EM FRACASSO. PARA QUE SERVE ISSO? ACONTECE QUE SE A POSIO DE ENTRADA NO FOR VLIDA, OU SEJA, UMA OU AMBAS AS COORDENADAS NO PERTENCEREM AO INTERVALO [1, 8], NENHUM MOVIMENTO SERIA VLIDO E SE NO PROVIDENCIARMOS UMA RESPOSTA ALTERNATIVA, NOSSA FUNO SERIA PARCIAL. MAS ISTO RESOLVE DE FATO NOSSO PROBLEMA? O QUE OCORRERIA SE A POSIO DE ENTRADA FOSSE (0, 0)? BOM, NOSSA FUNO DETERMINARIA QUE O PRIMEIRO MOVIMENTO PODERIA SER REALIZADO E ISTO NO VERDADE. A INVENO DE UM RESULTADO EXTRA PARA INDICAR QUE NO H SOLUO POSSVEL, TRANSFORMANDO UMA

7 2 FUNO PARCIAL EM UMA FUNO TOTAL, PARECE SER BOA, MAS COMO FOI FEITA NO RESOLVEU. EM GERAL O MELHOR NESTAS SITUAES PRECEDER TODA E QUALQUER TENTATIVA DE DETERMINAR A SOLUO ADEQUADA, POR UMA AVALIAO DA VALIDADE DOS DADOS DE ENTRADA. NESTE CASO, BASTARIA VERIFICAR SE OS DOIS ESTO NO INTERVALO [1, 8]. VAMOS CONSTRUIR AQUI UMA FUNO QUE AVALIA A PERTINNCIA DE UM VALOR A UM INTERVALO NUMRICO, CONFORME DEFINIO A SEGUIR: pert x a b = (x >= a) && (x<=b)

Especulando um pouco mais sobre a nossa soluo, podemos observar que o movimento m8, jamais ocorrer! Analisando os possveis movimentos chegaremos concluso de que para nenhuma posio, o oitavo o nico movimento possvel. Sugerimos fortemente que o leitor prove este teorema. Portanto a soluo final pode ser: qualmov x y = if not (pert x 1 8) || not (pert y 1 8) then 0 else if pmov x y then 1 else if smov x y then 2 else if tmov x y then 3 else if qmov x y then 4 else if qtmov x y then 5 else if sxmov x y then 6 else 7

9.4. REVISITANDO O PROBLEMA 1: Observando a soluo encontrada para o problema 1, constatamos que embora a noo de movimento do cavalo seja nica, quem precisar saber se um dado movimento vlido, precisar conhecer o nome das oito funes. Embora seja cedo para falarmos de interface homemmquina, j d para dizer que estamos sobrecarregando nosso usurio ao darmos oito nomes para coisas to parecidas. Ser que temos como construir uma s funo para tratar o problema? Vamos reproduzir aqui a interface das oito: pmov x y smov x y tmov x y qmov x y qtmov x y sxmov x y stmov x y omov x y

7 3 Propositadamente escrevemos o nome delas com um pedao em vermelho e outro em preto. Seria alguma homenagem algum time que tem essas cores? Na verdade estamos interessados em destacar que a pequena diferena nos nomes sugere que temos uma mesma funo e que existe um parmetro oculto. Que tal explicit-lo? Podemos agora ter uma funo com 3 parmetros, sendo o primeiro deles para indicar o nmero do movimento que nos interessa. A interface agora seria: mov m x y Agora, por exemplo, para solicitar a avaliao do stimo movimento para um cavalo em (3, 4), escrevemos: ? mov 7 3 4 True ? Muito bem, e como codificaremos isso? 9.4.1. SOLUO - Precisamos encampar em nossa soluo o fato de que a nossa funo possui diferentes formas de avaliao, para diferentes valores do domnio, algo parecido com a soluo do problema 2, ou seja, a nossa funo no continua e portanto temos que selecionar qual a definio apropriada para um determinado valor de m. Devemos construir uma rvore de deciso. Aqui deixamos esta tarefa a cargo do leitor e passamos direto codificao conforme apresentamos a seguir: mov m x y = if not (pert m 1 8) False else if m == 1 then else if m == 2 then else if m == 3 then else if m == 4 then else if m == 5 then else if m == 6 then else if m == 7 then else omov where pmov = ... smov = ... tmov = ... ... then pmov smov tmov qmov qtmov sxmov stmov

9.4.2. Anlise da soluo - Ao contrrio da soluo do problema 2, onde necessariamente a validade dos movimentos tinha que ser verificada do primeiro

7 4 para o ltimo, pois nos interessava saber qual o primeiro possvel de ser realizado, o leitor pode observar que esta ordem aqui no necessria. Tanto faz se perguntamos primeiro se m=7 ou se m=3. Ser que podemos tirar algum proveito disso? Alertamos o iniciante, que devemos sempre identificar propriedades internas do problema e explor-las adequadamente. Qual a influncia desta ordem na eficincia da avaliao de uma expresso submetida ao HUGS? Para responder, basta lembrar que as condies so avaliadas seqencialmente. Por exemplo, se m=8, teremos que avaliar 8 condies, se m=1 faremos 2 avaliaes e se m est fora do domnio faremos uma avaliao. Ou seja, no pior caso faremos 8 avaliaes e no melhor caso uma (1). Em mdia, ao longo do uso da funo, assumindo uma distribuio uniforme dos valores de m, faremos 4 avaliaes. E se o intervalo fosse de 100 elementos distintos, quantas avaliaes de condies faramos em mdia? Ser possvel elaborar solues onde este nmero de avaliaes seja menor? A resposta sim! J que a ordem das avaliaes no importa, podemos buscar uma ordem mais conveniente para reduzir o nmero de avaliaes por cada instncia avaliada. A idia geral para estes casos obtida a partir de um conceito de vasta utilidade na Computao. Falamos de rvore binria e o leitor por certo ouvir falar muito dela ao longo da vida enquanto profissional da rea. O caminho consiste em dividir intervalo considerado ao meio e fazer a primeira pergunta, por exemplo, m<=4? Dividindo em 2 o intervalo de comparaes, para cada um destes podemos novamente dividir ao meio, at que no mais tenhamos o que dividir, como ilustramos no diagrama a seguir, onde cada linha representa um passo da diviso dos intervalos. <1 <1 <1 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 8 8 8 >8 >8 >8

Que tambm podemos representar por:

7 5

A codificao ficar ento:


mov m x y = if not (pert m 1 8) then False else if m <= 4 then if m<= 2 then if m== 1 then pmov else smov else if m==3 then tmov else qmov else if m<= 6 then if m==5 then qtmov else sxmov else if m == 7 then stmov else omov where pmov = ... smov = ... tmov = ... ...

Se fizermos uma anlise das possibilidades veremos que para qualquer valor de m o nmero mximo de avaliaes que faremos ser sempre igual a quatro! E se fosse 100 valores para m, qual seria o nmero mximo de comparaes? E para 1000? E 1000000? O nmero de comparaes, seguindo este esquema, aproximadamente igual ao logaritmo do nmero de valores na base 2. Portanto para 100 teramos 7, para 1000 teramos 10 e para um milho teramos 20. Veja que bem inferior ao que obtemos com o esquema anterior, tambm denominado de linear. Confira a comparao na tabela abaixo.

7 6 nmero de valores 8 100 1000 1000000 <<<<< inserir exerccios>>> esquema linear (nmero mdio) 8 50 500 500000 esquema binrio (nmero mximo) 4 7 10 20

7 7 10. TUPLAS 10.1. INTRODUO: At ento trabalhamos com valores elementares. Ou seja, valores atmicos, indivisveis a nvel das operaes de seu tipo de dados. Por exemplo, True, 523, 8.234, so valores elementares dos tipos Boolean, Integer e Float, respectivamente. No podemos, por exemplo, nos referir, dentro da linguagem, ao primeiro algarismo do valor 523. Dizemos que esses so tipos primitivos da linguagem. Alm desses trs, o Hugs prov ainda o tipo char. O elenco de tipos primitivos de uma linguagem pode ser entendido como o alicerce da linguagem para a descrio de valores mais complexos, que so denominados genericamente de valores estruturados. Os problemas que pretendemos resolver esto em universos mais ricos em abstraes do que esse das linguagens. Para descrever esses mundos, precisamos usar abstraes apropriadas para simplificar nosso discurso. Por exemplo, quando quero saber onde algum mora, eu pergunto: Qual o seu endereo? Quando quero saber quando um amigo nasceu, eu pergunto: Qual a data do seu nascimento? E quando quero saber para onde algum vai deslocar o cavalo no jogo de xadrez, eu pergunto: Qual a nova posio? Os nomes endereo, data e posio designam valores estruturados. Uma data tem trs partes: dia, ms e ano. Um endereo pode ter quatro: rua, nmero, complemento e bairro. J a posio no tabuleiro tem duas partes, linha e coluna. Para possibilitar a descrio de valores dessa natureza, o Hugs dispe de um construtor denominado tupla. Podemos definir uma tupla como um agregado de dados, que possui quantidade pr-estabelecida de componentes (dois ou mais), e onde cada componente da tupla pode ser de um tipo diferente (primitivo ou no). 10.2. DEFINIO DO CONCEITO: A representao de uma tupla feita com a seguinte sintaxe: (t1, t2, t3, ..., tn) Onde cada ti um termo da tupla. Se Ti o tipo de ti, ento o universo de uma tupla dado por: TT = T1 x T2 x ... x Tn Sabendo-se que os conjuntos bases dos tipos Ti so ordenados, tambm os elementos de TT o sero.

7 8 Exemplos de Tuplas: Inteno uma data uma posio no tabuleiro de xadrez uma pessoa um ponto no espao uma carta de baralho Representao (15, 05, 2000) (3, 8) ("Maria Aparecida", "solteira", (3, 02, 1970)) (3.0, 5.2, 34.5) (7, "espada") (True, 3) (False, div 5 2)

1 2 3 4 5 6 7

(x/=0 && y /= 0,
(x > y, if x*y /= 0
8
then if x > y then div x y else div y x else 0)

(x, y, x + y)

10.3. COMPONDO TUPLAS: Os exemplos apresentados j parecem suficientes para que tenhamos entendido como descrever um valor do tipo tupla. Vamos ento apenas comentar sobre os exemplos e ilustrar o uso de tuplas nas definies. Uma tupla um valor composto. Isto significa que devemos colocar entre parntesis e separados por vrgulas os componentes deste valor. Cada componente um valor, descrito diretamente ou atravs de expresses envolvendo operadores. Nos exemplos de 1 a 7, todos eles usam constantes. O exemplo 7 apresenta um dos valores descrito por uma expresso. No exemplo 3, um dos termos uma outra tupla. Qualquer termo pode ser uma tupla. Um valor pode tambm ser paramtrico, como no exemplo 9, onde temos uma tupla de 3 termos, todos eles paramtricos, mas o terceiro depende dos dois primeiros. Podemos dizer que esta tupla descreve todas as triplas onde o terceiro termo pode ser obtido pela soma dos dois primeiros. No exemplo 8 podemos observar o uso de expresses condicionais. Observa-se a tambm a descrio de um termo do tipo boolean, atravs de uma expresso relacional combinada com operadores lgicos. Vejamos agora alguns exemplos de uso de tuplas na descrio de valores. Exemplo 1: Desejamos definir uma funo, para que dados 2 valores, seja produzido uma tripla onde os dois primeiros termos so idnticos aos elementos fornecidos, em ordem inversa, e o terceiro termo seja igual soma dos dois.

7 9
triplaS a b = ( b, a, a + b )

Exemplo 2: Vamos definir uma funo que produza o quociente e o resto da diviso inteira de dois nmeros.
divInt a b = ( q, r) where q = div a b r = rem a b

Exemplo 3: Voltemos definio das razes de uma equao do 2o. grau. Vimos anteriormente que como eram duas, precisvamos definir tambm duas funes. Agora podemos agrup-las em uma nica definio:
re2g a b c = ( x1, x2) where x1 x2 e duploA

= ((-b) + e)/ duploA = ((-b) - e)/ duploA = sqrt (b^2 - 4.0*a*c) = 2.0 * a

8 0 Exemplo 4: Voltemos aos movimentos do cavalo no jogo de xadrez. Vamos definir uma funo que produza a nova posio, usando o primeiro movimento vlido segundo o que se discutiu em Resolvendo Problemas - Os Movimentos do Cavalo.
qPos x y = if f x2 && f y1 then (x2,y1) else if f x1 && f y2 then (x1,y2) else if g x1e && f y2 then (x1e,y2) else if g x2e && f y1 then (x2e,y1) else if g x2e && g y1e then (x2e,y1e) else if g x1e && g y2e then (x1e,y2e) else if f x1 && f y2e then (x1,y2e) else (0,0) where x1 = x + 1 x2 = x + 2 y1 = y + 1 y2 = y + 2 x1e = x - 1 x2e = x - 2 y1e = y - 1 y2e = y - 2 f w = w <= 8 g w = w >= 1

Qual o valor de qPos 1 9 ? O que h de errado? Reescreva qPos de forma a contornar o problema encontrado. 10.4. SELECIONANDO TERMOS DE UMA TUPLA: Assim com precisamos compor uma tupla na descrio dos mapeamentos de uma funo, tambm precisamos decomp-la. Quando uma funo possui tuplas como parmetros, para usar seus termos necessrio que se possa referenci-los.. Ilustraremos aqui vrias formas, utilizando a definio que soluciona o seguinte problema: Desejamos determinar a distncia entre dois pontos no plano. 1. Utilizando a clusula where :
dist p1 p2 = sqrt (dx^2 + dy^2) where dx = x1 - x2 dy = y1 - y2 (x1,y1) = p1 (x2,y2) = p2

8 1 Observe a elegncia da definio da tupla (x1, y1)! Por anlise da definio, sabemos que o tipo de p1 e p2 tupla de 2 termos. Quando submetemos a avaliao de uma instncia, o sistema casa p1 com um par de valores e a partir da pode determinar o valor de cada termo de nossa tupla (x1, y1).
? dist (0.0,0.0) (5.0,5.0) -- o sistema casa p1 com (0.0,0.0) -- e p2 com (5.0,5.0) -- logo x1=0.0, y1=0.0, x2=5.0 e y2=5.0 7.07107

2. Construindo funes seletoras :


prim (x,y) = x seg (x,y) = y dist p1 p2 = sqrt (dx^2 + dy^2) where dx = prim p1 - prim p2 dy = seg p1 - seg p2

Com esta abordagem, podemos generalizar e construir funes seletoras para tuplas com uma quantidade de termos qualquer. importante destacar que tuplas com quantidade diferente de termos precisam ter o seu prprio elenco de funes seletoras. Em particular, para o caso acima, onde o nmero de termos 2, o prprio HUGS j possui as funes seletoras, fst (primeiro) e snd (segundo). Poderamos t-las usado diretamente, mas preferimos ilustrar como se constri. Podemos reescrever a soluo usando-as.
dist p1 p2 = sqrt (dx^2 + dy^2) where dx = fst p1 - fst p2 dy = snd p1 - snd p2

3. Explicitando os componentes:
dist (x1,y1) (x2,y2) = sqrt (dx^2 + dy^2) where dx = x1 - x2 dy = y1 - y2

<<<<introduzir exerccios >>>>>

8 2 11. VALIDAO DE DADOS 11.1. INTRODUO: Como sabemos, toda funo tem um domnio e um contradomnio. Em Hugs, quando tentamos avaliar uma instncia de uma definio, usando valores fora desse domnio, podemos receber como resposta mensagens nem sempre esclarecedoras. Quando se trata do usurio de nosso programa, esta situao se mostra mais indesejvel ainda. Aqueles que constroem a definio podem discernir com mais facilidade a natureza dos problemas que ocorrem durante o seu desenvolvimento. O mesmo no se pode esperar de algum que no tem conhecimento dos elementos internos de nossas definies. Tipicamente os erros sero de duas naturezas. Pode ser que o tipo da instncia esteja correto mas nossa definio use alguma funo primitiva que no se aplica ao valor da instncia. Por exemplo, se temos a definio:
f x y z = div x y + z

e se a submetemos a uma instncia onde y = 0, teremos como resultado algo da seguinte natureza:
? f 5 0 3 Program error: {5 `div` 0} ?

Um outro tipo de problema ocorre quando o tipo de algum parmetro da nossa instncia no casa com o tipo inferido pelo Hugs. Por exemplo, se usamos um valor do tipo Float para y, obtemos:
? f 5 1.0 3 ERROR: Type error in application *** expression : *** term : *** type : *** does not match : ?

f 5 1.0 3 1.0 Float Int

Nesta seo trataremos do primeiro caso, deixando o segundo para outra oportunidade.

8 3 11.2. CARACTERIZANDO A SITUAO - Voltemos definio anteriormente apresentada:

f x y z = div x y + z

Neste caso, o tipo inferido pela linguagem para os dois primeiros parmetros o tipo Integer, visto que o operador div s se aplica a valores deste tipo. Portanto o universo ser formado por todos os possveis ternos de valores onde os dois primeiros so do tipo Integer e o ltimo, do tipo obtido pela unio dos tipos Float e Integer. Chamemo-lo de T. Entretanto, o domnio de nossa funo no exatamente o conjunto de constantes de T, posto que a funo no est definida para as constantes de T cujo segundo elemento nulo.

Desejamos construir uma funo que seja uma extenso da funo original e ao mesmo tempo lhe sirva como uma casca de proteo contra as violaes de domnio. Precisamos escolher um contradomnio da funo estendida (fx). Um candidato natural o contradomnio da funo original (f). E a imagem de nossa funo, o que podemos dizer dela? Ser que ela igual ao contradomnio? Ou ser que temos um subconjunto para o qual no exista um mapeamento? 11.3. CASO GERAL (IMAGEM IDNTICA AO CONTRADOMNIO): No caso geral, podemos encontrar duas situaes: ou o contradomnio idntico imagem, ou a determinao dos elementos que no pertencem imagem pode no ser fcil. Com isto no dispomos de valores no contradomnio que possam ser utilizados para mapearmos os valores que violam o domnio de f. Neste caso podemos estender o contradomnio (CD) de tal modo que o novo escolhido incorpore um valor que ser a imagem da extenso de f. Uma soluo geral bastante conveniente construir um novo contradomnio (NCD) para fx (extenso de f), formado por pares onde o primeiro elemento do tipo boolean e o segundo do contradomnio de f. Temos ento a seguinte estrutura:

8 4 NCD(fx) = (boolean, CD(f)) Para valores de x no domnio de f, teremos: fx x = (True, fx ) Para os valores de x fora do domnio teremos: fx x = (False, k ) onde k um valor qualquer pertencente ao contradomnio de f. Para o nosso exemplo inicial teramos ento:
fx x y z = if invalido x y z then (False,0) else (True, f x y z) where invalido x y z = ... f x y z = div x y + z

como se estivssemos criando uma casca protetora para a f. 11.4. FUNES QUE APRESENTAM PROBLEMAS EM VRIOS PARMETROS: Quando uma funo possui vrios parmetros, pode ocorrer que mais de um deles dem origem questo que aqui levantamos. Quando isso ocorre, pode ser relevante caracterizar a situao apropriadamente. Neste caso podemos usar um conjunto de constantes mais variado do que as constantes booleanas, permitindo que possamos associar com cada erro uma constante diferente. Podemos tomar como exemplo o problema do movimento dos cavalos no jogo de xadrez, especificamente a soluo genrica que produzimos com a funo mov m x y onde m o nmero do movimento, x a linha atual e y a coluna atual. Os trs parmetros so vlidos apenas para o intervalo [1, 8]. Portanto mov no est definida para os valores pertencentes ao subconjunto do universo formado por todas as triplas onde pelo menos um dos elementos no pertence ao intervalo [1, 8]. Por outro lado, o contradomnio conjunto booleano e portanto s possui 2 constantes, e ambas j esto comprometidas. Se quisermos distinguir os 3 tipos de violaes do domnio (movimento invlido, posio invlida, ambos invlidos) precisaremos usar um conjunto com pelo menos 4 constantes.

8 5 Podemos ento definir a funo movx da seguinte forma:


movx m x y = if not validom then if not validop then (3, False) else (1, False) else if not validop then (2, False) else (0, mov m x y)

11.5. CASO PARTICULAR (IMAGEM DIFERENTE DO CONTRADOMNIO): Suponha que existe pelo menos um elemento k que no pertence imagem, ou seja, a imagem est contida no contradomnio. Podemos construir uma extenso de f de tal forma que os elementos que no pertenam ao domnio sejam mapeados neste k e os demais sejam mapeados diretamente pela f . Quando existe tal k, nosso problema est resolvido. Basta que o usurio saiba que, quando a avaliao resultar em k, significa que a funo no se aplica para aquela instncia. Voltemos funo f introduzida anteriormente. Podemos, usando a proposta desta seo reescrever a sua definio, da seguinte forma:
fx x y z = if invalido x y z then k else f x y z where k = ... invalido x y z = ... f x y z = div x y + z

Infelizmente, para esse caso, o k no existe (prove!). Voltemos ao movimento do cavalo. Nesse caso, especificamente, porque o contradomnio original o conjunto booleano, poderamos ter tomado outro caminho. Poderamos usar nmeros negativos para indicar os 3 tipos de violao do domnio, o 0 para representar False e o 1 para representar True, eliminando com isso a necessidade de termos um novo domnio formado por pares. Vejamos como fica esta definio:
movx m x y = if not validom then if not validop then (-3) else (-1) else if not validop then (-2) else if mov m x y then 1 else 0

8 6 11.6. UM EXEMPLO - RAIZES DE UMA EQUAO DO 2O. GRAU: Voltemos ao problema de determinar as razes de uma equao do segundo grau. J sabemos que elas so duas e que podemos fazer uma nica funo para descrev-las, usando tupla. Sabemos ainda que o universo definido pelos tipos dos 3 parmetros (a, b, c), maior que o domnio da funo. Ou seja, a funo no est definida para instncias de a, b e c, onde se verifica a seguinte desigualdade:
(b ^ 2) + (4 * a * c) < 0

Precisamos, portanto de uma funo estendida.


re2gx a b c = (not (delta < 0), if delta < 0 then (0,0) else (x1, x2)) where delta = (b ^ 2) + (4 * a * c) x1 = ((-b) + sqrt delta) / (2 * a) x2 = ((-b) sqrt delta) / (2 * a)

Ou, de outra forma:


re2gx a b c = if delta < 0 then (False, (0, 0)) else (True, (x1, x2)) where delta = (b ^ 2) + (4 * a * c) x1 = ((-b) + sqrt delta) / (2 * a) x2 = ((-b) sqrt delta) / (2 * a)

11.7. Exerccios 1. Explique por que no existe o valor k que apie a definio da funo fx; 2. Jpojpoj 3. Pojpoj 4. Pojpoij

8 7 12. LISTAS 12.1. INTRODUO: A maioria dos itens de informao de nosso interesse esto agrupados, dando origem a um conceito muito importante para a resoluo de problemas, o agrupamento. Freqentemente estamos interessados em manipular esses agrupamentos para extrair informaes, definir novos itens ou avaliar propriedades desses agrupamentos. Tratamos anteriormente das tuplas, que so agrupamentos de tamanho predefinido e heterogneo, ou seja, cada elemento que participa do agrupamento pode ser de um tipo diferente. Agora estamos interessados em explorar um outro tipo de agregao, as listas. Este novo tipo, em HUGS, caracteriza-se por agregar quantidades variveis de elementos desde que todos eles sejam de um mesmo tipo. Vivemos cercados de listas. Elas esto em qualquer lugar onde precisamos registrar e processar dados. Vejamos alguns exemplos: 1. Lista de nmeros pares; 2. Lista dos livros lidos por uma pessoa; 3. Lista dos amigos que aniversariam em um dado ms; 4. Lista dos presidentes corruptos; 5. Lista dos vereadores decentes; 6. Lista das farmcias enganadoras; 7. Lista das disciplinas que j cursei; 8. Lista dos Lugares que visitei; 9. Lista dos nmeros feios; 10. Lista dos nmeros primos; 11. Lista das posies para as quais um cavalo pode se deslocar; 12. Lista das palavras de um texto; 13. Lista dos bug provocados pelo Windows; 14. Lista dos prmios Nobel ganhos pelo Bertrand Russel.; 15. Lista dos ttulos conquistados pelo Nacional Futebol Clube; 16. Listas dos funks compostos pelo Noel Rosa. Destas, algumas so vazias, outras so finitas e algumas infinitas. 12.2. CONCEITOS BSICOS: Uma lista uma seqncia de zero ou mais elementos de um mesmo tipo. Entende-se por seqncia uma quantidade qualquer de itens dispostos linearmente. Podemos representar uma lista pela enumerao dos seus elementos, separados por vrgulas e cercados por colchetes. [ e1, e2, .., en]

8 8 Por exemplo: 1. 2. 3. 4. 5. [] [1,3,5,7,9] ['a', 'e', 'i', 'o', 'u'] [(22,04,1500), (07,09,1822), (31,03,1964)] [[1,2,5,10], [1,11], [1,2,3,4,6,12], [1,13], [1,2,7,14], [1,3,5,15]]

importante ressaltar que em uma lista podemos falar do primeiro elemento, do quinto, do ensino, ou do ltimo. Ou seja, h uma correspondncia direta entre os nmeros naturais e a posio dos elementos de uma lista. Este ltimo fato nos lembra de um equvoco freqente, que queremos esclarecer de sada. A ordem que se adota em listas, por ser baseada nos nmeros naturais, comea do zero. Ou seja, o primeiro elemento de uma lista tem o nmero de ordem igual a zero. Por exemplo, na relao acima apresentada, a primeira lista vazia. Na lista do item 4 o elemento de ordem 1 a tupla (07, 09,1822) e na lista do item 5, o elemento de ordem zero (0) a lista [1,2,5,10]. Quanto ao tipo, podemos dizer que a segunda lista uma lista de nmeros, a terceira uma lista de caracteres, a quarta uma lista de triplas de nmeros e a quinta uma lista de listas de nmeros. Qual ser o tipo da primeira lista? Uma lista vazia de natureza polimrfica, isto , seu tipo depende do contexto em que seja utilizada, como veremos em momento oportuno. 12.3. FORMAS ALTERNATIVAS PARA DEFINIO DE LISTAS: Alm da forma bsica, acima apresentada, tambm conhecida como enumerao, onde explicitamos todos os elementos, dispomos ainda das seguintes maneiras: definio por intervalo, definio por progresso aritmtica e definio por compreenso. As duas primeiras formas apresentamos a seguir a terceira posteriormente. Definio por Intervalo De uma forma geral, podemos definir uma lista explicitando os limites inferior e superior de um conjunto conhecido, onde existe uma relao de ordem entre os elementos, no seguinte formato: [<limite inferior> .. <limite superior>]

8 9 Exemplos: abaixo listamos algumas submisses de listas definidas por intervalo e as correspondentes respostas do sistema HUGS.
1 Prelude> [1..5] [1,2,3,4,5] 2 Prelude> [-2..2] [-2,-1,0,1,2] 3 Prelude> [10..5] [] 4 Prelude> [-5.0..5.0] [-5.0,-4.0,-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0,4.0,5.0] 5 Prelude> [-1..-5] ERROR: Undefined variable "..-" 6 Prelude> [-1..(-5)] [] 7 Prelude> [1.6..10.0] [1.6,2.6,3.6,4.6,5.6,6.6,7.6,8.6,9.6] 8 Prelude> [1.5..10.0] [1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5]

Podemos observar aqui algumas aparentes surpresas: na definio 4 podemos observar que o HUGS considera sempre o intervalo de uma unidade entre os elementos da lista definida. Na definio 5, temos uma questo de ambigidade, 0 sinal de menos logo aps os dois pontos no entendido e o sistema sinaliza erro. A definio 6 contorna essa dificuldade. Deixo ao leitor buscar explicao para o que ocorre com as definies 7 e 8. Definio por Progresso Aritmtica Podemos definir qualquer progresso aritmtica por uma lista utilizando a seguinte notao: [<1o. termo>, <2o. termo> .. <limite superior>] Exemplos: observemos as definies a seguir e as respectivas respostas do sistema HUGS. Podemos perceber que dependendo do segundo termo da definio o sistema interpreta a P.A. como crescente ou decrescente.
1 Prelude> [1,2..6] [1,2,3,4,5,6] 2 Prelude> [-5,2..5] [-5,2] 3 Prelude> [-5,2..15] [-5,2,9] 4 Prelude> [-5,2..16] [-5,2,9,16] 5 Prelude> [1,1.1 .. 2] [1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0] 6 Prelude> [6,5..0] [6,5,4,3,2,1,0] 7 Prelude> [5,6..5]

9 0
[5] 8 Prelude> [3,7..1] []

12.4. OPERAES BSICAS : As listas, como j dissemos, so elementos da linguagem que podemos utilizar para descrever valores estruturados. Como nos demais tipos da linguagem, valores descritos por listas podem e devem ser usados na descrio de novos valores atravs da utilizao de operaes definidas sobre eles. A seguir so apresentadas algumas dessas operaes. elem : avalia se um determinado elemento membro de uma lista. elem <elemento> <lista> Exemplos:
Main> True Main> False Main> False Main> True elem 5 [-5..15] elem (-10) [-5..15] elem 20 [-5..15] elem 15 [-5..15]

length : descreve o tamanho de uma lista. length <lista> Exemplos:


Prelude>length [1..100] 100 (2528 reductions, 3442 cells) Prelude>length [1..100] + length [1..100] 200 (5050 reductions, 6873 cells) Prelude> a + a where a = length [1..100] 200 (2530 reductions, 3442 cells)

indexao : podemos descrever como um novo valor, cada termo de uma lista. Para tanto basta indicarmos a posio do elemento dentro da lista, considerando que o primeiro elemento tem a ordem zero. <lista>!!<ndice> Exemplos:

9 1
1 Prelude> [3,4,6,74,45]!!0 3 2 Prelude> [3,4,6,74,45]!!4 45 3 Prelude> [1,5..20]!!3 13 4 Prelude> [[[1],[2,3,4]]]!!0!!1!!2 4 5 Prelude> [3,4,6,74,45]!!3 74 6 Prelude> [3,4,6,74,45]!!3 + [2,3]!!0 76 7 Prelude> [3,4,6,74,45]!!(0+1) 4 8 Prelude> [3,4,6,74,45]!!(i+j) where i=3; j=0 74 9 Prelude> [84,76,23,124,763,23]!!([0,1,2,3]!!2) 23 10 Prelude> [1,5..20]!!5 Program error: Prelude.!!: index too large

concat : descreve uma nova lista obtida pela concatenao de uma lista de listas. concat <lista de listas> Exemplos:
1 Prelude>concat [[1..5],[1,10..100],[9]] [1,2,3,4,5,1,10,19,28,37,46,55,64,73,82,91,100,9] (473 reductions, 747 cells) 2 Prelude>concat [[1]] [1] (25 reductions, 35 cells) 3 Prelude> length (concat [[1..5],[1,10..100],[9]]) 18 (451 reductions, 638 cells) 4 Prelude> concat [[length [10,87..500]], [length [10,87,500]]] [7,3] (228 reductions, 309 cells) 5 Prelude> length (concat [[length [10,87..500]], [length [10,87,500]]]) 2 (30 reductions, 35 cells)

Pode tambm ser usado com a sintaxe infixada usando o operador ++ Exemplos:

9 2
1 Prelude> [1] ++ [1] [1,1] (33 reductions, 48 cells) 2 Prelude> [1] ++ [] [1] (23 reductions, 33 cells) 3 Prelude> [ ] ++ [ ] ERROR: Cannot find "show" function for: *** Expression : [] ++ [] *** Of type : [a] 4 Prelude> [1..5] ++ [1,10..100] ++ [9] [1,2,3,4,5,1,10,19,28,37,46,55,64,73,82,91,100,9] (467 reductions, 738 cells)

construtor : descreve uma nova lista onde o primeiro termo um dado elemento e os demais so os componentes de uma lista tambm dada.. <elemento> : <lista> Exemplos:
1 Prelude> 3: [4,5,6] [3,4,5,6] 2 Prelude> [3]:[[4,5,6]] [[3],[4,5,6]] 3 Prelude> [3: [4,5,6]] [[3,4,5,6]] 4 Prelude> [3: [4,5,6]]!!0 [3,4,5,6] 5 Prelude> [3: [4,5,6]]!!0!!3 6

head : descreve o primeiro elemento de uma lista.. tail : descreve uma sublista contendo todos os elementos, exceto o primeiro elemento de uma lista dada.

Teorema importante: head xs : (tail xs) = xs

last : descreve o ltimo elemento de uma lista.. init : descreve uma sublista contendo todos os elementos, exceto o ltimo elemento de uma lista dada.

9 3 Teorema importante:

init xs ++ [last xs] = xs Importante: As funes head, last, init e tail no possuem em seu domnio a
lista vazia. Portanto ela no deve ser instncia de avaliao para qualquer uma delas. <elemento> : <lista> Exemplos:
1 Hugs> head [1,2,3,4,5,6] 1 2 Hugs> tail [1,2,3,4,5,6] [2,3,4,5,6] 3 Hugs> tail [1,2,3,4,5,6] [2,3,4,5,6] 4 Hugs> last [1,2,3,4,5,6] 6 5 Hugs> init [1,2,3,4,5,6] [1,2,3,4,5] 6 Hugs> x == (head x : tail x) where x = [10..15] True 7 Hugs> init [10..15] ++ tail [10..15] [10,11,12,13,14,11,12,13,14,15]

12.5. DEFINIO POR COMPREENSO: Uma lista pode ser descrita atravs da enumerao de seus elementos, como j vimos atravs de vrios exemplos. Esta forma tambm denominada de definio por extenso, visto que todos os componentes precisam ser explicitados. Podemos tambm descrever listas atravs das condies que um elemento deve satisfazer para pertencer a ela. Em outras palavras, queremos descrever uma lista atravs de uma inteno. Esta forma anloga que j conhecemos para descrio de conjuntos. Por exemplo, usual escrever a notao abaixo para descrever o conjunto formado pelo quadrado dos nmeros naturais menores que 10. P = { quadrado de x | x natural e menor que 10} ou ainda mais formalmente, P = { x2 | x pertence a N e x <10} Podemos observar, no lado direito da definio, que ela formada por duas partes. A primeira uma expresso que descreve os elementos, usando para isso

9 4 termos variveis que satisfazem condies de pertinncia estabelecidas pela segunda parte. expresso varivel pertinncia x^2 x x pertence a N e x <10

Em nosso caso, no estamos interessados em descrever conjuntos e sim listas. E isso tem algumas implicaes prticas. Por exemplo, em um conjunto a ordem dos elementos irrelevante, para listas no. bom lembrar ainda que em uma lista, o mesmo valor pode ocorrer varias vezes, em diferentes posies. A sintaxe que usaremos a seguinte: [ <expresso> | <pertinncia> ] Onde: <expresso> - expresses usuais em Hugs para definio de valores, inclusive condicionais. <pertinncia> - descrio dos elementos a serem considerados para avaliao da <expresso> A pertinncia formada por uma seqncia de qualificadores de dois tipos de construes: os geradores e os predicativos. Os geradores descrevem uma lista de onde se originam os elementos a serem considerados, usando a sintaxe: <termo> <- <lista> Por exemplo, vejamos a descrio da lista dos quadrados dos nmeros menores que 5.
Prelude> [x^2| x<-[0..4]] [0,1,4,9,16]

Os predicativos so expresses descrevendo valores booleanos, envolvendo termos j definidos anteriormente (inclusive por geradores). Vejamos o exemplo a seguir, onde descrevemos uma sublista de nmeros mpares, tendo como origem de gerao uma lista definida por uma Progresso Aritmtica.
Prelude> [x | x<-[1,4..100],odd x] [1,7,13,19,25,31,37,43,49,55,61,67,73,79,85,91,97]

importante destacar que as expresses de pertinncia so avaliadas da esquerda para direita.

9 5 Por exemplo, se na expresso acima, primeiro colocssemos a expresso booleana "odd x", o sistema acusaria um erro, visto que ao tentar a avaliar "odd x", a varivel "x" ainda no estaria definida.
Prelude> [x | odd x, x<-[1,4..100]] ERROR: Undefined variable "x"

Isto s ocorre porque o sistema usa uma ordem pr-definida! Vejamos como usar este novo conceito na escrita de novos scripts. A seguir apresentamos a definio de trs novas funes. A primeira, slpares, define uma sublista formada pelos quadrados dos elementos pares de uma lista dada. A segunda, lmenor, define uma sublista formada pelos elementos de uma dada lista, que so menores que um elemento fornecido. A terceira, pmaioresk, ilustra o uso da clusula if-then-else para a gerao de elementos de uma lista.

-- Dada uma lista 'xs' defina uma sublista formada -- pelo quadrado dos elementos que so pares -slpares xs = [x^2 | x<- xs, even x] Main> :l preparalista.txt Reading file "preparalista.txt": Hugs session for: E:\HUGS98\lib\Prelude.hs preparalista.txt Main> slpares [1,4..50] [16,100,256,484,784,1156,1600,2116] Main> slpares [1156,144] [34,67,99,23,12,3,67,99]

--- Determinar a sublista de elementos menores que 'x' -- em uma lista 'xs -lmenor x xs = [ y | y <-xs, y < x] ... Main> lmenor 45 [1,5,6,86,34,76,12,34,86,99] [1,5,6,34,12,34] Main> lmenor 1 [1,5,6,86,34,76,12,34,86,99] []

9 6
Main> lmenor 100 [1,5,6,86,34,76,12,34,86,99] [1,5,6,86,34,76,12,34,86,99]

--- Determinar a lista de elementos gerados condicionalmente a uma -- constante dada k. pmenoresk k xs = [ if x > k then x2 else x + 2 | x <-xs] ... Main> pmenoresk 30 [1,5,6,86,34,76,12,34,86,99] [1,25,36,88,36,78,144,36,88,101]

Quando mais de um gerador utilizado, devemos levar em conta que para cada elemento do gerador mais a esquerda sero gerados todos os elementos dos geradores subseqentes. Vejamos o exemplo a seguir onde se descreve uma lista de pontos do plano cartesiano, localizados no primeiro quadrante e delimitado pelas ordenadas 3 e 5.
--- Determinar a lista dos pontos do plano dentro da -- regiao definida pela origem, a cordenada (eixo y) -- 5 e a abscissa (eixo x) 3. -pontos = [ (x,y) | x <- [0..3], y <- [0..5]] ... Main> pontos [(0,0),(0,1),(0,2),(0,3),(0,4),(0,5), (1,0),(1,1),(1,2),(1,3),(1,4),(1,5), (2,0),(2,1),(2,2),(2,3),(2,4),(2,5), (3,0),(3,1),(3,2),(3,3),(3,4),(3,5)]

Entre dois geradores podemos usar predicativos, como se observa no exemplo a seguir.

9 7
--- Determinar a lista dos pontos do plano dentro da -- regiao definida pela origem, a cordenada (eixo y) -- 5 e a abscissa (eixo x) 3. Considere apenas os -- pontos onde x impar e y par. -pontos1 = [ (x,y) | x <- [0..3], odd x, y <- [0..5], even y ] ... Main> pontos1 [(1,0),(1,2),(1,4),(3,0),(3,2),(3,4)]

12.6. DEFINIO POR COMPREENSO - EXPLORANDO DETALHES: Vamos explorar um problema onde exista mais riqueza de detalhes quanto ao uso de predicativos. Determinar os pares de valores, onde:

-------

o primeiro mltiplo do segundo; o primeiro dado pelos elementos impares de uma P.A de primeiro termo igual a 1, a razo igual 3 e o ultimo termo menor ou igual a 100; o segundo termo dado pelos elementos de uma P.A de primeiro termo igual a 1, a razo igual 4 e o ultimo termo menor ou igual a 50; um dos dois diferente da unidade; os dois termos so diferentes.

A funo paresE, traduz literalmente o enunciado. As P.A.'s so realizadas diretamente pelo mecanismo para definio de P.A. embutido na linguagem. Os predicativos foram inseridos na posio em que suas variveis j esto instanciadas. = [ (x,y) | x <- [1,4..100], odd x, y <- [1,5..50], (x/=1 || y/= 1), x/=y, mod x y == 0]

-paresE1

... Main> paresE1 [(7,1),(13,1),(19,1),(25,1),(25,5),(31,1),(37,1), (43,1),(49,1),(55,1),(55,5),(61,1),(67,1),(73,1), (79,1),(85,1), (85,5),(85,17),(91,1),(91,13),(97,1)]

Vejamos algumas observaes sobre a soluo acima apresentada:

8 o predicado odd poderia ser colocado em qualquer lugar mais a frente, entretanto o desempenho cairia, visto que iramos produzir valores desnecessrios para "y"; a expresso (x/=1 || y/= 1) desnecessria visto que s ser falsa quando ambos, x e y, forem iguais a 1, mas nesse caso eles sero iguais e portanto falsificariam a expresso a seguir x/=y; podemos reescrever a expresso x <- [1,4..100] de tal maneira que gere apenas valores impares e assim descartar a expresso odd x. Para tanto basta mudar a P.A. para [1,7..100]; pode-se observar que os valores de y que interessam so sempre menores que os de x ( j que y divisor de x). Portanto, a segunda P.A poderia ser substituda por [1,5..(x-1)]. Acontece que agora poderemos geram valores para y maiores que 50 e isto no interessa. O que fazer? Que tal substitula por: [1, 5..(if x < 50 then (x-1) else 50)]

Eis ento uma nova verso para nossa funo:


paresE2 = [ (x,y) | x <- [1,7..100], y <- [1,5..(if x < 50 then (x-1) else 50)], x/=y, mod x y == 0]

Podemos agora refletir sobre uma possvel generalizao para a nossa funo, considerando-se duas listas quaisquer. Neste caso, o esforo realizado para melhorar o desempenho seria em vo porque no conhecemos a priori a natureza das duas listas. Nossa funo poderia ser:
paresE3 xs ys = [ (x,y) | x <- xs, odd x, y <- ys, x/=y, mod x y == 0]

Apenas a expresso (x/=1 || y/= 1) poderia ser eliminada. O objetivo de nossa verso original poderia ser obtido pelo uso da nova funo aplicada s listas especficas. Conforme se observa a seguir:
Main> paresE3 [1,4..100] [1,5..50] [(7,1),(13,1),(19,1),(25,1),(25,5),(31,1),(37,1),(43,1), (49,1),(55,1),(55,5),(61,1),(67,1),(73,1),(79,1),(85,1), (85,5),(85,17),(91,1),(91,13),(97,1)] (16878 reductions, 23992 cells)

9 9 Agora podemos ainda inspecionar o que de fato acontece com o desempenho das trs verses.
Main> paresE1 [(7,1),(13,1),(19,1),(25,1),(25,5),(31,1),(37,1),(43,1), (49,1),(55,1),(55,5),(61,1),(67,1),(73,1),(79,1),(85,1), (85,5),(85,17),(91,1),(91,13),(97,1)] (22894 reductions, 32210 cells) Main> paresE2 [(7,1),(13,1),(19,1),(25,1),(25,5),(31,1),(37,1),(43,1), (49,1),(55,1),(55,5),(61,1),(67,1),(73,1),(79,1),(85,1), (85,5),(85,17),(91,1),(91,13),(97,1)] (15124 reductions, 22014 cells)

Coloquemos os valores obtidos em uma tabela. verso paresE1 paresE2 paresE3 redues clulas 22894 32210 15124 22014 16878 23992

Aqui podemos constatar que a verso paresE3, bastante similar a paresE1, a menos da generalizao, possui eficincia bem superior. Lembre-se que a nica diferena a eliminao da comparao dos dois termos com o valor 1. Para ver o que est acontecendo, vamos construir ainda uma outra verso, similar a paresE1, eliminando a comparao citada e descrevendo as P.A.'s fora dos geradores, assimilando-se assim verso paresE3. Veja que com isso a nova verso, que obtivemos partindo de paresE1, possui eficincia similar a paresE3. Confirma-se ento a observao de que a definio de listas dentro dos geradores produz perdas.
paresE4 = [ (x,y) | x <- xs, odd x, y <- ys, x/=y, mod x y == 0] where xs = [1,4..100] ys = [1,5..50]

... main> paresE4 [(7,1),(13,1),(19,1),(25,1),(25,5),(31,1),(37,1),(43,1), (49,1),(55,1),(55,5),(61,1),(67,1),(73,1),(79,1),(85,1), (85,5),(85,17),(91,1),(91,13),(97,1)] (16878 reductions, 23992 cells)

1 00

12.7. OPERAES PARA DETERMINAR SUBLISTAS: Existem algumas operaes predefinidas no HUGS para descrevermos sublistas de uma lista dada. Nada que no possa ser feito com o que j apresentamos at aqui. Entretanto o seu uso pode ajudar na prtica do reuso e contribuir bastante para a clareza de um programa. Grupo I - Considerando um tamanho especificado take k xs - define uma lista com os k primeiros elementos de uma lista xs. drop k xs - define uma lista com os elementos de xs, a partir do elemento seguinte aos k primeiros. Vejamos a ilustrao a seguir.
Prelude> take 3 [0..10] [0,1,2] (156 reductions, 221 cells) Prelude> drop 3 [0..10] [3,4,5,6,7,8,9,10] (358 reductions, 513 cells) Prelude> [xs!!i | i <-[0..(k - 1)]] where xs = [0..10]; k = 3 [0,1,2] (249 reductions, 336 cells) Prelude> [xs!!i | i <-[k..length xs - 1]] where xs = [0..10]; k = 3 [3,4,5,6,7,8,9,10] (1591 reductions, 2072 cells) Prelude> (take 3 [1..10] ++ drop 3 [1..10]) == [1..10] True (658 reductions, 980 cells)

Na verdade podemos escrever uma descrio geral para take e drop usando listas por compreenso. Alm disso, sabemos que a concatenao de take e drop para um certo k, aplicado uma lista xs, igual prpria lista.

take k xs = [xs!!i | i <-[0..(k - 1)]] drop k xs = [xs!!i | i <-[k..length xs - 1]] vale o seguinte teorema: Take k xs ++ drop k xs = xs

Grupo II - Considerando a satisfao de um predicado pred. Vale lembrar que um predicado uma funo cujo valor resultante do tipo boolean.

1 01 takeWhile pred xs - define uma lista com os primeiros elementos de uma lista xs satisfazendo o predicado pred. dropWhile pred xs - define uma lista com os elementos de xs, a partir do primeiro elemento que no satisfaz o predicado pred. Vejamos a ilustrao a seguir.
Prelude> takeWhile even [1..10] [] Prelude> takeWhile odd [1..10] [1] Prelude> dropWhile odd [1..10] [2,3,4,5,6,7,8,9,10] Prelude> dropWhile even [1..10] [1,2,3,4,5,6,7,8,9,10] Prelude> takeWhile (<5) [1..10] [1,2,3,4] Prelude> dropWhile (<5) [1..10] [5,6,7,8,9,10] Prelude> takeWhile (<5) [1..10] ++ dropWhile (<5) [1..10] == [1..10] True

Exerccios: Kjoj Ionopi Oijoip Joij Oioi Iojo

1 02 13. Resolvendo Problemas com Listas Neste captulos desenvolveremos a soluo para alguns problemas mais complexos. A inteno apresentar o uso de estratgias de propsito geral que podem ser teis na resoluo de novos problemas. Discutimos tambm algumas questes relativas ao desempenho das solues. 13.1 PROBLEMA 1 : Dada uma lista, determine o seu maior elemento. Comecemos por definir, usando a linguagem de conjuntos, quem este elemento. Dizemos que k o maior elemento de um conjunto C, se e somente se, o subconjunto de C formado por todos os elementos maiores que k vazio. Em linguagem de lista isto equivale a dizer que se C uma lista, a sublista de C formada pelos caras de C maiores que k vazia. Vejamos como fica a codificao em Haskell.
--- definindo uma funo para determinar, em uma lista, -- a sublista dos elementos maiores que um dado x -maiores x xs = [ y | y <- xs, y > x] ---- Em listas, podemos ter elementos repetidos, e em particular -- podemos ter vrios exemplares do maior elemento. -- Chamemos esses caras de os "maiorais da lista". -- Vamos construir uma funo para descrev-los. -maiorais xs = [ k | k <- xs, maiores k xs == [] ] --- Como eles so todos idnticos podemos tomar o primeiro deles -- como soluo de nosso problema. -maximo xs = head (maiorais xs) --

13.2 PROBLEMA 2: Dada uma lista, verifique se ela no decrescente. Como aquecimento, vamos considerar listas de nmeros e a noo usual de ordem no decrescente. Nosso problema : Antes de programar, vamos resgatar a definio de seqncias no decrescentes. Definio : Uma seqncia S est em ordem no decrescente se e somente se qualquer um de seus elementos menor ou igual aos seus sucessores. Em

1 03 outras palavras, podemos dizer que a coleo de elementos de S que so maiores que seus sucessores vazia.
--- lista dos maiores que os sucessores -lms1 xs = [ xs!!i | i <-[0..length xs j <-[i+1..length xs xs!!i > xs!!j] --- a seqncia est ordenada se a lista -- que so maiores que algum sucessor -ord1 xs = (lms1 xs) == [] ... Main> ord1 [1..10] True (10801 reductions, 13891 cells) Main> ord1 [10,9..1] False (405 reductions, 571 cells)

2], - 1], dos elementos vazia

13.3. DISCUTINDO EFICINCIA: Observando a avaliao da funo ord1, apresentada na seo anterior, para uma lista j ordenada, a lista [1,2,3,4,5,6,7,8,9,10], constatamos um nmero muito grande de redues. Convm questionar os motivos.
Main> ord1 [1..10] True (10801 reductions, 13891 cells) Main> ord1 [10,9..1] False (405 reductions, 571 cells)

Em geral os motivos para um baixo desempenho so de duas naturezas: explorao inadequada das propriedades do problema e escolha inadequada dos mecanismos da linguagem. A seguir fazemos uma pequena explorao desses dois aspectos. 13.3.1. EXPLORANDO PROPRIEDADES DO PROBLEMA - Analisando a nossa definio anterior constatamos que ela diz mais do que precisamos. Ela avalia cada elemento com respeito a todos sucessores. Na verdade, nossa definio pode ser melhorada. Basta saber que cada elemento tem que ser menor ou igual ao seu sucessor imediato. Vamos reescrever a nossa definio: Definio : Uma seqncia S est em ordem no decrescente se e somente se qualquer um de seus elementos menor ou igual ao seu sucessor imediato. Em outras palavras, podemos dizer que a coleo de elementos de S que so maiores que seus sucessores imediatos vazia.

1 04 Vejamos ento a implementao em Haskell e sua aplicao s mesmas instncias do problema:


--- lista dos elementos maiores que o sucessor imediato -lms2 xs = [ xs!!i | i <-[0..length xs - 2], xs!!i > xs!!(i+1)] -ord2 xs = (lms2 xs) == [] ... Main> ord2 [1..10] True (2236 reductions, 2885 cells) Main> ord2 [10,9..1] False (314 reductions, 449 cells)

Podemos observar uma queda no nmero de redues da ordem de 79%!!! Para o pior caso, ou seja, quando todos os elementos satisfazem a propriedade estabelecida. No melhor caso, onde o primeiro j no satisfaz a propriedade, a queda foi da ordem de 22%. Na utilizao de clulas, os ganhos foram da mesma ordem. 13.3.2. EXPLORANDO OS MECANISMOS DA LINGUAGEM - Uma outra investida que podemos fazer com respeito ao uso adequado dos mecanismos da linguagem. As solues acima apresentadas processam as listas atravs de ndices, ou seja, fazem um acesso aleatrio aos elementos da lista. Como j foi discutido, o acesso seqencial possui realizao mais eficiente.
--- Para manusear os pares de adjacentes, ao -- invs de usar ndices, usemos a funo zip -- aplicada a um par de listas construdas com base em xs -- a)lista formada pelos elementos de xs, exceto o ltimo, -que pode ser obtida com a funo init; -- b)lista formada pelos elementos de xs, exceto o primeiro, -que pode ser obtida com a funo tail. -- Com isso obtemos uma lista formada pelos pares adjacentes. -adjacentes xs = zip (init xs) (tail xs) ... Main> adjacentes [1..10] [(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10)] (414 reductions, 822 cells) Main> adjacentes [10,9..1] [(10,9),(9,8),(8,7),(7,6),(6,5),(5,4),(4,3),(3,2),(2,1)] (364 reductions, 667 cells) ---

1 05
-- A nova funo para definir lista dos maiores -- que os sucessores. Agora trabalharemos com os pares -lms3 ps = [ (x,y) | (x,y) <- ps, x>y] --- A nova verso de 'ord' -ord3 xs = lms3 (adjacentes xs) == [] ... Main> ord3 [1..10] True (313 reductions, 483 cells) Main> ord3 [10,9..1] False (82 reductions, 145 cells)

O ganho obtido para a instncia considerada foi de 86% no nmero de redues e de 83% no nmero de clulas utilizadas, com respeito segunda definio. Exerccios 1. Lknkhn 2. Lknlk 3. Lkhlk 4. lhnlkhlkj~joiwehj 5. Oihophp

1 06 14. Paradigma Aplicativo

14.1. INTRODUO: A descrio de funes, como acontece com outras formas de representao de conhecimento, admite vrios estilos. Dependendo do problema que estamos tratando, um estilo pode ser mais conveniente que outros. Podemos dizer que influi muito na escolha, o quanto desejamos ou necessitamos, falar sobre como computar uma soluo. A descrio de solues tem um espectro de operacionalidade que vai do declarativo at o procedural, em outras palavras, do que desejamos computar ao como queremos computar.. Uma situao que ocorre com freqncia na descrio de funes a necessidade de aplicar uma funo, de forma cumulativa, uma coleo de elementos. Em outras palavras, desejamos generalizar uma operao para que seu uso se estenda a todos os elementos de uma lista. Chamemos este estilo de paradigma aplicativo. Por exemplo, suponha que desejamos obter a soma de todos os elementos de uma lista. A operao adio (+) segundo sabemos, de natureza binria, ou seja, opera sobre dois elementos produzindo um terceiro. Para operar sobre todos os elementos de uma lista de forma a obter a soma total, podemos oper-los dois a dois, obtendo com isso resultados intermedirios, que por sua vez podero ser novamente operados e assim sucessivamente at que se obtenha o resultado final. Observemos o processo para uma instncia: Obter a soma dos elementos da lista [5, 9, 3, 8, 15, 16] Podemos tomar os pares de elementos, primeiro com segundo, terceiro com quarto e assim sucessivamente. expresso nova expresso reduo 5 + 9 = 14 3 + 8 = 11 15 + 16 = 31 14 + 11 = 25 25 + 31 = 56

+ [5, 9, 3, 8, 15, 16] + [14, 3, 8, 15, 16] + [14, 11, 15, 16] + [14, 11, 31] + [25, 31] + [56]

+ [14, 3, 8, 15, 16] + [14, 11, 15, 16] + [14, 11, 31] + [25, 31] + [56]
56

A escolha dos pares, no caso da adio, no importa. As redues poderiam ser aplicadas em qualquer ordem, visto que a operao adio comutativa. Se, pode ser qualquer uma, ento podemos estabelecer uma ordem, como por

1 07 exemplo, da esquerda para a direita, usando em cada nova reduo o elemento resultante da reduo anterior.

Expresso

nova expresso

Reduo 5 + 9 = 14 14 + 3 = 17 17 + 8 = 25 25 + 15 = 40 40 + 16 = 56

+ [5, 9, 3, 8, 15, 16] + [14, 3, 8, 15, 16] + [17, 8, 15, 16] + [25, 15, 16] + [40, 16] + [56]

+ [14, 3, 8, 15, 16] + [17, 8, 15, 16] + [25, 15, 16] + [40, 16] + [56]
56

Em HUGS existe um operador que permite a descrio de computaes desta natureza. Este operador denomina-se foldl. A sua utilizao requer ainda que seja indicado um valor especial para a operao considerada. Este elemento tomado como ponto de partida para as redues, ou seja, a primeira aplicao da operao sobre o valor especial e o primeiro elemento da lista. Eis a sintaxe:

foldl <operao> <valor especial> <lista>


A ordem estabelecida para as redues semelhante ilustrao acima, ou seja, caminha-se da esquerda para direita, usando o resultado da reduo anterior para a nova reduo. expresso
foldl op ve [x0, x1, x2,...,xn] op [(op (op ve x0) x1), x2,...,xn] op [op(op((op (op ve x0) x1) x2)... xn)]

nova expresso
op [(op ve x0), x1, x2,...,xn] op [op((op (op ve x0) x1) x2),...,xn] op(op((op (op ve x0) x1) x2)... xn)

Merece aqui um destaque, foldl na verdade um funo, com 3 parametros, sendo que um deles uma outra funo. Dizemos neste caso que foldl uma funo de segunda ordem. O tipo da operao tem que ser:

1 08
<alfa> -> <beta> -> <beta> onde : <alfa> pode ser do mesmo tipo de <beta>; <beta> tem que ser do tipo dos componentes da lista; o valor especial do tipo <alfa>

Vejamos ento a definio do operador sum disponvel no HUGS e cujo objetivo a descrio da soma dos elementos de uma lista.

sum xs = foldl (+) 0 xs

OBS: 1. Os operadores infixados so indicados entre parntesis. 2. O valor especial o zero, visto que no desejamos que o valor especial modifique o resultado da soma de todos os elementos. Entretanto, ele joga um papel muito especial quando a lista for vazia.
prelude> sum [] 0

3. Em exemplos futuros veremos outros usos para o valor especial.

14.2. ALGUMAS OPERAES IMPORTANTES: Assim como a somatria, existem outras operaes importantes, de grande utilidade, que podem ser obtidas pelas seguintes equaes usando foldl.
--- produto -valor especial = 1 -product xs = foldl (*) 1 xs --- conjuno -valor especial = True -and xs = foldl (&&) True xs --- disjuno -valor especial = False -or xs = foldl (||) False xs

Exemplo 01: Usando product para descrever o fatorial de um nmero

1 Sabemos que: O fatorial de um nmero ao produto de todos os nmeros naturais de 1 at n.


--- definio de fatorial -fat n = product [1..n] ... ? fat 5 120 ? fat 0 1 ? fat 1 1

natural

n>0

09 igual

Exemplo 02: Podemos usar a disjuno (or) generalizada para definir uma funo que avalia se em uma dada lista de nmeros pelo menos um deles impar.
--- pelo menos um impar -umImpar xs = or [odd x | x <- xs] ... ? umImpar [2,2,2,2,2,2,2,2] False ? umImpar [2,2,2,1,2,2,2,2] True ? umImpar [] False

14.3. O MENOR ELEMENTO DE UMA LISTA: Estamos interessados em obter uma funo que associe uma lista xs com o elemento de xs que seja o menor de todos. Anteriormente j apresentamos uma verso para a funo que descreve o maior elemento de uma lista, que bastante similar a esta. Na oportunidade exploramos uma propriedade que o elemento maior de todos deve satisfazer. No caso do menor elemento, podemos explorar uma propriedade anloga. Em uma lista xs, dizemos que k o menor elemento de xs, se e somente se a sublista de xs formada por elementos menores que k vazia.

1 10
--- menores descreve os elementos menores que um -- dado x em uma lista xs -menores x xs = [ y | y <- xs, y < x] -- minimo descreve a sublista de xs dos elementos -- que no possuem menores que eles em xs -minimos xs = [ k | k <- xs, menores k xs == [] ] --- Como eles so todos idnticos podemos tomar o -- primeiro deles -- como soluo de nosso problema. -menorL0 xs = head (menores xs)

Vamos explorar agora o problema a partir da generalizao da operao menor. Em sua forma bsica, a funo menor associa dois nmeros quaisquer com o menor entre eles. Precisamos identificar um elemento que no interfira no resultado para fazer o papel de valor especial. Para a operao menor podemos observar que este papel pode ser desempenhado por qualquer um dos elementos da lista, visto que o menor entre dois valores idnticos o prprio valor. Como pode ser qualquer um, podemos escolher o primeiro elemento de xs (head).
--- menor de dois -menor x y = if x < y then x else y --- menor da lista -menorL xs = foldl menor (head xs)xs ... ? menorL [5,5,4,4,4,6,6,6,3,3,3,11,1,0] 0 (84 reductions, 157 cells) ? menorL [5] 5 (5 reductions, 13 cells) ? menorL [ ] ERROR: Unresolved overloading *** type : Ord a => a *** translation : menorL []

Podemos observar aqui que a funo menorL parcial pois no se aplica a lista vazia. 14.4. INSERO ORDENADA E ORDENAO DE UMA LISTA: A ordenao de dados uma das operaes mais realizadas em computao. Diariamente, em todos os computadores do mundo, faz-se uso intensivo dela. Este assunto muito especial e por isso mesmo profundamente estudado. Cabe-nos aqui fazer uma

1 11 breve passagem pelo assunto, sem, contudo nos aprofundarmos nas questes de eficincia, que central no seu estudo. Ser que podemos usar o conceito de generalizao de uma operao para descrever a ordenao de uma lista? Que operao seria essa? 14.4.1. INSERO EM LISTA ORDENADA - Vamos comear discutindo uma outra questo mais simples: dada uma lista, com seus elementos j dispostos em ordem no decrescente, como descrever uma lista na mesma ordem, acrescida de um elemento tambm fornecido? Podemos observar que se a lista xs est em ordem no decrescente, com respeito ao elemento x (dado), podemos descrev-la atravs de dois segmentos: xs = <menores que x> ++ <maiores ou iguais a x> Para acrescentar x a xs, basta concatenar x entre os dois segmentos, obtendo a nova lista ys, assim: ys = <menores que x em xs> ++ [x] ++ <maiores ou iguais a x em xs>
--- insero ordenada --insord xs x = takeWhile (< x) xs ++ [x] ++ dropWhile (< x) xs ... Main> insord [] 10 [10] (27 reductions, 49 cells) Main> insord [10] 20 [10,20] (54 reductions, 84 cells) Main> insord [10,20] 30 [10,20,30] (79 reductions, 119 cells) Main> insord [10,20,30] 5 [5,10,20,30] (71 reductions, 110 cells) Main> insord [5,10,20,30] 25 [5,10,20,25,30] (126 reductions, 183 cells)

14.4.2. ORDENAO - A APLICAO SUCESSIVA DE INSORD, CONFORME ILUSTRADA ACIMA, NOS D UMA PISTA PARA NOSSA GENERALIZAO. PODEMOS PEGAR CADA ELEMENTO DA LISTA A SER ORDENADA E INSERI-LO EM ORDEM EM UMA OUTRA LISTA QUE SER

1 12 PAULATINAMENTE CONSTRUDA, J ORDENADA. VAMOS SEGUIR O EXEMPLO ACIMA, ONDE DESEJAMOS ORDENAR A LISTA [10,20,30,5,25]:

lista parcial [] [10] [10,20] [10,20,30] [5, 10, 20, 30]

novo elemento 10 20 30 5 25

reduo [10] [10,20] [10,20,30] [5, 10, 20, 30] [5, 10, 20, 25, 30]

O ponto de partida, neste caso, a lista vazia. Vamos tomar ento a lista vazia como o valor especial. Vejamos como fica ento nossa definio para ordenao de listas.
--- ordenao -ordena xs = foldl insord [] xs ... Main> ordena [10,20,30,5,25] [5,10,20,25,30] (220 reductions, 344 cells) Main> ordena [1..10] [1,2,3,4,5,6,7,8,9,10] (1055 reductions, 1505 cells) Main> ordena [10,9..1] [1,2,3,4,5,6,7,8,9,10] (448 reductions, 712 cells)

14.5. INVERSO DE UMA LISTA: Dada uma lista xs, desejamos descrever a lista formada pelos elementos de xs tomados em ordem inversa. Para resolver o problema precisamos inventar uma funo bsica passvel de generalizao. Vamos comear descrevendo a funo insAntes.

1 13
--- Insere um elemento antes do primeiro elemento -- de uma dada lista. Funo similar ao operador -- (:) exceto pela ordem invertida dos parmetros -insAntes xs x = x : xs ... Main> insAntes [1..5] 0 [0,1,2,3,4,5] (171 reductions, 255 cells) Main> insAntes [] 0 [0] (22 reductions, 29 cells)

Tentemos agora a generalizao. A inteno incluir cada elemento da lista xs que desejamos inverter, antes do primeiro elemento de uma lista que iremos construindo gradativamente. O valor especial ser a lista vazia. Vejamos um exemplo onde inverteremos a lista [0, 1, 2, 3, 4] lista parcial [] [0] 1, 0] [2, 1, 0] [3, 2, 1, 0] novo elemento 0 1 2 3 4 reduo [0] [1, 0] [2, 1, 0] [3, 2, 1, 0] [4, 3, 2, 1, 0]

Vamos ento usar o operador foldl para construir a generalizao desejada:


-- inversao -inverte xs = foldl insAntes [] xs ... Main> inverte [0..4] [4,3,2,1,0] (172 reductions, 259 cells) Main> inverte [4,3..4] [4] (74 reductions, 110 cells) ... Main> reverse [4,3..4] [4] (74 reductions, 111 cells) Main> reverse [0..4] [4,3,2,1,0] (171 reductions, 257 cells)

1 14 Observe a similaridade entre o desempenho da funo reverse, pr-definida, com o desempenho da inverte que acabamos de definir.

14.6. INTERCALAO DE LISTAS: Dadas duas lista xs e ys, ambas em ordem no decrescente, desejamos descrever uma nova lista em ordem no decrescente, formada por todos os elementos das duas listas. Um processo bastante conhecido, chamado de balance line, consiste em ir transferindo para a nova lista, os elementos de uma das listas de entrada, enquanto estes forem menores que os da outra. Quando a condio no mais satisfeita, fazemos o mesmo para a outra lista. Por exemplo, vamos intercalar as listas [2, 4, 6, 8] e [1, 3, 5]. Vejamos o desenrolar do processo. lista parcial [] [1] [1, 2] [1, 2, 3] [1, 2, 3, 4] [1, 2, 3, 4, 5] [1, 2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6, 8] Andamento em xs [2, 4, 6, 8] [2, 4, 6, 8] [ 4, 6, 8] [ 4, 6, 8] [6, 8] [6, 8] [ 8] [] Andamento em ys [1, 3, 5] [3, 5] [3, 5] [5] [5] [] [] [] Reduo [1] [1, 2] [1, 2, 3] [1, 2, 3, 4] [1, 2, 3, 4, 5] [1, 2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6, 8]

Vamos precisar aqui de uma bela engenharia para a construo da funo a generalizar. Desta vez, nossa entrada formada por duas listas e como sabemos o operador foldl, a cada vez, processa um elemento de uma determinada lista. Isto nos leva a ter que inventar tambm a lista a ser processada. A funo bsica pode ser inventada a partir da descrio de um passo do processo que denominamos de balance line. Em cada passo temos como entrada uma lista parcialmente construda e duas listas parcialmente processadas. Como sada teremos mais um passo de construo da lista resultante e o andamento no processamento de uma das listas. Na lista em construo devemos inserir o menor entre os cabeas (head) das duas listas. Aquela que tiver o menor cabea dar origem a uma nova lista, da qual foi excludo o primeiro elemento, ou seja, ser idntica ao resto (tail) da lista escolhida.

1 15
--- Descrio de um passo do Balance Line. -- 1) Quando uma das duas listas for vazia a -outras diretamente concatenada no final -da lista em construo. -passoBL (xs,ys,zs) = if (ys == []) then ([],[],zs++xs) else if (xs == []) then ([],[],zs++ys) else if (head xs <= head ys) then (tail xs,ys,zs++[head xs]) else (xs, tail ys,zs++[head ys]) ... ... aplicao sucessiva da funo passoBL intercalao ... das listas acima propostas ... Main> passoBL ([2,4,6,8],[1,3,5],[]) ([2,4,6,8],[3,5],[1]) (121 reductions, 219 cells) Main> passoBL ([2,4,6,8],[3,5],[1]) ([4,6,8],[3,5],[1,2]) (122 reductions, 222 cells) Main> passoBL ([4,6,8],[3,5],[1,2]) ([4,6,8],[5],[1,2,3]) (123 reductions, 225 cells) Main> passoBL ([4,6,8],[5],[1,2,3]) ([6,8],[5],[1,2,3,4]) (124 reductions, 228 cells) Main> passoBL ([6,8],[5],[1,2,3,4]) ([6,8],[],[1,2,3,4,5]) (128 reductions, 239 cells) Main> passoBL ([6,8],[],[1,2,3,4,5]) ([],[],[1,2,3,4,5,6,8]) (116 reductions, 223 cells) ... Main> passoBL ([1..5],[],[]) ([],[],[1,2,3,4,5]) (190 reductions, 329 cells) Main> passoBL ([],[1..5],[]) ([],[],[1,2,3,4,5]) (193 reductions, 339 cells) Main> passoBL ([1..3],[4..5],[]) ([2,3],[4,5],[1]) (219 reductions, 371 cells)

A generalizao, de forma que possamos aplicar a funo gradativamente, de tal forma que todo o processo se complete, requer a inveno de uma lista sobre a qual ocorra a repetio. O nmero de aplicaes sucessivas ser no mximo igual soma dos comprimentos das listas a serem intercaladas. Podemos ento definir a aplicao sobre a lista dos nmeros de 1 at a soma dos tamanhos.

1 16
--- Funo para Intercalar duas listas ordenadas -- 1) a funo passoBL repetidamente aplicada, sobre -o resultado obtido no passo anterior; -- 2) a funo passoBL binria, como exigido por foldl; -- 3) a aplicao sucessiva controlada pelo comprimento -da lista resultante; -- 4) o resultado final obtido pela seleo do terceiro -elemento da tripla atravs da primitiva "thd3" -baLine xs ys = thrd3 (baLine3 xs ys) -thrd3 (x,y,z) = z -baLine3 xs ys = foldl passoBL (xs,ys,[]) [1..tr] where tr = (length xs)+(length ys) --- Descrio de um passo do Balance Line. -- 1) Quando uma das duas listas for vazia a -outras diretamente concatenada no final -da lista em construo. -- 2) O parmetro k apenas para estabelecer o tipo -binrio exigido por foldl -passoBL (xs,ys,zs) k = if (ys == []) then ([],[],zs++xs) else if (xs == []) then ([],[],zs++ys) else if (head xs <= head ys) then (tail xs,ys,zs++[head xs]) else (xs, tail ys,zs++[head ys]) ... Main> thrd3 (10,20,30) 30 (11 reductions, 12 cells) Main> baLine3 [1..3] [4..6] ([],[],[1,2,3,4,5,6]) (514 reductions, 896 cells) Main> baLine [1..3] [4..6] [1,2,3,4,5,6] (485 reductions, 784 cells) Main> baLine [1..5] [3..7] [1,2,3,3,4,4,5,5,6,7] (807 reductions, 1326 cells) Main> baLine [2, 4, 6, 8] [1, 3, 5] [1,2,3,4,5,6,8] (425 reductions, 696 cells)

Exerccios: 1. Sdknfvlnlc 2. Fsponmposfdnponsdf 3. psnmfdponmposds

1 17 15. Processamento de Cadeias de Caracteres primeiros passos

15.1. INTRODUO: Alm de nmeros, nosso mundo povoado por textos. Cada vez mais se torna presente o uso de computadores para nos auxiliar na tarefa de armazenar, recuperar e processar documentos. Neste captulo estamos interessados em fazer uma breve introduo ao uso de computadores nessas tarefas. O ponto de partida o tipo caracter (chr), que nos permite representar textos na memria (principal e secundria) dos computadores. Veremos tambm como agrup-los para compor palavras, frases e por fim documentos.

15.2. O TIPO CHAR : O tipo char formado por um conjunto de smbolos. Um outro nome usado para esta coleo alfabeto, ou seja, o conjunto de tomos que serviro de base para a construo de cadeias complexas, inclusive os textos usuais. Entre os smbolos citados podemos destacar trs agrupamentos relevantes, tais como: 1. As letras maisculas do alfabeto; 2. As letras minsculas do alfabeto; 3. Os algarismos arbicos; Estes trs agrupamentos gozam de uma propriedade muito importante. Dentro deles os smbolos possuem uma relao de ordem, de tal forma que podemos usar a noo usual de ordenao para letras e algarismos. Alm destes, podemos citar ainda os sinais de pontuao e alguns smbolos com funes especiais, como, por exemplo, indicador de final de linha de texto. Os smbolos so sempre apresentados em HUGS entre aspas simples, para que possam ser diferenciados dos nomes de parmetros, funes e outros. Por exemplo, a letra a deve ser denotada por 'a' . A definio a seguir ajuda a esclarecer esta necessidade. f a = (a, 'a') Aqui usamos a letra a trs vezes. A primeira, da esquerda para direita, nomeia um parmetro da funo f. Na segunda ocorrncia, utilizamos o parametro da funo para se constituir do primeiro elemento de uma tupla. J a terceira ocorrncia se refere constante a. Vejamos as respostas do sistema para diferentes usos da funo f
1 Main> f 3 (3,'a')

1 18
2 Main> f 5 (5,'a') 3 Main> f a ERROR - Undefined variable "a" 4 Main> f 'a' ('a','a') 5 Main> f 'aa' ERROR - Improperly terminated character constant 6 Main> f 'b' ('b','a') 7 Main> f a where a='a' ('a','a')

Nas situaes 1, 2, e 6, o parametro a instanciado para os valores 3, 5 e b , resultando nos pares (3, a), (5,a) e (b, a). Na situao 4, o parmetro a instanciado para a constante a, produzindo o par (a, a). Na situao 3, o uso de a est incorreto, pois como no est entre as aspas simples, interpretado como um parmetro, que no est instanciado quando deveria estar. Na situao 7, ao contrrio da situao 3, o valor de a instanciado atravs da clusula where e a situao fica similar situao 4. A coleo total dos smbolos de nosso alfabeto forma uma seqncia de tal forma que podemos fazer o mapeamento entre a subseqncia de nmeros naturais, de zero (0) a 255 e a seqncia de smbolos. Duas funes bsicas permitem que se faa a converso entre as duas seqncias: 1. A funo chr associa um nmero natural no intervalo [0,255] com o caracter correspondente. Por exemplo, chr 64 = '@' e chr 38 = '&'. 2. A funo ord faz o mapeamento inverso, ou seja, associa um smbolo com o nmero natural correspondente. Por exemplo, ord '?' = 63 e ord '%' = 37. A tabela a seguir apresenta alguns dos agrupamentos importantes.
Algarismos Letras Maisculas Letras Minsculas

1 19 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 102 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126

Alm das operaes ord e chr, podemos contar com os operadores relacionais que foram apresentados no Captulo 6. Da mesma forma que existem os operadores para comparao de nmeros, existem os operadores relacionais que comparam dois smbolos, como no exemplo:
Prelude> 'c' > 'h' False

O significado de uma operao relacional sobre characteres determinado com base na ordem destes com respeito tabela apresentada para codificao desses smbolos. Assim, podemos dizer que: Se x e y so do tipo caractere, x > y se e somente se ord x > ord y Podemos agora construir algumas definies interessantes, conforme se apresenta nos quadros a seguir.:

1 20
--- verifica se um dado smbolo letra -letra x = (maiuscula x) || (minuscula x) -maiuscula x = pertence x ('A','Z') minuscula x = pertence x ('a','z') pertence x (a,b) = (x >= a) && (x <= b)

--- verifica se um smbolo um algarismo -algarismo x = pertence x ('0','9') --- Associa uma letra minuscula com a sua -- correspondente maiuscula e mantm o -- smbolo fornecido nos demais casos -caps x = if minuscula x then chr (ord x - 32) else x

--- Determina a posio relativa de uma letra -- dentro do alfabeto, onde as maisculas e -- minsculas possuem a mesma posio. -- Outros smbolos devem ser associados ao -- valor 0 (zero) -ordAlfa x = if letra x then ord (caps x) - 64 else 0

Eis a aplicao em algumas instncias:

Eis mais alguns exemplos de funes com o tipo char.


--

1 21
-- verifica se um smbolo uma letra vogal -vogal x = letra x && ocorre (caps x) vogais where vogais = ['A','E','I','O','U'] -ocorre x xs = or [x == y | y<- xs]

--- verifica se um smbolo uma letra -- consoante -consoante x = letra x && (not (vogal x)) --

--- Descreve uma lista de pares onde o primeiro termo -- um nmero entre 0 e 255 e o segundo o caracter -- correspondente. O intervalo desejado informado -- por um par de valores no intervalo 0 a 255. -tabOrdChr (i,f) = [(x, chr x) | x <- [i..f]]

Vejamos alguns exemplos de uso das definies acima apresentadas:


Main> tabOrdChr (65,70) [(65,'A'),(66,'B'),(67,'C'),(68,'D'),(69,'E'),(70,'F')] (357 reductions, 604 cells) Main> tabOrdChr (97,102) [(97,'a'),(98,'b'),(99,'c'),(100,'d'),(101,'e'),(102,'f')] (357 reductions, 607 cells) Main> tabOrdChr (45,50) [(45,'-'),(46,'.'),(47,'/'),(48,'0'),(49,'1'),(50,'2')] (357 reductions, 604 cells)

15.3. O TIPO STRING: Podemos agrupar tomos do tipo caracter (char) para formar o que denominamos de cadeia de caracteres, usualmente chamadas de "palavra". O mecanismo para agregar o construtor da lista. Podemos por exemplo, escrever em HUGS a lista ['c','i','d','a','n','i','a'] para representar a palavra cidadania. Assim procedendo podemos escrever qualquer texto, uma vez que um texto no nada mais nada menos que uma longa cadeia de smbolos envolvendo letras e sinais de pontuao. A separao de palavras obtida pelo uso de um caracter especial, denominado de espao, que tem representao interna igual a 32. Por exemplo, para representar a expresso "Vamos nessa!", usamos a lista: ['V','a','m','o','s',' ','n','e','s','s','a','!'].

1 22 Uma boa notcia que o HUGS nos proporciona uma maneira mais amistosa para tratar com lista de caracteres. Em HUGS podemos representar uma lista de caracteres, envolvendo a cadeia por aspas duplas, o que por certo, alm de mais elegante e legvel, no poupa trabalho. Por exemplo, a cadeia acima representada por ser tambm escrita na seguinte forma: "Vamos nessa!" uma lista de caracteres o HUGS associa um tipo sinnimo, denominado string. Assim, as duas representaes acima so idnticas, conforme podemos observar na avaliao abaixo:
Prelude> "Vamos nessa!" == ['V','a','m','o','s',' ','n','e','s','s','a','!'] True (64 reductions, 102 cells)

Um bom lembrete que, cadeias de caracteres so definidas como listas, e como tais, podemos usar sobre elas todas as operaes que sabemos at agora sobre listas. Por exemplo, podemos construir uma funo para contar a quantidade de vogais existente em uma cadeia.
contaVogais xs = length vogais where vogais = [x | x <-xs, vogal x] ... Main> contaVogais "Vamos nessa!" 4 (966 reductions, 1383 cells)

15.4. FUNES BSICAS PARA O TIPO STRING: Uma cadeia de caracteres, por ser uma lista, herda todas as operaes que j apresentamos para as listas. Alm dessas, podemos contar ainda com algumas operaes que apresentamos a seguir: words xs - Associa uma cadeia de caracteres com a lista de palavras nela contida. Entende-se por palavra um agrupamento de smbolos diferentes do smbolo espao (" ").
Prelude> words "Se temos que aprender a fazer, vamos aprender fazendo!" ["Se","temos","que","aprender","a","fazer,", "vamos","aprender","fazendo!"] (2013 reductions, 3038 cells)

1 23 Podemos observar que os smbolos usuais de separao (por exemplo, "," e "!" so considerados como parte das palavras. Vamos agora construir uma funo que considere os smbolos usuais de separao, alm do espao.
--- A funo palavras -palavras xs = [ takeWhile letra x | x <- words xs] ---... Main> palavras "Se temos que aprender a fazer, vamos aprender fazendo!" ["Se","temos","que","aprender","a","fazer","vamos","aprender","fazendo"] (3869 reductions, 5444 cells) Main> palavras "jose123 maria456 joana!!!" ["jose","maria","joana"] (1445 reductions, 2081 cells) Main> words "jose123 maria456 joana!!!" ["jose123","maria456","joana!!!"] (951 reductions, 1423 cells)

De fato, a funo palavras trata a questo a que nos propnhamos, abandonar os smbolos de pontuao. Acontece que ela abandona muito mais que isso, como podemos ver no exemplo, onde a cadeia "jose123" perde o seu sufixo numrico, tornando-se apenas "jose".

Vamos construir uma nova funo ento onde isso possa ser resgatado.
--- A funo palavras1 -palavras1 xs = [ takeWhile alfa x | x <- words xs] where alfa x = letra x || algarismo x ---... Main> palavras1 "x123 y456 aux!!!" ["x123","y456","aux"]

Bom, parece que agora temos uma soluo adequada.

1 24

Exerccios Kjbkj Kjn Ono Onoi

1 25 16. O PARADIGMA RECURSIVO

16.1. INTRODUO: Como j falamos anteriormente, existem vrias maneiras de definir um conceito. A essas maneiras convencionamos chamar de paradigmas. Aqui trataremos de mais um destes, o paradigma recursivo. Dizer que trataremos de mais um simplificar as coisas, na verdade este paradigma um dos mais ricos e importantes para a descrio de computaes. O domnio deste paradigma de fundamental importncia para todo aquele que deseja ser um expert em Programao de Computadores enquanto cincia e tecnologia. De uma maneira simplificada podemos dizer que o ncleo deste paradigma consiste em descrever um conceito de forma recursiva. Isto equivale a dizer que definiremos um conceito usando o prprio conceito. Apesar de disto parecer muito intrigante, no se assuste, aos poucos, quando esboarmos melhor a idia ela se mostrar precisa, simples e poderosa. Vamos pensar num conceito bem corriqueiro. Que tal definirmos o conceito escada. Como podemos descrever escada usando a prpria escada? A resposta bem simples: Uma escada igual a um degrau seguido de uma escada (Figura 15.1).

escada degrau Figura 15.1 Uma escada

escada

Fcil no ? Ser que isto basta? Onde est o truque? Parece que estamos andando em crculo, no mesmo? Para entender melhor vamos discutir a seguir alguns elementos necessrios para a utilizao correta da recurso na definio de novas funes.

16.2. DESCRIO RECURSIVA DE UM CONCEITO FAMILIAR: Antes de avanar em nossa discusso vamos apresentar mais um exemplo. Desta vez

1 26 usaremos um que bastante familiar para alunos de cincias exatas. Estamos falando da descrio do fatorial de um nmero. J vimos neste curso uma forma de descrever este conceito dentro do HUGS quando estudamos o paradigma aplicativo. Na oportunidade usamos a seguinte descrio:

O fatorial de um nmero natural n > 0 igual ao produto de todos os nmeros naturais de 1 at n.

Ou ainda em notao mais formal:

n ! = 1 x 2 x 3 x ... x n
Em HUGS, como j vimos, teremos a seguinte definio:
--- definio (aplicativa) de fatorial -fat n = product [1..n] ... ? fat 5 120 ? fat 0 1 ? fat 1 1

H uma outra forma de definir, tambm familiar aos alunos do primeiro ano universitrio: O Fatorial de um nmero natural n igual ao produto deste nmero pelo fatorial de seu antecessor. Novamente, sendo mais formal, podemos escrever:

n ! = n x (n - 1) !
E em HUGS, como ficaria? Que tal a definio a seguir?
--- definio recursiva de fatorial -fat n = n * fat (n - 1)

Vamos exercitar a definio:

1 27
Main> fat 5 (23967 reductions, 47955 cells) ERROR: Control stack overflow

Bom, parece que houve um pequeno problema com nossa definio. A avaliao de fat 5 produziu uma situao de erro. Vamos deixar para entender este erro melhor para depois. Por enquanto j podemos adiantar que ele foi provocado por um pequeno esquecimento de nossa parte. Na verdade a nossa definio recursiva para fatorial estava incompleta. Esta que exibimos s se aplica aos naturais maiores que zero. A definio do fatorial de zero no recursiva, ela independente: O fatorial de zero igual a 1. Temos ento duas definies para fatorial e precisamos integr-las. Vejamos uma tentativa: O Fatorial de um nmero natural n : 1. igual a 1 se n=0; 2. igual ao produto deste nmero pelo fatorial de seu antecessor, se n > 0 Vamos ver como essa integrao pode ser feita em HUGS. Podemos de imediato observar que trata-se de uma definio condicional e logo nos vem a lembrana de que nossa linguagem possui um mecanismo, as expresses condicionais.
--- definio recursiva de fatorial -- (corrigida) -fat n = if n==0 then 1 else n * fat (n - 1)

Vamos submeter algumas situaes para o HUGS:


Main> fat 5 120 (79 reductions, 124 cells) Main> fat 20 2432902008176640000 (258 reductions, 466 cells) Main> fat 0 1 (18 reductions, 18 cells)

1 28 Pelo visto agora deu tudo certo. 16.3. ELEMENTOS DE UMA DESCRIO RECURSIVA: Em uma descrio recursiva devemos ter em conta certo elementos importantes. fundamental que todos eles sejam contemplados para que nossas descries estejam corretas. O exemplo anteriormente apresentado suficiente para ilustrar todos eles. Vamos ento discuti-los: Definio geral : Toda definio recursiva tem duas partes, uma delas se aplica a um valor qualquer do domnio do problema, denominamos de geral. Esta tem uma caracterstica muito importante, o conceito que est sendo definido deve ser utilizado. Por exemplo, para definir fatorial de n, usamos o fatorial do antecessor de n. Observe aqui, entretanto que o mesmo conceito foi utilizado, mas no para o mesmo valor. Aplicamos o conceito a um valor mais simples, neste caso o antecessor de n. Definio independente : A outra parte da definio destinada ao tratamento de um valor to simples que a sua definio possa ser dada de forma independente. Este elemento tambm conhecido como base da recurso. No caso do fatorial, o valor considerado o zero. Obteno de valores mais simples : Para aplicar o conceito a um valor mais simples precisamos de uma funo que faa este papel. No caso do fatorial, usamos a subtrao de n por 1, obtendo assim o antecessor de n. Em cada caso, dependendo do domnio do problema e do problema em si, precisaremos encontrar a funo apropriada. Funo auxiliar : Na definio geral, para obter um valor usando o valor considerado e o valor definido recursivamente, em geral faz-se necessrio o uso de uma funo auxiliar. Algumas vezes esta funo pode ser originada a partir de um conceito aplicvel a dois elementos e que desejamos estender aos elementos de uma lista. Um exemplo o caso da somatria dos elementos de uma lista, como veremos adiante. No caso do fatorial esta funo a multiplicao. Garantia de atingir o valor independente : fundamental que a aplicao sucessiva da funo que obtm valores mais simples garanta a determinao do valor mais simples. Este valor tambm denominado de base da recurso. Por exemplo, no caso do fatorial, sabemos que aplicando a subtrao sucessivas vezes produziremos a seqncia: n, (n-1), (n-2), ... 0 Esta condio fundamental para garantir que ao avaliarmos uma expresso atingiremos a base da recurso. Voltemos definio do fatorial para destacarmos os elementos acima citados, como podemos observar no quadro esquemtico a seguir:

1 29

16.4. AVALIANDO EXPRESSES: A esta altura dos acontecimentos a curiosidade sobre como avaliar expresses usando conceitos definidos recursivamente j deve estar bastante aguada. No vamos, portanto retardar mais essa discusso. Apresentamos a seguir um modelo bastante simples para que possamos entender como avaliar expresses que usam conceitos definidos recursivamente. Novamente no precisaremos entender do funcionamento interno de um computador nem da maneira como uma determinada implementao de HUGS foi realizada. Basta-nos o conceito de reduo que j apresentamos anteriormente. Relembremos o conceito de reduo. O avaliador deve realizar uma seqncia de passos substituindo uma expresso por sua definio, at que se atinja as definies primitivas e os valores possam ser computados diretamente. Vamos aplicar ento este processo para realizar a avaliao da expresso

fat 5 passo Reduo Justificativa

1 30 0 fat 5 1 5 * fat 4 2 5*(4 * fat 3) 3 5*(4* (3 * fat 2)) 4 5*(4*(3*(2 * fat 1))) 5 5*(4*(3*(2*(1 * fat 0) 6 5*(4*(3*(2*(1 * 1)))) 7 5*(4*(3*(2*1))) 8 5*(4*(3*2) 9 5*(4*6) 10 5 * 24 11 120 expresso proposta substituindo fat por sua definio geral Idem Idem Idem Idem usando a definio especfica usando a primitiva de multiplicao Idem Idem Idem Idem

Surpreso(a)? Simples, no? assim mesmo, bem simples. A cada passo vamos substituindo uma expresso por outra at que nada mais possa ser substitudo. O resultado surgir naturalmente. Mais tarde voltaremos ao assunto. 16.5. RECURSO EM LISTAS: A esta altura deste curso j estamos certos que o uso de lista indispensvel para escrever programas interessantes. Em vista disso, nada mais bvio que perguntar sobre o uso de recurso em listas. Veremos que o uso de definies recursivas em listas produz descries simples, precisas e elegantes. J est na hora de alertar que os valores sobre os quais aplicamos os conceitos que queremos definir recursivamente possuem uma caracterstica importantssima, eles em si so recursivos. Por exemplo, qualquer valor pertencente aos naturais pode ser descrito a partir da existncia do zero e da funo sucessor (suc). Vejamos como podemos obter o valor 5: 5 = suc(suc(suc(suc(suc 0))))) As listas so valores recursivos. Podemos descrever uma lista da seguinte maneira: Uma lista : 1. a lista vazia; 2. um elemento seguido de uma lista

1 31 Esta natureza recursiva das listas nos oferece uma oportunidade para, com certa facilidade, escrever definies recursivas. A tcnica consiste basicamente em: 1. Obter a definio geral: isto consiste em identificar uma operao binria simples que possa ser aplicada a dois valores. O primeiro deles o primeiro (head) da lista e o outro um valor obtido pela aplicao do conceito em definio ao resto (tail) da lista; 2. Obter a definio independente, que se aplicar base da recurso. Esta, em geral, a lista vazia; 3. Garantir que a aplicao sucessiva do tail levar base da recurso. Na Figura 15.2 ilustramos o processo recursivo de obter listas cada vez menores, atravs da aplicao da funo tail. Ao final do processo obteremos a lista vazia ([ ]). [xo, x1, x2, x3, x4 ... xn-1]

xo [x1, x2, x3, x4 ... xn-1] x1 [x2, x3, x4 ... xn-1] x2 [x3, x4 ... xn-1] x3 [x4 ... xn-1] x4 [... xn-1]

head

tail

...

xn-1 [ ] Figura 15.2 componentes recursivos de uma lista Exemplo 01 - Descrever o somatrio dos elementos de uma lista. Soluo - Podemos pensar da seguinte maneira: o somatrio dos elementos de uma lista igual soma do primeiro elemento da lista como o somatrio do resto da lista. Alm disso, o somatrio dos elementos de uma lista vazia igual a zero.

1 32 somat [xo, x1, x2, x3, x4 ... xn-1] xo + somat [x1, x2, x3, x4 ... xn-1] X0 + x1 + somat [x2, x3, x4 ... xn-1] X0 + x1 + x2 + somat [x3, x4 ... xn-1] X0 + x1 + x2 + x3 + somat [x4 ... xn-1] X0 + x1 + x2 + x3 + somat [x4 ... xn-1] ... [... x ] X0 + x1 + x2 + x3 + x4 + somat n-1 X0 + x1 + x2 + x3 + x4 + ... + xn-1+ somat [ ] X0 + x1 + x2 + x3 + x4 + ... + xn-1 + 0 Figura 15.2 desenvolvimento da computao de somatrio dos elementos de uma lista Vejamos ento a codificao:
--- definio recursiva da somatria dos -- elementos de uma lista -somat xs = if null xs then 0 else head xs + somat (tail xs)

A seguir alguns exemplos de uso:


Main> somat [4,5,2,7,9] 27 (52 reductions, 60 cells) Main> somat [1..10] 55 (275 reductions, 421 cells) Main> somat [1000,9999..1] 0 (45 reductions, 68 cells) Main> somat [1000,999..1] 500500 (18051 reductions, 25121 cells)

Exemplo 02 - Descrever a funo que determina o elemento de valor mximo uma lista de nmeros. Soluo: O mximo de uma lista o maior entre o primeiro elemento da lista e o mximo aplicado ao resto da lista. Uma lista que tem apenas um elemento tem como valor mximo o prprio elemento (Figura 15.3).

1 33
maximo [xo, x1, x2, x3, x4 ... xn-1] maior( xo , maximo [x1, x2, x3, x4 ... xn-1] ) maior( xo , maior(x1, maximo [x2, x3, x4 ... xn-1])) )) maior( xo , maior(x1, maior(x2, maximo [x3, x4 ... xn-1] ))) maior( xo , maior(x1, maior(x2, maior(x3, maximo [x4 ... xn-1] )))) maior( xo , maior(x1, maior(x2, maior(x3, maior(x4, ... maximo[xn-2 , xn-1]))))) maior( xo , maior(x1, maior(x2, maior(x3, maior(x4, ... maior(xn-2 , maximo[ xn-1]))))) maior( x15.3 , maior(x , maior(x2, maior(x3, maior(x , ... maior(x x )))))) Figura desenvolvimento da computao do mximo o 1 4 n-2 elemento , n-1

de

uma lista

A definio recursiva apresentada a seguir:


--- definio recursiva do mximo de uma lista -maximo xs = if null (tail xs) then head xs else maior (head xs) (maximo (tail xs)) -maior x y = if x > y then x else y

E vamos acompanhar agora algumas submisses:


Main> maximo [4,6,7,89,32,45,98,65,31] 98 (126 reductions, 150 cells) Main> maximo ([1..1000]++[1500,1400..1]) 1500 (31419 reductions, 44567 cells) Main> maximo [100,(100 - k) .. 1] where k = 80 100 (91 reductions, 125 cells)

E agora uma surpresa.


Main> maximo [ ] ERROR: Unresolved overloading *** Type : Ord a => a *** Expression : maximo []

Voc consegue explicar? Exemplo 03 - Descrever a funo que verifica se um dado valor ocorre em uma lista tambm dada.

1 34 Soluo : Podemos pensar da seguinte maneira: Um dado elemento k ocorre em uma lista se ele igual ao primeiro elemento da lista ou se ele ocorre no resto da lista. Em uma lista vazia no ocorrem elementos quaisquer (Figura 15.4).

ocorre k [xo, x1, x2, x3, x4 ... xn-1] k = xo | ocorre k [x1, x2, x3, x4 ... xn-1] k = xo | (k = x1 | ocorre k [x2, x3, x4 ... xn-1]) k = xo | (k = x1 | ( k = x2 | ocorre k [x3, x4 ... xn-1])) k = xo | (k = x1 | ( k = x2 | (k = x3 | ocorre k [x4 ... xn-1]))) k = xo | (k = x1 | ( k = x2 | (k = x3 | (k = x4 ) || ocorre k [... xn-1])))) ... k = xo | (k = x1 | ( k = x2 | (k = x3 | (k = x4 ) | ... ocorre k [xn-1]))))) k = xo | (k = x1 | ( k = x2 | (k = x3 | (k = x4 ) | ... | (k = xn-1)| ocorre k [ ])))))

Figura 15.4 desenvolvimento da computao da ocorrncia de um elemento em uma lista Vejamos ento a codificao:
--- descreve a ocorrncia de dado k em uma lista xs -ocorre k xs = if null xs then False else (k==head(xs)) || ocorre k (tail xs)

E algumas submisses:
Main> ocorre 5 [8,65,46,23,99,35] False (71 reductions, 111 cells) Main> ocorre 5 [8,65,46,5,23,99,35] True (47 reductions, 58 cells) Main> ocorre 5 [ ] False (16 reductions, 30 cells)

1 35 Exemplo 04 - Descrever a funo que obtm de uma lista xs a sublista formada pelos elementos que so menores que um dado k : Soluo : Precisamos descrever uma nova lista, vamos denomin-la de menores, em funo de xs e de k. Quem ser esta nova lista? Se o primeiro elemento de xs for menor que k, ento ele participar da nova lista, que pode ser descrita como sendo formada pelo primeiro elemento de xs seguido dos menores que k no resto de xs. Se por outro lado o primeiro no menor que k, podemos dizer que a lista resultante obtida pela aplicao de menores ao resto da lista. Novamente a base da recurso definida pela lista vazia, visto que em uma lista vazia no ocorrem elementos menores que qualquer k. A codificao apresentada a seguir:
--- define a lista de menores que um dado elemento em -- uma lista dada -menores k xs = if null xs then xs else if head xs < k then head xs : menores k (tail xs) else menores k (tail xs)

Desta podemos obter as seguintes avaliaes:


Main> menores 23 [8,65,46,5,23,99,35] [8,5] (122 reductions, 188 cells) Main> menores 46 [8,65,46,5,23,99,35] [8,5,23,35] (135 reductions, 175 cells) Main> menores 5 [] [] (17 reductions, 24 cells)

16.6. EXPLORANDO REUSO: Segundo o Professor George Polya, aps concluir a soluo de um problema, devemos levantar questionamentos a respeito das possibilidades de generalizao da soluo obtida. Dentro deste esprito, vamos explorar um pouco a soluo obtida para o problema descrito a seguir. Exemplo 5 (Sub-lista de nmeros pares) : Dada uma lista xs, desejamos descrever uma sublista de xs formada apenas pelos nmeros pares existentes em xs. Soluo: Devemos considerar, como no problema de encontrar a sublista dos menores (Exemplo 4), a existncia de suas situaes:

1 36 1. O primeiro elemento da lista um nmero par, neste caso a sublista resultante dada pela juno do primeiro com a sublista de pares existente no resto da lista. 2. O primeiro no par. Neste caso a sublista de pares em xs obtida pela seleo dos elementos pares do resto de xs. Concluindo, tomemos como base da recurso a lista vazia, que obviamente no contm qualquer nmero. Eis a soluo em HUGS:
--- sublista de nmeros pares -slpares xs = if null xs then xs else if even (head xs) then head xs : slpares (tail xs) else slpares (tail xs)

E a avaliao de algumas instncias:


Main> slpares [1..10] [2,4,6,8,10] (322 reductions, 438 cells) Main> slpares [1,3..100] [] (962 reductions, 1183 cells)

Vamos agora, seguindo as orientaes do mestre Polya, buscar oportunidades de generalizao para esta funo. Podemos fazer algumas perguntas do tipo: 1. Como faria uma funo para determinar a sublista dos nmeros mpares a partir de uma dada lista? 2. E se quisssemos a sublista dos primos? 3. E que tal a sublista dos mltiplos de cinco? Uma breve inspeo na soluo acima nos levaria a entender que a nica diferena entre as novas funes e a que j temos a funo que verifica se o primeiro elemento satisfaz uma propriedade, no caso presente a de ser um nmero par (even), conforme destacamos a seguir:

1 37
--- sublista de nmeros pares -slpares xs = if null xs then xs else if even (head xs) then head xs : slpares (tail xs) else slpares (tail xs) --- sublista de nmeros impares -slimpar xs = if null xs then xs else if odd (head xs) then head xs : slimpar (tail xs) else slimpar (tail xs) --- sublista de nmeros primos -slprimo xs = if null xs then xs else if primo (head xs) then head xs : slprimo (tail xs) else slprimo (tail xs)

Isto nos sugere que a funo avaliadora pode ser um parmetro. Pois bem, troquemos ento o nome da funo por um nome mais geral e adicionemos sua interface mais uma parmetro. Este parmetro, como sabemos, dever ser do tipo:

alfa -> Boolean


Vejamos ento o resultado da codificao, onde a propriedade a ser avaliada se converte em um parmetro:
--- sublista de elementos de xs que satisfazem -- a propriedade prop -sublista prop xs = if null xs then xs else if prop (head xs) then head xs : sublista prop (tail xs) else sublista prop (tail xs)

Vejamos ento algumas aplicaes na nossa funo genrica para determinar sublistas:

1 38
Main> sublista even [1..10] [2,4,6,8,10] Main> sublista odd [1..10] [1,3,5,7,9] Main> sublista (<5) [1..10] [1,2,3,4] Main> sublista (>=5) [1..10] [5,6,7,8,9,10]

Observe que a funo que havamos anteriormente definido para determinar os elementos menores que um certo valor k, da mesma forma que a funo para determinar os maiores que k, est contemplada com a nossa generalizao. As duas ltimas avaliaes no quadro acima ilustram a determinao da sublista dos valores menores que 5 e a dos maiores ou iguais a 5. Exerccios: Descreva funes em HUGS que utilizem recurso para resolver os problemas abaixo. 1. Obter a interseo de duas listas xs e ys. 2. Dadas duas strings xs e ys, verificar se xs prefixo de ys. 3. Dadas duas strings xs e ys, verificar se xs sufixo de ys. 4. Dadas duas strings xs e ys, verificar se xs sublista de ys. 5. inverter uma lista xs; 6. Definir a funo tWhile, que tenha o mesmo comportamento que a funo takeWhile. 7. Definir a funo dWhile, que tenha o mesmo comportamento que a funo dropWhile. 8. verificar se uma string um palndrome (a string a mesma quando lida da esquerda para a direita ou da direita para a esquerda). 9. Verifique se uma string uma palavra. Defina uma palavra como formada apenas por letras. 10. verificar se os elementos de uma lista so distintos. 11. determinar a posio de um elemento x em uma lista xs, se ele ocorre na lista. 12. descrever a lista das palavras que existem no texto, dado um texto. 13. Dadas duas listas xs e ys, ordenadas em ordem crescente, obter a lista ordenada resultante da intercalao de xs e ys. 14. calcular a combinao de uma lista xs, p a p.

1 39

17. ORDENAO RECURSIVA DE DADOS, ALGUNS PROBLEMAS CORRELATOS E ALGUMAS TCNICAS DE PROPSITO GERAL
17.1 INTRODUO: Voltemos ento ao problema de ordenar os elementos de
uma lista, para o qual j discutimos uma soluo no paradigma aplicativo. Dada uma lista xs desejamos descrever sua ordenao. Vamos comear propondo e resolvendo um problema mais simples. Insero ordenada: Dada uma lista ordenada xs e um elemento k desejamos descrever uma lista a partir de xs, na qual esteja includo o valor k, com a condio de que a nova lista tambm esteja ordenada. Soluo : Voltemos a nossa estratgia para obter solues recursivas. Aqui tambm temos dois casos: 1. O valor k menor que o primeiro da lista xs, neste caso a lista resultante descrita pela juno de k com a lista xs; 2. O valor k maior ou igual ao primeiro elemento da lista xs, neste caso a lista resultante descrita pela juno do primeiro da lista xs com a lista obtida pela insero ordenada de k no resto da lista xs.

insord k Xs =

k < x0

k : Xs

Caso contrrio x0 : insord k Xs

Figura 17.1 insero ordenada de um elemento k em uma lista Xs A codificao pode ser realizada da seguinte forma:
--- insero ordenada de um valor k em uma -- lista ordenada (no decrescente) -insord k xs = if null xs then [k] else if k < head xs then k : xs else head xs : (insord k (tail xs))

1 40 E a seguir algumas aplicaes da soluo:


Main> insord 5 [0,2..10] [0,2,4,5,6,8,10] (230 reductions, 407 cells) Main> insord 5 [10,15..50] [5,10,15,20,25,30,35,40,45,50] (248 reductions, 379 cells) Main> insord 5 [-10,15..0] [-10,5] (92 reductions, 135 cells) Main> insord 5 [-10,-5..0] [-10,-5,0,5] (154 reductions, 220 cells) Main> insord 5 [] [5] (23 reductions, 32 cells)

Agora j podemos voltar ao nosso problema inicial de ordenao de listas. Vamos em busca de uma primeira soluo: Soluo : A ordenao no decrescente de uma lista xs qualquer igual insero ordenada do primeiro da lista na ordenao do resto da lista.
--- ordenao de uma lista -ordena xs = if null xs then xs else insord (head xs) (ordena (tail xs))

Vejamos a aplicao da soluo algumas instncias:


Main> ordena [3, 4, 50,30,20,34,15] [3,4,15,20,30,34,50] (241 reductions, 330 cells) Main> ordena [100,93..50] [51,58,65,72,79,86,93,100] (568 reductions, 780 cells)

1 41 17.2 DIVISO E CONQUISTA (UMA TCNICA PODEROSA): Alguns problemas possuem solues mais facilmente descritas, algumas at mais eficientes, quando quebramos o problema em partes menores, descrevemos a soluo de cada parte e depois combinamos as solues parciais para obter a soluo completa. Este mtodo denominado de "diviso e conquista". Basicamente buscamos encontrar instncias do problema onde a soluo seja imediata. . Nesta seo veremos alguns exemplos desta abordagem. O primeiro deles, a pesquisa binria, trata da busca de um elemento em uma lista ordenada. Os outros dois, mergesort e quicksort, apresentam solues alternativas para a ordenao de uma lista. 17.2.1. PESQUISA BINRIA - Voltemos a um problema j apresentado anteriormente, verificao da ocorrncia de um elemento a uma lista. Segundo a definio que apresentamos para a funo ocorre, apresentada no exemplo 3 do Captulo 16. Podemos constatar que para avaliar expresses onde o elemento procurado no ocorre na lista, o avaliador de expresses precisar fazer uma quantidade de comparaes igual ao comprimento da lista considerada. Na mdia de um conjunto de avaliaes, considerando as avaliaes de expresses em que o elemento procurado est na lista, e que a cada vez estaremos procurando por um elemento distinto, teremos um nmero mdio de comparaes da ordem de (n / 2). Se n for muito grande ficaremos assustados com o nmero de comparaes. Por exemplo, para uma lista de 1000000 (um milho) de elementos, em mdia teremos que fazer 500 mil comparaes. Se pudermos garantir que a lista est ordenada, ento podemos fazer uso de uma estratgia j discutida anteriormente para reduzir este nmero. Estamos falando da rvore binria de pesquisa. A estratgia que usaremos consiste em, a cada passo de reduo, abandonarmos metade da lista considerada a partir da comparao de k com o elemento que se encontra na metade da lista. Se o elemento buscado (k) for igual ao elemento central, ento o processo de avaliao est encerrado. Quando isto no ocorre, devemos ento escolher em qual lista devemos procur-lo. Quando ele menor que o elemento central devemos busclo na sublista que antecede o central, caso contrrio devemos busc-lo na sublista dos seus sucessores. Novamente a base da recurso determinada pela lista vazia. Nesta abordagem, a cada escolha abandonamos metade da lista restante. Desta forma, o nmero de comparaes dado pelo tamanho da seqncia: n/1, n/2, n/4, ... , n/n Para simplificar a anlise podemos escolher um n que seja potncia de 2. Neste caso podemos assegurar que o comprimento da seqncia dado por: Log n na base 2

1 42 Voltando ento ao nmero de comparaes necessrias para localizar um elemento, podemos constatar que em uma lista com 1 milho de elementos, ao invs das 500 mil comparaes da soluo anterior, precisaremos no pior caso, de apenas 20 comparaes. Isso mesmo, apenas 20. Vamos ento codificao em HUGS:
--- pesquisa binria -pesqbin k xs = if null xs then False else if k == pivot then True else if k < pivot then pesqbin k menores else pesqbin k maiores where p = div (length xs) 2 menores = take p xs maiores = tail (drop p xs) pivot = head (drop p xs)

E a seguir, a avaliao de algumas instncias:


Main> ocorre 1023 [0..1023] True (24592 reductions, 32797 cells) Main> pesqbin 1023 [0..1023] True (71563 reductions, 92060 cells)

17.2.2 MERGESORT - Existem outras maneiras de se descrever a ordenao de uma lista. Uma delas, denominada mergesort, se baseia na intercalao de duas listas j ordenadas. Comecemos ento por discutir a intercalao que, em si mesmo, j representa uma ferramenta intelectual bastante interessante. Intercalao: Antes de ver o mergesort podemos apresentar uma verso recursiva para a intercalao de duas listas em ordem no decrescente. Soluo: A intercalao de duas listas ordenadas xs e ys pode ser descrita atravs de dois casos: 1. se o primeiro elemento de xs menor que o primeiro elemento de ys ento a intercalao dada pela juno do primeiro elemento de xs com a intercalao do resto de xs com ys; 2. caso contrrio, a intercalao descrita pela juno do primeiro elemento de ys com a intercalao do resto de ys com xs;

1 43 A codificao resultante pode ser observada a seguir:


--- Intercala duas listas em ordem no decrescente -intercala xs ys = if (null xs) || (null ys) then xs ++ ys else if head xs <= head ys then head xs : intercala (tail xs) ys else head ys : intercala xs (tail ys)

E a seguir, algumas submisses e avaliaes do HUGS:


Main> intercala [1,3..10] [0,2..10] [0,1,2,3,4,5,6,7,8,9,10] Main> intercala [0,2..10] [1,3..10] [0,1,2,3,4,5,6,7,8,9,10] Main> intercala [0,2..10] [] [0,2,4,6,8,10] Main> intercala [] [] ERROR: Unresolved overloading *** Type : Ord a => [a] *** Expression : intercala [] [] Main> intercala [] [0,2..10] [0,2,4,6,8,10] Main> intercala [0,2..10] [0,2..10] [0,0,2,2,4,4,6,6,8,8,10,10] Main> intercala [9,7..1] [10,8..1] [9,7,5,3,1,10,8,6,4,2] (o que houve que no ficou ordenada?)

Voltemos ao mergesort, ou, em bom portugus, ordenao por intercalao. Soluo : A ordenao de uma lista por mergesort igual intercalao do mergesort da primeira metade da lista com o mergesort da segunda metade. Esta soluo explora a noo de rvore binria. Neste caso, a lista original dividida em 2 partes, cada uma delas em outras duas e assim sucessivamente at que esta quebra no seja mais possvel. A figura Fig. 17.1 ilustra o processamento da ordenao de uma lista.

1 44

Vejamos ento como fica a codificao em HUGS.


--- ordena uma lista pela intercalao da ordenao de -- suas duas metades -mergesort xs = if null (tail xs) then xs else intercala (mergesort m) (mergesort n) where m = take k xs n = drop k xs k = div (length xs) 2

1 45 Main> mergesort [1..10] [1,2,3,4,5,6,7,8,9,10] (1593 reductions, 2185 cells) Main> mergesort [10,9..1] [1,2,3,4,5,6,7,8,9,10] (1641 reductions, 2236 cells)

17.2.3. QUICKSORT - Existe uma maneira muito famosa de resolver o mesmo problema de ordenao, usando ainda a noo de diviso e conquista, muito parecida com o mergesort. Implementaes desta soluo reduzem sensivelmente o nmero de comparaes necessrias e so, portanto muito utilizadas. Soluo : Na verso usando o mergesort dividamos a instncia original exatamente ao meio. Nesta vamos dividir tambm em duas, mas com seguinte critrio: a primeira com os elementos menores que um elemento qualquer da lista e a segunda com os elementos maiores ou iguais a ele. Este elemento denominado pivot e existem vrias formas de escolh-lo. A melhor escolha aquela que produzir as sublistas com comprimentos bem prximos, o que repercutir no desempenho da avaliao. Aqui nos limitaremos a escolher como pivot o primeiro elemento da lista. Assim sendo, aps obter a ordenao das duas listas, basta juntar a ordenao da primeira, com o pivot e finalmente com a ordenao da segunda. A figura Fig. 9.2 ilustra a aplicao do quicksort a uma instncia do problema.

1 46

E a seguir vejamos a codificao.


quicksort xs = if (null xs) || (null (tail xs)) then xs else quicksort (sublista (< pivot) (tail xs)) ++ [pivot] ++ quicksort (sublista (>= pivot) (tail xs)) where pivot = head xs

Convidamos o leitor a apreciar e discutir a elegncia, a compacidade e a clareza da descrio do quicksort.

1 47 Vejamos a avaliao de algumas instncias:


Main> quicksort [4,5,6,7,8,3,2,1] [1,2,3,4,5,6,7,8] (595 reductions, 755 cells) Main> quicksort [1..10] [1,2,3,4,5,6,7,8,9,10] (1536 reductions, 1881 cells) Main> quicksort [10,9..1] [1,2,3,4,5,6,7,8,9,10] (1541 reductions, 1952 cells) Main> mergesort [10,9..1] [1,2,3,4,5,6,7,8,9,10] (1647 reductions, 2283 cells) Main> mergesort xs == quicksort xs where xs = [1..10] True (2805 reductions, 3563 cells) Main> mergesort [2,14,16,23,29,35,47,68,70,90] [2,14,16,23,29,35,47,68,70,90] (1414 reductions, 1922 cells) Main> quicksort [2,14,16,23,29,35,47,68,70,90] [2,14,16,23,29,35,47,68,70,90] (1357 reductions, 1618 cells) Main> ordena [2,14,16,23,29,35,47,68,70,90] [2,14,16,23,29,35,47,68,70,90] (236 reductions, 336 cells)

17.3. PROCESSAMENTO DE CADEIAS DE CARACTERES: As cadeias de caracteres, como j vimos, tambm so listas, portanto o uso de recurso com cadeias segue as mesma recomendaes. Para ilustrar vamos apresentar alguns exemplos. Exemplo 01 - [Palndromo] Dada uma cadeia de caracteres verifique se um palndromo. Segundo o dicionrio, um palndromo uma frase ou palavra, que no importando o sentido que se l, significa a mesma coisa. Por exemplo, "Socorram-me subi no nibus em Marrocos". Vejam que a quantidade de espaos, os separadores e os trminos de palavra no so considerados. Aqui vamos tratar a questo de forma simplificada, os separadores sero tratados como caracteres comuns. Soluo : Neste caso, importante observar que podemos olhar a cadeia como sendo formada por pares de valores eqidistantes dos extremos. Um cadeia palndromo se os seus extremos so iguais e o meio da lista um palndromo. A base da recurso so as cadeias vazias ou aquelas com apenas um elemento.

1 48 palndromo [x0, x1, x2, x3, x4, x5, ..., x n-1] x0 = x n-1 & palndromo [x1, x2, x3, x4, x5, ..., ] x0 = & (x1 = x n-1 & palndromo [ x2, x3, x4, x5, ..., ] ) x0 = & (x1 = x n-1 & ( X2 = Xn-2 & palndromo [x3, x4, x5, ..., ] )) Figura 17.1 desenvolvimento da computao da funo palndromo

Vejamos ento a codificao em HUGS e a avaliao para algumas instncias. E agora uma avaliao de algumas listas candidatas a palndromo:
--- Verifica se uma sentena Palndromo --palindromo xs = if null xs || null (tail xs) then True else (head xs == last xs) && palindromo (meio xs) where meio xs = init (tail xs)

Seguindo nosso padro de apreentao,vejamos como ficam algumas avaliaes:


Main> palindromo "socorrammesubinoonibusemmarrocos" True (687 reductions, 698 cells) Main> palindromo "socorram-me subi no onibus em marrocos" False (891 reductions, 907 cells) Main> palindromo "ama" True (31 reductions, 43 cells) Main> palindromo "papagaio" False (29 reductions, 45 cells) Main> palindromo "arara" True (49 reductions, 61 cells)

1 49 Exemplo 02 - [Prefixo] Dadas duas cadeias de caracteres verifique se a primeira idntica subcadeia formada pelos primeiros caracteres da segunda. Por exemplo, "aba" prefixo da cadeia "abacaxi" e "pre" prefixo de "prefixo". Soluo : De imediato podemos dizer que uma cadeia xs prefixo de uma cadeia ys quando: i) ii) iii) o primeiro elemento de xs igual ao primeiro elemento de ys e; o restante de xs prefixo do restante de ys.

Quanto base da recurso, temos que considerar duas situaes: i) ii) A primeira tem como base que a cadeia vazia prefixo de qualquer outra cadeia; A segunda leva em conta que nenhuma cadeia pode ser prefixo de uma cadeia vazia (exceto a cadeia vazia). Vejamos como fica em Haskell:
--- Verifica se uma cadeia xs prefixo -- de uma segunda (ys) -prefixo xs ys = if null xs then True else if null ys then False else (head xs == head ys) && prefixo (tail xs) (tail ys)

As avaliaes de expresses a seguir nos permitem observar o funcionamento de nossa descrio:


Main> prefixo "aba" "abacadraba" True Main> prefixo "" "abacadraba" True Main> prefixo "pre" "prefixo" True Main> prefixo "prefixo" "pre" False Main> prefixo "prefixo" "" False

1 50 Exemplo 03 - [Casamento de Padro] Verificar se uma cadeia satisfaz um determinado padro um processamento muito til e constantemente realizado na prtica da computao. Aqui nos ateremos a uma forma simplificada deste problema que consiste em verificar se uma cadeia subcadeia de outra. Soluo : Uma rpida inspeo nos leva constatao de que o problema anterior parecido com este, exceto pelo fato de que a primeira cadeia pode ocorrer em qualquer lugar da segunda. Podemos dizer ento que a primeira cadeia ocorre na segunda se ela um prefixo da primeira ou se ela ocorre no resto da segunda. Vejamos como fica em HUGS:
--- Verifica se uma cadeia -- de uma outra (ys) -subcadeia xs ys = if null then else xs subcadeia ys || null (tail ys) False prefixo xs ys || subcadeia xs (tail ys)

A avaliao das expresses a seguir ajuda no entendimento:


Main> True Main> True Main> True Main> True Main> False Main> False subcadeia "" "prefacio" subcadeia "pre" "prefacio" subcadeia "cio" "prefacio" subcadeia "efa" "prefacio" subcadeia "acido" "prefacio" subcadeia "efa" ""

Exerccios: i) ii) iii) iv) v) vi) Jonoihoi Ionoihno Noinboiho Oioho[ Oihnoihjo Oinoihjpo

1 51

18. EXERCCIOS COMPLEMENTARES


Apresentamos a seguir alguns exerccios que visam suprir material para o leitor que desejar praticar um pouco mais com a programao atravs de descries funcionais. Para cada um dos problemas a seguir d uma descrio funcional na linguagem Haskell. Sugerimos que o leitor edite as definies em um arquivo de scripts e use essas definies em alguns exemplos para certificar-se se suas definies esto corretas. Para cada funo elabore uma planilha de teste, indicando os valores para os quais as mesmas sero avaliadas e quais os resultados esperados, insira a planilha como comentrio, conforme se ilustra a seguir. Exemplo : Descrio do problema: Dados dois nmeros a e b mapeie-os no maior deles. Soluo: -- def : mapeia dois nmeros a e b no maior deles -- teste : maior 3 4 ==> 4; maior 4 3 ==> 4; maior 3 3 ==> 3 maior a b = if a > b then a else b 18.1 Grupo I Problemas Gerais 1. Dados quatro nmeros p1, p2, p3 e p4, mapeie-os na sua soma se a diviso desta soma por 5 exata e em zero caso contrrio. 2. Dado um nmero inteiro, verifique se ele pertence ao intervalo (0,100) e divisvel por 3 e por 5. 3. O operador || (OU inclusivo), provido pelo Hugs, mapeia dois valores booleanos a e b em True quando pelo menos um deles True e em False caso contrrio. Escreva uma funo que denominaremos de oux (OU exclusivo) que se assemelha ao OU inclusivo mas que mapeia em False quando ambos valores so True. 4. Dados 3 valores a, b e c determine a mdia aritmtica dos valores extremos. ? media 10 35 4 19.5 ? media 50 10 8 29

1 52 5. Dados trs nmeros inteiros distintos, calcule o quadrado do sucessor do maior nmero. 6. Dados 3 pontos p1, p2 e p3, do plano cartesiano, determine se eles formam um tringulo, e se for o caso,determine sua rea. 7. A empresa LucroCerto decidiu dar aos seus funcionrios um abono de Natal. A gratificao ser baseada em dois critrios: o nmero de horas extras trabalhadas e o nmero de horas que o empregado faltou ao trabalho. O critrio estabelecido para calcular o prmio : subtrair dois tros das horas que o empregado faltou de suas horas extras, obtendo um valor que determina o nmero de pontos do funcionrio. A distribuio do prmio feita de acordo com a tabela abaixo. Pontos Obtidos de 41 31 21 11 1 a ... 40 30 20 10 Prmio em R$ 500,00 400,00 300,00 200,00 100,00

8. Considere dois pontos p1 e p2 no plano cartesiano. Estamos interessados em identificar as seguintes relaes entre eles: i. por p1 e p2 podemos traar uma reta paralela ao eixo horizontal; ii. por p1 e p2 podemos traar uma reta paralela ao eixo vertical; iii. p1 e p2 esto no mesmo quadrante; iv. p1 e p2 esto em quadrantes diferentes; v. p1 e p2 esto em quadrantes opostos (1 e 3 ou 2 e 4); vi. p1 e p2 esto em quadrantes adjacentes (1-2, 2-3, 3-4, 1-4); 9. Dados dois pontos no plano cartesiano, eles podem ser idnticos, podem determinar uma reta paralela a um dos dois eixos, ou determinar uma reta que corta os dois eixos. Determine qual o caso em que dois dados pontos se enquadram e, se ocorre o terceiro, qual a rea do tringulo determinado pela reta e os eixos. 10. Dados um segmento de reta r, atravs de dois pontos, a e b, localizados no primeiro quadrante, e um ponto p qualquer, determine se p pertence ao segmento, ou se p pertence ao prolongamento de r, ou ainda se p est acima da reta ou se p est abaixo.

1 53 11. Dados o canto superior esquerdo e o canto inferior direito de um retngulo R, paralelo aos eixos, determine quantos quadrantes so cobertos por ele. 12. Dados dois retngulos, paralelos aos eixos, determine se h ou no interseo entre eles. Determine ainda, se for o caso, a rea de interseo entre dois retngulos. 13. Considere um retngulo definido por seus cantos superior esquerdo e inferior direito. Podemos traar um losango a partir de pontos localizados no ponto mdio de cada um de seus lados. Definimos com isso seis regies. i. fora do retngulo; ii. o tringulo superior esquerdo; iii. o tringulo superior direito; iv. o tringulo inferior direito; v. o tringulo inferior esquerdo; vi. o interior do losango. vii. Dado um ponto p, determine a sua localizao. viii. 14. Dados 3 nmeros, determine se com os trs eu posso formar uma progresso aitimtica (PA), onde dois deles quaisquer so termos consecutivos e um terceiro a razo. 15. Dados 3 nmeros, determine se com os trs eu posso formar uma progresso gepmtrica (PG), onde dois deles quaisquer so termos consecutivos e um terceiro a razo. 16. Considere que o preo de uma passagem de avio em um trecho, pode variar dependendo da idade do passageiro. Pessoas com 60 ou mais anos de idade pagam apenas 60% do preo total. Crianas at 10 anos, pagam 50% e bebs (abaixo de 2 anos) pagam apenas 10%. Escreva uma definio que tenha como entrada o valor nominal da passagem e a idade do passageiro e produz o valor a ser pago. 17. Dados dois nmeros inteiros, considere que eles possuem no mximo 5 algarismos. Determine em que quantidade de algarismos na mesma posio eles so iguais. ?qalg 123 124 2 ?qalg 1234 4321 0

1 54 18. Dados dois pontos p e q, no plano cartesiano, tome a origem dos eixos como o eixo dos ponteiros de um relgio analgico, p como a posio da extremidade do ponteiro maior e q como a do ponteiro menor. Determine a quantidade total de minutos decorridos desde o incio do dia. 19. Dados trs nmeros a, b, c. Determine quais das seguintes relaes eles mantm entre si: a) os trs so diferentes; b) apenas dois so iguais; c) os trs so iguais. 20. Considere que um dado nmero inteiro est armazenando um valor v escrito na base octal. Pede-se: a) verifique se realmente o nmero dado est na base 8; b) determine qual o valor deste nmero na base decimal. 21. Considere um tabuleiro de xadrez de dimenses infinitas, considere ainda que a numerao das casas dada por um par de nmeros inteiros. Sabemos que o cavalo possui oito movimentos conforme a figura 3. m3 m4 C m5 m6 m7 m8 M3 m2 m1

Escreva uma funo para determinar a nova posio obtida pela aplicao de cada movimento posio X. O resultado dever ser produzido com um nmero de 2 casas.

18.2 Grupo 2 Geomtricos I Dado um ponto P(x,y) do plano cartesiano, defina funes que descrevam a sua pertinncia nas situaes abaixo especificadas: 1. Um retngulo (com lados paralelos aos eixos cartesianos) dado pelas coordenadas do canto superior esquerdo e do canto inferior direito, como mostrado na figura.

1 55

2. Um losango , com os seus eixos paralelos aos eixos cartesianos, dado pelas coordenadas do vrtice esquerdo e do vrtice superior, como mostrado na figura.

3. Um crculo dado pelo seu centro C e seu raio r.

4. A regio R1 (regio cinza), do retngulo dado pelas coordenadas do canto superior esquerdo e do canto inferior direito, como mostrado na figura abaixo:

5. A regio R2 do losango (regio cinza), sendo dados os pontos E e D do retngulo e sabendo-se que o crculo tangente aos lados do losango.

1 56

18.3 Grupo 3 Geomtricos II Resolva os problemas abaixo priorizando o uso de modularizao. Procure tambm utilizar quando for adequado, o conceito de definio local atravs da clusula where. 1. Considere a figura e descreva uma funo para calcular cada uma das reas da regies R1, R2 e R3. A funo tem como parmetros as coordenadas dos pontos P (x1, y1) e Q (x2,y2). Observe que o ponto Q o centro do crculo, que a altura do tringulo issceles igual ao raio do crculo e que um dos lados do tringulo paralelo ao eixo dos x.

Y Q y2 P R1 R2 2 R1 X R3

y1

x1

x2

2. Dada uma reta descrita por dois pontos P (x1, y1) e Q (x2,y2), escreva uma funo que determine o valor da coordenada no eixo dos y a partir de uma coordenada fornecida no eixo dos x. coordy x1 x2 y1 y2 x = ... 3. Considere a figura 2 e descreva uma funo para determinar cada uma das reas das regies R1, R2 e R3. A funo tem como parmetros as coordenadas dos pontos P e Q. Observe que um dos lados do tringulo issceles coincide com o eixo dos x e que um dos seus vrtices a origem. Observe ainda que os lados do retngulo so paralelos aos eixos.

1 57

Y y1 R2 y2 R3 x1 x2 X R1 1

4. Considere um pea de altura h cuja base e o topo so hexgonos de lado l. Considere ainda que esta pea possui um furo cilndrico de raio r com centro no eixo. Descreva uma funo para determinar o volume da pea.

5. Considere uma pea cilndrica com raio r e altura h. Considere ainda que esta pea possui um furo em forma hexagonal de lado l, com centro no eixo da pea. Descreva uma funo para determinar o volume da pea.

1 58 6. Considera a figura abaixo, onde est representada a regio R correspondente a interseo de dois crculos de mesmo raio r. Escreva uma funo para calcular a rea dessa regio, sabendo-se que dado o ngulo do setor do crculo determinado pelos pontos de interseo das duas circunferncias.

r R

7. Descreva uma funo que calcule a rea (representada pela cor cinza) de uma flor formada por quatro crculos de mesmo raio r, cujos centros so os vrtices de um quadrado, conforme ilustrado na figura a seguir. O miolo da flor um crculo oco de raio r1.

18.4 Grupo IV - Geomtricos 3 1) Problemas de pertinncia de um ponto P (x,y) nas regies hachuradas, utilizando expresses lgicas. a) Descrio da regio hachurada: o centro C (c1, c2) e o raio r do crculo maior so dados. Considera-se tambm que os raios dos crculos inscritos so r/3 e 2r/3.

1 59 b) Descrio da regio hachurada: seja E (x1, y1) o vrtice superior esquerdo de um quadrado de lado a paralelo aos eixos cartesianos. Considere que as ptalas da flor so formadas por semi-crculos de raio a/2 e centros no ponto mdio de cada lado do quadrado e que o miolo formado por dois crculos de raios a/4 e a/8. E a

a/2 a/8 a/4

c) Descrio da regio hachurada: o centro C (c1, c2) e o raio r do crculo maior so dados. Considera-se tambm que os raios dos crculos inscritos so r/2 e r/4.

1 60 2) Problemas de mapeamento de um ponto P (x,y) em sua regio de pertinncia, utilizando descries condicionais, de forma adequada. a) Sejam E (x1, y1) e S (x2, y2) os vrtices esquerdo e superior, respectivamente, de um losango cujos eixos so paralelos aos eixos cartesianos. Considere as regies descritas abaixo:
regio 1: regies hachuradas, externas losango, no crculo superior regio 2 : regies hachuradas, interna losango, no crculo superior regio 3 : no losango e fora dos ciculos regio 4: regies hachuradas, externas losango, no crculo inferior regio 5 : regies hachuradas, interna losango, no ao ao

ao ao

b) So dados os pontos E (x1, y1) e D (x2, y2) e sabe-se que o raio dos semicrculos extermos igual (y1 - y2 ) /2.

1 61 19. APLICAES Neste captulo apresentamos uma srie temtica de exerccios, buscando dar ao leitor uma viso mais ampla das possibilidades de uso da programao funcional. A inteno apresentar vrios contextos onde precisamos programar computadores. Em todos, o contexto descrito e vrios exerccios so apresentados. Aos professores e estudantes, sugerimos que o contexto sirva de pretexto para a formulao e resoluo de novos exerccios. Comeamos pelo Domin Bar, onde, buscamos na ludicidade do jogo, apresentar as necessidades de manipular informao. Na seqncia apresentamos uma srie de problemas considerando as necessidades de informao de um Banco de Sangue, o manuseio de mensagens de um Correio Eletrnico, a organizao de uma Lista de Compras, um sistema de Passagens Areas, Gerncia Acadmica, Agncia de Turismo e exerccios sobre Espetculos Teatrais. 19.1 O DOMIN BAR: O domin de nmeros uma coleo de pedras, utilizado na maioria das vezes como um excelente passatempo. Das tantas formas de utilizar o domin, destacamos uma, utilizada no Amazonas, principalmente em Manaus, mas tambm em muitas praias pelo mundo afora onde existirem amazonenses, em particular nas praias de Fortaleza. Os Amazonenses costumam cham-la de domin bar", em homenagem a uma tribo que habitava a regio onde foi fundada a cidade de Manaus. A maioria dos exerccios deste captulo foram desenvolvidos em Manaus, no final da dcada de 80. De l pra c, vrios outros foram acrescentados, mas a lista como um todo permanece indita. A inteno desta seo apresentar alguns poucos exerccios resolvidos e propor outros. A idia no desenvolver o jogo e sim, inspirar-se em situaes do jogo para propor exerccios interessantes e desafiadores. Deixamos o desenvolvimento do jogo completo como sugesto para o trabalho em grupos. Ao final do captulo discutiremos um pouco sobre a programao do jogo. Preliminares: O material do jogo um conjunto formado por 28 "peas", cada uma delas com duas "pontas". Cada "ponta" representa um valor de 0 (zero) a seis (6), perfazendo portanto 7 valores diferentes. Cada valor possui um nome prprio: o Zero chama-se "branco", o um chama-se "s", o dois o "duque", o trs chama-se "terno", o quatro a "quadra", o cinco a "quina" e o seis denomina-se "sena". O nome de uma "pedra" dado pelo nome de suas "pontas", por exemplo, "quina e terno", o nome da "pedra" que possui em uma ponta o valor 5 e na outra o valor 3. As pedras que possuem o mesmo valor nas duas pontas so denominadas de "carroa". Para cada tipo de valor existem 7 pedras, por exemplo, para o "terno" teremos: terno e branco, terno e s, terno e duque, carroa de terno, quadra e terno, quina e terno, sena e terno. O jogo , em geral, disputado por duplas, ganhando a que fizer o maior numero de pontos, a partir de um mnimo pr-estabelecido. A seguir apresentamos em detalhes os vrios elementos do jogo.

1 62 Peas do Jogo: Os elementos do jogo so (28) vinte e oito peas, cada uma com duas pontas, na qual marcado um valor que varia de 0 a 6. Para jogar, as "pedras" so embaralhadas e escolhidas pelos jogadores. A cada jogador cabem 7 pedras. Com o desenrolar do jogo a quantidade de pedras vai sendo decrescida, at que, eventualmente chegue em zero. Participantes: duas duplas (eventualmente pode ser jogado individualmente, com 2, 3 ou 4 jogadores). Objetivo: atingir um total mnimo de 200 pontos. Vence o jogo a dupla que ao final de uma rodada tiver o maior nmero de pontos. Dinmica: o jogo se desenvolve em uma quantidade qualquer de eventos menores denominados de rodada. A figura 18.1 ilustra um instante de jogo.

Figura 18.1 um instante do jogo de domin, com quatro pontas abertas: terno, s, duque e quadra.

Rodada: em uma rodada, um aps o outro, no sentido horrio, os jogadores vo fazendo suas jogadas, combinando suas pedras de domin com a figura que j est formada na mesa de jogo.

1 63 Pontuao: existem 4 formas para obter pontos: 1. Durante o jogo, a figura formada na mesa possui 1 (quando existe apenas uma pea assentada), 2, 3 ou 4 pontas. soma dos valores dessas pontas denomina-se de: os pontos da mesa. Quando essa soma produz um mltiplo de 5, o jogador que sentou a ltima pedra pode requerer que eles sejam anotados em favor de sua dupla. Veja que s o jogador que sentou a pedra pode reivindicar os pontos e isto tem que ocorrer antes que o prximo jogador sente a sua pedra; 2. Quando um jogador no possui pedra para colocar na mesa (ou seja, uma que combine com uma das pontas), ele passa a vez, e a dupla adversria ganha 10 pontos. Se um jogador percebe que com a colocao de sua pea ele conseguir fazer com que todos os demais passem, inclusive o seu parceiro, ele pode anunciar que deu um passe geral e com isso ganhar de bnus 50 pontos. 3. Quando um jogador descarta sua ltima pea em uma rodada diz-se que ele bateu, e, portanto ganhou a rodada. Com isso ele ganha de bnus 10 pontos e mais o mltiplo de 5 ligeiramente inferior soma dos valores constantes nas peas que sobraram nas mos dos adversrios (garagem). Se a batida for feita com uma carroa, o bnus de 20 pontos. 4. Quando ocorre uma situao onde nenhum dos jogadores consegue jogar, embora estejam com peas na mo, diz-se que o jogo est fechado. Neste caso ganha a rodada a dupla cuja soma dos valores das peas for o menor. A soma das peas da dupla adversria computada em seu favor, como no caso 3. Posio dos Jogadores: Os membros de cada dupla so colocados em posies alternadas, de forma que as jogadas (colocao de peas) seja feita de forma alternada entre as duplas adversrias. Por exemplo, em um jogo presencial, podemos usar, como suporte para colocao das peas, uma mesa de quatro lugares, ficando os parceiros sentados frente-a-frente. Distribuio das Peas: a distribuio das 28 peas entre os 4 jogadores deve ser feita de forma aleatria. Na prtica, em um jogo com peas fsicas, viram-se as peas de cara para baixo e mistura as peas com as mos. Cada jogador vai retirando as suas prprias peas. Quem comea uma rodada: Uma rodada sempre iniciada com a colocao de uma carroa. Na primeira rodada do jogo, a carroa a ser utilizada de sena (6), cabendo pois ao jogador que a tirou comear o jogo. As rodadas seguintes so iniciadas pelo jogador que bateu a rodada anterior, com a carroa que ele preferir. Se ele no possui carroa, ele passa e o jogador seguinte (da dupla adversria) inicia o jogo, se este tambm no possuir, passa a frente. Uma Jogada: Estando na sua vez de jogar, o jogador deve escolher uma das pedras de sua mo, e coloca-la na mesa de jogo, combinando com alguma das pontas abertas. A escolha da pea a ser jogada deve contribuir para o objetivo da dupla que ganhar o jogo, isso significa, em linhas gerais, escolher uma pedra

1 64 que me permita fazer o maior nmero de pontos e, quando isso no for possvel, escolher uma pedra que reduza o nmero de pontos que os adversrios possam fazer com base em minha jogada. H, entretanto algumas nuances a serem consideradas: Quando eu jogo fazendo pontos devo buscar maximizar meus pontos e minimizar os que o jogador adversrio possa fazer a partir da minha jogada; Se o jogo estiver prximo do trmino, e a dupla adversria ameaa completar os 200 pontos, pode ser desejvel adiar o trmino, no fazendo os pontos. Por exemplo, suponha que a dupla adversria tem 185 pontos e a minha 130. Se eu tiver uma pea na mo que faz 25 pontos, mas se possvel ao adversrio possuir uma pea que lhe permita fazer 15 pontos, eu posso escolher outra pea, deixando assim de obter os 25 pontos; Quem abre uma rodada, bater a rodada a menos que passe. Tendo em vista que ao ganhar uma rodada, h bnus para a dupla, posso deixar de marcar ponto visando vencer a rodada; Idem para tentar evitar que a dupla adversria ganhe a rodada (quando foro a passada de um adversrio que comeou a rodada, a batida passa para o meu parceiro). Um passe geral d um bnus de 50 pontos, isso pode me levar a busc-los, desde que as condies do jogo, definidas pelas peas de minha mo, combinadas com o que j foi jogado, se mostrem propcias.

Exerccios: A seguir apresentamos alguns exerccios, baseados no domin. Para fins didticos separamos em grupos. Grupo I 1. Escreva a funo pedrap que associe um par a True se e somente se (sss) o par uma representao vlida para uma "pedra" e False caso contrrio. Exemplos de uso: 1. pedrap (2, 7) ==> False 2. pedrap ((-3), 4) ==> False 3. pedrap (3,4) ==> True Soluo: pedrap (x,y) = validap x && validap y validap x = elem x [0..6] 2. Escreva a funo maop que associe uma lista de pares de inteiros a True sss a lista uma representao vlida para a "mo" de um jogador e False caso contrrio.

1 65 Exemplos de uso: 1. 2. 3. 4. maop [ ] True maop [((-3), 4)] False maop [(3,4)] True maop [ (1,2), (1,5), (2,0), (2,4), (3,3), (1,1), (0,0), (4,0)] False

Soluo: maop [ ] = True maop (x:xs) = (length xs <= 6) && pedrap x && maop xs

3. Escreva a funo carrocap que associe um par a True sss o par uma "carroa" e False caso contrrio. 4. Escreva a funo tem_carroca_p que associe uma "mo" a True sss a mo possuir pelo menos uma carroa e False caso contrrio. 5. Escreva a funo tem_carrocas que associe a uma "mo" a lista das "carroas" nela contida. Grupo II Em vrios momentos do jogo faz-se necessrio saber a quantidade de pontos associado uma coleo de pedras. Em particular, no final do jogo, quem "sentou" a sua ltima pedra faz jus "garagem" que determinada a partir dos pontos que restaram na(s) mo(s) dos adversrios. 6. Escreva a funo pontos que associe uma lista de "pedras" a soma dos pontos das pedras nela contidos. Onde os pontos de uma pedra a soma de suas pontas. Soluo: pontos [ ] =0 pontos (x:xs) = ponto x + pontos xs where ponto (x,y) = x + y 7. Escreva a funo garagem que associe uma lista de "pedras" ao maior mltiplo de 5 (cinco), menor ou igual soma dos pontos nela contidos. 8. Escreva a funo pedra_igual_p que associe dois pares de inteiros a True sss representam a mesma pedra e False caso contrrio. bom lembrar que a ordem das pontas irrelevante, assim (2,4) e (4,2) representam a mesma pedra.

1 66 9. Escreva a funo ocorre_pedra_p que associe uma "pedra" e uma "mo" a True sss a "pedra" ocorre na "mo" e False caso contrrio. 10. Escreva a funo ocorre_valor_p que associe um valor vlido para "ponta" e uma "mo" e produza True sss o valor ocorre em alguma pedra da mo e False caso contrrio. 11. Escreva a funo ocorre_pedra que associe a um valor e uma "mo", uma lista contendo as pedras da "mo" que possuem o valor dado. 12. Escreva a funo pedra_maior que associe uma "mo" a pedra de maior valor na "mo" dada. Uma pedra p1 maior que uma outra p2 sss a soma das pontas de p1 for maior que a soma das pontas de p2. 13. Escreva a funo ocorre_valor_q que associe um valor e uma "mo" e produza o nmero de pedras na mo que possuem o valor dado. 14. Escreva a funo ocorre_carroca_q queassocie uma mo quantidade de carroas nela existentes. 15. Escreva a funo tira_maior que associe uma mo a uma lista similar "mo" de onde foi extrada a pedra de maior ponto. 16. Escreva a funo tira_maior_v que associe um valor e uma "mo" lista similar "mo" de onde se extraiu a pedra de maior pontos de um determinado valor para ponta. Grupo III O jogo se desenvolve pela colocao, pelo Jogador da vez, de uma pedra que combine com alguma das "pontas" da "mesa". Num momento genrico do jogo temos quatro pontas disponveis para execuo de uma jogada. Uma ponta pode ser simples ou uma carroa. As carroas so dispostas de tal forma que todos os seus pontos estejam para "fora". Chamaremos "mesa" lista de pontas disponveis para jogada. Pontas simples sero representadas por listas de um elemento e carroas por uma lista com dois elementos idnticos. Por exemplo, a "mesa" ilustrada na Figura 18.2 representada pela qudrupla ( [5,5], [5], [0],[4] ). Uma ponta ainda no aberta representada por lista vazia. Dizemos que h marcao de pontos em uma mesa quando a soma das pontas um mltiplo de 5. Os pontos a serem marcados a soma das pontas, com as carroas contando em

1 67 dobro.

Figura 18.2 desenvolvimento do jogo, no instante em que temos nas pontas externas, uma carroa de quina, uma quina, branco e quadra.

17. Escreva a funo mesap que associe uma qudrupla de listas a True sss a qudrupla for uma descrio vlida de "mesa". Soluo:
mesap (p1,p2,p3,p4) = vponta p1 && vponta p2 && vponta p3 && vponta p4 where vponta (x:y:xs) = if not (null xs) then False else validap x && vponta (y:xs) vponta (x :[ ] ) = validap x validap x = elem x [0..6]

18. Escreva a funo carroca_m_p que associe uma mesa a True sss pelo menos uma das pontas for carroa. 19. Escreva a funo pontos_marcados que associe uma mesa ao o nmero de pontos a serem marcados se a soma das pontas for mltiplo de cinco e zero em caso contrrio.

1 68 20. Escreva a funo pode_jogas_p que associe uma "pedra" e uma "mesa" a True sss a pedra possui uma ponta que combina com pelo menos uma das pontas da mesa. 21. Escreva a funo marca_ponto_p que tenha como entrada uma "pedra" e uma "mesa" e produza True sss a pedra pode ser jogada fazendo pontos em uma das pontas da mesa. Lembre-se que as carroas devem ser contadas pelas duas pontas da pedra. 22. Escreva a funo maior_ponto que tenha associa uma pedra e uma mesa ao nmero da "ponta" da mesa onde pode ser marcado o maior valor de ponto que ser marcado pela pedra. Considere que a em uma "mesa" as pontas so numeradas a partir de zero, da esquerda para a direita. 23. Escreva a funo joga_pedra que associe uma "pedra", uma "mesa" e um nmero de "ponta" da mesa a uma nova mesa obtida ao se jogar a "pedra" na "ponta" indicada. 24. Escreva a funo jogap que associe uma "mo" e uma "mesa" e produza True sss existe pelo menos uma pedra na mo que possa ser jogada em pelo menos uma ponta da mesa. Caso contrrio produza False. 25. Escreva a funo jogada que associe uma "mo" e uma mesa ao nmero da pedra na mo e nmero da ponta na mesa onde pode ser feita a jogada que marque mais ponto. Considere inclusive jogada onde no h marcao de ponto. 26. Escreva a funo faz_jogada que associe uma "mo" e uma "mesa" e produza uma nova "mesa" obtida por se jogar marcando o maior nmero de pontos possvel 19.2 Banco de Sangue: para facilitar o atendimento da demanda por transfuses de sangue o sistema de sade criou os chamados Bancos de Sangue. Como sabemos, cada transfuso s pode ser realizada usando tipos de sangue apropriados. A adequao de um determinado tipo de sangue baseada em estudos cientficos que identificou quatro tipos sangneos, denominados de A, B, AB e O. Outros estudos identificaram ainda a existncia do chamado fator RH que pode ser positivo (+) ou negativo (-), assim o sangue de qualquer indivduo classificado de acordo com esses dois atributos. Por exemplo, dizemos que fulano possui sangue tipo O e fator RH positivo, e abreviamos para O+. Em um dado Banco de Sangue, diariamente, so feitas doaes por pessoas de diferentes tipos sangneos, para as quais feito um registro contendo o nmero da carteira de identidade do doador (RG), o sexo (S), a data da doao (DD), a data de nascimento (DN), o tipo sangneo (TS), o fator RH (RH) e a quantidade doada (QD) (250 ou 500 ml). O sangue doado guardado em recipientes com uma capacidade fixa (250 ml). Tambm, diariamente so feitas requisies pelos hospitais (H), cada requisio indica as caractersticas do sangue (tipo e fator RH) e a quantidade solicitada (QS). Sabemos que homens e mulheres possuem intervalos de tempo diferentes para fazer doaes. Para homens o intervalo mnimo de 2 (dois) meses e para mulheres de 3 (trs). A idade mxima para doadores 60 anos.

1 69 Sejam as seguintes estruturas Doao Requisio (RG, S, DD, DN, TS, RH, QD) (H, TS, RH, QS)

Exerccios: Escreva programas em HUGS para resolver os seguintes problemas: 1. Dada uma lista de doaes, obtenha a quantidade total de sangue doado por tipo sangneo e fator RH. O resultado ser uma tupla (um item para cada combinao de tipo sangneo com fator RH) com triplas explicitando o tipo sangneo, o fator RH e a quantidade total. Quando no houver doao de uma dado par tipo-fator deve ser indicado o valor zero. Por exemplo: ( (A, +, 0), ... (O,+, 5500) ...) 2. Para uma dada lista de doaes, determine a lista dos dias de um dado ms onde as doaes foram menores que a mdia mensal. 3. Dada uma lista de doaes e a data atual, determine a lista de doadores que j esto aptos a fazerem novas doaes. 4. Dada a lista de doadores e o ms, determinar o nmero de doadores que esto aptos a doar sangue naquele ms. (Essa e a questo 3 parecem anlogas, no?) 5. Determine a relao de doadores que fazem doaes com o maior ndice de regularidade. O ndice de regularidade dado pela nmero de vezes que o intervalo entre as doaes coincidem, dividido pelo nmero de doaes menos um. 6. Dada a lista de doadores, verificar o tipo sangneo que mais comumente doado. 7. Dada a lista de doadores e o ano, determine o ms em que houve mais doaes naquele ano. 8. Dada a lista de requisies de um determinado hospital, determinar a lista de tipos sangneos com os respectivos fatores RH, que possuem seus pedidos atendidos pelo banco de sangue. 9. Determinar, para um dado hospital em um determinado ano, a demanda mensal de sangue, por tipo sangneo e fator RH. 10. Determinar a lista de doadores que no esto mais aptos a fazer doaes, considerando a data atual. 11. Considere o estoque atual do banco de sangue, determinado pela funo estoque (prob 1), e uma lista com vrias requisies. Leve em conta que o

1 70 estoque pode ser insuficiente para atender completamente todos os pedidos. Determine o estoque atualizado aps o atendimento dos pedidos e produza uma lista das requisies atendidas, constando a quantidade que foi de fato fornecida. 12. No problema 11, considere que voc deseja atender cada hospital solicitante, de forma proporcional ao seu pedido, considerando os pedidos de cada tipo sangneo separadamente. Por exemplo, suponha que: o total de pedidos de sangue O+ de 12.000 ml, que o hospital h1 solicitou 3.000 ml de sangue O+ e que no estoque 8.000 ml. Podemos observar que o pedido para o sangue O+ do hospital h1 representa 25 % do total. Neste caso o hospital h1 ser atendido com 25 % de 8.000 ml que representa 2.000 ml. Produza uma lista como os pedidos atendidos e outra com os pedidos pendentes. 13. Considere a poltica de atendimento do problema 12 mas leve em conta que um dado pedido deve ser atendido completamente. Considere o exemplo do problema anterior, e suponha que os pedidos do hospital h1 para o sangue O+ so 4, (h1, O, +, 1.500), (h1, O, +, 1.000) e (h1, O, +, 250) e (h1, O, +, 500). Neste caso, considerando que os pedidos esto em ordem de prioridade, seriam atendidos os pedidos (h1, O, +, 1.500) e (h1, O, +, 250). 14. Modifique a poltica de atendimento do problema 14 para que o atendimento seja tal que o hospital h1 use da melhor forma possvel a proporcionalidade que lhe cabe. No caso do exemplo apresentado no problema 14, o pedido de 250 ml seria descartado visto que atendendo o pedido de 500 ml o hospital h1 estar usando melhor a parte que lhe cabe. (escolher a combinao mais apropriada)

19.3 Correio Eletrnico: Considere um sistema de mensagens eletrnicas. Uma mensagem pode ser descrita por uma tupla contendo o remetente, o destinatrio, a data de envio, o assunto e o corpo da mensagem. Mensagens podem ser acumuladas em listas para posterior acesso. Para facilitar o acesso podemos construir ndices baseados nos dados contidos na mensagem. Por exemplo, podemos ter um ndice baseado no remetente para facilitar o acesso a todas as mensagens de um dado remetente. Considere as seguintes estruturas: mensagem ndice (remetente, destinatrio, data, assunto, corpo) [ (argumento1,[ordem na lista de mensagens]), (argumento2, []), ...]

Exerccios: Elabore programas em HUGS, usando recurso, para atender aos seguintes problemas. A interface (nome e parmetros) das funes dado em cada uma das questes. 1. (indexa msgs) Dada uma lista de mensagens, produza o ndice das mensagens por remetente. Um ndice ter a seguinte estrutura: [ (remetente1, lista de ocorrncias), (remetente2, lista de ocorrncias), ...] onde lista de

1 71 ocorrncias formada pela posio na lista de mensagens onde o remetente ocorre. Por exemplo: [ (jose@inf.ufes.br, [1, 23]), (maria@inf.ufes.br, [10, 20, 50]), ...] 2. (consulta r p) Considere definidos um ndice por remetente, um ndice por palavras constantes no assunto das mensagens e uma lista de mensagens. Dados um remetente (r) e uma palavra(p), obtenha a lista de mensagens enviadas por r onde a palavra p ocorre no assunto. remetentes palav_assunto mensagens = [(remetente1, [...]),(remetente2, [...]), ... ] = [ (palavra1. [...]),(palavra2. [...]), ... ] = [ mensagem1, mensagem2, mensagem3, ... ]

3. (msgPmes a r msgs) Dado um ano (a), um remetente (r) e uma lista de mensagens (msgs), verificar a quantidade mensagens enviadas por r em cada ms. 4. (busca p ind msgs) Considere um ndice construdo na forma de lista ( indb). O primeiro elemento um par com uma palavra (p) e a lista de mensagens (msgs) onde p ocorre, o segundo elemento uma lista no mesmo formato de indb, para as palavras menores que p e o terceiro para as palavras maiores que p. ndice = [ (palavra1, [...]), ndice para palavras menores que p, ndice para palavras maiores que p] Quando no houver palavras menores ou maiores que uma dada palavra, o ndice igual a uma lista vazia. Dada uma palavra p, o ndice (indb) e a lista de mensagens (msgs), descreva a lista mensagens onde p ocorre, usando o ndice dado.

5.(palavPassunto msgs) Considere definida uma lista de palavras irrelevantes


(lis). Dada uma lista de mensagens (msgs) produza um ndice com as palavras distintas que ocorrem nos assuntos das mensagens e no ocorrem em lis. Para cada palavra deve ser produzido tambm a lista das posies na lista de mensagens (msgs) onde ela ocorre. lis = [ palavra1, palavra2. ... ]

6. (releva msgs li lf) Dada uma lista de mensagens podemos obter uma lista de palavras relevantes. Define-se como palavra relevante em uma lista mensagens (msgs) aquelas cuja freqncia satisfazem um intervalo para o qual so dados um limite superior (ls) e um limite inferior (li).

1 72

7.(constante msgs a) Dada uma lista de mensagens (msgs), determinar a lista


de remetentes que enviaram pelo menos uma mensagem para cada ms de um dado ano a.

8.(freqData msgs m) Para uma dada lista de mensagens desejamos obter a


quantidade de mensagens para cada dia de um dado ms m. 9. (identico indb1 indb2) Dados dois ndices no formato de rvore binria de pesquisa desejamos verificar se so idnticos. Dizemos que dois ndices so idnticos quando a palavras e as listas de ocorrncia coincidem e os subndices das palavras menores e o das palavras maiores respectivamente so idnticos. ndice = ( (palavra1, [...]), ndice para palavras menores que p, ndice para palavras maiores que p) 10. (palavOrd indb) Dado um ndice no formato de rvore binria de pesquisa produza uma lista das palavras nele contidas de tal forma que as palavras se apresentem em ordem alfabtica crescente. 11. (resgate indb) Dado um ndice no formato de rvore binria de pesquisa produza uma lista das palavras que ocorrem em cada mensagem. A lista resultante ter o seguinte formato:
[ [palavras da mensagem de ordem 0], [palavras da mensagem de ordem 1 ], ... ]

12. (balance arbinpq) Uma rvore binria de pesquisa est balanceada se e somente se a quantidade (q1) de elementos no subindice das palavras menores difere da quantidade (q2) de elementos no subindice das palavras maiores de no mximo um (1) e q1 maior ou igual a q2. q2 + 1 >= q1 >= q2

13.(insOrd indb msg) Dados um ndice (indb) no formato de rvore binria de


pesquisa e uma mensagem (msg), descreva a nova rvore obtida pela insero das palavras das mensagem (msg), exceto as irrelevantes.

14.(perfil msg diret fga) Um diretrio uma lista de assuntos, cada um dos
quais associado a uma coleo de palavras. Dada uma mensagem e um diretrio podemos atribuir mensagem um perfil que uma lista de valores indicando o grau de aproximao (ga) dela com cada assunto. O ga de uma mensagem com respeito a um assunto pode ser obtido com base na freqncia com que as palavras a ele associadas ocorrem na mensagem.

1 73 Considere que a funo que calcula o ga fornecida e opera sobre uma lista de inteiros. Considere os seguintes formatos:
Diretrio Perfil [ (assunto1, [palavra1, palavra2, ...]), (assunto2, [palavra1, palavra2, ...]), ...] [ (assunto1, ga1), (assunto2,ga2), ...]

19.4 Lista de Compras: Para realizar um determinado projeto necessitamos adquirir certos componentes eletrnicos. No mercado de componentes existem vrios fornecedores que vendem seus produtos com preos diferenciados. A escolha da melhor alternativa para satisfao de nossas compras depende de vrios fatores, dos quais o melhor preo um dos mais importantes. Considere as seguintes definies:
Tabela Preo de Uma lista contendo todos os preos dos componentes comercializados por um determinado revendedor. Cada elemento da lista um par no formato (material, preo). Exemplo: [(potenciometro, 2.50), (resistor-100k, 0.30), (capacitor-10mF,0.50), (indutor-10R,3.00)] Pedido de Uma lista contendo todos os materiais necessrios para um determinado projeto, Compra com suas respectivas quantidades. Cada elemento da lista um par no formato (material, quantidade). Exemplo: [(transformador, 50), (fonte DC, 10), (resistor-200k,100)] Lista de Uma lista contendo a tabela de preos de todos os revendedores, no formato: Revendedores [ (revendedor1, [tabela de preo] ), ...]

Exerccios: Elabore programas em HUGS, usando recurso, para atender aos seguintes problemas. O nome das funes dado em cada uma das questes. 1. (custo) Dado o resultado da pesquisa de preos de um pedido de compra, para um certo fornecedor, no formato [ (material1, qtde, preo), (material2, qtde, preo), ... ], queremos obter o custo total da compra se optarmos por esse fornecedor. 2. (fornece) Dado um pedido de compra e a tabela de preos de um determinado revendedor, obtenha a lista dos materiais que ele pode fornecer. 3. (subprojeto) Considere os pedidos de compra para dois projetos (p1 e p2). Eventualmente alguns itens do pedido do projeto p1 podem ocorrer no pedido de p2, possivelmente com quantidades distintas. Dizemos que um projeto p1 subprojeto de p2 se cada componente de p1 tambm componente de p2 em quantidade idntica ou inferior. 4. (lfornecedor) Dado um pedido de compra e a lista de revendedores, descrever a lista de fornecedores para cada componente, com seus respectivos preos, no formato [(material1,[rev1, rev2,...] ), (material2, [...]), ...]

1 74 19.5 Passagens areas: Considere que vrias companhias areas brasileiras oferecem vos dirios para vrias regies do mundo. Devido a competitividade do mercado, vrias so as ofertas promocionais de vos nacionais e internacionais. Cada vo identificado pela companhia area, o nmero do vo, a rota, a tarifa em reais e a data de partida. A rota descrita por uma lista onde o primeiro elemento corresponde origem, o ltimo elemento corresponde ao destino e os outros elementos correspondem s escalas do vo. Para escolher e reservar um determinado vo, um passageiro deve fornecer as seguintes informaes: a origem, o destino e a data de partida desejados. Um vo atende a um pedido de reserva se, para a data de partida desejada, a origem requisitada coincide com a origem definida na rota do vo e o destino requisitado coincide com alguma escala ou com o destino da rota do vo. A tarifa a mesma, da origem para qualquer escala ou destino da rota. Considere as seguintes definies: vo Consiste em uma tupla definida com os seguintes componentes: (<companhia area>, <no>, <rota>, <tarifa>, <partida>) Exemplo: (VARIG,480,[rio,salvador,macei],430,(09,07,2001))

Pedido de Uma tupla definida com os seguintes componentes: reserva (<origem>, <destino>, <partida>) Exemplo: (rio, salvador, (09,07,2001)) Obs: Companhia area, origem e destino so do tipo string, rota uma lista de strings, n e tarifa so nmeros e partida uma tripla de nmeros. Exerccios: Elabore programas em HUGS para resolver os problemas propostos. O nome das funes assim como seus parmetros so dados para cada uma das questes. Escolha duas questes para resolver utilizando descrio por listas e duas utilizando recurso. 1. (vos lv pr) Dada uma lista de vos e um pedido de reserva, descreva a lista de companhias areas que atendem ao pedido de reserva. 2. (mtarifa lv pr) Considerando a funo descrita na questo anterior, das companhias areas que atendem a um determinado pedido de reserva, obter aquela que oferece a menor tarifa. 3. (partidas dt ds lv) Dados uma data e um destino, obter o nmero de partidas para aquele destino, naquela data. 4. (vsescalas lv dt) Dada a lista de vos, descrever a lista de vos sem escalas, atravs do nmero do vo. A resposta deve ser no formato: [ n do vo,...]

1 75 19.6 Gerncia Acadmica: Considere a gerncia acadmica dos cursos de graduao de uma universidade. As disciplinas cursadas por um aluno so registradas em seu histrico. O registro deve conter o cdigo da disciplina, o ano e o semestre em que foi cursada e a nota obtida. Semestralmente o aluno deve requerer matrcula em novas disciplinas. O pedido de matrcula realizado atravs da apresentao das disciplinas desejadas pelo aluno. Um dos critrios para conseguir se matricular em uma disciplina que o aluno tenha cumprido, com aprovao, os pr-requisitos da disciplina. Um aluno aprovado em uma disciplina se obtiver mdia superior ou igual a 5 (cinco). Cada curso possui uma grade curricular que relaciona cada disciplina do curso com seus respectivos prrequisitos. Considere as seguintes definies:
Histrico Escolar Um par contendo o cdigo de matrcula do aluno e a lista de disciplinas cursadas. Cada disciplina cursada representada por uma tripla com o cdigo da disciplina, o ano e o semestre que ela foi cursada e a nota obtida. Formato: (matrcula, [ (disciplina, (ano, semestre), nota), ... ]) onde matrcula = (ano, curso, nmeroIdentificaoIndividual) Cadastro de Uma lista contendo, para cada disciplina, um par com o cdigo da Disciplinas disciplina e a quantidade de crditos. Grade Curricular Um par com o cdigo do curso e uma lista de pares onde cada par representa uma disciplina (cdigo) e uma lista dos seus prrequisitos. Formato: (curso, [(disciplina, [disciplina, disciplina,...]), ...]) Pedido de matrcula Um par com o cdigo do aluno e uma lista contendo o cdigo das disciplinas nas quais o aluno deseja se matricular. Formato: (matrcula, [pedido1, pedido2, ...]) Oferta Uma lista contendo as turmas a serem ofertadas, com seus horrios e limite de vagas. Formato: [(disciplina, turma, quantidade_de_vagas, horrio),...] onde horrio = [(dia_da semana, hora_inicial, hora_final), ...] Lista de disciplinas Um par contendo o cdigo do curso e uma lista de pares, onde cada de um curso, par representa um perodo do curso e uma lista das disciplinas do apresentadas por perodo. perodo Formato: (curso, [(perodo, [disciplina, disciplina,...])

Histrico Escolar

Cadastro de Disciplinas

Um par contendo o cdigo de matrcula do aluno e a lista de disciplinas cursadas. Cada disciplina cursada representada por uma tripla com o cdigo da disciplina, o ano e o semestre que ela foi cursada e a nota obtida. Formato: (matrcula, [ (disciplina, (ano, semestre), nota), ... ]) onde matrcula = (ano, curso, registro) Uma lista contendo, para cada disciplina, um par com o cdigo da disciplina e a quantidade de crditos.

1 Grade Curricular Lista de disciplinas de um curso, apresentadas por perodo 76 Um par com o cdigo do curso e uma lista de pares onde cada par representa uma disciplina (cdigo) e uma lista dos seus prrequisitos. Formato: (curso, [(disciplina, [disciplina, disciplina,...]), ...]) Um par contendo o cdigo do curso e uma lista de pares, onde cada par representa um perodo do curso e uma lista das disciplinas do perodo. Formato: (curso, [(perodo, [disciplina, disciplina,...])

Exerccios: Escreva funes em Hugs para resolver os problemas propostos abaixo, usando os nomes indicados em negrito. A palavra semestre, nestes
problemas, representa um elemento do tipo (ano,s), onde s = 1 ou s = 2. 1. 2. 3.

(credse) Dado um histrico, o cadastro de disciplinas e um semestre, descrever o total de crditos cumpridos no semestre. (ncred) Dado um histrico e o cadastro de disciplinas, descrever a quantidade de crditos cumpridos por semestre. (dncursadas) Dado um histrico e uma lista com as disciplinas por perodo, descrever a lista das disciplinas no cursadas ainda pelo aluno, dos perodos j cumpridos. Esta lista deve ter o seguinte formato: [(perodo,[disciplina,..]), (perodo,[disciplina,...]),...] (maxcred) Dada uma lista de histricos, identificar a lista de alunos que possuem o maior nmero de crditos cumpridos. (conterep) Dado um histrico, contar o nmero de reprovaes. (jubila) Verificar se um determinado aluno se encontra em situao de jubilamento (possui trs reprovaes em uma mesma disciplina). (abandono) Verificar se o aluno deixou de cursar disciplinas em algum semestre. (divida) Obter a lista das disciplinas que foram cursadas por um dado aluno, nas quais ele ainda no obteve aprovao. (reprova) Obter uma lista de reprovaes por perodo, para um dado aluno. O coeficiente de rendimento (CR) de um dado aluno determinado pela mdia ponderada das notas obtidas, tendo como peso, o nmero de crditos das disciplinas. Determine o CR de um dado aluno. Obter uma lista das disciplinas de um dado curso, que no possuem pr-requisito. Dada uma disciplina, verificar se o aluno cumpriu seus prrequisitos.

4. 5. 6. 7. 8. 9.

10.(crend)

11.(semprereq)

12.(cumprereq) 13.(dividas)

Obter para um dado aluno, a lista de disciplinas que ele ainda no cursou, com respeito a uma dada grade curricular.

1
14.(sugestao)

77 Obter para um dado aluno, a lista de disciplinas que ele est apto a cursar, com respeito a uma dada grade curricular. Obter uma lista de pedidos de disciplinas para as quais os prrequisitos foram cumpridos. Dada uma lista com os pedidos de todos os alunos, obtenha uma lista das disciplinas solicitadas, sem repetio. Obter a lista de alunos que solicitaram uma dada disciplina, com seus respectivos coeficientes de rendimentos. A lista de alunos deve estar em ordem crescente por coeficiente de rendimento. A lista resultante deve ter o seguinte formato:
[(aluno1, coeficiente_de_rendimento1),(aluno2, coeficiente_de_rendimento2), ...]

15.(lcumprereq) 16.(ldiscsol)

17.(sol_disciplinas_ord)

19.7 Agncia de Turismo: Uma agncia de turismo possui o mapa atualizado de reservas dos hotis de uma determinada regio. Para cada hotel, todas as informaes pertinentes aos tipos de quarto oferecidos so registrados no mapa. Este mapa representado por uma lista de tuplas, seguindo o seguinte formato: [(nome_hotel, [(tipo_quarto, valor_diria, situao), ...] ), ...] onde nome_hotel do tipo string; tipo_quarto uma string; valor_diria um nmero real positivo; situao: nmero inteiro positivo que indica a quantidade de quartos livres do tipo indicado.

Para o melhor entendimento da representao da lista de hotis no hugs, considere o seguinte exemplo: lhoteis = [("peterle", [("simples", 50.0, 5),("duplo", 75.8, 10), ("luxo", 110.0, 2)] ), ("ibis", [("simples", 45.0, 3),("duplo", 65.5, 15), ("luxo", 95.0, 3)] ), ("novotel", [("simples", 65.6, 10),("duplo", 90.5, 20), ("luxo", 150.0, 10)] )] Exerccios: Considerando o formato desta lista de hotis apresentada acima, resolva o seguinte problema, descrevendo funes em HUGS. 1. Dados um tipo de quarto e a lista de hotis, apresente a lista com o nome do hotel ou com os nomes dos hotis que possuem a oferta mais barata para aquele tipo de quarto. 2. Avalie a funo definida no problema 1 para os parmetros adequados, considerando a lista de hotis como a dada acima.

1 78 19.8 Espetculos Teatrais: Vrios espetculos esto sendo apresentados em um grande teatro da cidade. Para cada um dos espetculos, registra-se o mapa de ocupao da platia, conforme as vendas dos ingressos. A platia est representada por m filas numeradas de 1 a m, sendo que cada fila contm n cadeiras tambm numeradas de 1 a n. Considere a seguinte representao para os dados: Lugar na platia (fila, cadeira), onde fila representada por um inteiro de 1 a m e cadeira, por um inteiro de 1 a n. Platia Lista de duplas (lugar, situao) sendo que a situao : 1 para indicar lugar ocupado e 0 para indicar lugar vago. Teatro Lista de duplas (espetculo, platia) onde espetculo representado por um inteiro de 1 a p. Exerccios: Escreva um script em HUGS, com funes que resolvam os problemas abaixo. Nomes para cada uma das funes so sugeridos ao final do enunciado de cada problema. 5. Dada uma platia pls, descreva a quantidade total de lugares ocupados (totalOcup). 6. Dado um lugar lg e uma platia pls, verifique se o lugar lg est livre (estaLivre). 7. Dado um lugar lg e uma platia pls, verifique se existe algum vizinho lateral de lg que est livre (vizinhoLivre). 8. Dada uma fila fl e uma platia pls, descreva a lista de cadeiras livres da fila fl (cadeirasLivresFila). 9. Dada uma platia pls, descreva a lista de cadeiras livres para cada fila (lugLivresFila) 10. Dada uma platia pls, descreva a(s) lista(s) com o maior nmero de cadeiras livres (filaMaxLivre). 11. Dado um teatro trs e um espetculo ep, descreva a sua platia (plateiaEsp). 12. Dado um teatro trs, um espetculo ep e uma fila fl, descreva a lista de cadeiras livres da fila fl (cadeirasLivresFilaEsp).

1 79 20. ENTRADA E SAIDA DE DADOS 20.1 INTRODUO: Os programas que apresentamos e propusemos at ento, se basearam em um padro especfico de interao entre o usurio e o sistema. O interpretador HUGS est constantemente solicitando uma expresso, que em seguida avaliada por ele e o resultado apresentado ao usurio. Vejamos o modelo ilustrado na figura 20.1. A avalio de uma expresso leva em conta as definies disponveis em bibliotecas e as construdas pelos programadores.

expresso

scripts

usurio

Interpretado r HUGS

resultado

Figura 20.1 Modelo de Interao usurio-interpretador HUGS Algumas vezes entretanto este modelo de interao no adequado tendo em vista que o programa do usurio no pode tomar a deciso de pedir ou no um dado ao usurio. Tudo tem que ser informado antecipadamente. Exemplo 1: Desejamos fazer um programa que interaja com o usurio para que ele tente descobrir um nmero oculto. A interao do programa s deve continuar enquanto o jogador no descobrir o nmero oculto. E veja, no d para antecipar antes e codificar isto em uma expresso. A Figura 20.2 mostra um esquema da interao necessria. O programa pode comear pedindo um valor ao usurio. Se o usurio fornece um valor idntico ao valor oculto, o programa exibe a mensagem anunciando que o jogador venceu e encerra o jogo. Caso contrrio o programa solicita um novo palpite.

1 80

Jogo encerrado

sim
Valor fornecido = Nmero oculto ?

valor

no
Fornea outro valor

Figura 20.2 Interaes para descobrir um nmero oculto

Nestes casos, no queremos descrever mapeamentos entre conjunto de valores e sim seqncia de aes. o contato das funes com o mundo. Ainda podemos usar funes para determinar valores, mas quando precisamos, temos que estabelecer uma seqncia de aes a serem executadas. Agora o que nos interessa definir programas, atravs de seqncias de aes. Vejamos uma soluo para o joguinho acima introduzido:

1 81 jogo1 = do putStrLn ">>fornea um nmero entre 0 e 10" valor <- getLine if valor == "5" then do putStrLn "acertou - parabns!" else do putStrLn "errou - tente outra vez!" jogo1

1 82 E algumas interaes:
Main> jogo1 >>fornea um nmero 3 errou - tente outra >>fornea um nmero 4 errou - tente outra >>fornea um nmero 2 errou - tente outra >>fornea um nmero 5 acertou - parabns!

entre 0 e 10 vez! entre 0 e 10 vez! entre 0 e 10 vez! entre 0 e 10

Vamos agora dissecar o programa: 1. Para estabelecer contato com o mundo precisamos de uma ao para leitura e outra para exibio de resultado. Aqui a leitura realizada atravs da primitiva getLine. Para exibir resultados fazemos uso da primitiva putStrLn. Enquanto getLine no precisa de um parmetro, visto que uma ao que sempre buscar na interao obter um valor, a putStr necessita de um valor para ser exibido; 2. O programa jogo1 no precisa de parmetro para realizar sua atividade, dado que tudo ser solicitado diretamente dentro do corpo do programa, na medida do necessrio; 3. Para informar que o que estamos definindo uma seqncia de aes e no uma descrio funcional, introduzida a partcula do, que pode ser traduzida pelo imperativo faa! 4. Para que um valor obtido pelo comando de leitura getLine, se torne disponvel para uso do programa precisamos internaliz-lo atravs do uso da primitiva representada pelo smbolo ;

valor getLine 5. Para indicar que desejamos continuar executando o programa podemos fazer uma chamada a ele mesmo, como o fizemos em: else do putStrLn "errou - tente outra vez!" jogo1

Você também pode gostar