Vamos a afianzar los conocimientos de Python que acabamos de adquirir haciendo algunos ejercicios, y así retener las peculiaridades de la sintaxis y aclarar algunos detalles a tener en cuenta cuando se trabaja en modo interactivo.
Vamos a escribir ahora una función que sume los n
primeros números naturales. Observa que podemos escribir una cadena de documentación (docstring) justo debajo de la definición de la función para explicar lo que hace.
In [1]:
def sumatorio(num):
"""Suma los `num` primeros números.
Ejemplos
--------
>>> sumatorio(4)
10
"""
suma = 0
for nn in range(1, num + 1):
suma = nn + suma
return suma
Lo que hemos hecho ha sido inicializar el valor de la suma a 0 e ir acumulando en ella los num
primeros números naturales.
In [2]:
sumatorio(4)
Out[2]:
In [3]:
help(sumatorio)
In [4]:
def sumatorio_mal(num):
for nn in range(1, num + 1):
suma = nn + suma
return suma
In [5]:
sumatorio_mal(4)
Para comprobar el resultado correcto, nada como acudir a la función sum
de Python, que suma los elementos que le pasemos:
In [6]:
list(range(1, 4 + 1))
Out[6]:
In [7]:
sum(range(1, 4 + 1))
Out[7]:
Ahora nuestra función es un poco más rara: tiene que sumar números naturales consecutivos y no pasarse de un determinado límite. Además, queremos el valor de la suma.
In [8]:
def suma_tope(tope):
"""Suma números naturales consecutivos hasta un tope.
"""
suma = 0
nn = 1
while suma + nn <= tope:
suma = suma + nn
nn += 1
return suma
In [9]:
suma_tope(9)
Out[9]:
In [10]:
suma_tope(9) == 1 + 2 + 3
Out[10]:
In [11]:
suma_tope(10) == 1 + 2 + 3 + 4
Out[11]:
La palabra clave assert
recibe una expresión verdadera o falsa, y falla si es falsa. Si es verdadera no hace nada, con lo cual es perfecto para hacer comprobaciones a mitad del código que no estorben mucho.
In [12]:
assert suma_tope(11) == 1 + 2 + 3 + 4
In [13]:
assert suma_tope(10 + 5) == 1 + 2 + 3 + 4
La normativa de exámenes es: "si un examen dura más de 3 horas, entonces debe tener un descanso". Los argumentos de la función son el tiempo en horas y un valor True
o False
que indica si hay descanso o no.
In [14]:
def cumple_normativa(tiempo, descanso):
"""Comprueba si un examen cumple la normativa de la UPM.
"""
if tiempo <= 3:
return True
else:
#if descanso:
# return True
#else:
# return False
return descanso # ¡Equivalente!
In [15]:
cumple_normativa(2, False)
Out[15]:
In [16]:
if not cumple_normativa(5, descanso=False):
print("¡Habla con DA!")
Hallar $x = \sqrt{S}$.
http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
In [17]:
def raiz(S):
x = S / 2
while True:
temp = x
x = (x + S / x) / 2
if temp == x:
return x
Aquí estoy usando un truco de la aritmética en punto flotante: como la convergencia se alcanza rápidamente, llega un momento en que el error es menor que la precisión de la máquina y el valor no cambia de un paso a otro.
In [18]:
raiz(10)
Out[18]:
In [19]:
import math
math.sqrt(10)
Out[19]:
In [20]:
raiz(10) ** 2
Out[20]:
In [21]:
math.sqrt(10) ** 2
Out[21]:
Ahora tienes curiosidad, ¿verdad? :) http://puntoflotante.org/
Secuencia de Fibonacci: $F_n = F_{n - 1} + F_{n - 2}$, con $F_0 = 0$ y $F_1 = 1$.
$$0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...$$Con iteración:
In [22]:
def fib(n):
a, b = 0, 1
for i in range(n):
a, b = b, a + b # Bendita asignación múltiple
return a
In [23]:
fib(0), fib(3), fib(10)
Out[23]:
Con recursión:
In [24]:
def fib_recursivo(n):
if n == 0:
res = 0
elif n == 1:
res = 1
else:
res = fib_recursivo(n - 1) + fib_recursivo(n - 2)
return res
Imprimir una lista con los $n$ primeros:
In [25]:
def n_primeros(n):
F = fib_recursivo
lista = []
for ii in range(n):
lista.append(F(ii))
return lista
In [26]:
n_primeros(10)
Out[26]:
Implementar el sistema de reparto de escaños d'Hondt. Dicho sistema se basa en ir repartiendo escaños consecutivamente al partido con el máximo coeficiente, $c_i = \frac{V_i}{s_i + 1}$, donde $V_i$ es el número total de votos obtenido por del partido $i$, mientras que $s_i$ es el número de escaños asignados dicho partido (0 al comenzar el reparto).
Veamos por ejemplo el caso expuesto en Wikipedia:
Partido | Partido A | Partido B | Partido C | Partido D | Partido E |
---|---|---|---|---|---|
Votos | 340000 | 280000 | 160000 | 60000 | 15000 |
Todavía no hay ningún escaño asignado, así que los votos de cada partido se dividen por 1:
Partido | Partido A | Partido B | Partido C | Partido D | Partido E |
---|---|---|---|---|---|
Votos | 340000 | 280000 | 160000 | 60000 | 15000 |
Escaño 1 | 340000 | 280000 | 160000 | 60000 | 15000 |
Y por tanto el partido A recibe el primer escaño. Para repartir el segundo escaño se vuelven a dividr por 1 los votos de cada partido, salvo el partido A que se divide por 2, pues ya tiene un escaño:
Partido | Partido A | Partido B | Partido C | Partido D | Partido E |
---|---|---|---|---|---|
Votos | 340000 | 280000 | 160000 | 60000 | 15000 |
Escaño 1 | 340000 | 280000 | 160000 | 60000 | 15000 |
Escaño 2 | 170000 | 280000 | 160000 | 60000 | 15000 |
Así pues, el segundo escaño va para el partido B. Si se reparten 7 escaños como en el ejemplo de Wikpedia, la tabla final quedaría como sigue:
Partido | Partido A | Partido B | Partido C | Partido D | Partido E |
---|---|---|---|---|---|
Votos | 340000 | 280000 | 160000 | 60000 | 15000 |
Escaño 1 | 340000 | 280000 | 160000 | 60000 | 15000 |
Escaño 2 | 170000 | 280000 | 160000 | 60000 | 15000 |
Escaño 3 | 170000 | 140000 | 160000 | 60000 | 15000 |
Escaño 4 | 113333 | 140000 | 160000 | 60000 | 15000 |
Escaño 5 | 113333 | 140000 | 80000 | 60000 | 15000 |
Escaño 6 | 170000 | 93333 | 80000 | 60000 | 15000 |
Escaño 7 | 85000 | 93333 | 80000 | 60000 | 15000 |
Así que los partidos A y B obtendrían 3 escaños, mientras que el partido C obtendría 1 único escaño, quedando el resto de partidos fuera del proceso.
In [27]:
def hondt(votos, n):
s = [0] * len(votos)
for i in range(n):
c = [v[j] / (s[j] + 1) for j in range(len(s))]
s[c.index(max(c))] += 1
return s
In [28]:
v = [340000, 280000, 160000, 60000, 15000]
n = 7
hondt(v, n)
Out[28]:
En esta clase hemos visto cómo crear funciones que encapsulen tareas de nuestro programa y las hemos aplicado para respondernos ciertas preguntas sencillas.
Referencias