Programação Recursiva em Python
Programação Recursiva em Python
html
Recursão
Factorial
Considere-se o seguinte exemplo, que implementa a função factorial. Recorde-se que para um número
natural $n$ se tem:
O módulo Math, incluído na extensão Pylab, que vimos anteriormente, já disponibiliza uma
implementação.
In [5]: fact(6)
Out[5]: 720
1 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Este facto não deve impedir-nos de programarmos a nossa própria definição. Isto é algo que faremos
muitas vezes, não por razões de eficiência (a nossa definição será sempre menos eficiente que uma
definição hiper-optimizada predefinida), mas por razões pedagógicas, até porque nalgum momento
iremos com certeza necessitar de programar algo que de facto não está imediatamente disponível.
A implementação é muito simples, e em tudo semelhante à definição por casos que vimos acima.
In [8]: factorial(7)
Out[8]: 5040
2 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Python 3.6
Frames Objects
1 def factorial(x):
2 if x==0:
3 return 1
4 else:
5 return x*factorial(x-1)
6
7 factorial(4)
line that just executed
next line to execute
Step 1 of 22
Rendered by Python Tutor
Customize visualization (NEW!)
Claro que a recursão é um mecanismo bastante sensível, pelo que é muito fácil ocorrerem "problemas".
3 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
In [9]: factorial(4.3)
------------------------------------------------------------------
---------
RecursionError Traceback (most recent c
all last)
<ipython-input-9-d3f4cc53fa91> in <module>()
----> 1 factorial(4.3)
<ipython-input-6-b49233140dee> in factorial(x)
3 return 1
4 else:
----> 5 return x*factorial(x-1)
<ipython-input-6-b49233140dee> in factorial(x)
3 return 1
4 else:
----> 5 return x*factorial(x-1)
Por razões de eficiência, o sistema limita à partida a profundidade de uma cadeia de chamadas
recursivas. Neste caso isso é de facto benéfico, pois corríamos o risco de esperar para sempre pelo
resultado, já que esta chamada recursiva não é bem fundada. De todo o modo, se necessário, o limite de
recursão pode ser alterado manualmente.
À partida a disciplina de tipos da linguagem Python é relativamente permissiva, mas a robustez das
nossas definições face a valores indesejados dos argumentos (excepções) pode ser garantida
explicitamente de várias formas.
In [9]: factorial_robusto(5)
Out[9]: 120
In [10]: factorial_robusto(-7)
Outra solução, menos silenciosa mas igualmente eficaz, consiste na utilização da primitiva assert, que
poderá ser também bastante útil na depuração de erros de programação.
4 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
In [12]: factorial_robusto2(0)
Out[12]: 1
In [13]: factorial_robusto2(3.1)
------------------------------------------------------------------
---------
AssertionError Traceback (most recent c
all last)
<ipython-input-13-aa8c7abd33c4> in <module>()
----> 1 factorial_robusto2(3.1)
<ipython-input-11-b32ee8f8bc7e> in factorial_robusto2(x)
1 def factorial_robusto2(x):
----> 2 assert isinstance(x,int) and x>=0
3 return factorial(x)
AssertionError:
Existem outros métodos para controlo de excepções, nomeadamente usando try-raise-except, que não
abordaremos de momento. De todo o modo, por razões pedagógicas, estaremos em geral preocupados
com a implementação de soluções correctas para os problemas colocados, muito mais do que com a
robustez das soluções obtidas, e que pode sempre ser garantida a jusante.
Exponenciação
Outro exemplo útil, que revisitaremos adiante, consiste na nossa própria definição de exponenciação.
Como sabemos, se $x\neq 0$, tem-se:
5 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
In [13]: exponencial(0,10)
------------------------------------------------------------------
---------
AssertionError Traceback (most recent c
all last)
<ipython-input-13-2359369d710e> in <module>()
----> 1 exponencial(0,10)
<ipython-input-11-e31d77b0b325> in exponencial(x, n)
1 def exponencial(x,n):
----> 2 assert x!=0
3 if n==0:
4 return 1
5 else:
AssertionError:
Claro que neste caso seria imediato usar as funções predefinidas da linguagem Python.
In [6]: 2**10
Out[6]: 1024
In [18]: mdc(234,1108)
Out[18]: 2
Vale a pena notar que o módulo Math inclui uma definição equivalente a esta (gcd - greatest common
divisor).
6 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Para além dos números naturais, é possível explorar a estrutura indutiva de outros tipos para construir
definições recursivas. É o caso óbvio das listas, que podemos destruir até ficarem vazias.
Comprimento
Comecemos com um exemplo muito simples, o cálculo do comprimento de uma lista (obviamente sem
usar len).
In [20]: compr([4,5,6])
Out[20]: 3
Média
Queremos agora implementar uma função media que calcule o valor médio de uma lista de números.
Claramente, será necessário calcular a soma dos elementos da lista. Para tal, definiremos uma função
auxiliar, à custa da qual será muito simples calcular a média.
def media(w):
if w==[]:
print("erro, lista vazia")
else:
return somalista(w)/len(w)
In [22]: media([1,2,4])
Out[22]: 2.3333333333333335
7 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
É útil reflectir, a propósito destes últimos exemplos, em como determinar o valor do caso base de uma
definição recursiva. Quer na definição de compr, quer agora em somalista, o valor de base é 0. Já nas
definições de factorial e de exponenciação, o valor de base é 1. Por que será? Claramente, compr
e somalista manipulam listas, enquanto factorial e exponenciação manipulam números, mas
essa não é de todo a razão para esta discrepância. O que acontece é que enquanto compr e
somalista são definições que acumulam o resultado por somas sucessivas, factorial e
exponenciação acumulam o resultado por multiplicações sucessivas. Tipicamente, o valor do caso
base corresponderá ao elemento neutro da operação utilizada para acumular o resultado pretendido. Vale
a pena ter este facto em mente na construção das nossas definições.
Implementemos agora uma função ate que devolva a lista dos números naturais até um valor dado n
(exclusive), que permita obter o mesmo efeito de list(range(n)).
In [24]: ate(10)
Out[24]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Lista de factoriais
Atentemos agora no seguinte problema, que enquadra uma situação típica em programação. Queremos,
dada uma lista de valores naturais, calcular a lista dos seus factoriais (sem recorrer a definições por
compreensão).
In [26]: flista([5,7,10])
Prefixos
8 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Consideremos agora o problema de determinar se uma dada lista é ou não prefixo de outra, ou seja, se a
primeira lista é um segmento inicial da segunda lista. A ideia passa por garantir que cada um dos
elementos da primeira lista é igual ao da segunda. Tratando-se uma função de resultado Booleano, dita
um predicado, convencionamos dar-lhe um nome terminado por Q.
In [28]: prefixoQ([1,2,3],[1,2,3,4,5])
Out[28]: True
In [29]: prefixoQ([2,3],[1,2,3,4,5])
Out[29]: False
Outra situação recorrente ocorre quando queremos determinar, dada uma lista, se todos os elementos
têm (ou algum elemento tem) uma certa propriedade. A propriedade em causa não é importante,
podemos assumir apenas que é dada por algum predicado.
todosQ([2,4,6],parQ)
Out[2]: True
9 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
In [33]: algumQ([1,3,5,7],parQ)
Out[33]: False
Podemos interpretar os valores dos casos base True para todosQ e False para algumQ, tal como já foi
explicado antes, como os elementos neutros das operações que acumulam os resultados,
respectivamente, and e or. Para clarificar, atente-se na seguinte definição alternativa de todosQ.
Deixa-se como exercício ao leitor a construção de uma definição alternativa similar de algumQ.
Outros exemplos
Vale a pena praticar bastante a resolução de problemas, sendo na verdade a única verdadeira forma de
aprender a programar. Para ajudar nesse esforço vale a pena percorrer a seguinte lista de exemplos, um
pouco mais elaborados.
Capicuas
Uma capicua é um número natural que se lê de igual modo da esquerda para a direita ou da direita para
a esquerda. O conceito análogo, para palavras, é o de palíndromo. Começamos por definir um predicado
palindromoQ que determina se uma lista de valores dada é ou não um palíndromo. Definimos ainda
uma outra função auxiliar que extrai, dado um número natural, a lista dos seus dígitos. Torna-se simples,
de seguida, definir o predicado capicuaQ.
10 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
def digitos(n):
if n<10:
return [n]
else:
return digitos(n//10)+[n%10]
def capicuaQ(n):
return palindromoQ(digitos(n))
In [35]: palindromoQ([True,True,False])
Out[35]: False
In [36]: digitos(1073)
Out[36]: [1, 0, 7, 3]
In [37]: capicuaQ(12321)
Out[37]: True
Números primos
Pela sua importância, vale a pena implementar um teste de primalidade (naive, e portanto muito pouco
eficiente). Há testes de primalidade eficientes, mas a sua compreensão exige alguns conhecimentos de
teoria algébrica dos números. Aqui procuraremos apenas dividir o número em apreço por todos os que
lhe são menores, em busca de um hipotético divisor.
def primoQ(n):
return n>1 and not(temdivisorQ(n,2,n-1))
In [2]: primoQ(223)
Out[2]: True
11 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Tirando partido da definção anterior podemos construir facilmente a lista dos primos menores que um
dado valor.
In [4]: primosate(111)
Out[4]: [2,
3,
5,
7,
11,
13,
17,
19,
23,
29,
31,
37,
41,
43,
47,
53,
59,
61,
67,
71,
73,
79,
83,
89,
97,
101,
103,
107,
109]
O mesmo efeito poderia ser obtido com uma definição por compreensão.
Out[7]: [2, 3, 5, 7]
Podemos ainda definir uma função que dado n nos devolve o n-ésimo primo.
12 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
def proxprimos(i,k):
if k==1 and primoQ(i):
return i
elif k>1 and primoQ(i):
return proxprimos(i+1,k-1)
else:
return proxprimos(i+1,k)
return proxprimos(2,n)
In [28]: primo(100)
Out[28]: 541
A definição de primo ilustra ainda uma outra possibilidade fundamental, visível na forma como se
encaixou a definição da função auxiliar proxprimos, que se costuma designar por encapsulamento.
Dentro de uma definição, todos os nomes (que não sejam declarados globais) têm carácter local. Assim
sendo, a função auxiliar não tem de facto existência exterior à definição, o que evita o povoamento
desnecessário do espaço de trabalho.
In [45]: ?proxprimos
Também é útil, por vezes, a construção de recursões potencialmente mal fundadas. É o caso da seguinte
definição, que dada uma sucessão $\{s_n\}_{n\in\mathbb{N}}$ procura o menor valor de $n$ tal que
$s_n$ é zero (se existir).
return tenta(0)
pesqzero(sucessao1)
Out[20]: 5
13 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
def sucessao2(n):
return cos(n*pi/100)
pesqzero(sucessao2)
Out[21]: 50
pesqzero(sucessao3)
------------------------------------------------------------------
---------
RecursionError Traceback (most recent c
all last)
<ipython-input-22-300421e24595> in <module>()
2 return 1
3
----> 4 pesqzero(sucessao3)
<ipython-input-19-fd5ce75fc44a> in pesqzero(s)
6 return tenta(n+1)
7
----> 8 return tenta(0)
<ipython-input-19-fd5ce75fc44a> in tenta(n)
4 return n
5 else:
----> 6 return tenta(n+1)
7
8 return tenta(0)
<ipython-input-19-fd5ce75fc44a> in tenta(n)
4 return n
5 else:
----> 6 return tenta(n+1)
7
8 return tenta(0)
Considere-se o problema de dado um número real (com precisão arbitrária) determinar (se existir, claro)
a posição em que um certo dígito ocorre, pela n-ésima vez na sua expansão decimal.
14 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
return contar(d,n,num,1,1)
0.4285714285714285714285714285714285714285714285714285714285714285
714285714285714285714285714285714285714285714285714285714285714285
714285714285714285714285714285714285714285714285714285714285714285
7143
In [3]: nposdig(4,3,[Link](3,7))
Out[3]: 13
In [4]: print([Link])
3.1415926535897932384626433832795028841971693993751058209749445923
078164062862089986280348253421170679821480865132823066470938446095
505822317253594081284811174502841027019385211055596446229489549303
82
In [5]: nposdig(9,1,[Link])
Out[5]: 5
In [6]: nposdig(9,20,[Link])
Out[6]: 187
In [7]: nposdig(1,1,10**-100)
Out[7]: 100
A algoritmia é o ramo da ciência da computação que estuda a eficiência de algoritmos. Existem diversas
técnicas, mais ou menos gerais, para melhorar a eficiência dos programas que escrevemos. Vamos ver,
sucintamente, as ideias por detrás de algumas dessas técnicas.
15 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Esta técnica napoleónica está por detrás de muitos dos melhores algoritmos existentes para diversos
fins. Claro que a ideia da recursão é sempre a de reduzir o cálculo de uma função para determinados
valores ao cálculo da mesma função para valores mais simples. No entanto, esta simplificação pode ser
feita a várias velocidades.
Atente-se na seguinte definição alternativa da função exponencial desenvolvida acima, mas em que,
num só passo, se reduz o expoente a metade.
In [24]: sqrmult(2,10)
Out[24]: 1024
Out[27]: 107150860718626732094842504906000181056140481170553360744375038837
035105112493612249319837881569585812759467291755314682518714528569
231404359845775746985748039345677748242309854210746050623711418779
541821530464749835819412673987675591655439460770629145711964776865
42167660429831652624386837205668069376
Out[28]: 107150860718626732094842504906000181056140481170553360744375038837
035105112493612249319837881569585812759467291755314682518714528569
231404359845775746985748039345677748242309854210746050623711418779
541821530464749835819412673987675591655439460770629145711964776865
42167660429831652624386837205668069376
Memoização
16 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Out[31]: 10946
Out[32]: 14930352
A razão para esta ineficiência é simples: por exemplo, para calcular fibonacci(35) é necessário
calcular fibonacci(34) e fibonacci(33), mas o cálculo de fibonacci(34) também necessita de
calcular fibonacci(33), que é portanto calculado 2 vezes; é fácil perceber que então fibonacci(32)
será calculado 3 vezes, fibonacci(31) será calculado 5 vezes e assim sucessivamente, dando origem
a um processo (pior do que) exponencial.
A solução passa por refazer a definição de forma a que cada valor do factorial seja calculado não mais
do que uma vez.
def fibgo(a,b,k):
if k==0:
return a
else:
return fibgo(b,a+b,k-1)
return fibgo(1,1,n)
Out[34]: 573147844013817084101
17 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Esta ideia, que consiste em memorizar os valores intermédios necessários de forma a que não
necessitem de ser recalculados é usualmente conhecida por memoização, tem um papel fundamental em
técnicas de programação dinâmica.
Talvez ainda mais interessante é o exemplo que consiste no cálculo do valor máximo de uma lista de
números.
Esta definição funciona mas é extremamente ineficiente. Se usarmos $S_n$ para denotar o número
máximo de vezes que é necessário comparar elementos da lista no cálculo da função é simples de
verificar que $S_1=0$ e $S_{n+1}=1+2 S_n$. A sucessão tem os valores $0,1,3,7,15,31,63,\dots$ e
facilmente se verifica que de facto $S_n=2^{n-1}-1$ cresce exponencialmente com $n$.
Out[35]: 24
Out[36]: 25
18 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Out[39]: 25
Se quisermos cingir-nos ao paradigma recursivo, uma solução simples passa por calcular o valor apenas
uma vez passando-o como argumento a uma função auxiliar que o utiliza (as vezes que forem
necessárias).
if w==[]:
print("erro")
elif len(w)==1:
return w[0]
else:
return maior(w[0],max3(w[1:]))
Out[3]: 25
CPU times: user 1.22 ms, sys: 242 µs, total: 1.47 ms
Wall time: 1.47 ms
Out[5]: 259
Outra solução, não menos interessante, passa por ir actualizando e transportando ao longo da
computação o valor máximo dos elementos da lista que já foram analisados.
if w==[]:
print("erro")
else:
return maxparcial(w[1:],w[0])
19 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Out[7]: 25
CPU times: user 2.67 ms, sys: 1.26 ms, total: 3.93 ms
Wall time: 3.13 ms
Out[8]: 259
Iteração
As definições de fib2 ou max3 acima, têm outra característica fundamental: ambas dão origem a um
processo a que é usual chamar de iterativo (tail-recursion em inglês). Isto significa que cada chamada
recursiva é imediatamente resolvida, não tendo o sistema necessidade de alocar espaço de memória
para armazenamento de cálculos intermédios.
Toda a definição recursiva pode ser transformada, com alguma experiência, numa definição iterativa. Isto
tem vantagens de eficiência (não totalmente patentes em Python, pois por opção dos seus autores não é
disponibilizado um mecanismo de optimização para tail-recursion frequente noutras linguagens de
programação), mas também conceptual. O mecanismo subjacente a esta transformação é o passo
fundamental que necessitamos de dar para entrar noutro paradigma de programação: a programação
imperativa.
def factorialaux(i,r):
if i==0:
return r
else:
return factorialaux(i-1,r*i)
return factorialaux(n,1)
A ideia essencial é a de conseguir fazer a definição com recurso a uma função auxiliar com argumentos
adicionais, que usamos para transportar explicitamente os valores auxiliares necessários ao cálculo dos
valores intermédios.
Atente-se em mais um exemplo, desta vez uma definição iterativa da função flista.
20 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
def flistaaux(wfalta,wfeito):
if wfalta==[]:
return wfeito
else:
return flistaaux(wfalta[1:],wfeito+[factorial(wfalta
[0])])
return flistaaux(w,[])
Deixa-se como exercício encontrar implementações iterativas correspondentes a cada um dos exemplos
trabalhados neste notebook (que não o sejam já, claro).
In [38]: flistaiter([7,8,9])
Out[1]:
21 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Out[2]:
É claro que se escolhermos de forma aleatória uniforme N pontos no quadrado 1x1 e K deles estiverem
dentro do quarto de círculo então 4K/N será uma aproximação (racional) razoável de $\pi$, que
melhorará à medida que N aumenta. Podemos programar este método?
A primitiva random da extensão random dá-nos um valor (pseudo-)aleatório uniforme no intervalo [0, 1).
In [4]: random()
Out[4]: 0.49093974003847074
In [5]: random()
Out[5]: 0.4035082212201775
return 4*hits(n)/n
In [7]: recpi(10)
Out[7]: 3.2
22 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
In [8]: recpi(100)
Out[8]: 3.44
In [9]: recpi(1000)
Out[9]: 3.108
23 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
In [10]: recpi(10000)
24 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
------------------------------------------------------------------
---------
RecursionError Traceback (most recent c
all last)
<ipython-input-10-42f8ecfe9bff> in <module>()
----> 1 recpi(10000)
<ipython-input-6-bbe8f5685ae4> in recpi(n)
8 return hits(k-1)
9
---> 10 return 4*hits(n)/n
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
6 return 1+hits(k-1)
7 else:
----> 8 return hits(k-1)
9
10 return 4*hits(n)/n
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
6 return 1+hits(k-1)
7 else:
----> 8 return hits(k-1)
9
10 return 4*hits(n)/n
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
25 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
6 return 1+hits(k-1)
7 else:
----> 8 return hits(k-1)
9
10 return 4*hits(n)/n
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
26 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
6 return 1+hits(k-1)
7 else:
----> 8 return hits(k-1)
9
10 return 4*hits(n)/n
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
6 return 1+hits(k-1)
7 else:
----> 8 return hits(k-1)
9
10 return 4*hits(n)/n
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
27 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
6 return 1+hits(k-1)
7 else:
----> 8 return hits(k-1)
9
10 return 4*hits(n)/n
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
6 return 1+hits(k-1)
7 else:
----> 8 return hits(k-1)
9
10 return 4*hits(n)/n
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
28 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
<ipython-input-6-bbe8f5685ae4> in hits(k)
4 return 0
5 elif random()**2+random()**2<1:
----> 6 return 1+hits(k-1)
7 else:
8 return hits(k-1)
In [13]: recpi(10000)
Out[13]: 3.1228
In [14]: recpi(10000)
Out[14]: 3.146
29 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
return 4*hits(0,n)/n
In [21]: iterpi(10000)
Out[21]: 3.1392
In [22]: iterpi(10000)
Out[22]: 3.1468
Sumário
Bibliografia
30 de 31 02/01/2021, 00:30
NB04 - Programacao recursiva [Link]
Think Python: How to think like a computer scientist: A. Downey, Green Tea Press, 2012.
Introduction to Computation and Programming Using Python (revised and expanded edition): J. V. Guttag,
MIT Press, 2013.
The Art of Computer Programming: D. E. Knuth, Addison-Wesley (volumes 1--3, 4A), 1998.
Learning IPython for Interactive Computing and Data Visualization: C. Rossant, Packt Publishing, 2013.
31 de 31 02/01/2021, 00:30