A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

21 Abril de 2005Recursividade e Iteração1 Recursividade e Iteração (cont.) Processamento de Texto Pedro Barahona DI/FCT/UNL Abril 2005.

Apresentações semelhantes


Apresentação em tema: "21 Abril de 2005Recursividade e Iteração1 Recursividade e Iteração (cont.) Processamento de Texto Pedro Barahona DI/FCT/UNL Abril 2005."— Transcrição da apresentação:

1 21 Abril de 2005Recursividade e Iteração1 Recursividade e Iteração (cont.) Processamento de Texto Pedro Barahona DI/FCT/UNL Abril 2005

2 21 Abril de 2005 Recursividade e Iteração 2 Recursividade para Resolução de Problemas A recursividade pode ser usada na resolução de problemas, difíceis de resolver por outras técnicas de programação. Tal é o caso das Torres de Hanoi: dadas três torres (estacas) pretende-se passar uma pirâmide de peças ordenadas de uma torre para outra, movendo-se uma peça de cada vez, para o topo de uma torre encimada por uma peça menor.

3 21 Abril de 2005 Recursividade e Iteração 3 Apesar de aparentemente complicado, este problema tem uma solução recursiva simples. Para passar n peças de uma torre (A) para outra (C) 1.Passar n-1 peças da torre inicial (A) para a torre livre (B) 2.Mover a última peça, para a torre final (C) 3.Passar as n-1 peças da torre B para a torre final (C). Torres de Hanoi - Recursividade

4 21 Abril de 2005 Recursividade e Iteração 4 Torres de Hanoi: Movimentos Necessários Baseados nesta resolução recursiva podemos –Determinar o número de movimentos necessários –Determinar os movimentos necessários O número de movimentos necessários é bastante simples de determinar, na versão recursiva hanoi_count(n) = hanoi_count(n-1)+1+ hanoi_count(n-1) Neste caso, pode-se evitar a dupla recursividade (ver adiante) de uma forma muito simples hanoi_count(n) = 2*hanoi_count(n-1) + 1 Finalmente, há que especificar a condição de paragem (n=1) hanoi_count(1) = 1

5 21 Abril de 2005 Recursividade e Iteração 5 Torres de Hanoi: Movimentos Necessários Um programa Octave para resolver o programa é imediato function c = hanoi_count(n) if n == 1 c = 1; else c = 2*n_hanoi_count(n-1)+1; end; endfunction; De notar o aumento exponencial do número de movimentos necessários

6 21 Abril de 2005 Recursividade e Iteração 6 Torres de Hanoi O problema propriamente dito pode ser resolvido com base num vector T, com 3 números, correspondentes ao número de peças em cada uma das torres. Notar que não é necessário indicar o tamanho de cada peça, porque o algoritmo nunca coloca uma peça sobre uma menor! O movimento de uma só peça da torre A para a torre B, usado no corpo da recursão e na sua terminação, pode ser feito com uma função auxiliar, move_hanoi(T,A,B), especificada da forma óbvia (tira uma peça de A e aumenta em B). T = [3,1,1]

7 21 Abril de 2005 Recursividade e Iteração 7 Torres de Hanoi function T = hanoi(T,N,A,B) % move N peças de A para B if N == 1 T = hanoi_move(T,A,B); % move a peça de A para B else C = 6-A-B; % C é a outra torre! T = hanoi(T,N-1,A,C); % move N-1 peças de A para C T = hanoi_move (T,A,B);% move 1 peça de A para B T = hanoi(T,N-1,C,B); % move N-1 peças de C para B end; endfunction; function T = hanoi_move(T,A,B) T(A) = T(A) - 1; T(B) = T(B) + 1; disp(T); endfunction;

8 21 Abril de 2005 Recursividade e Iteração 8 O funcionamento do programa pode ser visto com a chamada >> hanoi([4,0,0],4,1,3); Torres de Hanoi hanoi(_,2,1,3) hanoi(_,2,3,2) hanoi(_,3,1,2) move(_,1,2) hanoi(_,2,2,1) hanoi(_,2,1,3) hanoi(_,3,2,3) move(_,2,3) move(_,1,3)

9 21 Abril de 2005 Recursividade e Iteração 9 Recursão e Iteração Em geral, uma função ou procedimento definidos recursivamente podem-no ser tambem de uma forma iterativa (através de ciclos). Em geral, a definição recursiva é mais declarativa na medida em que explicita o que se pretende obter e não a forma como se obtem (ou seja, um determinado programa que é usado). Por outro lado, uma definição iterativa, embora não permita uma compreensão tão imediata, é geralmente mais eficiente, já que as instruções de programação de baixo nível para a iteração são mais eficientes que as de chamadas de funções. No entanto, estas diferenças são geralmente pouco importantes, excepto em casos de recursão múltipla, em que a ineficiência pode ser catastrófica.

10 21 Abril de 2005 Recursividade e Iteração 10 Recursão e Iteração function f = fib(n); % versão recursiva if n <= 2 f = 1; else f = fib(n-1) + fib(n-2); endif; endfunction; function f = fib(n) % versão iterativa if n <= 2 f = 1; else f1 = 1; f2 = 1; for i = 3:n f = f1+f2; f1 = f2; f2 = f; endfor; endif; endfunction;

11 21 Abril de 2005 Recursividade e Iteração 11 Recursão e Iteração Esta é a situação da função de Fibonacci, em que o seu valor depende de 2 chamadas recursivas. Como as chamadas são independentes, a mesma função acaba por ser recalculada várias (muitas !) vezes Na realidade, o número de funções chamadas é o próprio número de fibonacci (7:1, 6:1, 5:2, 4:3, 3:5, 2:8) que aumenta exponencialmente com o valor de n.

12 21 Abril de 2005 Recursividade e Iteração 12 Recursão e Iteração Para se ter uma ideia do aumento, podemos notar que apesar de inicialmente pequenos os números tornam-se rapidamente enormes tornando proibitiva a sua computação recursiva (normal).

13 21 Abril de 2005 Recursividade e Iteração 13 Memorização Por vezes é possível aliar a declaratividade da versão recursiva, com a eficiência da versão iterativa, através da memorização dos valores já computados. Por exemplo se se pretenderem os primeiros 100 números de fibonacci, pode criar-se uma tabela, fib_m, com os valores já computados. –Se fib_m(n) ainda não contiver o valor de fib(n), então determina-se fib(n) e escreve-se em fib_m(n). –Caso contrário, apenas se retorna o valor de fib_m(n). Para que este esquema seja possível, é conveniente que a tabela fib_m seja visível por todas as instâncias da função fib(n). Para evitar passá-la como parâmetro deve declarar-se como uma variável global.

14 21 Abril de 2005 Recursividade e Iteração 14 Variáveis Globais em Octave Em Octave, para que uma variável seja global, ela deve ser declarada no programa principal com a declaração global. No caso actual, se se pretende um vector linha com 100 elementos inicializados a zero, devemos declarar a variável global fib_m = zeros(1,100); global fib_m; Uma vez declarada uma variável global, ela pode ser eliminada através da declaração clear. Se pretendermos um vector com 200 elementos deveremos fazer clear fib_m fib_m = zeros(1,200)

15 21 Abril de 2005 Recursividade e Iteração 15 Memorização Para que, na função, a variável fib_m considerada seja a variável global e não uma variável local, a variável deve ser identificada novamente como global. function f = fib_mem(n); %versão recursiva c/ memória global fib_m; if fib_m(n) > 0 f = fib_m(n); else if n <= 2 f = 1; else fib_m(n) = fib_mem(n-1)+fib_mem(n-2); f = fib_m(n); endif; endfunction;

16 21 Abril de 2005 Recursividade e Iteração 16 Processamento de Texto Muita informação útil, nomeadamente em tarefas de gestão, não é do tipo numérico. Por exemplo, variadas entidades (pessoas, empresas, disciplinas, departamentos, etc...) têm associado um nome que se pode querer processar (por exemplo ordenar). Este é apenas um exemplo de situações em que se pretende que os programas efectuem processamento de texto. Todas as linguagens de programação prevêem pois tipos de dados para este fim, nomeadamente –Caracteres; –Cadeias de caracteres (strings).

17 21 Abril de 2005 Recursividade e Iteração 17 Caracteres Os caracteres mais utilizados (representados no código ASCII - American Standard Code for Information Interchange ) incluem Letras (52), maiúsculas (26) e minúsculas (26) Dígitos (10) Espaço e outros caracteres visíveis (34) – ( ) [ ] { },. : ; = + - * \ | / ^ ~ ´ ` # $ % & _ ! Caracteres de controle (32) –horizontal tab (\t), new line (\n), alert (\a),... Outros caracteres, (ç, ã, ñ, š, ø,,, Σ, ш, ך,, غغ) só podem ser representados em códigos mais avançados e não são suportados em algumas linguagens de programação (em Octave, uma variável não pode ter o nome acção)

18 21 Abril de 2005 Recursividade e Iteração 18 Cadeias de Caracteres Cadeias de caracteres (strings) são sequências (ordenadas) de caracteres. Em quase todas as linguagens, dados do tipo caracter e cadeia (incluindo simples caracteres) são representados entre delimitadores, que podem ser aspas ( ) ou plicas ( ). Devem sempre abrir-se e fechar-se com o mesmo tipo de delimitadores. Quando se pretende incluir um dos delimitadores no texto, podem usar-se sequências de escape –nome = Maria Martins d\Albuquerque ou usar-se o outro delimitador –nome = Maria Martins dAlbuquerque –frase = Ele exclamou: Óptimo e fugiu

19 21 Abril de 2005 Recursividade e Iteração 19 Cadeias de Caracteres e Vectores Em geral, e Octave não foge à regra, cadeias de caracteres são implementadas como vectores dos códigos dos caracteres. Muitas funções e operações em Octave exigem a utilização do tipo correcto. Duas funções permitem transformar –Vectores em cadeias : toascii: >> a = toascii(ABC) a = [65,66,67] –Cadeias em vectores : setstr: >> b = setstr([97,98,99]) b = abc O Octave não é muito estrito no que se refere aos tipos de dados. Por exemplo, permite operações numéricas com cadeias, fazendo a conversão de tipos necessária >> c = abc* 1 c = [97,98,99] Nota: Estas facilidades tornam difícil a detecção de erros de programação e não devem ser usadas (ou apenas com muito cuidado)

20 21 Abril de 2005 Recursividade e Iteração 20 Conversão de Cadeias de Caracteres Cadeias de caracteres podem ser processados de várias formas. Para as mais comuns, existem funções pré-definidas. Algumas dessas funções permitem converter cadeias de caracteres que representam números para os próprios números. Exemplo: Dada a cadeia (com espaços), a sua conversão para um número é obtida com a função str2num. >> s = ; a = str2num(s); b = 2*a b = É interessante comparar o resultado acima com (porquê???) >> s = ; b = 2*s s = [64,100,102,92,110,108,64,64] A conversão oposta, pode fazer-se com a função num2str.

21 21 Abril de 2005 Recursividade e Iteração 21 Concatenação de Cadeias de Caracteres As cadeias podem ser concatenadas. Esta operação é utilizada para juntar numa só cadeia a informação que está dispersa por várias cadeias. Por exemplo, para juntar –O(s) nome(s) próprio(s) ao(s) apelido(s) –Os vários campos de um enedereço (rua, nº, andar, local, etc.) O Octave tem uma função strcat, para esse efeito. Exemplo: Juntar um nome próprio e um apelido. >> np = Rui; ap = Lopes; nome= strcat(np,,ap) nome = Rui Lopes De notar a utilização da cadeia com um branco ( ) para espaçar o nome próprio e o apelido.

22 21 Abril de 2005 Recursividade e Iteração 22 Partição de Cadeias de Caracteres As cadeias podem ser partidas noutras mais simples. Neste caso pode haver várias formas de fazer a partição. Uma possível é através de caracteres que funcionam como separadores (tipicamente espaços). O Octave tem uma função, split, para esse efeito, criando uma matriz de cadeias, cada cadeia na sua linha, com brancos acrescentados se necessário Exemplo: Separar os nomes (próprios e apelidos) de uma pessoa. >> nome = Rui da Costa Pina; nms = split(nome, ) nms = Rui da Costa Pina

23 21 Abril de 2005 Recursividade e Iteração 23 Extracção de Cadeias de Caracteres Por vezes estamos interessados apenas em partes de uma cadeia. Uma forma comum de o fazer é indicar –o índice do primeiro caracter pretendido para a subcadeia; e –o comprimento da subcadeia. O Octave tem uma função, substr, para esse efeito. Por exemplo: Separar os nomes (próprios e apelidos) de uma pessoa. >> nome = Rui da Costa Pina; nm1 = substr(nome,1,3), nm2 = substr(nome,5,2), nm3 = substr(nome,8,5), nm4 = substr(nome,14,4), nm1= Rui, nm2= da, nm3= Costa, nm4= Pina Os índices variam de 1 ao comprimento da cadeia. Este comprimento é obtido pela função length. >> nome = Rui da Costa Pina; x = length(nome) x= 17

24 21 Abril de 2005 Recursividade e Iteração 24 Comparação de Caracteres Uma operação vulgar no processamento de texto é a ordenação por ordem alfabética. Esta ordenação requer a comparação alfabética de caracteres. Esta pode ser feita através da comparação numérica dos códigos dos caracteres. A comparação só é fácil se os códigos usados respeitam a ordem alfabética, o que acontece em todos os códigos. Por exemplo em ASCII, o código dos caracteres A e B é, respectivamente, 65 e 66, pelo que se pode fazer a correspondência pretendida o caracter c1 vem antes do caracter c2 c1 < c2 Exemplo: >> teste = a < b teste = 1

25 21 Abril de 2005 Recursividade e Iteração 25 Comparação de Cadeias de Caracteres A comparação literal pode ser obtida a partir da comparação caracter a caracter. O Octave tem uma função, strcmp, para verificar se duas cadeias são idênticas. >> nm1 = Rui Costa; nm2 = Rui Costa; t = strcmp(nm1,nm2) t = 1 Para o teste de precedência alfabética (designado por <<) o Octave não dispõe de funções predefinidas. Mas elas podem ser definidas tendo em conta a comparação caracter a caracter. Vamos pois definir uma função my_str_before como: my_str_before (s1,s2) = 1se s1 << s2 0se s1 = s2 -1se s1 >> s2

26 21 Abril de 2005 Recursividade e Iteração 26 Comparação de Cadeias de Caracteres function t = my_str_tail(s) c = length(s); if c == 1 t =""; else t = substr(s,2,c-1); endif; endfunction; Dada a natureza recursiva da função my_before, esta utiliza uma função auxiliar, my_str_tail, para obter a cauda da cadeia (isto é, sem o seu primeiro caracter). A função my_before compara os primeiros caracteres das cadeias (se existirem). Se estes forem iguais, compara as caudas das cadeias (chamada recursiva).

28 21 Abril de 2005 Recursividade e Iteração 28 Comparação de Cadeias de Caracteres A comparação de cadeias de caracteres interpretáveis (por exemplo, de texto em português) é mais complexa. Os problemas mais frequentes são de 3 tipos: –Ocorrência de espaços (e outros caracteres brancos) Rui Santos = Rui Santos ??? –Tratamento de letras maiúsculas e minúsculas Rui Santos = RUI SANTOS ??? –Caracteres especiais (com acentos e cedilhas) João França = Joao Franca ??? Estes problemas têm de ser considerados no contexto apropriado (Franca e França são apelidos diferentes, ou o terminal (telemóvel) não tinha o caracter ç ?), e requerem algoritmos dedicados.

29 21 Abril de 2005 Recursividade e Iteração 29 Comparação de Cadeias com Brancos Os caracteres brancos servem para separar os significativos. Os mais vulgares são os espaços, mas existem outros para mudança de linha (\n, \r ou \f), ou tabulação (\t e \v). No código ASCII todos têm códigos inferiores a 32 (espaço). A comparação de cadeias pode simplificar-se se a comparação fôr feita após normalização. Esta normalização, consiste em –eliminar todos os brancos prefixos/sufixos, i.e. antes/depois do primeiro/último caracter significativo. –Substituir todos os separadores (grupos de brancos, tabs, mudanças de linha, etc. por um só branco). Algumas funções pre-definidas podem auxiliar na normalização, mas o Octave não tem esta função predefinida.

30 21 Abril de 2005 Recursividade e Iteração 30 Substituição de Brancos por Espaços Assumindo que todos os caracteres brancos têm código inferior a 32, podemos utilizar a função my_str_remctr, indicada abaixo, para substituir todos os caracteres brancos por espaços. function t = my_str_remctr(s) for i = 1:length(s) if toascii(s(i)) < 32 t(i) = " "; else t(i) = s(i); endif; endfor; endfunction;

31 21 Abril de 2005 Recursividade e Iteração 31 Eliminação de Brancos Prefixos e Sufixos O Octave dispõe de uma função (deblank) que elimina todos os espaços sufixos. A eliminação dos brancos prefixos pode igualmente usar essa função se se inverter (passá-la de trás para a frente) a cadeia. Essa inversão pode usar a função my_str_rev, indicada abaixo function r = my_str_rev(s) c = length(s); for i = 1:c r(i) = s(c-i+1); endfor endfunction;

32 21 Abril de 2005 Recursividade e Iteração 32 Eliminação de Espaços Repetidos A eliminação dos espaços repetidos pode ser feita usando a função my_str_remrep, indicada abaixo. A função percorre toda a cadeia mantendo a informação (na variável booleana ultimo_branco) sobre se o último caracter era branco. Nesse caso, se o caracter fôr espaço não o copia (seria repetido). function t = my_remrep(s) j = 1; ultimo_branco = 0; for i = 1:length(s) if s(i) != " " t(j) = s(i); j = j+1; ultimo_branco = 0; elseif !ultimo_branco t(j) = s(i); j = j+1; ultimo_branco = 1; endif; endfor; endfunction;

33 21 Abril de 2005 Recursividade e Iteração 33 Normalização de Cadeias de Caracteres A normalização de cadeias de caracteres pode ser feita usando a função my_str_norm, indicada abaixo, que utiliza todas as funções anteriores, da forma esperada. Primeiro, substitui os brancos por espaços. Depois elimina os espaços sufixos. Em terceiro lugar elimina os brancos prefixos (eliminando os brancos sufixos da cadeia invertida, invertendo de novo o resultado). Finalmente, os espaços repetidos são removidos. function sn = my_str_norm(s) s1 = my_str_remctr(s) s2 = deblank(s1); s3 = my_str_rev(deblank(my_str_rev(s2))); sn = my_str_remrep(s3); endfunction;

34 21 Abril de 2005 Recursividade e Iteração 34 Comparação de Cadeias com Brancos function b = my_str_norm_before(s1,s2) sn1 = my_str_norm(s1); sn2 = my_str_norm(s2); b = my_str_before(sn1,sn2); endfunction; A comparação de cadeias de caracteres pode ser feita usando a função my_str_norm_before, indicada abaixo, que não considera os caracteres brancos. As diferenças podem ser exemplificadas em baixo. >> t = my_str_before(Rui Lopes, Rui Lopes) t = -1 >> t = my_str_norm_before(Rui Lopes, Rui Lopes) t = 0

35 21 Abril de 2005 Recursividade e Iteração 35 Comparação com Maiúsculas/Minúsculas A comparação de cadeias de caracteres pode ser igualmente prejudicada pela existência de letras maiúsculas e minúsculas. O Octave tem algumas funções que facilitam o tratamento deste tipo de situações, nomeadamente as funções tolower e toupper, que convertem os caracteres maiúsculos / minúsculos em caracteres minúsculos / maiúsculos. >> s1 = \n Rui \t Lopes; s2 = RUI lopes; sn1 = toupper(s1), sn2 = toupper(s2), t1 = my_str_norm_before(s1,s2), t2 = my_str_norm_before(sn1,sn2) sn1 = \n RUI \t LOPES sn2 = RUI LOPES t1 = -1 t2 = 0

36 21 Abril de 2005 Recursividade e Iteração 36 Conversão entre Maiúsculas/Minúsculas As funções anteriores assumem um código ASCII, em que os caracteres brancos têm códigos abiaxo de 32. Nesse código ASCII, a conversão entre maiúsculas e minúsculas pode ser feita adicionando ou subtraindo a sua diferença aos códigos respectivos. Esta diferença é 32, como pode ser verificado em >> dif = toascii(A) – toascii(a) dif = -32 No entanto, a utilização destes valores pode ser problemática, se forem usados outros códigos. É da responsabilidade da implementação da linguagem interpretar ter em atenção os códigos usados (que podem não ser ASCII) e disponibilizar primitivas independentes desses códigos.

37 21 Abril de 2005 Recursividade e Iteração 37 Conversão independente do Código Algumas dessas primitivas são –isalpha(s) 1 se s fôr alfabético (maiúscula ou minúscula) –islower(s)1 se s fôr uma minúscula –isupper(s)1 se s fôr uma maiúscula –isdigit(s)1 se s fôr um dígito –isalnum(s)1 se s fôr dígito ou alfabético –ispucnt1 se s fôr um caracter de pontuação –iscntrl(s)1 se s fôr caracter de controle Desta forma as funções poderão ser rectificadas para se tornarem independentes do código usado para representação dos caracteres. Em particular, o teste toascii(s(i)) < 32 pode/deve ser substituido por iscntrl(s2)

38 21 Abril de 2005 Recursividade e Iteração 38 Cadeias com Caracteres Especiais Os caracteres com cedilhas e acentos, típicos do português, não fazem parte do código ASCII básico, e os seus códigos em ASCII estendido não respeitam a ordem natural. Por exemplo, como os códigos dos caracteres a, s e ã são, respectivamente 97, 115 e 227, o nome João está alfabeticamente após José, ao contrário do que acontece com Joao. Uma forma de manter a ordenação pretendida é utilizar, para efeitos de ordenação, as cadeias com os caracteres acentuados substituídos pelos caracteres não acentuados. O Octave dispõe de uma função (strrep) que substitui numa cadeia base, todas as de uma (sub)cadeia por outra. >> s1 = João; s2 = strrep(s1,ã,a) s2 = Joao


Carregar ppt "21 Abril de 2005Recursividade e Iteração1 Recursividade e Iteração (cont.) Processamento de Texto Pedro Barahona DI/FCT/UNL Abril 2005."

Apresentações semelhantes


Anúncios Google