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