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

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

Embed Size (px)

Text of 21 Abril de 2005Recursividade e Iteração1 Recursividade e Iteração (cont.) Processamento de...

  • Slide 1
  • 21 Abril de 2005Recursividade e Iterao1 Recursividade e Iterao (cont.) Processamento de Texto Pedro Barahona DI/FCT/UNL Abril 2005
  • Slide 2
  • 21 Abril de 2005 Recursividade e Iterao 2 Recursividade para Resoluo de Problemas A recursividade pode ser usada na resoluo de problemas, difceis de resolver por outras tcnicas de programao. Tal o caso das Torres de Hanoi: dadas trs torres (estacas) pretende-se passar uma pirmide de peas ordenadas de uma torre para outra, movendo-se uma pea de cada vez, para o topo de uma torre encimada por uma pea menor.
  • Slide 3
  • 21 Abril de 2005 Recursividade e Iterao 3 Apesar de aparentemente complicado, este problema tem uma soluo recursiva simples. Para passar n peas de uma torre (A) para outra (C) 1.Passar n-1 peas da torre inicial (A) para a torre livre (B) 2.Mover a ltima pea, para a torre final (C) 3.Passar as n-1 peas da torre B para a torre final (C). Torres de Hanoi - Recursividade
  • Slide 4
  • 21 Abril de 2005 Recursividade e Iterao 4 Torres de Hanoi: Movimentos Necessrios Baseados nesta resoluo recursiva podemos Determinar o nmero de movimentos necessrios Determinar os movimentos necessrios O nmero de movimentos necessrios bastante simples de determinar, na verso 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 condio de paragem (n=1) hanoi_count(1) = 1
  • Slide 5
  • 21 Abril de 2005 Recursividade e Iterao 5 Torres de Hanoi: Movimentos Necessrios 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 nmero de movimentos necessrios
  • Slide 6
  • 21 Abril de 2005 Recursividade e Iterao 6 Torres de Hanoi O problema propriamente dito pode ser resolvido com base num vector T, com 3 nmeros, correspondentes ao nmero de peas em cada uma das torres. Notar que no necessrio indicar o tamanho de cada pea, porque o algoritmo nunca coloca uma pea sobre uma menor! O movimento de uma s pea da torre A para a torre B, usado no corpo da recurso e na sua terminao, pode ser feito com uma funo auxiliar, move_hanoi(T,A,B), especificada da forma bvia (tira uma pea de A e aumenta em B). T = [3,1,1]
  • Slide 7
  • 21 Abril de 2005 Recursividade e Iterao 7 Torres de Hanoi function T = hanoi(T,N,A,B) % move N peas de A para B if N == 1 T = hanoi_move(T,A,B); % move a pea de A para B else C = 6-A-B; % C a outra torre! T = hanoi(T,N-1,A,C); % move N-1 peas de A para C T = hanoi_move (T,A,B);% move 1 pea de A para B T = hanoi(T,N-1,C,B); % move N-1 peas 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;
  • Slide 8
  • 21 Abril de 2005 Recursividade e Iterao 8 O funcionamento do programa pode ser visto com a chamada >> hanoi([4,0,0],4,1,3); 400 310 211 202 112 211 220 130 031 022 112 211 202 112 013 004 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)
  • Slide 9
  • 21 Abril de 2005 Recursividade e Iterao 9 Recurso e Iterao Em geral, uma funo ou procedimento definidos recursivamente podem-no ser tambem de uma forma iterativa (atravs de ciclos). Em geral, a definio recursiva mais declarativa na medida em que explicita o que se pretende obter e no a forma como se obtem (ou seja, um determinado programa que usado). Por outro lado, uma definio iterativa, embora no permita uma compreenso to imediata, geralmente mais eficiente, j que as instrues de programao de baixo nvel para a iterao so mais eficientes que as de chamadas de funes. No entanto, estas diferenas so geralmente pouco importantes, excepto em casos de recurso mltipla, em que a ineficincia pode ser catastrfica.
  • Slide 10
  • 21 Abril de 2005 Recursividade e Iterao 10 Recurso e Iterao function f = fib(n); % verso recursiva if n 0 f = fib_m(n); else if n
  • 21 Abril de 2005 Recursividade e Iterao 19 Cadeias de Caracteres e Vectores Em geral, e Octave no foge regra, cadeias de caracteres so implementadas como vectores dos cdigos dos caracteres. Muitas funes e operaes em Octave exigem a utilizao do tipo correcto. Duas funes 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 no muito estrito no que se refere aos tipos de dados. Por exemplo, permite operaes numricas com cadeias, fazendo a converso de tipos necessria >> c = abc* 1 c = [97,98,99] Nota: Estas facilidades tornam difcil a deteco de erros de programao e no devem ser usadas (ou apenas com muito cuidado)
  • Slide 20
  • 21 Abril de 2005 Recursividade e Iterao 20 Converso de Cadeias de Caracteres Cadeias de caracteres podem ser processados de vrias formas. Para as mais comuns, existem funes pr-definidas. Algumas dessas funes permitem converter cadeias de caracteres que representam nmeros para os prprios nmeros. Exemplo: Dada a cadeia 23.76 (com espaos), a sua converso para um nmero obtida com a funo str2num. >> s = 23.76 ; a = str2num(s); b = 2*a b = 47.52 interessante comparar o resultado acima com (porqu???) >> s = 23.76 ; b = 2*s s = [64,100,102,92,110,108,64,64] A converso oposta, pode fazer-se com a funo num2str.
  • Slide 21
  • 21 Abril de 2005 Recursividade e Iterao 21 Concatenao de Cadeias de Caracteres As cadeias podem ser concatenadas. Esta operao utilizada para juntar numa s cadeia a informao que est dispersa por vrias cadeias. Por exemplo, para juntar O(s) nome(s) prprio(s) ao(s) apelido(s) Os vrios campos de um enedereo (rua, n, andar, local, etc.) O Octave tem uma funo strcat, para esse efeito. Exemplo: Juntar um nome prprio e um apelido. >> np = Rui; ap = Lopes; nome= strcat(np,,ap) nome = Rui Lopes De notar a utilizao da cadeia com um branco ( ) para espaar o nome prprio e o apelido.
  • Slide 22
  • 21 Abril de 2005 Recursividade e Iterao 22 Partio de Cadeias de Caracteres As cadeias podem ser partidas noutras mais simples. Neste caso pode haver vrias formas de fazer a partio. Uma possvel atravs de caracteres que funcionam como separadores (tipicamente espaos). O Octave tem uma funo, split, para esse efeito, criando uma matriz de cadeias, cada cadeia na sua linha, com brancos acrescentados se necessrio Exemplo: Separar os nomes (prprios e apelidos) de uma pessoa. >> nome = Rui da Costa Pina; nms = split(nome, ) nms = Rui da Costa Pina
  • Slide 23
  • 21 Abril de 2005 Recursividade e Iterao 23 Extraco 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 funo, substr, para esse efeito. Por exemplo: Separar os nomes (prprios 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 funo length. >> nome = Rui da Costa Pina; x = length(nome) x= 17
  • Slide 24
  • 21 Abril de 2005 Recursividade e Iterao 24 Comparao de Caracteres Uma operao vulgar no processamento de texto a ordenao por ordem alfabtica. Esta ordenao requer a comparao alfabtica de caracteres. Esta pode ser feita atravs da comparao numrica dos cdigos dos caracteres. A comparao s fcil se os cdigos usados respeitam a ordem alfabtica, o que acontece em todos os cdigos. Por exemplo em ASCII, o cdigo dos caracteres A e B , respectivamente, 65 e 66, pelo que se pode fazer a correspondncia pretendida o caracter c1 vem antes do caracter c2 c1 < c2 Exemplo: >> teste = a < b teste = 1
  • Slide 25
  • 21 Abril de 2005 Recursividade e Iterao 25 Comparao de Cadeias de Caracteres A comparao literal pode ser obtida a partir da comparao caracter a caracter. O Octave tem uma funo, strcmp, para verificar se duas cadeias so idnticas. >> nm1 = Rui Costa; nm2 = Rui Costa; t = strcmp(nm1,nm2) t = 1 Para o teste de precedncia alfabtica (designado por
  • 21 Abril de 2005 Recursividade e Iterao 27 Comparao de Cadeias de Caracteres function b = my_str_before(s1,s2) c1 = length(s1); c2 = length(s2); if c1 == 0 & c2 == 0 b = 0; elseif c1 == 0 & c2 > 0 b = 1; elseif c1 > 0 & c2 == 0 b = -1; else % c1 > 0 & c2 > 0 if s1(1) < s2(1) b = 1; elseif s1(1) > s2(1) b = -1; else t1 = my_str_tail(s1); t2 = my_str_tail(s2); b = my_str_before(t1,t2); endif; endfunction;
  • Slide 28
  • 21 Abril de 2005 Recursividade e Iterao 28 Comparao de Cadeias de Caracteres A comparao de cadeias de caracteres interpretveis (por exemplo, de texto em portugus) mais complexa. Os problemas mais frequentes so de 3 tipos: Ocorrncia de espaos (e outros caracteres brancos) Rui Santos = Rui Santos ??? Tratamento de letras maisculas e minsculas Rui Santos = RUI SANTOS ??? Caracteres especiais (com acentos e cedilhas) Joo Frana = Joao Franca ??? Estes problemas tm de ser considerados no contexto apropriado (Franca e Frana so apelidos diferentes, ou o terminal (telemvel) no tinha o caracter ?), e requerem algoritmos dedicados.
  • Slide 29
  • 21 Abril de 2005 Recursividade e Iterao 29 Comparao de Cadeias com Brancos Os caracteres brancos servem para separar os significativos. Os mais vulgares so os espaos, mas existem outros para mudana de linha (\n, \r ou \f), ou tabulao (\t e \v). No cdigo ASCII todos tm cdigos inferiores a 32 (espao). A comparao de cadeias pode simplificar-se se a comparao fr feita aps normalizao. Esta normalizao, 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, mudanas de linha, etc. por um s branco). Algumas funes pre-definidas podem auxiliar na normalizao, mas o Octave no tem esta funo predefinida.
  • Slide 30
  • 21 Abril de 2005 Recursividade e Iterao 30 Substituio de Brancos por Espaos Assumindo que todos os caracteres brancos tm cdigo inferior a 32, podemos utilizar a funo my_str_remctr, indicada abaixo, para substituir todos os caracteres brancos por espaos. 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;
  • Slide 31
  • 21 Abril de 2005 Recursividade e Iterao 31 Eliminao de Brancos Prefixos e Sufixos O Octave dispe de uma funo (deblank) que elimina todos os espaos sufixos. A eliminao dos brancos prefixos pode igualmente usar essa funo se se inverter (pass-la de trs para a frente) a cadeia. Essa inverso pode usar a funo 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;
  • Slide 32
  • 21 Abril de 2005 Recursividade e Iterao 32 Eliminao de Espaos Repetidos A eliminao dos espaos repetidos pode ser feita usando a funo my_str_remrep, indicada abaixo. A funo percorre toda a cadeia mantendo a informao (na varivel booleana ultimo_branco) sobre se o ltimo caracter era branco. Nesse caso, se o caracter fr espao no 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;
  • Slide 33
  • 21 Abril de 2005 Recursividade e Iterao 33 Normalizao de Cadeias de Caracteres A normalizao de cadeias de caracteres pode ser feita usando a funo my_str_norm, indicada abaixo, que utiliza todas as funes anteriores, da forma esperada. Primeiro, substitui os brancos por espaos. Depois elimina os espaos sufixos. Em terceiro lugar elimina os brancos prefixos (eliminando os brancos sufixos da cadeia invertida, invertendo de novo o resultado). Finalmente, os espaos repetidos so 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;
  • Slide 34
  • 21 Abril de 2005 Recursividade e Iterao 34 Comparao 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 comparao de cadeias de caracteres pode ser feita usando a funo my_str_norm_before, indicada abaixo, que no considera os caracteres brancos. As diferenas 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
  • Slide 35
  • 21 Abril de 2005 Recursividade e Iterao 35 Comparao com Maisculas/Minsculas A comparao de cadeias de caracteres pode ser igualmente prejudicada pela existncia de letras maisculas e minsculas. O Octave tem algumas funes que facilitam o tratamento deste tipo de situaes, nomeadamente as funes tolower e toupper, que convertem os caracteres maisculos / minsculos em caracteres minsculos / maisculos. >> 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
  • Slide 36
  • 21 Abril de 2005 Recursividade e Iterao 36 Converso entre Maisculas/Minsculas As funes anteriores assumem um cdigo ASCII, em que os caracteres brancos tm cdigos abiaxo de 32. Nesse cdigo ASCII, a converso entre maisculas e minsculas pode ser feita adicionando ou subtraindo a sua diferena aos cdigos respectivos. Esta diferena 32, como pode ser verificado em >> dif = toascii(A) toascii(a) dif = -32 No entanto, a utilizao destes valores pode ser problemtica, se forem usados outros cdigos. da responsabilidade da implementao da linguagem interpretar ter em ateno os cdigos usados (que podem no ser ASCII) e disponibilizar primitivas independentes desses cdigos.
  • Slide 37
  • 21 Abril de 2005 Recursividade e Iterao 37 Converso independente do Cdigo Algumas dessas primitivas so isalpha(s) 1 se s fr alfabtico (maiscula ou minscula) islower(s)1 se s fr uma minscula isupper(s)1 se s fr uma maiscula isdigit(s)1 se s fr um dgito isalnum(s)1 se s fr dgito ou alfabtico ispucnt1 se s fr um caracter de pontuao iscntrl(s)1 se s fr caracter de controle Desta forma as funes podero ser rectificadas para se tornarem independentes do cdigo usado para representao dos caracteres. Em particular, o teste toascii(s(i)) < 32 pode/deve ser substituido por iscntrl(s2)
  • Slide 38
  • 21 Abril de 2005 Recursividade e Iterao 38 Cadeias com Caracteres Especiais Os caracteres com cedilhas e acentos, tpicos do portugus, no fazem parte do cdigo ASCII bsico, e os seus cdigos em ASCII estendido no respeitam a ordem natural. Por exemplo, como os cdigos dos caracteres a, s e so, respectivamente 97, 115 e 227, o nome Joo est alfabeticamente aps Jos, ao contrrio do que acontece com Joao. Uma forma de manter a ordenao pretendida utilizar, para efeitos de ordenao, as cadeias com os caracteres acentuados substitudos pelos caracteres no acentuados. O Octave dispe de uma funo (strrep) que substitui numa cadeia base, todas as de uma (sub)cadeia por outra. >> s1 = Joo; s2 = strrep(s1,,a) s2 = Joao