¿Cómo se configura el entorno para simular una caminata de borrachos?
Primero, es esencial importar las clases que hemos creado para simular nuestra caminata. Estas son BorachoTradicional, Campo, y Coordenada. Reiterar la distinción entre "Campo" (el módulo) y "Campo" (la clase) es fundamental.
El siguiente paso es establecer un entorno para ejecutar el programa mediante if __name__ == "__main__": asegurando que nuestro código se ejecute cuando sea llamado desde la terminal. Luego definimos las distancias de las caminatas y la cantidad de intentos de simulación, que serán 10, 100, 1000, y 10000 pasos en 100 intentos cada una. Estos múltiplos permiten medir más precisamente la media de los resultados logrados.
¿Cómo definimos la función main?
La función main es vital ya que coordina la simulación. Recibe tres parámetros:
distancias_de_caminata: lista de enteros indicando la cantidad de pasos por simulación.
num_intentos: número de veces que cada simulación se debe ejecutar para obtener una media precisa.
tipo_de_borracho: la clase del borracho que se utilizará, como BorachoTradicional.
Código de ejemplo para la función main
defmain(distancias_de_caminata, num_intentos, tipo_de_borracho):for dist in distancias_de_caminata:# Simula la caminata para cada distancia y número de intentos distancias = simular_caminata(dist, num_intentos, tipo_de_borracho)# Genera estadísticas de las simulaciones distancia_media =round(sum(distancias)/len(distancias),3) distancia_maxima =max(distancias) distancia_minima =min(distancias)# Imprime resultadosprint(f'{tipo_de_borracho.__name__} tuvo una caminata aleatoria de {dist} pasos')print(f'Distancia media: {distancia_media}')print(f'Distancia máxima: {distancia_maxima}')print(f'Distancia mínima: {distancia_minima}\n')
¿Cómo implementamos la simulación de la caminata?
La función simular_caminata organiza cómo un borracho se desplazará paso a paso desde una coordenada inicial (0, 0).
Inicialización: Crea una instancia del tipo de borracho y establece el punto de inicio en (0, 0).
Iteración: Por cada intento, se crea un nuevo campo y se añade el borracho en la coordenada inicial.
Movimiento: Utiliza la función caminata para mover el borracho según el número de pasos definidos y calcula la distancia.
¿Qué se debe tener en cuenta al ejecutar la simulación?
Finalmente, la ejecución del programa debe hacerse asegurando que la función main incluya las llamadas adecuadas para cada tipo de simulación. Además, es fundamental asegurarse de que las estadísticas calculadas sean precisas y se almacenen y muestren de manera significativa a los usuarios.
Este método robusto y sistemático garantiza que la simulación del borracho sea exhaustiva, cubriendo una variedad de distancias y obteniendo estadísticas de importancia crítica para la comprensión de estas simulaciones aleatorias.
Si tienes dudas o comentarios sobre este código, no dudes en usar el sistema de comentarios, donde recibirás apoyo de la comunidad. ¡Sigue adelante y mantén la curiosidad!
El problema es que el profesor Aroesti IMPLEMENTA directo sus algoritmos, sin explicar el proceso mental o lógico que lo llevo a saber que ese algoritmo es el mejor. Eso provoca que nosotros solo veamos como escribe código sin saber EXACTAMENTE cuál es el propósito de lo que el profesor programa. Por favor Aroesti, si ves este mensaje trata de incluir en estos videos una pequeña sección al inicio que nos explique de manera GRÁFICA qué es lo que intentas lograr con cada clase de tu código y CÓMO SE RELACIONAN ENTRE SÍ.
A mi parecer el profesor David es muy buen profesor, hay muchos conceptos avanzados en cada uno de sus cursos explicados de una forma eficiente. Mi recomendación es ir realizando código de forma intermitente durante la clase, o bien abrir un jupyter notebook para entender a fondo lo que se está realizando, incluso mejor, intentar mejorar el código que se está implementando. Me pasó con el curso de Ingeniería de Datos con Python, donde tuve que buscar mucha documentación anexa al curso, pero sin duda cuando apruebas los cursos del profesor David, sales con 1kg de conocimientos más. Así que no te des por vencido compañero, keep learning!
Tengo la misma impresión que tu, explica un poco con sus palabras el algoritmo, pero no hay por lo menos un diagrama de flujo o algún soporte extra del algoritmo.
Estuvo muy pesada la clase, creo que muchos estamos solo copiando el código para que quizás más adelante podamos entender. Faltan muchas explicaciones.
en esas mismas estoy.......
estoy igual
Realice este código no pensando en la solución planteada por el tutor, sino estableciendo una logica lógica para solucionar este ejercicio. Por lo que mi código es muy diferente a lo anteriormente planteado basándome en la ejecución de 3 pasos:
Decidir sobre que eje me voy a desplazar
Realizar desplazamiento calculando la posición final
Actualizar las listas para obtener el tracking del camino recorrido
Módulo Principal
La lógica de este módulo parte del entendimiento que al momento de graficar el plot final, deben estar almacenados en dos listas los movimientos realizados por el “borracho” (pasos_x, pasos_y), como esta probabilidad de decisión es del 25% (arriba, abajo, izquierda, derecha) en cada paso, es importante entender que si la decisión de desplazarse fue sobre el eje horizontal (pasos_x) no debe afectar los valores correspondientes al eje vertical (pasos_y) y viceversa; por tal motivo en el módulo principal únicamente se toma la decisión de realizar el movimiento de manera vertical u horizontal.
Módulo de movimiento
Una vez decidido el eje sobre el cual se va a realizar el movimiento se determina hacia dónde va a ser realizado el siguiente paso (positivo o negativo) de manera aleatoria, como este afecta de forma iterativa la última posición del sujeto “borracho” debe obtenerse la última posición y aplicarle el respectivo movimiento.
Como ejemplo podría tomarse el caso de que durante la simulación el borracho decidió caminar un paso hacia la derecha X 1 y el siguiente paso es hacia la izquierda 1 X por lo que la posición final será el mismo lugar de partida (por esa razón el sujeto esta “borracho” xD), en términos de programación el número de pasos realizados fueron 2 aumentando el tamaño de la lista, pero el ultimo valor es cero, reflejando la acción de dar un paso y luego devolverse.
La lista debería tener estos valores:
pasos_x =
[0 --> origen / paso 0 /
1 --> derecha / paso 1
0] --> izquierda / paso 2 / vuelvo al origen
Como todos los pasos fueron en el eje horizontal el vertical debe permanecer vacío
[0 --> paso 0
0 --> paso 1
0] --> paso 2
Módulo de igualación de listas
Este modulo únicamente iguala el tamaño de las listas repitiendo el ultimo valor en la lista sobre la que no se efectúa ningún desplazamiento.
Ya con las listas actualizadas y todos los pasos realizados solo me queda graficar las dos variables para ver el “camino del borracho”
import os
import random as random
from bokeh.plottingimport figure, output_file, show
os.system('cls')# Inicializa las listas
pasos_x =[0]pasos_y =[0]# Módulo de movimiento
def mover(pasos):#print(f'iteracion: {i}') move = random.choice([-1,1])#print(f'choice: ({move})') last =len(pasos) delta = pasos[last-1]+ move
pasos.append(delta)#print(pasos)return pasos
# Módulo de igualación de listas
def equal_array(pasos): last =len(pasos) pasos.append(pasos[last-1])return pasos
# Módulo Principaldef random_direction(pasos_x, pasos_y, num):for i inrange(num): direc = random.choice([-1,1])if direc ==-1:#print(f'Horizontal') pasos_x =mover(pasos_x) pasos_y =equal_array(pasos_y)else:#print(f'Vertical') pasos_y =mover(pasos_y) pasos_x =equal_array(pasos_x)#print(pasos_x,pasos_y)return pasos_x, pasos_y
# Inicio del programa con ingreso de cantidad de pasos mediante consola
num =int(input('Numero de pasos aleatorios: '))random_direction(pasos_x, pasos_y, num)# Modulo de plotting
output_file("line.html")plot =figure(plot_width=600, plot_height=600)plot.line(pasos_x, pasos_y, line_width=2)show(plot)
Gracias, es bueno tener otras alternativas para implementar este código. Pasa el link a tu github tambíen. Saludos
excelente aporte desde otra pespectiva.
Me gustan los temas que quieren abordar con esta serie de cursos de python, pero un problema como este deberia tener una explicación (whiteboarding) previa, para entender lo que vamos a hacer, pues creo que al final del dia solo estamos viendo como David escribe codigo y tendremos que entender todo por nuestra cuenta.
Si viste los cursos anteriores allí te dan todas las bases para entender lo que estamos haciendo, en antes de escribir el código da una idea de que haremos.
Todo tiene más sentido cuando eliges una ruta e aprendizaje, así podrás ver la base de todo y no perderte ningún concepto
Yo soy nueva programando y me costo casi que todo el día para poder entender esto, pero luego de rayar bastante en el cuaderno, repasar, buscar más información y hacer unas pruebas en la terminal creo que pude entenderlo. Aqui van mis recomendaciones:
Hagan un diagrama UML de las clases. Yo lo hice en la clase pasada y aunque no es perfecto me ayudo a entender las dependencias entre clases. Sabiendo esto se hace más facil entender lo que viene. Dejo el UML que hice por aquí:
Analicen el orden del código y vayan armándolo función por función. Por ejemplo, la "primera" función que se ejecuta es main(), que a su vez, tiene en sí misma la funcion simular_caminata(), que tiene al mismo tiempo la funcion caminata(). Si lo hacen en papel les va a quedar algo así:
Si escriben el código linea por linea y funcion por funcion se darán cuenta que le programa en esencia lo que hace es:
Mover el borracho x pasos y en cada paso registrar su nueva coordenada.
Añadir esa nueva coordenada a una lista de distancias recorridas
Hacer operaciones con la lista de distancias recorridas.
Espero que ayude, he visto muchos comentarios en donde se quejan sobre la falta explicación del código, pero creo que esa es justamente la parte que nos toca a nosotros: desarrollar herramientas para entender por nosotros mismos el código. No siempre va a haber alguien que nos las haga fácil.
Mil gracias! Estoy de acuerdo contigo, es buscar por uno mismo la mejor manera de entender toda la lógica que tiene el código.
el comentario!.... ahora si entendi, muchas gracias
Estos cursos son muy buenos, pero podrian ser mucho mejor si se explicaran los algoritmos en vez de solo implementarlos, tienen ejemplos claros en los cursos de Freddy, el explica graficamente y luego implementa. No me gusta comparar pero con esa metodologia estos cursos estarian a un nivel muy alto. Ojala en proximos cursos de David podamos ver eso ya que el es sin duda uno de los mejores profesores.
Hola, @jonatancadavidtorres. 🤓
Veo que no eres la primera en compartir tu inquietud con esta parte del curso. Te agradezco mucho que nos lo hagas saber, el apoyo y la opinión de los Platzinautas es muy importante. 💚
Encontraremos la forma de mejorar este tipo de explicaciones. Por ahora te comparto dos cursos que me fueron muy útiles para entender esta clase de programas:
Compañero te entiendo, yo estaba igual pero es cuestión de repasar algunos conceptos y luego regresar, a este punto los conocimientos se van integrando y requiere que tu mismo vayas leyendo el código... animos!!!
Hola, si a alguno le costó algo de trabajo entender el código tal vez este colab (Jupyter Notebook de Google) les sirva, tiene el código en un sólo documento junto con la documentación para ir siguiendolo. Saludos.
Luis Fernando me ayudo mucho tu documentación. Gracias
Gracias! me ha ayudado mucho!
Creo que la forma correcta seria que primero explicara de manera grafica que debemos hacer para nosotros también tener algún precedente y no solo copiar el código conforme el profesor lo escribe
Ya lo hizo , no?
No se porque, pero los últimos cursos que he visto de David, he sentido que su forma de explicar ha desmejorado... pareciera mas una demostración de lo que el sabe hacer y no una clase donde se enseñe a hacer algo... puede ser que sea yo, pero la verdad siento que para aprender basicamente me toca tomar el titulo del tema e ir a investigar a otra parte, porque aqui solo veo lo que el Profe hace pero no explica el porque de las cosas...
Hola Andrés, es posible que tengas esta percepción al requerir profundizar más en la programación orientada a objetos y entender mejor el código. Esto es algo que me sucedió.
Sería bueno que el profesor comentara el código a medida que lo va escribiendo para mejorar el entendimiento de los algoritmos
exacto, en la parte de rango debería decir range, por lo demás esta genial.. muchas gracias por compartir
Estuvo muy buena esta serie de el camino de borrachos, aplicamos al mismo tiempo varios conocimientos adquiridos en cursos y clases pasadas
Aunque creo que David podría asignar nombres un poquito mejores para algunas variables y así lograr un mejor entendimiento del código... Por ejemplo: La lista declarada como "distancias_de_caminata" no tiene mucho que ver con su significado y funcionamiento en el código... ya que en realidad esa lista no guarda las distancias de las caminatas de los borrachos... mas bien guarda las 4 cantidades diferentes de pasos (10, 100, 1000 & 10000 pasos) que va a dar un borracho en la simulación.
Saludos y que Viva México!! <3
Me llamó la atención el:
tipo_de_borracho.__name__
Alguien me explica eso porfa?
El profesor en ese punto guarda en la variable "tipo_de_borracho" los datos de la clase borracho tradicional. Luego, para llamar el valor de __name__ de esta clase generada debe hacerlo con la siguiente sintaxis:
nombre_de_clase.variable_de_clase
por lo que en este caso usa:
tipo_de_borracho.__name__
Si te quedo alguna duda me avisas! :)
Pero, ¿por qué name y no nombre? no me queda muy claro
esta es la parte cuando te sientas con los codos sobre las rodillas y aumentas tu concentración al maximo en pleno juego de play station.
bien, después de dos días de arduo trabajo, les dejo unos consejos y el código funcional. Lo primero es reforzar sus conocimientos previos, y si en caso no entienden vean videos de youtube e investiguen, en mi caso yo me descargue un libro de introduccion a python que habla de los mismos temas que ya pasamos pero con mayor detalle, practiquen y practiquen lo basico en la terminal y cuando no entiendan, pruebenlo en la terminal. y repito nuevamente, practique lo basico, hasta entender y dominar.
aqui el codigo del primer archivo: camino_de_borracho.py
el nombre de los archivos es muy importante porque lo utilizaremos mas adelante.
import random
classBorracho: def __init__(self, nombre): self.nombre= nombre
classBorrachoTradicional(Borracho): # clase base, genera un contructor con init
def __init__(self, nombre):super().__init__(nombre) def camina(self): # camina aleatoriamente entre 4 opciones
return random.choice([(0,1),(0,-1),(1,0),(-1,0)]) #choice permite generar varias opciones que tienen la misma probabilidad
segundo archivo: coordenada.py
classCoordenada: def __init__(self, x, y): #contructor
self.x= x
self.y= y
def mover(self, delta_x, delta_y): # deltas definen cuanto se mueven a cada direccion.regresa una nueva coordenada con la suma de la coordenada actual + los cambios en delta x
#cada que generamos un cambio creamos una nueva coordenada, es inmutable,returnCoordenada(self.x+ delta_x, self.y+ delta_y) def distancia(self, otra_coordenada): # estamos en una coordenada actual y necesitamos otra coordenada, para calcular la distancia usamos pitagoras
delta_x = self.x- otra_coordenada.x #diferencia, se calcula la distancia entre dos coordenadas.delta_y= self.y- otra_coordenada.yreturn(delta_x**2+ delta_y**2)**0.5
tercer archivo: campo.py
classCampo: def __init__(self): #contructor
self.coordenadas_de_borrachos={} #crea un diccionario de las coordenadas de los borrachos.defañadir_borracho(self, borracho, coordenada): #que borracho queremos recibir y donde estara
self.coordenadas_de_borrachos[borracho]= coordenada #se guarda dentro del diccionario, y se designa esta operacion a coordenada
def mover_borracho(self, borracho): #que borracho vamos a mover
delta_x, delta_y = borracho.camina() #cuando camina el borracho regresa una tupla, aleatorio.coordenada_actual= self.coordenadas_de_borrachos[borracho] #la coordenada actual guardada en el diccionario
nueva_coordenada = coordenada_actual.mover(delta_x, delta_y) #con la coordenada actual le decimos que se mueva con el delta x, y el delta y.self.coordenadas_de_borrachos[borracho]= nueva_coordenada #guardamos nuevamente la coordenada del borracho en el diccionario.defobtener_coordenada(self, borracho): #consulta de donde anda un borracho al final del programa.return self.coordenadas_de_borrachos[borracho] #devuelve el valor actual en el diccionario.
aquí importaremos los tres archivos con from indicando las clases que vamos a usar:
from camino_de_borrachos importBorrachoTradicional #importacion de clases.from campo importCampo #campo es el modulo y Campo es la clase.from coordenada importCoordenadadef caminata(campo, borracho, pasos): inicio = campo.obtener_coordenada(borracho) #cual es el inicion, nos debe dar al inicio(0,0)for _ inrange(pasos): #para el rango de los pasos, tantos pasos se diga
#de campo con la funcion mover borracho, se le entrega como parametro un borracho.campo.mover_borracho(borracho) #le decimos a la coordenada de inicio
return inicio.distancia(campo.obtener_coordenada(borracho))def simular_caminata(pasos, numero_de_intentos, tipo_de_borracho): #llamada a tipo de borracho, a diferencia de llamarlo directamente como borracho tradicional, se lo recibe como parametro de la funcion
# lo que se hace es inicializar una instancia de borracho tradicional o de cualquier tipo de borracho que se le mande."agnostica" recibe un borracho, cualquie tipo.borracho=tipo_de_borracho(nombre="David") origen =Coordenada(0,0) distancias =[] #variable que guarda las distancias en cada una de las simulaciones."""por cada intento, el _ indica que no utilizaremos variable """for _ inrange(numero_de_intentos): campo =Campo() #simulacion
campo.añadir_borracho(borracho, origen) #se añade un borracho y un origen de coordenada.simulacion_caminata=caminata(campo, borracho, pasos) #resultado de la funcion caminata,(todavia no esta implementada) distancias.append(round(simulacion_caminata,1)) #añadir a las distancias la simulacion de la caminata, round permite que no tenga ningun decimal.return distancias
""" definicion de main """def main(distancias_de_caminata, numero_de_intentos, tipo_de_borracho):for pasos indistancias_de_caminata: #recuerde que son 10,100,1000,10000 distancias =simular_caminata(pasos, numero_de_intentos, tipo_de_borracho) #esto es lo que va a estar haciendo la simulacion.distancia_media=round(sum(distancias)/len(distancias),4) #4 son 3 decimales, es la media de los datos.distancia_maxima=max(distancias) #el dato maximo de la distancia
distancia_minima =min(distancias) #__name__ nos da el nombre de la clase,print(f"{tipo_de_borracho.__name__} caminata aleatoria de {pasos} pasos")print(f"Media = {distancia_media}")print(f"Max = {distancia_maxima}")print(f"Min = {distancia_minima}")if __name__ =="__main__": #End point
distancias_de_caminata =[10,100,1000,10000] #simulacion de 10 pasos,100 pasos,..., numero_de_intentos =100 #las simulaciones se corren varias veces para obtener su media.""" recibir classe de borracho, en vez inizializar la clase la vamos a ponerlo como referencia """main(distancias_de_caminata, numero_de_intentos,BorrachoTradicional)
el resultado aleatorio: no tiene que ser lo mismo porque es aleatorio.
BorrachoTradicional caminata aleatoria de 10 pasos
Media=2.91Max=6.0Min=0.0BorrachoTradicional caminata aleatoria de 100 pasos
Media=8.642Max=22.4Min=1.4BorrachoTradicional caminata aleatoria de 1000 pasos
Media=28.488Max=58.9Min=2.0BorrachoTradicional caminata aleatoria de 10000 pasos
Media=83.948Max=210.0Min=10.3
en mi caso tuve errores que me costo encontrar pero que son errores casi invisibles a la vista, pero al final después de buscar si funciona.
no te rindas!!
Jesse muchas gracias por realizar el analisis de este algoritmo, logre entenderlo mejor.
from borracho importBorrachoTradicionalfrom campo importCampofrom coordenada importCoordenada#Obtiene la distancia entre la 1ra coord y la ultima
def caminata(campo, borracho, pasos): inicio = campo.obtener_coordenada(borracho) #Obtenemos la coordenada(0,0),el origen
#inicio es el objeto coordenada de la clase Coordenada, aca esta el truco
for _ inrange(pasos): #Pasos=10, aca se va a mover 10 veces, luego 100 y asi
campo.mover_borracho(borracho)"""def mover_borracho(self, borracho): delta_x, delta_y = borracho.camina() coordenada_actual = self.coordenadas_de_borrachos[borracho] nueva_coordenada = coordenada_actual.mover(delta_x, delta_y) self.coordenadas_de_borrachos[borracho]= nueva_coordenada"""return inicio.distancia(campo.obtener_coordenada(borracho)) #Sacamos la distancia entre la primera coordernada(0,0) y la ultima despues de los 10 pasos
#Numero de intentos siempre es 100#Pasos:10,100,10000,100000def simular_caminata(pasos, numero_de_intentos, tipo_de_borracho): borracho =tipo_de_borracho(name ='David') #obj de la clase Borracho #Crea un objeto de la clase Coordenada origen =Coordenada(0,0) distancias =[]for _ inrange(numero_de_intentos): #100 veces
#Objeto de la clase campo
campo =Campo() campo.anadir_borracho(borracho, origen) #campo tiene borracho(Borracho) y origen(Coordenada) simulacion_caminata =caminata(campo, borracho, pasos) #Obtenemos una distancia
distancias.append(round(simulacion_caminata,1))return distancias
#Obtenemos100 distancias y la anexamos a la lista
def main(distancias_de_caminata, numero_de_intentos, tipo_de_borracho):for pasos indistancias_de_caminata: #Obtenemos100 distancias por cada paso
distancias =simular_caminata(pasos, numero_de_intentos, tipo_de_borracho) #Aca sacan la media y todo eso
if __name__ =='__main__': distancias_de_caminata =[10,100,1000,10000] numero_de_intentos =100main(distancias_de_caminata, numero_de_intentos,BorrachoTradicional)```
Realmente no es dificil el algoritmo, de hecho es bastante sencillo.
Si escriben el código de forma procedimental veran la sencillez.
Siento que se volvió complejo porque el profe lo escribió con programación orientado a objetos desde el inicio. Lo que es bueno, porque modularizó ya los distintos componentes, y la próxima vez que escriba otro tipo de borracho solo será agregando el borracho a una clase.
cuando empece la ruta le entendía muy claro a David, incluso me anticipaba, siento que va muy rapido, y que no esta siendo claro, en este punto me han sido de gran ayuda los comentarios del curso por que ya han realizado el curso personas, con las mismas dudas y su explicación es más breve
subió bastante de nivel la clase, costo trabajo seguirla
No es dificil el codigo pero la explicacion de David es como si solo estuviera leyendo el codigo y es dificil de seguir
No es dificil el codigo, pero bastaaaaaante enredadito el borracho, por el nombre de las variables.