Usarei notação F# para os algoritmos.

1) Algoritmo imperativo, que depende de mutabilidade:
let mutable i = n
let mutable B = ""
while i > 0 do
    B <- B + A
    i <- i - 1
printf "%A" B

2) Algoritmo recursivo, apenas com valores imutáveis:
let rec concatena A = function
    | 1 -> A
    | i -> A + concatena A (i-1)
printf "%A" (concatena A n)

3) Algoritmo recursivo com "tail-recursion" (evita stack-overflow) usando
acumulador:
let rec concatena A acc = function
    | 0 -> acc
    | i -> concatena A (acc + A) (i - 1)
printf "%A" (concatena A "" n)

4) Algoritmo recursivo com "continuation passing style" (evita
stack-overflow):
let rec concatena (A:string) f = function
    | 1 -> f A
    | i -> concatena A (fun s -> f(A) + s) (i - 1)
printf "%A" (concatena A (fun x -> x) n)



Para quem tem background de C, Pascal, ou derivados ou similares, a solução
1 deve ser a mais óbvia. É aquela que vc diz ao computador exatamente o que
fazer a cada passo, alterando o valor das variáveis (por isso se chama
imperativa).

Mas perceba que a solução 2 é muito mais simples de se compreender. Ela
quebra o problema em 2 problemas: um trivial, e outro reduzido. O trivial é:
concatenar 1 vez é o mesmo que retornar a própria string. O reduzido é:
concatenar n vezes é o mesmo que concatenar A ao resultado da concatenação
de (n-1) vezes.

As soluções 3 e 4 são a mesma coisa que a 2, mas usam duas técnicas
distintas para permitir ao compilador de criar certas otimizações que
impossibilitarão um problema de "stack-overflow" por conta de um grande
número de chamadas recursivas.

A solução 3 usa "tail recursion", isto é, a chamada recursiva é a última
coisa que se faz na função. O compilador pode, nesse caso, transformar essa
chamada recursiva num loop. No final, o código compilado será muito próximo
ao código da solução 1, só que vc pôde obter esse código escrevendo seu
algoritmo duma forma de bem mais alto nível.

A solução 4 usa o que se chama "continuation passing style", isto é, vc
passa à função uma outra função que deve ser chamada assim que a primeira
terminar de executar. Esse talvez seja o mais difícil de "pegar a idéia" pra
quem não está acostumado. Isso só é possível de se fazer de maneira simples
em linguagens "funcionais".


Bruno

--
Bruno FRANÇA DOS REIS

msn: [email protected]
skype: brunoreis666
tel: +55 11 9961-7732

http://brunoreis.com
http://brunoreis.com/tech (en)
http://brunoreis.com/blog (pt)

GPG Key: http://brunoreis.com/bruno-public.key

e^(pi*i)+1=0


2010/4/8 Diogo FN <[email protected]>

> Boa Tarde, pessoal da lista.
>
> Então, me ajuda nessa?
>
> * Dada uma string A e um número N, definir e imprimir uma string B que
> consiste na reprodução da cadeia A, N vezes.
>
> ------------------------------
> Veja quais são os assuntos do momento no Yahoo! + Buscados: Top 
> 10<http://br.rd.yahoo.com/mail/taglines/mail/*http://br.maisbuscados.yahoo.com/>-
> Celebridades<http://br.rd.yahoo.com/mail/taglines/mail/*http://br.maisbuscados.yahoo.com/celebridades/>-
> Música<http://br.rd.yahoo.com/mail/taglines/mail/*http://br.maisbuscados.yahoo.com/m%C3%BAsica/>-
> Esportes<http://br.rd.yahoo.com/mail/taglines/mail/*http://br.maisbuscados.yahoo.com/esportes/>
>

Responder a