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


domingo, 15 de julio de 2018

Trabajar con vectores en R

El lenguaje de programación R está orientado al cálculo científico y en especial a la estadística por lo que el manejo de vectores se encuentra muy desarrollado.

Creación de vectores

Podemos crear vectores con datos numéricos, string o booleanos pero sin mezclar tipos. Si mezclamos se convierten todos a string.

# Asignamos valores al vector v
v <- c(1,-3,5,7,9.5)
w <- c(100,200,300,400,500)
# Imprimimos v, w
v
w
# Los vectores pueden contener strings
character_vector <- c("a", "b", "c")
character_vector
# Los vectores pueden contener valores lógicos
boolean_vector <- c(TRUE, FALSE, TRUE)
boolean_vector


Nombrar vectores

En algunos casos puede ser necesario dar un nombre a los valores de un vector.


#Vector de pérdidas y ganancias diarias de una semana
pg <- c(170, -20, 50, -160, 290)
#Imprimimos el vector pg aún sin ser nombrado
pg
#Asignamos días como nombres del vector pg
names(pg) <- c("Lun", "Mar", "Mie", "Jue", "Vie")
# Imprimimos el vector después de ser nombrado
pg
#Podemos asignar los días de la semana a un vector
dias <- c('Lun','Mar','Mie','Jue','Vie')
dias
#Creamos otro vector de perdidas y ganancias
beneficio <- c(-19,-86,125,-343,71)
#Nombramos el vector
names(beneficio) <- dias
beneficio #Imprimimos el vector ya nombrado

Sumar vectores

La suma de vectores da como resultado otro vector que es suma de los elementos de ambos vectores. Por el contrario si utilizamos la función sum() sobre un vector el resultado será la suma de todos los elementos de ese vector.

a <- c(1, 3, 4) 
b <- c(2, 2, 3)
c <- a + b       #El vector c es suma de los vectores a y b
a                #Imprimimos a
b                #Imprimimos b
c                #Imprimimos c
#Elevamos los elementos de a usando como potencias los de b
#El resultado no se asigna a ninguna variable simplemente se imprime
a^b
#Suma de todos los elementos de un vector
sum(c)
#Comprobamos que la suma de todos los elementos de c es igual a los de a y b juntos
sum(c)==sum(a+b)


Elementos de un vector

Podemos trabajar con elementos individuales o conjuntos de elementos de un vector usando los corchetes [].


beneficio <- c(-19,-86,125,-343,71)
print('Imprimimos el vector sin nombrar')
beneficio
print('Imprimimos el segundo elemento del vector')
beneficio[2]
dias <- c('Lun','Mar','Mie','Jue','Vie')
#Nombramos el vector
names(beneficio) <- dias
print('Ahora al imprimir el 2º elemento del vector se verá el nombre')
beneficio[2]
print('Imprimimos el valor del viernes')
beneficio['Vie']
print('Imprimimos el valor del miércoles y del viernes')
beneficio[c('Mie','Vie')]
print('Veamos los tres elementos centrales')
beneficio[c(2, 3, 4)]
print('Días centrales entre 2 y 4')
centrales <- beneficio[2:4]
centrales
#cat imprime dos elementos separados por coma
#mean calcula la media de los elementos de un vector
cat('La media de los días centrales es',mean(centrales))


sábado, 14 de julio de 2018

Introducción a R

El lenguaje de programación R especializado en estadística y cálculo científico se está expandiendo estos años como alternativa gratuita a otros como SPSS o MatLab. Aunque como alternativa a MatLab tenemos Octave del que puede verse la entrada titulada Comandos básicos en Octave.

Podemos instalar R en nuestro PC o ejecutarlo desde alguna página web donde esté disponible de forma online. Por ejemplo http://rextester.com/l/r_online_compiler

Parte del material introductorio sobre R se ha obtenido adaptando los ejemplos contenidos en el siguiente repositorio de  un curso de DataCamp.



Operaciones básicas

Veamos algunas operaciones básicas en R.

#suma (+)
2+3
#resta (-)
8-5
#producto (*)
5*8
#división (/)
19/17
#potenciación(^)
2^3
#módulo (%%)
5%%2

La salida es la siguiente.

Asignación de variables

Veamos como se asignan variables numéricas, booleanos y strings.

# Asignación de valores a x e y
x <- 1
y <- 12/(4+2)+3
# Imprimimos el valor de las variables
x
y
# Asignación de booleanos
a <- TRUE
b <- FALSE
# Imprimimos las variables a y b
a
b
# Asignación de cadenas alfanuméricas
p <- 'Madrid'
q <- "Ciudad de México"
# Imprimimos los dos variables string
p
q

La salida es la siguiente.

Clase de valor: class

Para determinar el tipo de valor de una variable se usa class().

# Declare variables of different types:
mi_numero <- 15
mi_cadena <- "Madrid"
mi_logico <- TRUE

# Vemos de que clase son las variables
class(mi_numero)
class(mi_cadena)
class(mi_logico)

La salida es la siguiente.


viernes, 13 de julio de 2018

Media ponderada

Reto: Media ponderada

Calcular la media ponderada de una serie de valores.




Vamos a calcular la media aritmética y la media ponderada de una serie de exámenes. Conocemos la nota de las prueba y su peso. Los pesos vienen dados en tanto por uno y han de sumar uno, que equivale al 100%. Hemos puesto unos datos para que diferencien bien ambas medias. La media aritmética saldrá 6,5 y la ponderara será de 8,37, ya que los pesos mayores recaen en los exámenes donde se ha obtenido mejor calificación.

Método 1

Disponemos de las notas (lista x) y de los pesos (lista w). La condición sum(w)==1 ha de arrojar el valor True, lo que permite comprobar que los pesos suman uno. Inicializamos la variable arit que calculará la media aritmética. Nos metemos en un blucle for que recorrerá todas las calificaciones de la lista x. En cada iteración ira acumulando las notas en la variable arit. Al finalizar el bucle dividimos el contenido de la variable arit entre el número de elementos de la lista x, de esta forma ya tendremos calculada la media aritmética y pasamos a imprimirla.
Inicializamos la variable pondera con el valor cero. Esta variable calculará la media ponderada. Nos metemos en un bucle for que recorrerá los números desde el cero hasta cinco, ya que la longitud de x es seis. En cada ciclo del bucle la variable pondera irá acumulando cada una de las calificaciones multiplicada por su peso en tanto por uno. Al finalizar el bucle la variable pondera ya contendrá la media aritmética ponderada que pasaremos a imprimir con un cierto redondeo.

#Notas de los exámenes
x=[7,4,9,3,6,10]
#Pesos de cada examen. Suman 1=100%
w=[.1,.05,.25,.06,.09,.45]
print('¿Los pesos suman 1?:',sum(w)==1.)
arit=0
for i in x:
  arit+=i
arit/=len(x)
print('Media aritmética:',arit)
pondera=0
for i in range(len(x)):
  pondera+=x[i]*w[i]
print('Media ponderada:',round(pondera,6))


Método 2

En este método utilizamos una notación condensada para los bucles for. Para la media aritmética el bucle for utiliza una única variable instrumental i, pero en el caso de la media ponderada son necesarias dos variable auxiliares i, j. También hemos tenido que emplear zip para unir las listas sobre las que operamos x y w.

x=[7,4,9,3,6,10] #Notas
w=[.1,.05,.25,.06,.09,.45] #Pesos
arit=round(sum(i for i in x)/len(x),6)
print('Media aritmética:',arit)
pondera=round(sum(i*j for i,j in zip(x,w)),6)
print('Media ponderada:',pondera)


Método 3

Importamos la librería científica NumPy que nos permite trabajar con vectores (arrays). Para calcular la media aritmética utilizamos mean que es una función disponible en la librería NumPy y que precisamente calcula la media aritmética de los valores que contiene la lista x.
Convertimos las listas x y w en los array xa y wa. La nota media ponderada se obtiene sin más que multiplicar ambos vectores y sumar su resultado.

import numpy as np
x=[7,4,9,3,6,10] #Notas
w=[.1,.05,.25,.06,.09,.45] #Pesos
arit=np.mean(x)
print('Media aritmética:',arit)
xa=np.array(x)
wa=np.array(w)
pondera=round(sum(xa*wa),6)
print('Media ponderada:',pondera)

martes, 10 de julio de 2018

Convertir monedas y billetes en Python

Reto: Conversión de monedas y billetes

Dada una cantidad de dinero indicar cuantos billetes y monedas de cada tipo son necesarios como mínmo.



Dado un cierto importe en euros deseamos conocer el mínimo número de monedas y billetes necesarios para alcanzar esa cifra. Disponemos de una lista con los tipos de billetes y monedas existentes, desde el billete de 500 € hasta la moneda de un céntimo (0,01 €). Son quince tipos de elementos entre billetes y monedas los que tenemos en la zona euro.

El procedimiento utilizado se basa en calcular un cociente entre la cifra inicial disponible en euros  y 500 que es el billete más grande. La parte entera nos dará el número de billetes de 500 € necesarios, y el resto se usará como denominador en la siguiente división. La segunda división se realiza dividiendo entre 200 que es el siguiente billete. La parte entera nos dará el número de billetes de 200 € necesarios y el resto se convertirá en el numerador de la siguiente división. Este proceso se sigue reiteradamente hasta llegar a la moneda más pequeña que es la de un céntimo.



Método 1

Definimos la lista T que contiene los quince tipos de billetes y monedas existentes en la zona euro. Inicializamos la lista S con quince ceros. Esta lista contendrá la salida obtenida indicando en cada uno de sus elementos el número de billetes y monedas necesarios de cada tipo para llegar a cubrir la cifra dada en euros y conseguir que sean mínimas las monedas y billetes utilizados. La lista S es la solución al caso práctico planteado.
Generamos aleatoriamente x que es la cifra en euros que vamos a descomponer. Utilizamos random.randint que únicamente nos permite generar números aleatorios enteros entre un par de ellos dados como argumentos. Si bien nosotros precisamos que la cifra en euros tenga dos decimales. Para ello, usamos un pequeño truco que consiste en dividir entre 100 el valor obtenido. De esta forma, lo que obtendremos para x son valores entre 1.000,00 € y 3.000,00 €.
En el algoritmo el primer paso usa x como numerador del cociente que iremos realizando reiteradamente, pero luego el numerador será el resto obtenido en el paso previo. Esto hace que tengamos que definir el primer resto como resto=x.

Nos metemos en un bucle for que recorre quince valores entre 0 y 14. Dentro del bucle usamos la función divmod que utiliza como argumentos el numerador y el denominador, y que devuelve dos valores que son la parte entera y el resto. Se podría haber obtenido el mismo resultado usando la división entera en Python (//) y el cálculo del módulo(%). Imprimimos S[i] que contiene el número de monedas y billetes necesarios del tipo T[i]. Al recorrer el bucle los quince elementos de estas listas lo que obtendremos por pantalla es un listado con todos los billetes y monedas necesarios de cada tipo para alcanzar la cifra inicial de x euros.



Finalmente lo que hacemos es comprobar que todos esos billetes y monedas multiplicados por el valor en euros de cada uno de los tipos resulte igual a la cifra x inicial. El último elemento a imprimir (total==x) es una condición que nos indicará con True si coinciden el total obtenido multiplicando y sumando los diferentes valores con el importe x inicial.

import random
T=[500,200,100,50,20,10,5,2,1,.5,.2,.1,.05,.02,.01]
S=[0]*15 #salida por tipo de billete y moneda
x=random.randint(100000,300000)/100
resto=x
print('Disponemos de',x,'euros.')
print('Se pueden descomponer en:')
for i in range(len(T)):
  S[i], resto = divmod(round(resto,6), T[i])
  print(int(round(S[i],4)),'de',T[i],'€')
print('Comprobación')
total=0
for i in range(len(T)):
  total+=S[i]*T[i]
total=round(total,6)
print(total,total==x)


Método 2

En este caso disponemos de la lista C de quince posiciones que contendrán el número de billetes y monedas disponibles inicialmente de cada tipo, que se generan de forma aleatoria. Esta composición de billetes y monedas, a priori no será óptima y lo que pretendemos es encontrar la composición dada por la lista de salida S que nos proporcione el número mínimo de monedas y billetes necesarios.

Dada la lista C vamos a calcular que importe total en euros supone este dinero. Para ello vamos a emplear dos procedimientos que luego podremos ver que coinciden.

  • El primer procedimiento requiere definir la variable suma que inicializamos con el valor cero. Nos metemos en un bucle for que recorrerá los quince elementos de la lista. Vamos calculando cada elemento C[i] de forma aleatoria y vamos obteniendo la suma acumulada multiplicando cada elemento i-ésimo de las listas T y C. De esta forma hemos obtenido el dinero inicialmente disponible que queda recogido en la variable suma.
  • El segundo procedimiento es mucho más sintético y no necesita definir la variable suma y no necesita hacer uso del bucle for anterior. Directamente podemos calcular x de forma condensada en una sola línea con la expresión sum([a * b for a, b in zip(T,C)]) que equivale a la función sumaproducto de Excel.
Una vez conocido el importe de los x euros lo primero que hacemos es usar un bucle for para mostrar en pantalla su composición según las diferentes monedas y billetes disponibles inicialmente, imprimiendo C[i] y T[i].



Luego imprimimos por pantalla la frase que indica nuestra intención es cambiar esas monedas y billetes por otra composición que sea mínima. Siguiendo la imagen, se puede ver la frase que dice 'Los 2692.38 € se pueden descomponer en:'. En esta frase el importe que se cita coincide con el que se muestra inicialmente, e ilustran los dos procedimientos vistos anteriormente. La primera cifra es x y la segunda es la variable suma.

El resto del algoritmo es igual que el del método anterior, salvo que al final no hacemos la comprobación que se hizo en el método 1, y que en este caso lo que hacemos es ver de cuántos billetes y monedas iniciales hemos partido y a cuantos hemos llegado. En general, se podrá apreciar una significativa reducción.


import random
T=[500,200,100,50,20,10,5,2,1,.5,.2,.1,.05,.02,.01]
C=[0]*15 #caja disponible
S=[0]*15 #salida por tipo de billete y moneda
suma=0
for i in range(15):
  C[i]=random.randint(0,5)
  suma+=T[i]*C[i]
x=sum([a * b for a, b in zip(T,C)]) #sumaproducto
print('Disponemos de',round(x,6),'euros.')
print('Están compuestos por:')
for i in range(len(T)):
  print(C[i],'de',T[i],'€')
print('Queremos cambiarlos por los mínimos billetes y monedas posibles.')
print('Los',round(suma,6),'€ se pueden descomponer en:')
resto=x
for i in range(len(T)):
  S[i], resto = divmod(round(resto,6), T[i])
  print(int(round(S[i],4)),'de',T[i],'€')
print('Teníamos',sum(C),'billestes y monedas','y los hemos reducido a',int(sum(S)))

lunes, 9 de julio de 2018

Convertir segundos en Python

Reto: Convertir segundos

Dados un cierto número se segundos expresarlos como días, horas, minutos y segundos.




Solicitamos al usuario o bien obtenemos de forma aleatoria un número de segundos totales hasta un valor máximo de dos millones. El objetivo consiste en convertirlos a un formato que nos diga cuantos días, horas, minutos y segundos contienen. Por ejemplo, 2.000.000 segundos equivalen a 23 días, 3 horas, 33 minutos y 20 segundos. Podemos ver seguidamente los cálculos en Excel.



Hemos utilizado la función int que calcula la división entera y la función mod que calcula el módulo, resto o resíduo de la división.

Método 1

En Python los cálculos son los mismos. Para hacer la división entera se usa la expresión numerador//denominador y para hacer el módulo se usa la expresión numerador%denominador, lo cual nos da el resto. También tenemso que saber que un día tiene 86.400 segundos, una hora tiene 3.600 segundos y un minuto tiene 60 segundos. Hemos tenido que usar dos variables auxiliares denominadas resto1 y resto2. Hubiera surgido también la variable resto3 pero esta no ha sido necesaria ya que finalmente este concepto coincide con el número de segundos s que quedan al final.

print('Un minuto tiene',60,'segundos')
print('Una hora tiene',60*60,'segundos')
print('Un día tiene',60*60*24,'segundos')
print('_'*28+'\n')
while True:
  x =int(input('Número de segundos: ') or 2000000)
  if x>2000000:
    print("Introduzca un valor hasta dos millones.")
  else:
    break
d=x//86400
resto1=x%86400
h=resto1//3600
resto2=resto1%3600
m=resto2//60
s=resto2%60
print( '%d días, %d horas, %d minutos, %d segundos' % \
  (d, h, m, s)))


Método 2

Con este método los segundos iniciales se obtienen de forma aleatoria hasta un máximo de dos millones. Para ir calculando la división entera y el resto hemos usaso una función que viene definida internamente en Python que se llama divmod. Esta función utiliza como argumentos el numerador y el denominador y devuelve dos valores numéricos, el primero es la división exacta y el segundo el resto. Hemos necesitado al igual que en el caso anterior dos variables auxiliares para recoger el retos1 (r1) y el resto2 (r2).

import random
x=random.randint(1,2000000)
print(x,'segundos =')
d, r1 = divmod(x, 86400)
h, r2 = divmod(r1, 3600)
m, s = divmod(r2, 60)
print(d,'días',h,'horas',m,'minutos',s,'segundos')


Frecuencias en Python

Reto: Frecuencias

Construir una lista que contenga el código de 6 aeropuertos internacionales: MAD, JFK, LHR, CDG, AMS, FRA. Generar un dado de seis caras, con las siguientes probabilidades 25%, 22%, 18%, 14%, 11%, 10%, que corresponden a cada uno de los aeropuertos respectivamente. Generar un listado de 100 aeropuertos extraídos entre los seis del array y que aparezcan de forma aleatoria cada uno según su probabilidad. Finalmente mostramos los aeropuertos y el número de veces que aparece cada uno de ellos.




Los elementos de la lista (aeropuertos) no son equiprobables. Tenemos que conseguir que salgan de forma aleatoria pero cada uno con el peso que se le ha asignado. Generamos un listado con cien aeropuertos y luego calculamos la frecuencia con la que aparece cada uno de ellos. Esas frecuencias no necesariamente han de coincidir exactamente con los pesos asignados ya que estamos trabajando en el campo de la incertidumbre.

Método 1

Importamos la libreria random para trabajar con números aleatorios. Importamos la libreria numpy para poder luego usar cumsum que nos dará las probabilidades acumuladas. Inicializamos la lista F con seis ceros. Esta lista contendrá al final las frecuencias con las que aparece cada aeropuerto. Imprimimos la lista L de aeropuertos disponibles y la lista P con las probabilidades o pesos de cada uno de ellos. Con cumsum construimos la lista A que contendrá el acumulado de las probabilidades individuales de cada aeropuerto. Imprimimos la lista de pesos acumulados A.
Definimos la función intervalo que recibe como argumentos r (un número random entre cero y uno) y A que es la lista de pesos acumulados.
Nos metemos en un bucle for para generar los cien aeropuertos. Dentro del bucle generamos un número aleatorio r  y llamamos a la función intervalo que nos devolverá un número aleatorio entre 0 y 5, pero este número ya no será equiprobable sino que estará cargado con los pesos definidos para cada aeropuerto. Ese número se llamará z y se usará como índice para obtener el aeropuerto usándolo con la lista L, así L[z]. Construiremos la lista de frecuencias con la expresión F[z]+=1 que acumulará un 1 cada vez que aparezca el aeropuerto de índice z.
Imprimimos un separador para las FRECUENCIAS. Nos metemos en un bucle for que recorre los valores 0 a 5 que es el índice que usaremos para imprimir las listas F (frecuencias), L (abreviatura del aeropuerto), C (ciudad del aeropuerto).




import random
import numpy as np
random.seed()
L=['MAD','JFK','LHR','CDG','AMS','FRA']
P=[.25,.22,.18,.14,.11,.10]
C=['Madrid','New York','London','Paris','Amsterdam','Frankfurt']
F=[0]*6 #frecuencia de cada aeropuerto
print(L)
print('probabilidad:',P)
A=np.cumsum(P) #acumulado
print('acumulada: ',A)
def intervalo(r,A):
  for i in range(len(A)):
    if r<=A[i]:
      return(i)
for j in range(100):
  r=random.random()
  z=intervalo(r,A)
  F[z]+=1
  print(L[z])
print('--- F R E C U E N C I A S ---')
for k in range(6):
  print(F[k],L[k],C[k])

También podríamos haber calculado la lista A con las probabilidades acumuladas usando las siguientes línea de código en sustitución de la expresión A=np.cumsum(P). Esto nos permitiría ahorrarnos importar la librería numpy.

A=[P[0]]*6 #probabilidad acumulada
for i in range(1,len(P)):
  A[i]=round(A[i-1]+P[i],4)


Método 2

Este método usa menos líneas de código que el anterior. Importamos de la librería random el elemento choices. Inicializamos las listas L, P y F. Esta última la inicializamos con seis valores todos ellos iguales a cero, y finalmente contendrá las frecuencias de aparción de cada aeropuerto. Nos metemos en un bucle for de cien elementos para generar todos los aeropuertos de forma aleatoria no uniforme. Con range(6) generamos una lista con los números 0 a 5. Con choices(range(6),P) lo que hacemos es elegir de forma aleatoria uno de esos seis valores numéricos de la primera lista según la probabilidad P dada por la segunda lista. Esas probabilidades actúan como los pesos o importancia relativa que tiene cada uno de los elementos a la hora de ser elegidos. La variable que obtenemos es x que contiene el elemento elegido en forma de lista. Por ejemplo, x puede resultar ser [5] que significaría que ha sido elegido el último elemento de la lista que va entre 0 y 5. Como necesitamos que ese valor no venga dado en forma de lista, sino que lo necesitamos en formato de número entero, lo consguimos con la variable y definida como y=x[0] que lo que hace es obtener el primer y único elemento de la lista x.
Imprimimos el aeropuerto usando L[y] y en el print añadimos end=' '. Eso lo que hace es evitar que se impriman los aeropuertos en vertical y deja un espacio en blanco entre ellos.
Contruimos la lista F con las frecuencias con las que se presentan cada uno de los aeropuertos. Finalmente imprimimos la lista de aeropuertos y las frecuencias asociadas. Esto se consigue usando zip que fusiona las dos listas en una sucesión de tuplas. Si intentamos imprimir el objeto zip no veríamos el resultado esperado ya que es necesario encapsularlo con alguno de estos elementos.

  • list --> lista, se ven los corchetes []. Es el sistema que hemos utilizado
  • tuple --> tupla, se vería contenido entre paréntesis ()
  • dict --> diccionario, se vería contenido entre llaves {}





from random import choices
L=['MAD','JFK','LHR','CDG','AMS','FRA']
P=[.25,.22,.18,.14,.11,.10]
F=[0]*6 #frecuencia de cada aeropuerto
print(L)
print('probabilidad:',P)
for i in range(100):
  x=choices(range(6),P)
  y=x[0]
  print(L[y], end=' ')
  F[y]+=1
print('\n','-'*25,' F R E C U E N C I A S ','-'*26)
print(list(zip(L,F)))


Método 3

Importamos el elemento choice de numpy.random. Observe que no se trata del mismo elemento que en el caso anterior. Este va en singular choice y el anterior estaba en plural choices. Incluso pertenecen a librerías diferentes. En este método y gracias al uso de choice nos ahorramos tener que construir la lista con las probabilidades acumuladas ya que ahora lo único que tenemos que hacer es proporcionar a esta función la lista L (relación de aeropuertos) y la lista P (probabilidadades individuales). La función choice nos devuelve uno de los seis aeropuertos elegido de forma aleatoria según los pesos proporcionados por la lista P de probabilidades. Con el aeropuerto z elegido vamos contruyendo una lista a con append. Como estamos dentro del bucle for la lista a finalmente contendrá cien aeropuertos que imprimiremos.
Para hacer el análisis de frecuencias usamos collections.Counter(a) que nos dará un diccionario que contiene como clave cada uno de los aeropuertos y como valor su frecuencia de aprición. Este diccionario viene ordenado de mayor a menor frecuencia de acaecimiento, por lo que no siempre veremos primero el aeropuerto de Madrid que es el más probable.




from numpy.random import choice
import collections
L=['MAD','JFK','LHR','CDG','AMS','FRA']
P=[.25,.22,.18,.14,.11,.10]
a=[] #lista que contendrá los 100 aeropuertos
for i in range(100):
  z=choice(L, p=P) #elige de una lista según pesos
  a.append(z)
print(a)
print(collections.Counter(a)) #dict con las frecuencias

sábado, 7 de julio de 2018

La píldora de Matrix en Python

¿Qué píldora tomó Neo? ... Con este pequeño juego programado en Python podrás elegir la píldora roja o la píldora azul.

En el siguiente enlace puedes ver el código en acción.

Observa que para retrasar la aparición de algunas frases hemos usado la librería time para pausar un poquito con time.sleep.

import time

def inicio():
  print('Seguiste al conejo blanco como te dijeron.')
  print('Te llevaron a una habitación donde te encontraste con Morfeo')
  print('Después de que te contaran una historia que no te pareció ni real ni convincente Morfeo te de la opción...')
  time.sleep(1)
  print('La pildora roja...')
  time.sleep(1)
  print('O la pildora azul...')
  time.sleep(0.5)

def pildora():
  while True: 
    x = input('¿Cuál de las dos pildoras elegiras? (1 ó 2)')
    if x=='1' or x=='2':
      break
  return int(x)

def final():
  if pildora() == 1:
    print('Has elgido la pildora roja')
    print('Por ello podrás ver la vida real.')
  else:
    print('Has elegido la pildora azul')
    print('Permaneceras en la ignorancia durante toda tu vida.')

def again():
  while True:
    r=input('Quieres volver a decidir? (Si ó No)').lower() or 'n'
    if r in ('n', 'no', 'nop', 'nope'):
      print('Gracias por jugar. Y recuerda que ...')
      print('... no existen preguntas sin respuesta, solo preguntas mal formuladas.')
      break
    elif r in ('s', 'si', 'y', 'yes'):
      inicio()
      final()
      again()
      break
      
inicio()
final()
again()

viernes, 6 de julio de 2018

Juego de la tirada más larga

Reto: Juego de la tirada más larga

Cada tirada genera una sucesión de números aleatorios entre 1 y 100. La tirada finaliza cuando se obtiene un número par, entre 40 y 60. El juego lanza 20 tiradas y al final se dice que tirada ha sido la más larga. 




Método 1

Necesitaremos la variable maxi para contabilizar el número de elementos de la tirada más larga. Nos metemos en un bucle for para hacer las 20 tiradas. Dentro del bucle inicializamos la variable texto como una cadena vacía. Esta variable contendrá los números que componen una tirada. La variable n contará el número de elementos que componen una tirada. Nos metemos en un bucle while para ir generando los elementos de cada tirada. En este caso ha de ser un bucle de tipo while ya que no sabemos a priori cuan larga será la tirada. Se genera el número aleatorio x, que se integra dentro de la variable de texto. Nos econtramos con un condicional if que pretende detectar cuándo se detendrá la generación de elementos dentro de una tirada.


Si el valor de x es par y está entre 40 y 60 entonces se cumplirá la condición e imprimiremos los números de la tirada i-ésima. Nos metemos en un nuevo condicional if para anotar el número de elementos de la tirada más larga. Esto se hace con la variable maxi, y con la variable tirmax lo que hacemos es anotar en cuál de las 20 tiradas se ha alcanzado el máximo. Esta será la tirada más larga. La instrucción break hace que nos salgamos del bucle while después de haber tratado la tirada i-ésima y devuelve el flujo del programa al bucle for. Si no se cumple la condición de haber llegado a un par entre 40 y 60, esto quiere decir que necesitamos generar un nuevo número aleatorio dentro de esta misma tirada y entonces tendremso que hacer n+=1 lo cual incrementa el valor del contador en una unidad. Al final se imprime la longitud de la tirada que más elementos tiene y se indica qué tirada fue en la que se alcanzó la máxima longitud.
Este método tiene el inconveniente de que si existe empate en el máximo entre dos o más tiradas no se indican todas ellas, unicamente se imprimirá una de ellas. Esto se soluciona en el método 2.


import random
maxi=0
for i in range(1,21):
  texto=''
  n=1
  while True:
    x=random.randint(1,100)
    texto+=str(x)+' '
    if x%2==0 and x>=40 and x<=60:
      print('Tirada',i,':',texto)
      if n>=maxi:
        maxi=n
        tirmax=i
      break
    n+=1
print('El maximo nº de elementos ha sido',maxi,'y se alcanza en la tirada',tirmax)


Método 2

En este caso hemos realizado una variante del caso anterior para que recoja varias tiradas en caso en empate. En la imagen adjunta se puede ve como las tiradas 7, 15, 17 y 18 empatan en longitud puesto que todas ellas tienen 9 elementos. Hemos logrado anotarlas usando la variable tirmax como un string que va recogiendo las cadenas cuando estas llegan al máximo.
La cadena tirmax añade una coma cada vez que se agrega un número. Lo que hemos hecho es eliminar la última coma y añadir un punto para cerrar la frase. Esto se logra con la expresión siguiente.

tirmax[:len(tirmax)-2]+'.'



import random
maxi=0
tirmax='' #texto que recoge la tirada o tiradas de longitud máxima
for i in range(1,21): #generamos las tiradas 1 a 20
  texto='' #cadena que recoge los valores numéricos de una tirada
  n=1 #número de elementos que tiene cada tirada
  while True:
    x=random.randint(1,100) #aleatorio entero entre 1 y 100
    texto+=str(x)+' ' #añadimos a la frase un nuevo elemento y un espacio
    if x%2==0 and 40<=x<=60: #cuando se ha de detener la generación de números en cada tirada
      print('Tirada',i,':',texto) #se imprime la frase de la tirada i-ésima
      if n>maxi: #si el nº de elemento de esta tirada (n) es mayor que el máximo que existía hasta ahora
        maxi=n #nuevo máximo
        tirmax=str(i)+','+' ' #si tenemos nuevo máximo la frase tirmax se inicializa con el indice de la tirada actual
      elif n==maxi: #si el nº de elemento de la tirada es igual al máximo actual
        tirmax+=str(i)+','+' ' #la frase tirmax añade el indice de la tirada actual
      break #nos salimos del bucle while porque ya se ha cumplido la condición del if
    n+=1 #contador: un nuevo elemento dentro de la tirada en la que estamos
print('El maximo nº de elementos ha sido ',maxi,' y se alcanza en ',tirmax[:len(tirmax)-2]+'.')
#al final se imprime tirmax pero se quita la última coma y se añade al final un punto.


Método 3

Con el código del método 2 puede llegar a ser muy tedioso ejecutarlo varias veces hasta que se obtenga una jugada donde dos o más tiradas de lógitud máxima se den simultaneamente.  Lo que hemos hecho con este método es embeber el código en un bucle while que busca que el número de tiradas repetidas de longitud máxima sea mayor o igual a un cierto valor. En el ejemplo hemos puesto que sean cuatro las tiradas repetidas.


También hemos añadido un condicional if que consigue que si el número que se genera aleatoriamente está entre 1 y 9 se le añade un espacio vacío al imprimirle en la fila de su tirada. Con ello lo que conseguimos es que las tiradas que tengan el mismo número de elementos queden visualmente con la misma longitud. Algo similar hemos añadido para que el número de tirada entre 1 y 0 lleve un espacio previo adicional para mejorar el aspecto visual. También hemos modificado el rango de variación del número aleatorio para que se mueva entre 1 y 99. Hemos evitado el 100 porque al tener tres dígitos visualmente puede alterar la longitud del texto cuando aparece en una tirada.


import random
while True:
  maximo=0
  tirmax=''
  for i in range(1,21):
    texto=''
    n=1
    while True:
      x=random.randint(1,99)
      if x>=10:
        texto+=str(x)+' '
      else:
        texto+=' '+str(x)+' ' #añadimos un espacio previo para que visualmente quede bien
      if x%2==0 and x>=40 and x<=60:
        if i>=10:
          print('Tirada',i,':',texto)
        else: #si i está entre 1 y 9 se antecede un espacio para que visualmente quede bien
          print('Tirada ',i,':',texto)
        if n>maximo:
          maximo=n
          tirmax=str(i)+','+' '
          repes=1 #contador de tiradas repetidas de longitud máxima
        elif n==maximo:
          tirmax+=str(i)+','+' '
          repes+=1 #el contador de tiradas repetidas máximas se incrementa
        break
      n+=1
  print('El maximo nº de elementos ha sido ',maximo,' y se alcanza en ',tirmax[:len(tirmax)-2]+'.')
  if repes>=4: #queremos un mínimo de 4 tiradas de máxima longitud
    break

jueves, 5 de julio de 2018

Booleanos en Python

Reto: Booleanos

Generar aletoriamente un número del 100.000 al 200.000. Si ese número tiene un tres pierdes la partida y si carece de treses entonces has tenido éxito en el juego.



Veamos varias soluciones al juego planteado, unas usan variables booleanas y otras no, unas usan funciones y otras no, unas usan un bucle para recorrer todos los caracteres del número aleatorio y otras no. Con esta casuística de soluciones podemos aprender bastante acerda de este tipo de casos. El ejemplo es muy parecido a la programación que necesitaríamos para determinar si un número es primo o no. En ese caso la idea es suponer que de entrada el número analizado si es primo y hasta que no se encuentre alguno de los anteriores que haga que al dividir entre él de división exacta no podremos descartarlo. Por tanto, será necesario buscar si hay división exacta recorriendo unos cuantos valores previos. Y hasta que no podamos descartar que ninguno de los números previos no da división exacta no podremos afirmar que el número candidato es primo. Aquí sucede lo mismo, hasta que no se analizan los seis dígitos que componen el número aleatorio del juego, no se podrá afirmar que hemos ganado. Solo cuando hemos descartado que todos ellos son distintos de tres entonces es cuando podemos afirmar que hemos ganado.

Método 1

Vamos a jugar a 'me quiere' y 'no me quiere' como si estuviéramos desojando una margarita. Tendremos éxito cuando el número aleatorio entre cien mil y docientos mil no tenga ninguna cifra igual a tres. Si aparece algún tres entonces habremos fracasado en el juego.
Creamos una variable booleana que inicialmente tendrá el valor True. Nos metemos en un condicional if que analiza si existe algún tres en el número aleatorio. Trabajamos con cadenas alfanuméricas para que nos funcione in que busca en el string para ver si localiza algún tres. Si se cumple la condición de que ha encontrado un tres entonces la variable booleana meQuiere se torna en False.
Finalmente nos metemos en otro condicional if que analiza el valor de la variable booleana. Observe que no es necesario poner meQuiere==True, sino que para ver si esta variable es verdadera simplemente se pone la variable booleana ya que en si misma ya nos dirá si es True o False.



import random
x=str(random.randint(100000,200000))
print(x)
meQuiere=True #inicialmente me quiere
if str(3) in x:
  meQuiere=False

if meQuiere:
  print('Me quiere')
else:
  print('No me quiere')


Método 2

Generamos el número aleatorio y lo convertimos en un string. Inicializamos la variable booleana premio como True. Nos metemos en un bucle for que recorre todos los caracteres del número. Si alguno de los caracteres es igual a tres entonces la variable booleana se convierte en False y con break detenemos el bucle.
Al final nos encontramos con otro condicional if que analiza la variable booleana premio. Si es verdadera imprime que hemos ganado y si es falsa entonces habremos perdido.

import random
x=str(random.randint(100000,200000))
print(x)
premio=True #inicializamos la variable booleana como verdadera
for i in x:
  if int(i)==3: 
    premio=False
    break  

if premio:
  print('Has ganado. BIEN!!!!!!')
else:
  print('Has perdido porque ha salido un 3')


Método 3

Los métodos 3, 4 y 5 solo se diferencian en la función ganare.
Disponemos de dos funciones. La función principal se lanza llamándola con la expresión jugar(). Esta primera función no lleva argumentos, por eso dentro de los paréntesis no se escribe nada, pero es necesario ponerlos. Lo primero que hace la función jugar es generar un número aleatorio y convertirlo en string. Dentro de la función nos encontramos con un condicional if que usa como condición una llamada a la otra función que se llama ganare y la pasa un argumento que es el número aleatorio generado en forma de cadena alfanumérica. La función ganare analiza el número entregado y si contiene un tres devuleve False y si no es así devuelve True. Este retorno hace que el condicional de la función jugar actúe de forma que si el resultado es True imprimirá que hemos ganado el juego y en caso contrario nos dice que hemos perdido.
La función ganare analiza si el argumento en forma de cadena contiene un tres.

import random

#Funcion que retorna True cuando no hay ningún tres
def ganare(x):
  for i in x:
    if int(i)==3:
      return False
  return True

def jugar():
  x=str(random.randint(100000,200000))
  if ganare(x):
    print(x,' He ganado. BIEN!!!!!!')
  else:
    print(x,' He perdido porque ha salido un 3 :(')

jugar()


Método 4

Los métodos 3, 4 y 5 solo se diferencian en la función ganare.
En este método la función ganare no tiene un for que recorra todos los caracteres buscando un tres. Directamente lo que hacemos es meternos en un condicional if que pregunta si un tres como string está en x, si la respuesta es positiva retorna un False y en caso contrario retorna un True. Observe que ni siquiera hemos usado else.

import random

def ganare(x):
  if str(3) in x:
      return False
  return True

def jugar():
  x=str(random.randint(100000,200000))
  if ganare(x):
    print(x,' He ganado. BIEN!!!!!!')
  else:
    print(x,' He perdido porque ha salido un 3 :(')

jugar()


Método 5

Los métodos 3, 4 y 5 solo se diferencian en la función ganare.
Aquí si usamos una variable booleana en la función ganare. La variable se llama premio y la inicializamos en True. Si el tres como string se encuentra en el número x entonces la variable booleana se torna en False. Al final la función devuelve el valor que contenga en ese momomento la variable booleana.

import random

#Funcion que retorna True cuando no hay tres
def ganare(x):
  premio=True
  if str(3) in x:
      premio=False
  return premio

def jugar():
  x=str(random.randint(100000,200000))
  if ganare(x):
    print(x,' He ganado. BIEN!!!!!!')
  else:
    print(x,' He perdido porque ha salido un 3 :(')

jugar()


Método 6

En este caso no trabajamos con funciones. Generamos el número aleatorio lo trasnformamos en una cadena alfanumérica. Nos metemos en un bucle for que recorre todos los caracteres. Dentro del bucle tenemos un condicional if que pregunta si el caracter analizado es un tres. En caso afirmativo imprime que hemos perdido y con un break termina el bucle for. En caso contrario se imprime que hemos ganado. Lo sorprendente es la indentación de else, ya que no es la que cabría esperar a la misma altura que el if. Como vemos else está al nivel del for, y funciona. Pero no podría ser de otra forma ya que si la ponemos a la altura del if cada ver que el dígito analizado no fuera un tres nos diría que hemos ganado.

import random
x=str(random.randint(100000,200000))
for i in x:
  if int(i) == 3:
    print(x,' He perdido porque ha salido un 3.')
    break
else:
  print(x,' He ganado. Fiesta!!!')


Método 7

Este método proporciona una solución con pocas líneas de código. Generamos el número aleatorio como un string. Nos metemos en un if que se cuestiona sobre si existe algún tres. En caso afirmativo imprime que hemos ganado y en caso contrario hemos perdido. Una solución rápida y sencilla.

import random
x=str(random.randint(100000,200000))
if '3' in x:
  print(x,'Has perdido')
else:
  print(x,'Has ganado. Felicidades!!!')


Método 8

Definimos la variable texto que inicializamos con la frase 'Has ganado, porque no ha salido ningún tres.'
Nos metemos en un bucle for que recorre las seis posiciones del número aleatorio generado. Dentro del bucle tenemos un condicional que detecta si alguno de los dígitos es un tres. En caso afirmativo se reescribe la frase de la variable texto informando que ha perdido. De esta forma si no se encuentra ningún tres la frase no se reescribe y se anuncia que se ha ganado.

import random
x=str(random.randint(100000,200000))
texto='Has ganado, porque no ha salido ningún tres.'
for i in x:
  if i=='3':
    texto='Lo siento. Has perdido porque ha salido un tres.'
print(x,texto)

miércoles, 4 de julio de 2018

Triángulos factibles en Python

Reto: Triángulos factibles

Dados tres lados decir si es posible construir un triángulo con ellos. En caso afirmativo decir si el triángulo formado es equilátero, isósceles o escaleno.




Un triángulo es factible cuando el lado mayor es menor que la suma de los otros dos.

  • Equilatero: los tres lados iguales
  • Isósceles: dos lados iguales
  • Escaleno: los tres lados distintos



Método 1

Generamos números aleatorios entre 1 y 100 para los tres lados. En lugar de detectar cuál es el mayor de los lados y cuáles son los otros dos, lo que hacemos es establecer una triple condición en el if usando and para evaluar que ninguno de los lados sea mayor que los otros dos. Si se cumple la condición el triángulo es factible y pasamos a determinar de qué tipo se trata. Si los tres lados son iguales se trata de un triángulo equilátero. Si dos lados son iguales se trata de un triángulo isósceles, para ello usamos un operador lógico or y analizamos los tres casos posibles. En caso contrario los tres lados serán distintos y se tratará de un triángulo escaleno.

import random
a=random.randint(1,100)
b=random.randint(1,100)
c=random.randint(1,100)
if a<(b+c) and b<(a+c) and c<(a+b):
  print('Si a =',a,', b =',b,'y c =',c,' entonces si se puede hacer un triangulo')
  if a==b==c:
    print('Equilatero')
  elif a==b or b==c or a==c:
    print('Isósceles')
  else:
    print('Escaleno')
else:
  print('Si a =',a,', b =',b,'y c =',c,' entonces no se puede hacer un triangulo')


Método 2

Usamos tres bucles for encadenados para recorrer todas las posibilidades para los lados a, b, c.

for a in range(1,5):
  for b in range(1,5):
    for c in range(1,5):
      texto=''
      if a<(b+c) and b<(a+c) and c<(a+b):
        texto='Con '+str(a)+','+str(b)+','+str(c)+' si se puede hacer un triangulo: '
        if a==b==c:
          texto+='Equilatero'
        elif a==b or b==c or a==c:
          texto+='Isósceles'
        else:
          texto+='Escaleno'
        print(texto)


Método 3

Creamos una lista denominada lados, que contien los tres lados del triángulo obtenidos aleatoriamente. Ordenamos la lista, de esta forma sabemos que el último valor de la lista será el mayor. La ventaja que tiene este procedimiento es que en el condicional if solo tenemos que analizar la condición c<(a+b) puesto que ya sabemos que c es el lado mayor. También tiene otra ventaja en el elif del isósceles ya que solo analizamos a==b y b==c. No será necesario analizar a==c ya que los valores están ordenados.

import random
random.seed()
a=random.randint(1,100)
b=random.randint(1,100)
c=random.randint(1,100)
lados=[a,b,c]
lados.sort()
a=lados[0]
b=lados[1]
c=lados[2]
print(lados)
if c<(a+b):
  print('Si es factible con esos lados.')
  if a==b==c:
    print('El triángulo es equilatero.')
  elif a==b or b==c:
    print('El triángulo es isósceles.')
  else:
    print('El triángulo es escaleno.')
else:
  print('No es factible con esos lados.')

Calcular la Letra del DNI en Python

Reto: Letra del DNI

Generar primero una lista con los números entre 0 y 10, luego generar otra lista con los números del 11 al 20. Unir ambas lista e imprimir el resultado.



En España el DNI (Documento Nacional de Identidad) tiene un número y una letra de control que se obtiene mediante un sencillo algoritmo: Wikipedia.


Método 1

Solicitamos a usuario el número del DNI. Definimos el string que contiene la secuencia de letras utilizadas en el algoritmo: TRWAGMYFPDXBNJZSQVHLCKE. Imprimimos la letra del DNI que se calcula obteniendo el resto, módulo o resíduo de dividir el DNI entre 23. El resto varia entre 0, que supone división exacta, y 22. Consultamos la palabra para ver el caracter que corresponde. Si el resto es cero corresponde una T y si es 22 corresponde una E.

n=int(input("Introduzca el número del DNI:"))
palabra='TRWAGMYFPDXBNJZSQVHLCKE'
print('La letra del DNI es: ', palabra[n%23])


Método 2

En este caso trabajamos con una lista en lugar de usar un string. Tambíen hemos incluido al incio unas líneas con replace que eliminarán los puntos o espacios que el usuario introduzca junto con el número del DNI.

x=input("Introduzca el número del DNI: ")
x=x.replace(' ','')
x=x.replace('.','')
x=int(x)
lista=['T','R','W','A','G','M','Y','F','P','D','X','B','N','J','Z','S','Q','V','H','L','C','K','E']
print(x)
print('La letra del DNI es: ', lista[x%23])

martes, 3 de julio de 2018

Trabajar con diccionarios en Python

Reto: Diccionarios

Dado un número del 1 al 12, mostrar el mes correspondiente y el número de días que tiene. Trabajar con diccionarios.




Método 1

Creamos el diccionario d en el que la clave son los números del 1 al 12 y el valor son los días que tiene cada mes. Consideramos que febrero siempre tiene 28 días para simplificar. Preguntamos al usuario por el més que quiere, que ha de ser un número entre 1 y 12. Creamos una tupla denominada mes con los meses del año. Observe que es una tupla porque hemos usado paréntesis en su creación. Si hubiéramos usado corchetes [] se trataría de una lista y el código también funcionaría bien. Primero imprimimos el mes consultando la tupla. Finalmente imprimimos el número de días que contiene ese mes consultando el diccionario.


d= {'1':31, '2':28, '3':31, '4':30, '5':31, '6':30, '7':31, '8':31, '9':30, '10':31, '11':30, '12':31}
x=input('¿Qué mes quiere?')
mes=('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec')
print(mes[int(x)-1])
print(d.get(x))


Método 2

Creamos el diccionario d donde la clave es el mes y el valor es el número de días que tiene ese mes. Creamos la lista mes con los meses del año en formato texto, a tres dígitos. Nos metemos en un bucle while True donde preguntamos al usuario por n que es el número de meses. Si n está en el rango 1 a 12 detendremos el bucle y sino seguiremos preguntando. Calculamos m consultando la lista mes. Recuerde que las listas comienzan por cero, este es el motivo por el que hemos restado 1 al proporcionar el índice de la lista. Finalmente imprimimos n, m y el número de días que contiene el mes haciendo una consulta al diccionario.

d={'Jan':31,'Feb':28,'Mar':31,'Apr':30,'May':31,'Jun':30,'Jul':31,'Aug':31,'Sep':30,'Oct':31,'Nov':30,'Dec':31}
mes=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
while True:
  n=int(input('Indique un mes con un número del 1 al 12:'))
  if n in range(1,13):
    break
m=mes[n-1]
print('El mes',n,'es', m,'y tiene',d[m],'días.')


Método 3

Generamos un número aleatorio entre 1 y 12. Definimos dos diccionarios donde en ambos la clave es un número entero entre 1 y 12. El primer diccionario contiene el nombre del mes y el segundo los días de ese mes. Finalmente imprimimos el valor numérico generado de forma aleatoria n, consultamos el diccionario primero para obtener el mes y el segundo para obtener el número de días que contiene.

import random
random.seed()
n=random.randint(1,12)
a={1:'Jan',2:'Feb',3:'Mar',4:'Apr',5:'May',6:'Jun',7:'Jul',8:'Aug',9:'Sep',10:'Oct',11:'Nov',12:'Dec'}
b={1:31,2:28,3:31,4:30,5:31,6:30,7:31,8:31,9:30,10:31,11:30,12:31}
print(' mes:',n,'-->',a[n],'\n','días =',b[n])


Método 4

Creamos un único diccionario cuyas claves son los números del 1 al 12 y cuyo valor es una lista de dos elementos, el primero es el mes y el segundo el número de días que tiene. También se podría haber usado una tupla en lugar de una lista. Si se usan corchetes se trata de una lista, y si usamos paréntesis se trata de una tupla.
Con un bucle for recorremos todos los elementos del diccionario y vamos llamando a los elementos dos elementos de la lista que contienen.

d={1:['Jan',31],2:['Feb',28],3:['Mar',31],4:['Apr',30],5:['May',31],6:['Jun',30],7:['Jul',31],8:['Aug',31],9:['Sep',30],10:['Oct',31],11:['Nov',30],12:['Dec',31]}
for i in range(1,13):
  print(i,':',d[i][0],d[i][1])


Método 5

Definimos la lista mes y la lista dias. También creamos la lista num generándola con range. Vamos a crear dos diccionarios d1 y d2 usando zip y dict. Lo que hace zip es unir dos iterables y dict convierte el resultado en un diccionario.
Con un bucle for recorremos todos los números de 1 al 12 y vamos llamando a los elementos de los dos diccionarios.

mes=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
dias=[31,28,31,30,31,30,31,31,30,31,30,31]
num=list(range(1,13))
d1=dict(zip(num,mes))
d2=dict(zip(num,dias))
for i in range(1,13):
  print(i,d1[i],d2[i])


Método 6

Este método es similar al anterior si bien usa un único diccionario. La función zip agrupa dos o más iterables, y los convierte en una tupla. Aquí lo usamos dos veces, la primera permite crear una tupla con el mes y los días que tiene ese mes. La segunda vez que se usa la función zip agrupa un número correlativo entre 1 y 12 con la tupla anterior y aprovechamos a convertir el resultado en un diccionario usando dict. De esta forma hemos obtenido un único diccionario denominado d que mostramos seguidamente.



mes=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
dias=[31,28,31,30,31,30,31,31,30,31,30,31]
num=list(range(1,13))
tupla=zip(mes,dias)
d=dict(zip(num,tupla))
for i in range(1,13):
  texto=''
  if i<10: --="" i="" str="" texto=""> '+d[i][0]+' '+str(d[i][1])
  print(texto)


Método 7

En este método usamos la función incluida en Python denominada enumerate que lo que hace es añadir a un objeto iterable una sucesión de números que comienza por cero. Si queremos que comience por 1 tenermos que añadir start=1.



mes=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
dias=[31,28,31,30,31,30,31,31,30,31,30,31]
d=dict(enumerate(zip(mes,dias), start=1))
for i in d:
    print(i,d[i])

Sucesión de Fibonacci programada en Python

Reto: Fibonacci

Dar los n primeros valores de la sucesión de Fibonacci.



La sucesión de Fibonacci es una famosa sucesión numérica que comienza con los números 0 y 1, luego los siguientes números se obtienen sumando los dos anteriores a él.

La serie se conoce como los números de Fibonacci y son los siguientes.

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, ... ... ...

Observe que 8 es la suma de los dos previos 3+5 y así se forman todos ellos. Por eso es necesario establecer los dos primeros. En muchas de las referencias que se pueden encontrar también se la denomina serie de Fibonacci.

Consideramos que los dos primeros elementos de la sucesión de Fibonacci son 0 y 1. En otras referencias consultadas se puede ver que los primeros elementos se considera que son 1 y 1. Esto no altera al resto de los elementos que se van obteniendo ya que la sucesión de Fibonacci se forma dando los dos primeros elementos y luego para obtener los restantes lo que se hace es sumar los dos previos.



Método 1

Solicitamos a usuario que nos de el número de elementos de la sucesión que desea generar. Establecemos en 5 el número mínimo de elementos a mostrar. Usamos la función max para que si el usuario nos proporciona un número menos a 5, se establezca n igual a 5.

n=max(int(input('¿Cuántos valores quieres? (minimo 5)')),5)
old=0
x=1
print(old)
print(x)
for i in range(0,n-2):
  y=x+old
  print(y)
  old=x
  x=y


Método 2

Con una estructura while True solicitamos el valor de n que se continuará preguntando hasta que el usuario introduzca un valor mayor que dos.
Trabajamos con listas donde los dos primeros elementos vienen dados y son 0 y 1. El resto se generan sumando los dos previos y se añaden a la lista con append.

while True:
  n=int(input('¿Cuántos valores quieres? (mínimo 3)'))
  if n > 2:
    break
x=[0,1]
for i in range(n-2):
  x.append(x[-1]+x[-2])
print(x)


Método 3

Trabajamos con una lista que inicializamos con los dos primeros valores 0 y 1. Nos metemos en un bucle for dentro del cual usamos append para ir añadiendo elementos nuevos a la sucesión de Fibonacci.


lista=[0,1]
for i in range(3,21):
  lista.append(lista[len(lista)-1]+lista[len(lista)-2])
print(list(lista))


Método 4

Trabajamos con una función dentro de la cual inicializamos las variables a y b con los valores 0 y 1 respectivamente. Nos metemos en un bucle for donde creamos una tercera variable auxiliar c que será la suma de a+b.


def fibo(n):
  a=0
  b=1
  for i in range(3,n+1):
    c=a+b
    a=b
    b=c
  return(c)
print(fibo(100))


Método 5

Trabajamos con una lista llamada fibo que vamos alimentando con append a cada ciclo de bucle for.


fibo=[0,1]
for i in range (50):
  fibo.append(fibo[-1]+fibo[-2])
print(fibo)


Método 6

Creamos una función a la que pasamos el parámetro n que nos indica el número de elementos de la sucesión de Fibonacci que deseamos. Dentro de la función definimos las variables a y b con los valores 0 y 1 respectivamente. Nos metemos en un bucle for que recorrerá los elementos que vamos a generar. Se imprime el valor de a y se deja un espacio vacío, evitando el retorno de carro. Asignamos a la variable a el valor de b, y a la b el valor de a+b. La última línea de código dentro de la función es un print() que equivale a un retorno de carro, pero permite imprimir el resultado.


def fibo(n):
  a,b=0,1
  for i in range(n):
    print(a,end=' ')
    a,b=b,a+b
  print()
fibo(15)

Valores de un polinomio en Python

Reto: Polinomio

Dado el polinomio y=x^4-3x^2+2 calcular el valor de y para valores de x que varían en el rango -2, +2 con incremento de 0,1.




Gráfico obtenido con Excel

Método 1

Importamos la librería numpy con el alias np. Esta librería nos permite acceder a funciones y comandos matemáticos, como por ejemplo arange que nos proporciona un rango similar a range pero además acepta un tercer argumento que es el paso o incremento utilizado.
Usamos round para controlar los decimales que se obtienen en los cálculos.

import numpy as np
for x in np.arange(-2.0, 2.1, 0.1):
  y= round(x,1)**4-3*round(x,1)**2+2 
  print(round(x,1),round(y,4))


Método 2

Usando una función que nos de el valor de y para un cierto x. Para no usar la librería numpy hemos utilizado un pequeño truco para poder utilizar range y obtener incrementos no enteros. Lo que hacemos es variar los valores del rango entre -20 y +20 de uno en uno, y luego dividir entre 10.
En este caso no hemos utilizado round y debido a ello obtenemos unos valores con muchos decimales que no serían los correctos, ya que los cálculos no se realizan con la precisión necesaria.

def y(x):
  return pow(x,4)-3*pow(x,2)+2

for k in range(-20,21):
  k/=10
  print(k,y(k))

Acumular en Python

Reto: Acumulado

Listar los números entre 1 y 10. En la columna contigua sus cuadrados, y en la tercera columna sus cubos. Al final dar la suma de todos los valores de cada columna.




Método 1

Inicializamos con el valor cero las tres variables que recogerán la suma de cada columna. Nos metemos en un blucle for que toma los valores 1 a 10. Acumulamos los valores de cada una de las tres variables s1, s2 y s3. Dentro del bucle imprimimos los valores de cada fila que son i, su cuadrado y su cubo. Finalmente, y fuera del bucle, imprimimos el valor de los acumulados.

s1=0
s2=0
s3=0
for i in range(1,11):
  s1=s1+i
  s2=s2+i**2
  s3=s3+i**3
  print(i,i**2,i**3)
print('_'*11)
print(s1,s2,s3)


Método 2

Inicializamos en cero los valores de las tres variables que acumularan s1, s2 y s3. Nos metemos en un bucle for donde tenemos la variable i para recorrer los números 1 a 10, la variable j contendrá sus cuadrados y la variable k sus cubos. Acumulamos usando s1+=i que equivale a s1=s1+i. Imprimimos, dentro del bucle, los valores i, j, k que constituyen las tres columnas. Finalmente, fuera del bucle, imprimimos los acumulados.

s1=s2=s3=0
for i in range(1,11):
  j=pow(i,2)
  k=pow(i,3)
  s1+=i
  s2+=j
  s3+=k
  print(i,j,k)
print('_'*11)
print(s1,s2,s3)



Método 3

Otra forma de acumular en Python es trabajar con listas y luego sumar todos sus elementos con sum.

a=list()
b=list()
c=list()
for i in range(1,11):
  j=pow(i,2)
  k=pow(i,3)
  a.append(i)
  b.append(j)
  c.append(k)
  print(i,j,k)
print('_'*11)
print(sum(a),sum(b),sum(c))