sábado, 11 de mayo de 2019

Cálculo de la TIR (Tasa Interna de Rentabilidad) en Python

Vamos a calcular la TIR que es la Tasa Interna de Rentabilidad o también denominada Tasa Interna de Retorno. En inglés se denomina IRR (Internal Rate of Return). La TIR nos proporciona la rentabilidad que proporciona una inversión financiera. Habitualmente existe un flujo de caja negativo en t=0 y luego una serie de flujos de caja en los periodos t=1 hasta t=n. Si los flujos de caja son de periodicidad anual la TIR obtenida será directamente un tanto anual, si la periodicidad de los flujos de caja es diferente a la anual, por ejemplo mensual, la TIR que se obtiene será la expresada en esa unidad temporal y tendremos que posteriormente anualizarla, ya que el concepto de TIR hace referencia a un tanto anual efectivo.

Veamos varios método para programar la TIR en Python.

Método 1

Cargamos la librería numPy y alimentamos la función irr con los flujos de caja de la inversión. Si en un momento dado no existiera flujo de caja se tendría que indicar poniendo cero. El resultdo obtenido vendrá dado en tanto por uno.
import numpy as np
flujos=[-4000,1400,1300,1200,1100,1000]
print (round(np.irr(flujos), 5))
El resultado es la TIR de la inversión expresada en tanto por uno 0.16289 que equivale a un 16,289%
anual, suponiendo que los flujos de caja se dieron con periodicidad anual.

Método 2

Programando la TIR mediante un algoritmo que calcula los puntos de corte con el eje de abcisas. Puesto que la TIR se define como aquel tipo de interés que hace el VAN igual a cero, lo que tenemos que hacer es calcular el punto de corte con el eje horizontal en el gráfico del VAN (Valor Actual Neto).

Para hacer este cálculo utilizamos un algoritmo de cálculo numérico por aproximaciones sucesivas. Partimos de una tasa de interés inferior muy baja ka=-0,5 que es negativa del 50%, y partimos de una tasa de interés superior muy alta kc=10 que supone una tasa positiva del 1.000%. Este algoritmo calculará la TIR de la inversión proporcionada si está comprendida entre ka y kc. Si está fuera de este rango responderá con el texto 'sin TIR'.
Calculamos un valor inferior para el VAN que denominamos inf y que se obtiene calculando el VAN a una tasa ka=-50%.
Calculamos un valor superior para el VAN que denominamos sup y que se obtiene calculando el VAN a una tasa kc=1000%.
El VAN inferiro, inf, seguramente salga negativo, y el VAN superior, sup, seguramente saldrá positivo. Bajo este supuesto es sobre el que nuestro algoritmo trabajará ya que si esto es así quiere decir que existirá un VAN que saldrá igual a cero a una cierta tasa de descuento, que será la TIR de la operación.
Lo que hacemos ahora es calcular la media aritmética entre ka y kc. A esa semisuma la denominamos kb.
kb=(ka+kc)/2

  • Calculamos el VAN al nuevo tipo kb y si es negativo eso indicará que la TIR es menor que kb y por lo tanto para un nuevo ciclo del bucle haremos que rc sea igual a kb. Graficamente lo que ha sucedido es que kb es una tasa que obtiene un VAN negativo por lo que la TIR buscada estará a su izquierda.
  • Si el VAN obtenido al nuevo tipo kb es positivo eso indicará que la TIR es mayor que kb y por lo tanto para un nuevo ciclo del bucle haremos que ra sea igual a kb. Graficamente lo que ha sucedido es que kb es una tasa que obtiene un VAN positivo por lo que la TIR buscada estará a su derecha.
De esta forma iremos acotando el valor de la TIR por la derecha y por la izquierda hasta que consideremos que el error comentido en el VAN por ambos lados es inferior a un cierto valor suficientemente pequeño.

Cuando el error es despreciable (inferior a 10-10) detenemos el bucle e imprimimos la TIR redondeando y expresada en porcentaje.

#La lista flujos incluye el desembolso inicial
def VAN(tasa,flujos):
  VA=0
  for j in range(len(flujos)):
    VA+=flujos[j]/(1+tasa)**j
  return VA

#print('VAN=',VAN(0.05,[-4000,1400,1300,1200,1100]))

def TIR(flujos):
  ka=-.5 #tasa de descuento inferior. Inicialmente -50%
  kc=10 #tasa de descuento superior. Inicialmente 1000%
  inf=VAN(ka,flujos) #VAN calculado con la tasa inferior
  sup=VAN(kc,flujos) #VAN calculado con la tasa superior
  if inf>=0 and sup<0:
    error=abs(inf-sup)
    while error>=1e-10:
      kb=(ka+kc)/2
      #print(kb)
      med=VAN(kb,flujos)
      if med<=0:
        kc=kb
      elif med>0:
        ka=kb
      inf=VAN(ka,flujos)
      sup=VAN(kc,flujos)
      error=inf-sup
    return kb
  else:
    return "sin TIR"

misFlujos1=[-4000,1400,1300,1200,1100]
misFlujos2=[-5000,1500,1600,1700,1800,1900]
print('TIR=',str(round(TIR(misFlujos2)*100,8))+'%')

lunes, 18 de marzo de 2019

Encriptar y desencriptar con Python

El codigo de abajo usando un diccionario encripta y desencripta le texto que tú le des.

d1={'00':'a','01':'b','02':'c','03':'d','04':'e','05':'f','06':'g','07':'h','08':'i','09':'j','10':'k','11':'l','12':'m','13':'n','14':'ñ','15':'o','16':'p','17':'q','18':'r','19':'s','20':'t','21':'u','22':'v','23':'w','24':'x','25':'y','26':'z'}
d2 = {v: k for k, v in d1.items()} #d2 es el diccionario inverso a d1

def encriptar(x,d2):
  resultado=''
  for i in x:
    resultado+=d2.get(i)
  return resultado

def desencriptar(y,d1):
  resultado=''
  for i in range(0,len(y),2):
    resultado+=d1.get(y[i]+y[i+1])
  return resultado

x=list(input("¿Qué frase quieres encriptar?").lower() or 'hola')
y=encriptar(x,d2)
print(y)
z=desencriptar(y,d1)
print(z)

Primero definimos el diccionario con los valores de las letras y el número que las identifica. Usando una función para encriptar, que empieza resultado como una variable vacía y usa un for para recorrer una por una las letras de la frase que nos ha dado el usuario, añadimos a resultado el número que representa a la letra que estamos analizando, devolvemos el valor final de resultados y lo imprimimos ya fuera del def.

Para el def desencriptar hacemos algo parecido, definimos resultado vacio, for recorriendo uno por uno los elementos de y, una variable que tiene el mismo valor que el mensaje encriptado, y luego añadimos a nuestra nueva variable, resultado, el valor que le corresponde a cada número de el diccionario de d2, que es el diccionario d1 pero cambiamos los números por las letras, y viceversa, devolvemos lo que eso nos dé.

Para finalizar el código definimos la variable x, que coge el mensaje del usuario, ejecutamos los dos def, y les damos los valores en los paréntesis, para encriptar y desencriptar e imprime todo.

martes, 12 de marzo de 2019

Histogramas avanzados en Python

En un post anterior explicaba como hacer un histograma simple, en este me gustaría expandir un poco mas en ello.

Para emepzar me gustaría explicar como darle un titulo o añadir algunas cosas para que quede mas bonito y la información repesentada se entienda mejor.

Para poner un titulo el codigo seria alg así:
 plt.title("Tú titulo")  

Si quisieramos decir que valor está en el valor

domingo, 10 de febrero de 2019

Calculadora de IVA

Calculadora de IVA

Programar dos casos para el cálculo del IVA. El caso A calcula el precio con IVA dados el precio base y el porcentaje de IVA. El caso B calcula el precio base dados el precio con IVA y el porcentaje de IVA.




Método 1

Creamos dos funciones, una para el método a y otra para el método b. Pedimos al usuario que indique qué método desea calcular. Para el método a pedimos el precio base y el porcentaje de IVA y proporcionamos el precio con IVA incluido. Para el método b pedimos el PVP (precio de venta al público) o precio con el IVA incluido, tambien pedimos el porcentaje de IVA y proporcionamos el precio base o precio sin IVA. Las funciones proporcionan el resultado final imprimiendo por pantalla el valor resultante redondeado a dos decimales.

def metodoA():
  base = float(input('Valor de base? ') or 200)
  percent = int(input('Valor de porcentaje? ') or 21)
  result = base * (1 + (percent / 100))
  print('\nBase=', base, '\nPorcentaje= ' + str(percent) + '%')
  print('Precio con IVA=', round(result,2))

def metodoB():
  conIVA = float(input('Precio con IVA? ') or 242)
  percent = int(input('Porcentaje? ') or 21)
  result = conIVA / (1 + (percent / 100))
  print('\nPrecio con IVA=',conIVA,'\nPorcentaje= '+str(percent)+'%')
  print('Precio base=', round(result,2))

print('\nCálculo del IVA \nDispone de dos métodos:\n')
print('Método a: Si damos el precio sin IVA y el porcentaje de IVA nos dará el PVP (Precio Venta Público)\n')
print('Método b: Si damos el precio con IVA y el porcentaje de IVA nos dará el precio base \n')
metodo = input('Que metodo quieres usar? (a/b) ')
metodo = metodo.lower()

while metodo != 'a' and metodo != 'b':
  metodo = input('El termino introducido no es valido\nQue metodo quieres usar? (a/b) ')
  metodo = metodo.lower()
if metodo == 'a':
  metodoA()
elif metodo == 'b':
  metodoB()

jueves, 27 de septiembre de 2018

La leyenda del Ajedrez

También puede interesarle ver Progresión geométrica en Python

A todos nos han contado la famosa leyenda del tablero de ajedrez y los granos de trigo. Se dice que un sabio enseñó a jugar al ajedrez a un rey de la India. Éste en recompensa le prometió darle lo que quisiera y el sabio pidió como recompensa un grano de trigo por la primera casilla del tablero y que por cada casilla adicional fuera doblando el numero de granos que había en la anterior. Los matemáticos del rey después de muchos días de cálculos le informaron que ese numero era tan grande que no había suficiente trigo en el mundo para pagar al sabio.

Para ilustrar el crecimiento geométrico hemos creado un código en Python para calcular ese número. Aquí tenéis el código.

 i=0  
 s=0  
 while i<64:  
  s+=2**i  
  print(i+1,2**i,s)  
  i+=1  
 print('Unos',int(round(s/25000000000000,0)),'millones de toneladas')  
 print('En 2018, la producción mundial fue de 750 millones de toneladas')  

La última línea se he añadido para dar una mejor perspectiva al enorme de numero que tenemos delante.

miércoles, 26 de septiembre de 2018

Histograma en Python

Para hacer un histograma en Python vamos ha utilizar la librería matplotlib y generaremos los valores de manera aleatoria. El código es este:

import matplotlib.pyplot as plt
import random as ran
values=[]
for x in range(1,11):
   values.append(ran.randrange(11))
plt.hist(values, bins=10)
plt.show()
Usando el for vamos a ir generando números aleatorios y metiendo los en values.
Aquí entra la parte de la librería matplotlib, le pedimos que ejecute hist para indicar que queremos hacer un histograma, también le damos el valor de values para indicar con valores queremos trabajar y por ultimo indicamos los bins que determina el numero de columnas que queremos que se divida la información. Lo imprimimos todo y ya está.

Una variación que podemos hacer es que sin que tú hagas nada te genere mas de histograma con este codigo:


import matplotlib.pyplot as plt
import random as ran
def histograma():
    values=[]
    for x in range(1,11):
        values.append(ran.randrange(11))
    #values=[0,0.6,1.4,1.6,2.2,2.5,2.6,3.2,3.5,3.9,4.2,6]
    plt.hist(values, bins=10)
    plt.show()

for x in range(1,6):
    histograma()

Nota: En la mayoría de paginas web que ejecutan Python no sé podrán ver los gráficos en sí. Para ello necesitaras usar un programa mas potente que pueda procesar las librerías.
Si ejecutas este código en algunos editores de código como PyCharm, al importar las librerías no solo tendrás que importarla escribiéndola en el código si no que tendrás que importarla desde el propio editor. Aquí os enseñamos cómo hacerlo: https://www.youtube.com/watch?v=aROm4KYHXLI&feature=youtu.be

lunes, 24 de septiembre de 2018

Adivina el número secreto en Python

Reto: Adivina el número secreto

Se genera un número aleatorio entero entre 1 y 100. El usuario debe adivinar el número secreto, diciendo en cada tirada si es mayor o menor.




Método 1

Importamos la librería random para generar el número aleatorio secreto n. Preguntamos al usuario por el primer número. Se añade int antes del input para convertir su respuesta en un número entero, ya que si esto no se hace se capturaría un string. Nos metemos en un bucle de tipo while donde la condición analiza si el número proporcionado por el usuario es distinto del número secreto. Dentro de bucle creamos un condicional if para el caso en que el número sea mayor o bien sea menor que el número secreto. En cada caso informamos al usuario con un mensaje donde se le pide que de otro número. Fuera del bucle tenemos una última línea de código que imprime un mensaje donde se felicita al usuario por haber adivinado el número secreto n.

import random
n=random.randrange(1,100)
nu=int(input('Dime el número que crees que he elegido: '))
while nu!=n:
    if nu>n:
        nu=int(input('El número es mas pequeño'))
    elif nu<n:
        nu=int(input('El número es mas grande'))
print('Felicidades has adivinado que el número secreto es:',n)


Método 2

En este método hemos añadido un contador c para ir anotando las tiradas que se realizan y al final informar al usuario sobre el número de tiradas necesarias hasta que ha adivinado el número secreto.



import random
n=random.randrange(1,100)
nu=int(input('Dime el número que crees que he elegido '))
c=1
while nu!=n:
  c+=1
  if nu>n:
      nu=int(input('El número es mas pequeño'))
  elif nu<n:
      nu=int(input('El número es mas grande'))
print('Felicidades has adivinado que el número secreto es:',n)
print('Y lo has adivinado en',c,'intentos.')

Progresión geométrica en Python

Reto: Progresión geométrica

Calcular cuantos granos de trigo tendríamos que utilizar si por cada casilla de un tablero de ajedrez pusiéramos un grano en la primera casilla, dos en la segunda, cuatro en la tercera, y así doblando hasta la última.



Este es el caso de la leyenda de los granos de trigo y el tablero de ajedrez.

También puede interesarle ver La leyenda del Ajedrez

Método 1

La variable s se inicializa en cero, y contendrá la suma de todos los granos de trigo que se van anotando en cada casilla. Nos metemos en un bucle for que usa la variable i que va entre cero y 64, incluido el cero y excluido el 64. Dentro del bucle calculamos el número de granos de la casilla i-ésima elevando al cuadrado, y esto se va acumulando en la variable s que es la suma de todos ellos. Se imprime el cómputo por cada casilla y fuera del bucle imprimimos nuevamente el resultado final en notación científica. Observe que hemos separado en dos líneas impresas usando /n. La notación científica se puede implementar usando la e minúscula o la E mayúscula.

s=0
for i in range(8*8):
  s+=2**i
  print(i+1,2**i,s)
print("En notación científica es %e,\n y el total es: %E granos de trigo." % (2**i,s))


Método 2

En este caso usamos un bucle de tipo while. Al final hacemos una estimación de que en un kilo de trigo hay 25.000 granos y con ella calculamos redondeando cuantos millones de toneladas serían necesarios, comparándolo con la producción mundial.

i=0
s=0
while i<64:
  s+=2**i
  print(i+1,2**i,s)
  i+=1
print('Unos',int(round(s/25000000000000,0)),'millones de toneladas')
print('En 2018, la producción mundial fue de 750 millones de toneladas')

miércoles, 29 de agosto de 2018

Generar y ordenar palabras en Python

Reto: Ordenar palabras

Crear una serie de 10 palabras donde sus letras se obtienen de forma aleatoria. Mostrar estas palabras y mostrar esas mismas palabras ordenadas alfabéticamente.



Método 1

Creamos la lista frase que contendrá diez palabras compuestas cada una de ellas por cuatro letras aleatorias. La variable L contienen todo el abecedario en forma de lista. El primer bucle for contiene diez ciclos para generar las diez palabras. En el segundo bucle for es donde generamos cada palabra recogida como string en la variable p. Para ello, se elige aleatoriamente cada letra de la lista L.
Una vez generada la palabra p está se añade a la lista L con append.


import random
frase=[]
L=list('abcdefghijklmnopqrstuvwxyz')
for i in range(0,11):
  p=''
  for j in range(4):
    p+=L[random.randint(0,25)]
  frase.append(''.join(p))
print(frase)
print(sorted(frase))


Método 2

Con este método vamos a crear palabras donde se alternen parejas de consonante y vocal. La variable n contiene el número de parejas elegidas. Si n es tres obtendremos palabras con seis letras. La variable c es un string que contiene las consonantes y la variable v es otra cadena con las vocales. Inicializamos la variable L como lista vacía. Nos metemos en un primer bucle for de diez ciclos para generar las diez palabras. El segundo bucle for añade aleatoriamente una letra consonante y luego una letra vocal para que formen parejas, y se repite n veces.

import random
n=3 # nº de parejas de letras consonante-vocal
c='bcdfghjklmnpqrstvwxyz'
v='aeiou'
L=[]
for i in range(10):
  palabra=''
  for j in range(n):
    palabra+=''.join(random.choice(c))
    palabra+=''.join(random.choice(v))
  L.append(palabra)
print(L)
print(sorted(L))

viernes, 24 de agosto de 2018

Alternos con excepciones

Reto: Alternos con excepciones

Imprimir diez números aleatorios sin repetición entre 100 y 130, excepto los números 110, 115, 120 y alternando par, impar, comenzando por par.




Método 1

Importamos randint de la librería random. Creamos la lista L inicialmente vacía. Nos metemos en un bucle while con 10 ciclos. Por cada vuelta generamos un número aleatorio par entre 100 y 130. Si el número generado no es 110, ni 115, ni 120, y no está en la lista L, para evitar repeticiones, entonces nos metemos en otro condicional if.
En el segundo condicional se analiza la condición de que el número aleatorio sea par y que el lugar (n) que toca sea par, para garantizar que se trata de la ubicación donde ha de ir un número par, entonces se añade a la lista con append. y el contador n se incrementa en 1. La otra condición del elif analiza si el número aleatorio en impar y toca que la ubicación donde tenga que ir sea también impar, entonces se añade con append y el contador n se incrementa en 1.
Finalmente se imprime la lista y luego se vuelve a imprimir ordenada con sort.

from random import randint
n=0
L=[]
while n<10:
  t=randint(100,131)
  if t not in (110,115,120) and t not in L:
    if t%2==0 and n%2==0: #par y toca par
      L.append(t)
      n+=1
    elif t%2!=0 and n%2!=0: #impar y toca impar
      L.append(t)
      n+=1
print(L)
L.sort()
print(L)


Método 2

Generamos la lista Lp que contendrá ordenados todos los números pares posibles, que son los comprendidos entre 100 y 130 salvo el 110 y el 120.
Generamos la lista Li que contendrá ordenados todos los números impares posibles, que son los comprendidos entre 100 y 130 salvo el 115.
Imprimimos las listas Lp y Li.
Con random.shuffle barajamos cada lista. Creamos la lista L, inicialmente vacía. Nos metemos en un bucle for de 5 ciclos. Aunque nos piden 10 números en este reto el bucle for es de 5 ciclos ya que en cada uno de ellos se genera una pareja de números, el primero par y el segundo impar. Para generar el número par se toma el primer par de la lista de pares Lp, que ya se desordenó anteriormente, y para generar el número impar se hace lo mismo con la lista de impares Li.
El resultado será una lista de números L que contiene 5 parejas de números par, impar, que comienzan por par y se van alternando.

import random
Lp=[i for i in range(100,131,2) if i not in (110,120)] #genera todos los pares posibles
Li=[i for i in range(101,131,2) if i!=115]             #genera todos los impares posibles
print(Lp)
print(Li)
random.shuffle(Lp) #baraja los pares
random.shuffle(Li) #baraja los impares
L=[]
for k in range(5): # son 5 parejas de par, impar.
  L.append(Lp[k])  # toma el pare de indice k
  L.append(Li[k])  # toma el impar de indice k
print(L)

domingo, 19 de agosto de 2018

Aleatorios con excepciones

Reto: Aleatorios con excepciones

Generar números aleatorios pares entre 100 y 130, salvo 110 y 120.

Veamos varios casos, que pueden ser:

  • con repetición
  • sin repetición




Método 1

Importamos la librería random. Creamos la lista L inicialmente vacía. Nos metemos en un bucle for con 16 ciclos. Por cada vuelta generamos un número aleatorio par entre 100 y 130. Si el número generado no es 110, ni 120, entonces se añade a la lista con append.
Finalmente se imprime la lista y luego se vuelve a imprimir ordenada con sorted.

import random
L = []
for i in range(16):
    x = random.randrange(100,131,2)
    if x not in (110,120):
        L.append(x)
print(L)
print(sorted(L))


Método 2

Este método realiza un tratamiento similar al anterior pero usa List Comprehensions para comprimir el código en una sola línea.

import random
L=[r for r in [random.randint(100,130) for s in range(30)] if r%2==0 and r not in (110,120)]
print(L)
print(sorted(L))


Método 3

En este caso no importamos la librería random completa, únicamente importamos el método randint que genera números aleatorios entre 50 y 65. Con un if eliminamos aquellos valores que sean 55 o 60. El valor de la variable i que supere el filtro se multiplica por 2 para obtener los pares entre 100 y 130, excluidos del tratamiento los valores 110 y 120.

from random import randint
L = [i*2 for i in [randint(50,65) for j in range(16)] if i not in (55,60)]
print(L)
print(sorted(L))


Método 4

Este método es similar al método anterior si bien no es necesario multiplicar i por dos ya que los valores generados exigimos que sean pares incluyéndolo como una condición adicional en el if.

import random
L = [i for i in [random.randint(100,130) for j in range(30)] if i not in (110,120) and i%2==0]
print(L)
print(sorted(L, reverse=True))


Método 5

Usamos rando.sample que nos permite elegir una muestra aleatoria entre los valores generados. En este caso los valores obtenidos serán sin repetición gracias a que este método está diseñado para elegir sin repetición de una secuencia de números.

import random
L=[i for i in random.sample(range(100,131,2),16) if i not in (110,120)]
print(L)
L.sort(reverse=True)
print(L)


Método 6

Usamos random.shuffle sobre la lista generada previamente. Este método devuelve una nueva lista mezclada, lo que permite obtener un resultado sin repetición.

import random
L=[i for i in range(100,131,2) if i!=110 and i!=120]
random.shuffle(L) #desordena la lista
print(L)
print(sorted(L))

sábado, 18 de agosto de 2018

Donut de colores

 Utilizando la librería matplotlib.pyplot hemos conseguido generar unos puntos de diferentes colores y que no se impriman cuando están dentro de un rango, en este caso hemos creado una forma redonda como si fuera un Donut, aunque se puede cambiar para que haga cualquier forma.

El codigo Python:
from math import sqrt  
import random  
import matplotlib.pyplot as plt  
n = 10000  
p=q=0  
plt.figure(figsize=(7,7))  
for i in range(n):  
  p = random.random() * 8 - 4  
  q = random.random() * 8 - 4  
  r = sqrt(p ** 2 + q ** 2)  
  if 2<r<4:  
    x,y=p,q  
    plt.plot(x,y,'o',markersize=1)  
plt.show()  

El resultado de ese codigo:

En el código utilizamos coordenadas cartesianas para saber en qué lugar van a estar los puntos, generamos aleatoriamente las variables x e y que pondrá los puntos aleatoriamente por toda la pantalla, no sin antes usando un if para filtrar los puntos que son impresos en la pantalla, aquí es donde podemos elegir la forma de la figura que se termine de imprimir en pantalla.

En nuestro caso esto es la parte que crea esa forma de donut.

p = random.random() * 8 - 4   
q = random.random() * 8 - 4   
r = sqrt(p ** 2 + q ** 2)   
if 2<r<4:   
  x,y=p,q   
  plt.plot(x,y,'o',markersize=1)   

Primero generamos p y q aleatoriamente con random.random(), como esto solo genera números entre uno y cero la multiplicarlo por ocho y restarle cuatro le damos los márgenes que queremos para las coordenadas cartesianas. Luego aplicamos el teorema de Pitágoras para saber a qué distancia está ese punto desde el centro del plano.

Esta imagen puede que ayude a entender lo que estamos intentando hacer:


Y luego usando un if, si ese punto está dentro de las coordenadas dos y cuatro entonces les paso los valores de p,q y x,y para añadirlo al plot y luego imprimirlo.

Nota: Si ejecutas este código en algunos editores de código como PyCharm, al importar la librería matplotlib no solo tendrás que importarla escribiéndola en el código si no que tendrás que importarla desde el propio editor. Aquí os enseñamos cómo hacerlo: https://www.youtube.com/watch?v=aROm4KYHXLI&feature=youtu.be

sábado, 4 de agosto de 2018

Generar números aleatorios sin repetición y ordenarlos en Python

Reto: Ordenar números

Imprimir una lista de 10 números aleatorios sin repetición que varíen en el rango 80 a 99. Volver a imprimir la lista pero ordenada.




Método 1

Definimos la función unico que tiene dos argumentos. La función, dado el número x y la lista L, detecta si x es único o esta repetido. Si el número x no está en la lista entonces retorna True, y si el número se encuentra ya en la lista entonces devuelve False.
El bucle while nos proporciona los 10 números aleatorios sin repetición que ha de llegar a tener la lista. En este caso el bucle ha de ser del tipo while, no valdría un for, ya que no conocemos el número de ciclos que serán necesarios, puesto que si no existen repeticiones serán 10 ciclos pero si las hay el número aumenta. Por cada repetición encontrada se ha de generar un nuevo x aleatorio. Los x únicos generados se anexionan a la lista con append.
Finalmente se imprime la lista L y se ordena con sort.




import random
def unico(x,L):
  esUnico=True
  for i in range(len(L)):
    if x==L[i]:
      esUnico=False
      break
  return esUnico
L=[]
j=0
while j<10:
  x=random.randint(80,99)
  if unico(x,L):
    L.append(x)
    j+=1
print(L)
L.sort()
print(L)


Método 2

Inicializamos la lista L con su primer valor, el de la posición cero. Esto se hace fuera del bucle while ya que el primer x estamos seguros de que no se repite respecto a los anteriores, ya que es el primero. Luego nos metemos en un bucle while que genera los demás x aleatorios que de momento son candidatos, hasta que no se compruebe que no están repetidos entre los elementos que ya se encuentran en la lista. Para conseguir establecer si el número candidato se ha de anexionar a la lista o no se hace usando un bucle for que contiene un condicional if. La clave está en el else que no pertenece al if sino al for.
Finalmente imprimimos la lista L y la ordenamos con sorted.

import random
L=[random.randint(80, 99)] #este es L[0]
i=1
while i<10:
  x=random.randint(80,99)
  for j in range(0, len(L)):
    if L[j]==x:
      break
  else:
    L.append(x)
    i+=1
print(L)
print(sorted(L))


Método 3

Esta es una variante del método anterior que mejora el código ya que usa en el if la instrucción in, o mejor dicho, not in, para detectar si el nuevo número aleatorio se encuentra entre los que ya se han añadido a la lista L.


import random
L=[random.randint(80, 99)] #este es L[0]
i=1
while i<10:
  x=random.randint(80,99)
  if x not in L:
    L.append(x)
    i+=1
print(L)
print(sorted(L))


Método 4

Importamos únicamente el método sample de la librería random que permite crear una lista eligiendo aleatoriamente 10 valores de un rango de números creado con range que varía entre 80 y 100 (excluido el 100).

Con sorted ordenamos la lista . Si deseamos que la ordenación sea inversa tendremos que indicarlo poniendo print(sorted(L,reverse=True)).

from random import sample
L=sample(range(80,100),10)
print(L)
print(sorted(L))


Método 5

Este método, al igual que el anterior, utiliza sample para elegir una muestra aleatoria entre los posibles valores que generamos utilizando List Comprehension.
Faltaría ordenar la lista, pero hemos preferido dejar el código así para que se vea que en dos líneas se puede llegar a obtener la lista de aleatorios sin repetición.


from random import sample
print(sample([x for x in range(80,100)],10))


Método 6

Creamos la lista L usando list y range. Esta lista contendrá todos los números enteros consecutivos entre 80 y 99. La instrucción random.shuffle(L) baraja aleatoriamente la lista L. Creamos la lista L10 que contendrá los 10 primeros elementos de la lista L. Imprimimos la lista L10. Ordenamos la lista L10 en sentido inverso usando sort. Si la queremos ordenar en sentido creciente simplemente dejaremos vacío lo que va entre sus paréntesis. Sería L10.sort().


import random
L=list(range(80,100))
random.shuffle(L) #baraja la lista
L10=L[:10] #crea otra lista con los 10 primeros elementos
print(L10)
L10.sort(reverse=True) #ordena la lista L10
print(L10)

viernes, 3 de agosto de 2018

Años bisiestos en Python

Reto: Bisiesto

Crear una función que dado un año diga si es bisiesto.



Podemos consultar la Wikipedia para saber qué años son bisiestos.
El calendario Juliano dio paso a calendario Gregoriano en 1582. Desde entonces se estableció la regla que nos dice cuando una año es bisiesto y por lo tanto tiene 366 días, en lugar de 365, ya que se añade un día más el 29 de febrero.

  • Un año es bisiesto si es múltiplo de 4, salvo que...
    • el año termine en 00, en cuyo caso, no será bisiesto, salvo que ...
      • el año sea múltiplo de 400, en cuyo caso, si será bisiesto.
Como podemos observar para que un año sea bisiesto existe una regla general (que sea múltiplo de 4) pero a esta regla general existe una excepción (que el año termine en 00, esto es, los finales de siglo) en cuyo caso el año no será bisiesto, y finalmente existe una excepción a la excepción anterior (que el año sea múltiplo de 400) en cuyo caso el año si será bisiesto.

Así por ejemplo, los años 2100, 2200, 2300 no serán bisiestos, pero el 2400 si lo será.


Método 1

Definimos una función que contiene un if con una condición lógica compleja que resume la regla que nos da el año bisiesto.




def bisiesto(x):
  if x%4==0 and (not(x%100==0) or x%400==0 ):
    texto='es bisiesto.'
  else:
    texto='es un año NO bisiesto.'
  return texto
x=int(input('Introduzca un año entre 1600 y 2500:'))
print(x,bisiesto(x))


Método 2

Generamos un año aleatorio y definimos una función que nos retornará True si se trata de una año bisiesto y nos retornará False si el año generado no es bisiesto. Con este método hemos optado por realizar varios if concatenados para resolver la lógica de los años bisiestos.

import random
random.seed()
x=random.randint(1600,2500)
def bisiesto(x):
  if x%4==0:
    if x%100==0:
      if x%400==0:
        return True
      else:
        return False
    else:
      return True
  else:
    return False
if bisiesto(x):
  print(x,'es un año bisiesto.')
elif not(bisiesto(x)):
  print(x,'no es un año bisiesto')

Nombrar elementos en CSS

En CSS si quieres afectar a algún elemento del HTML tienes varias opciones.

La mas obvia es referirse a los elementos por etiquetas, simplemente escribiendo la etiqueta como se haría en HTML sin el mayor y menor. Como esto:

 p {  
   background-color: red;  
 }  
Y el resultado seria algo a esto:

Pero si quisiéramos darle un color diferente a cada p le tendríamos que dar un nombre diferente a cada p, para ello en HTML habría que hacer algo así: 

 <p id='uno'>Y en este los dos</p>  
 <p id='dos'>estamos de colores distintos</p>  

Y para llamarlos en el CSS hay que poner un # delante del nombre y escribir los parámetros como haríamos normalmente, similar a esto:

 #uno {  
   background-color: red;  
 }  
 #dos {  
   background-color: blue;  
 }  

Y con esas dos cosas implementadas en tu código el resultado debería de ser este:
También se puede utilizar * para afectar a todos los elementos (esto también incluye el fondo).
Este seria un ejemplo:


 * {  
  margin:1;  
  padding:2;  
 }  

Series en Python

Reto: Series

Listar los números entre un valor inicial y uno final, con un cierto intervalo. Al final dar la suma de todos los valores listados.




Método 1

Establecemos tres valores concretos para las variables inicial, final e intervalo. Con el objeto de llegar a calcular la suma total creamos la variable total que inicializamos a cero. Nos metemos en un bucle for para recorrer con range todos los valores del rango usando el intervalo establecido. El objeto range nos permite recorrer un rango comenzando por el inicio, pero no llegando nunca al final exactamente. Observe que en la imagen no aparece listado el final que es 20.

La variable total actúa como acumulador sumando en cada vuelta del bucle el valor que tome la variable i en ese momento. Finalmente, y fuera del bucle imprimimos el valor de la variable total.



inicial=10
final=20
intervalo=2
total=0 #inicializamos la suma a cero
for i in range(inicial,final,intervalo):
  total+=i #la variable total actúa de acumulador
  print(i)
print('La suma es:',total)


Método 2

Generamos valores aleatorios para las variable inicial, final e intervalo. Imprimimos por pantalla los valores obtenidos. Creamos la variable i que luego usaremos en el bucle while y la inicializamos con el valor inicial. Creamos la lista L y la inicializamos como una lista vacía. La variable total inicialmente valdrá cero. Nos metemos en un bucle while que durará mientras la variable i sea menor que el valor final. Con append vamos añadiendo a la lista L los valores del intervalo dados por la variable i. Dentro del bucle while incrementamos el valor de la variable i con el importe del intervalo. Acumulamos los valores obtenidos en la variable total. Fuera del bucle imprimimos la lista L y mostramos el importe de la suma.



import random
random.seed() #barajamos la serie de números aleatorios
inicial=random.randint(100,130)
final=inicial+random.randint(10,20)
intervalo=random.randint(2,5)
print('inicial=',inicial)
print('final=',final)
print('intervalo=',intervalo)
i=inicial
L=[] #inicializamos L como una lista vacía
total=0 #inicializamos la suma a cero
while i<final:
  L.append(i) #añadimos el valor i a la lista L
  i+=intervalo #aumentamos el valor del contador
  total+=i
print(L) #imprimimos la lista
print('La suma es:',total)

Operaciones con números en Python

Reto: Operaciones con números

Dados dos números hacer con ellos las operaciones básicas.




Consulte la entrada titulada:



Método 1

Inicialmente hacemos que la variable x valga 15 y la variable y tome un valor de 3. Calculamos e imprimimos la suma, resta, multiplicación y división. Luego damos nuevos valores a x e y, en una sola línea de código. Calculamos la potencia x elevado a y. Damos a x el valor 11 y calculamos la división entera y el módulo.

x=15
y=3
print(x,'+',y,'=',x+y)
print(x,'-',y,'=',x-y)
print(x,'*',y,'=',x*y)
print(x,'/',y,'=',x/y)
x,y=2,3
print(x,'elevado a',y,'=',x**y)
x=11
print(x,'división entera entre',y,'=',x//y)
print(x,'módulo',y,'=',x%y)
#operadores lógicos
print(x,'es mayor que',y,x>y)
print(x,'es menor que',y,x<y)
print(y,'<',x,'<20',y<x<20)


Método 2

Generamos aleatoriamente los valores x e y. Calculamos al suma, resta, multiplicación y potencia. Para la división creamos una función con un control de excepciones para evitar la división por cero. Con try hacemos la división normal pero si detectamos que se puede llegar a producir un erro de ZeroDivisionError lo que hacemos con except es evitar ese error y en su lugar la función retorna un texto que informa del motivo de no haber realizado la división. Con ello evitamos que el programa lance un error que detenga la ejecución y confunda al usuario. También creamos una función para la división entera y otra para el cálculo del módulo con el control de excepciones correspondiente.


import random
x=random.randrange(1,10,2) #genera impares entre 1 y 9
y=random.randrange(3) #genera 0,1,2
print(x,'+',y,'=',x+y)
print(x,'-',y,'=',x-y)
print(x,'*',y,'=',x*y)
print(x,'elevado a',y,'=',x**y)
def div(x,y):
    try: return x/y
    except ZeroDivisionError: return 'error: denominador cero'
print(x,'/',y,'=',div(x,y))
def divent(x,y):
    try: return x//y
    except ZeroDivisionError: return 'error: denominador cero'
print(x,'división entera entre',y,'=',divent(x,y))
def modulo(x,y):
    try: return x%y
    except ZeroDivisionError: return 'error: denominador cero'
print(x,'módulo',y,'=',modulo(x,y))


Longitud de una cadena en Python

Reto: Longitud de una cadena

Crear una función que calcule la longitud de una cadena alfanumérica. Crear otra función que dada una cadena devuelva el primer caracter en mayúsculas y el resto en minúsculas. Pasar una palabra por ambas funciones y dar el resultado.




Método 1

Para calcular la longitud de una cadena lo mejor es usar len que se verá en el método 2, pero hemos querido usar aquí una forma alternativa de conseguirlo. De la misma manera para convertir una cadena en un nombre propio, existe capitalize que usaremos en el método 2, pero hemos querido ver cómo se puede conseguir sin usar esta función propia de Python. Primero usamos lower para pasar todo a minúsculas, y luego usamos upper aplicado al primer carácter para que esté mayúsculas.

def longitudCadena(x):
  contador=0
  for i in x:
    contador+=1
  return contador
def nombrePropio(x):
  y=x.lower()
  return y[0].upper()+y[1:]
x=input('Indique una palabra') or 'mADRId'
print(nombrePropio(x),'tiene',longitudCadena(x),'caracteres.')


Método 2

Usamos len para obtener la longitud del stringcapitalize para convertirlo en nombre propio. usaremos.

def longitudCadena(x):
  return len(x)
def nombrePropio(x):
  return x.capitalize()
x=input('Indique una palabra') or 'maDRid'
print(nombrePropio(x),'tiene',longitudCadena(x),'caracteres.') 

Capitalización compuesta en Python

Reto: Capitalización compuesta

Crear una aplicación que trabaje con la ley de capitalización compuesta.




Método 1

Preguntamos al usuario por el capital inicial, los años y el tipo de interés anual. Imprimimos el montante final alcanzado redondeado a dos decimales.

C=float(input('Introduzca el capital inicial') or 1000)
print('Capital inicial=',C)
n=float(input('Introduzca los años') or 3)
print('años=',n)
i=float(input('Introduzca el tipo de interés, por ejemplo 0.08 para 8%') or .08)
print('Tipo de interés anual=',i)
print('Capital final=',round(C*(1+i)**n,2))


Método 2

Generamos de forma aleatoria el capital inicial, el tiempo y el tanto de interés. Imprimimos el montante final que calcula una función.

import random
def montante(C,n,i):
  return C*(1+i)**n
C=random.randint(1000,9999)
print('Capital inicial=',C)
n=random.randint(1,10)
print('años=',n)
i=random.randint(2,20)/100
print('Tipo de interés anual=',i)
print('Capital final=',round(montante(C,n,i),2))

lunes, 16 de julio de 2018

Selección de elementos de un vector en R

Ya hemos visto que podemos usar los corchetes [] para obtener uno o varios elementos de un vector. Ahora vamos a conseguir selecciones más interesantes e incluso introduciremos filtros.



Operadores lógicos


<  menor que
>  mayor que
<= menor o igual que
>= mayor o igual que
== igual (comparación)
!= distinto (no igual)


a <- 5
a>4                   # TRUE  
a <- c(1,2,3,4,5)
a<=2                  # TRUE  TRUE FALSE FALSE FALSE
#Creamos el vector b
b <- a>=3
b                     # FALSE FALSE  TRUE  TRUE  TRUE
a*b                   # 0 0 3 4 5
a==b                  # FALSE FALSE FALSE FALSE FALSE
a!=b                  # TRUE TRUE TRUE TRUE TRUE



Selección de elementos de un vector

Observe que en el código siguiente la expresión beneficio[gano] nos permite seleccionar parte de un vector gracias a que en los corchetes [] hemos añadido un filtro o selección. Este filtro no es como hemos visto anteriormente indicando que elementos concretos queremos sino que se realiza introduciendo un vector denominado gano donde todos sus elementos son condiciones lógicas TRUE o FALSE. Esto actúa de filtro y nos devuelve únicamente lo elementos que cumplen ser verdaderos TRUE.


#Asignamos los días de la semana a un vector
dias <- c('Lun','Mar','Mie','Jue','Vie')
#Creamos un vector de perdidas y ganancias
beneficio <- c(-19,-86,125,-343,71)
#Nombramos el vector
names(beneficio) <- dias
beneficio #Imprimimos el vector ya nombrado
gano <- beneficio>0             #Creamos el vector gano con cinco booleanos
print('Vector gano:')
gano
#Creamos un vector solo con los resultados positivos
ganancias <- beneficio[gano] 
print('Estas son las ganancias: ')
ganancias



Operar con valores lógicos

Podemos asignar booleanos a variables o a vectores. Veamos algunas operaciones que se pueden realizar con valores lógicos.


#Asignamos un valor booleano a una variable
a <- TRUE
b <- FALSE
a            #Imprimimos a
b            #Imprimimos b
a*b  # 1*0=0
a*!b # 1*1=1
#Creamos los vectores v y w
v <- c(1,3,5,7,9)
w <- c(100,200,300,400,500)
#Imprimimos v, w y su suma
v
w
v+w
a & b         # AND
a | a         # OR