Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Visualización de Caminos Aleatorios

8/24
Recursos

Aportes 194

Preguntas 47

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Les presento al Drogado, la variante que pensé para resolver el reto de esta clase 😂 hace caminos aleatorios con floats en lugar de ints. Aquí el código y una gráfica de cada trayecto, dependiendo si hizo 10, 100, 1000 o 10000 pasos:

class Drogado(Borracho):

    def __init__(self, nombre):
        super().__init__(nombre)

    def camina(self):
        return (
            random.choice([
                (random.random(), random.random() * -1),
                (random.random() * -1, random.random()),
                (random.random() * -1, random.random() * -1),
                (random.random(), random.random()),
            ])
        )

Para los que se están preguntando como hacer los caminitos aquí les dejo un código corto usando las mismas clases implementadas BorrachoTradicional Campo y Coordenada

from borracho import BorrachoTradicional
from coordenada import Coordenada
from campo import Campo

from bokeh.plotting import figure, show

def main(distancia, inicio, borracho):
    campo = Campo()
    campo.anadir_borracho(borracho, inicio) #poner un borracho en origen
    ejecutar_caminata(campo, borracho, distancia)

def ejecutar_caminata(campo, borracho, distancia):
    x_arreglo = []
    y_arreglo = []
    x_arreglo.append(campo.obtener_coordenada(borracho).x)
    y_arreglo.append(campo.obtener_coordenada(borracho).y)
    for _ in range(distancia):
        campo.mover_borracho(borracho) #se actualiza las coordenadas del borracho
        x_arreglo.append(campo.obtener_coordenada(borracho).x)
        y_arreglo.append(campo.obtener_coordenada(borracho).y)

    graficar(x_arreglo, y_arreglo)

def graficar(x, y):
    figura = figure()
    figura.line(x, y)
    show(figura)

if __name__ == '__main__':
    distancia = 1000000
    inicio = Coordenada(0,0)
    borracho = BorrachoTradicional('Angel')
    main(distancia, inicio, borracho)

solo tendrán que modificar distancia para hacer sus gráficas más grandes 😉

Esta es la gráfica con un millón de pasos

Esta caminata fue de 5000 pasos. Inicio punto negro, final punto rojo; abajo está el ajuste del código para este tipo de gráfica. Me tome 6 horas entre entender el código y hacer la modificación, pero valió la pena el proceso.

from borracho import BorrachoTradicional
from campo import Campo
from coordenada import Coordenada

from bokeh.plotting import figure, show

def caminata(campo, pasos, tipo_de_borracho):

    borracho = tipo_de_borracho(nombre='David')
    origen = Coordenada(0, 0)
    campo.anadir_borracho(borracho, origen)

    coordenadas_x=[]
    coordenadas_y=[]

    coordenadas_x.append(origen.x)
    coordenadas_y.append(origen.y)

    for _ in range(pasos):
        campo.mover_borracho(borracho)
        coordenadas_x.append(campo.obtener_coordenada(borracho).x)
        coordenadas_y.append(campo.obtener_coordenada(borracho).y)

    return (coordenadas_x, coordenadas_y)

def graficar(x, y,pasos):
    grafica = figure(title='Random Walks',x_axis_label='x axis', y_axis_label='y axis')
    grafica.line(x, y, legend_label='walk', color='yellowgreen',name='juan') #recorrido

    # gráfica la línea inicial de movimiento porque no se puede graficar un punto
    grafica.line(x[0:2],y[0:2],color='black',line_width=10)
    grafica.line(x[-3:-1],y[-3:-1],color='red',line_width=10) #punto final y final-1
    grafica.line(x[0:-1:pasos-1],y[0:-1:pasos-1]) #linea de punto inicial a punto final
    show(grafica)

def main(pasos, tipo_de_borracho):
    campo=Campo()
    coordenadas_x, coordenadas_y = caminata(campo, pasos, tipo_de_borracho)
    graficar(coordenadas_x, coordenadas_y,pasos)

if __name__ == '__main__':

    pasos = 5000
    main(pasos, BorrachoTradicional)

Creo que a esta parte del curso le hace falta una implementación antes de Caminos Aleatorios, algo más simple como simular una partida de dados o algún juego de mesa sencillo. Por mucho que David vaya guiando, no es una buena práctica dar brincos sensibles de complejidad. Me refiero a que para explicar este problema necesitaron 3 lecciones (de más de 10 minutos) cuando sus ejemplos previos son explicados, casi sin excepción, en 1 lección. Un problema explicado en 2 lecciones hubiera sido un salto más prudente, o explicar el mismo problema en diferentes capas de complejidad (por ejemplo, comenzar explicándolo de manera iterativa y después añadir POO), así los alumnos con bases sólidas previas podrían brincar a las lectures con POO y los que lo necesiten, podrían comenzar con el caso más sencillo.

En este tutorial el profesor explica todo pero haciendo una introducción partiendo de una solución sencilla que se entiende con facilidad, después en vídeos posteriores propone soluciones más sofisticadas. La solución está en javascript, pero el punto es la manera en que propone su approach:
Coding Challenge #52: Random Walker

Esa es mi opinión, con base en mi experiencia (también soy profesor).

Esta es mi solución a la variación solicitada en la lecture:

Haciéndole unos pequeños cambios a la implementación se pueden ver los caminos que harían n borrachos con k cantidad de pasos xD.

Para hacer la implementación decidí partir del objetivo central y hacerlo desde cero. Creo que así se puede entender mejor el propósito y la funcionalidad del algoritmo presentado en la clase.

¡Por fin! Han sido valiosos los apuntes y aportes de varios compañeros, especialmente compartiendo la manera en que generaron la gráfica del camino aleatorio del borracho. Confieso que hubo un momento en que me desanimé un poco. Sin embargo dejé pasar algunos días, vi videos de otros cursos y retomé el ejercicio. Finalmente tengo estas 2 gráficas del camino aleatorio, para los mismos parámetros, se ven 2 comportamientos aleatorios muy distintos.

En mi caso agregué 2 tipos de borrachos mas, uno muy mareado, que de repente no avanza es decir, una delta de (0,0) y otro que nunca va a la izquierda:

Me llamó la atención que al quitarle una dirección la curva se vuelve lineal.

De paso grafiqué los caminos:

Si alguien le sirve aquí mi código: https://github.com/raag/caminos_aleatorios

Borracho aguardientero.

Mi propuesta se llama BorrachoDoblado al cual tiene más probabilidad de moverse hacía arriba o hacía la derecha sumando una unidad a su coordenada actual. Sin embargo, cae en la opción de moverse hacía abajo o a la izquierda, se modificará en 2 unidades su coordenada actual.

class BorrachoDoblado(Borracho):

	def __init__(self, nombre):
		super().__init__(nombre)

	def camina(self):
		return random.choice([(0,1),(0,1),(0,-2),(1,0),(1,0),(-2,0)])

La gráfica resultante con distancias_de_caminata = 10000 y numero_de_intentos = 1000 es la siguiente:

Bueno, en mi caso: Pausa y a revisar todo lo que he aprendido de Python hasta ahora.

Este fue el camino de 2 borrachos con 1,000:

con 10,000:

con 1,000,000 de pasos:

2 noches para pasar de este video…

yo quebrandome la cabeza con tres borrachos simples y veo que hay quien saco gráficas que parecen mapas >.<

Hice el programa para que se moviera en tres dimensiones, relicé las graficas con matplotlib ya que es el que sé utilizar. Adjunto los gif de 10, 1000 y 10000 pasos.

100 pasos

1000 pasos

10000 pasos

porque comparten esos mapas con manchas si la cosa es una linea no mas. pasos vs distancia

Con 100000 pasos

He hecho todos los cursos de Data Science hasta acá, y para ser honesto, no entiendo nada

Ahora, un par de simulaciones más de izquierda a derecha respectivamente 100 mil y 1 millón de intentos:

import random, math
from bokeh.plotting import figure, show

class Borracho:

    def __init__(self, nombre):
        self.nombre = nombre


class BorrachoTradicional(Borracho):

    def __init__(self, nombre):
        super().__init__(nombre)

    def camina(self):
        return random.choice([(0, 1), (0, -1), (1, 0), (-1, 0)])


class Coordenada:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def mover(self, delta_x, delta_y):
        return Coordenada(self.x + delta_x, self.y + delta_y)

    def distancia(self, otra_coordenada):
        delta_x = self.x - otra_coordenada.x
        delta_y = self.x - otra_coordenada.y

        return math.sqrt(delta_x ** 2 + delta_y ** 2)


class Campo:

    def __init__(self):
        self.coordenadas_borrachos = {}

    def anadir_borracho(self, borracho: Borracho, coordenada: Coordenada):
        self.coordenadas_borrachos[borracho] = coordenada

    def mover_borracho(self, borracho: Borracho):
        delta_x, delta_y = borracho.camina()
        coordenada_actual = self.coordenadas_borrachos[borracho]
        nueva_coordenada = coordenada_actual.mover(delta_x, delta_y)
        self.coordenadas_borrachos[borracho] = nueva_coordenada

    def obtener_coordenada(self, borracho: Borracho):
        return self.coordenadas_borrachos[borracho]


def caminata(campo, borracho, pasos):
    x_arreglo = []
    y_arreglo = []
    inicio = campo.obtener_coordenada(borracho)
    x_arreglo.append(inicio.x)
    y_arreglo.append(inicio.y)
    for _ in range(pasos):
        campo.mover_borracho(borracho)
        donde_se_movio = campo.obtener_coordenada(borracho)
        x_arreglo.append(donde_se_movio.x)
        y_arreglo.append(donde_se_movio.y)


    graficar(x_arreglo, y_arreglo)
    return inicio.distancia(campo.obtener_coordenada(borracho))


def simular_caminata(pasos, numero_de_intentos, tipo_de_borracho):
    borracho = tipo_de_borracho(nombre='Benjamin') #Funcion agnostic al tipo
    origen = Coordenada(0, 0)
    distancias = []
    for _ in range(numero_de_intentos):
        campo = Campo()
        campo.anadir_borracho(borracho, origen)
        simulacion_caminata = caminata(campo, borracho, pasos)
        distancias.append(round(simulacion_caminata))

    return distancias

def graficar(x, y):
    grafica = figure(title='Camino Aleatorio Borrachos', x_axis_label = 'Pasos', y_axis_label='Distancia')
    grafica.line(x, y, legend ='Distancia Media')
    show(grafica)



def main(distancias_de_caminata, numero_de_intentos, tipo_de_borracho):
    distancias_media_por_caminata = []
    for pasos in distancias_de_caminata:
        distancias = simular_caminata(pasos, numero_de_intentos, tipo_de_borracho)
        print(len(distancias))
        distancia_media = round(sum(distancias) / len(distancias), 4)
        distancia_maxima = max(distancias)
        distancia_minima = min(distancias)
        distancias_media_por_caminata.append(distancia_media)
        print(f'{tipo_de_borracho.__name__} tuvo una caminata aleatoria de {pasos} pasos')
        print(f'La distancias media es {distancia_media}')
        print(f'La distancia max es {distancia_maxima}')
        print(f'La distancia min es {distancia_minima}')



if __name__ == '__main__':
    distancias_de_caminata = [10, 100, 1000, 10000]
    numero_de_intentos = 1

    main(distancias_de_caminata, numero_de_intentos, BorrachoTradicional)

Hola comunidad.

Para los que tengan problema con el entorno virtual en windows: https://platzi.com/tutoriales/1104-python/5883-entornos-virtuales-de-python-en-windows/

Hola a todos, les comparto mi grafica con 10,000 pasos. Esta mi subclase, el psicópata, en azul (toma valores aleatorios entre -1 y 1 para x y y) y el borracho tradicional del profesor (en rojo). A su vez el amarillo y el verde son cambinaciones de las xs y ys del borracho con el psicópata. Agradezco sus comentarios.

Estuvo chevere el reto, yo hice un borracho que no pueda ir hacia atras, me disculpan si el codigo se ve desordenado que no soy muy de python, aunque me gusta.

class NoReturnDrunk(Drunk):
	def __init__(self, name):
		self.last_move = (0, 0)
		super().__init__(name)

	def walk(self):
		choices = [(0, 1), (0, -1), (1, 0), (-1, 0)]
                choice_back = (self.last_move[0] * -1, self.last_move[1] * -1)
		if choice_back in choices:
			choices.remove(choice_back)

		self.last_move = random.choice(choices)
		return self.last_move

Basicamente guardo el ultimo movimiento del borracho, luego lo invierto (porque si avanza en X, echarse para atras seria retroceder en X, lo mismo con Y) y luego descarto esa opcion, de las opciones posibles de movimiento.

Esto es con 100 pasos:

1000 pasos:

10000 pasos:

Buenas les dejo mi aporte quize agregar un poco de color a todo esto!!
Las pruebas son de [100000, 10000, 1000, 100] con 100 intentos cada una.
También realice una clase aparte para manejar el grafico:

from bokeh.plotting import figure, show
import random

class Chart:

    def __init__(self, title, x_label,  y_label):
        self.chart = figure(title=title, x_axis_label=x_label, y_axis_label=y_label)

    def draw_line(self, x_axis, y_axis):
        colors = ['green', 'red', 'blue', 'yellow', 'orange', 'pink', 'violet', 'gray', 'black', 'brown']
        self.chart.line(x_axis, y_axis, color=random.choice(colors))

    def show_chart(self):
        show(self.chart)

Cada intento intento toma un color aleatorio de una lista dentro de la clase Chart:

Solo debemos cambiar la distancia por coordenadas.

Hice un tutorial para este curso, sobre una manera de implementar este proyecto, con muy pocas líneas de código, usando sólo 3 funciones cortas y una clase.

Hice 3 tipos de caminantes diferentes, basándome en piezas de ajedrez:

Torre: Se mueve hacia arriba, abajo, izquierda o derecha:


.
Alfil: Se mueve en diagnonal:


.
Reina: Se mueve en todas las direcciones:

Modifiqué la función para que tenga más avance en una sola dirección

En la simulación con igualdad de distancia de movimiento:
Con la nueva función:

También grafiqué el último camino recorrido en ambos casos.
Cuando los avances son iguales:
Y esto es cuando se cambia la magnitud del avance en una sola dirección

He decidido extender un poco el proyecto del profesor os adjunto mi codigo https://gitlab.com/emidev98/ai-and-ml/-/tree/master/random_paths

Termine hasta mareado despues de la clase XD

no me salio nada d esto, puta vida

Hola,

A la clase Borracho le agregue pesos a cada una de las coordenadas como se muestra en el siguiente código.

import random

class Borracho:

    def __init__(self, name):
        self.name = name

class BorrachoTradicional(Borracho):

    def __init__(self, name):
        super().__init__(name)

    def camina(self):
        elements = [(0, 1), (0, -1), (1, 0), (-1, 0)]
        weigths = [0.4, 0.3, 0.2, 0.1]
        return random.choices(elements, weigths)

Como se muestra en la siguiente gráfica el resultado de la gráfica dado los pasos dados.

En el caso de la distancia recorrida la gráfica no cambia su forma

Excelente curso hasta ahora. Aplique la misma lógica de David en Unity para simular el camino aleatorio de un enemigo.

El video: https://giphy.com/gifs/2rs7Esu4W8eenQlNHw/html5

public class EnemyController : MonoBehaviour
{
    ....
    private Animator _animator;
    private Rigidbody2D _rb;

    private Vector2[] _path =
    {
        Vector2.left,
        Vector2.right,
        Vector2.up,
        Vector2.down
    };
    void Update()
    {
        timeToMoveCounter -= Time.deltaTime;

        if(timeToMoveCounter < 0)
        {
            Instantiate(fire1, this.transform.position, Quaternion.identity);
            
            int randonIndex = Random.Range(0, _path.Length);
            _movement = _path[randonIndex];
            
            _rb.velocity = _movement * speed;

            _animator.SetFloat("horizontal", _movement.x);
            _animator.SetFloat("vertical", _movement.y);

            timeToMoveCounter = timeToMove;


        }

        
    }

}

Acá dejo las clases con la modificación a borracho en que tendrá el cuarenta por ciento (40 %) de veces, la posibilidad de ir hacia arriba, repitiendo las cordenadas x = 0, y = 1. Como se puede ver en las gráficas al final de este largo post, la distancia recorrida en promedio es mucho mayor y así mismo es mucho menor la posibildiad de volver al punto de partida.

Clase borracho modificada:

import random

class Borracho:

    def __init__(self, nombre):
        self.nombre = nombre

class BorrachoTradicional(Borracho):

    def __init__(self, nombre):
        super().__init__(nombre)

    def camina(self):
        return random.choice([(0, 1), (0, 1), (0, -1), (1, 0), (-1, 0)])

Clase Campo:

class Campo:

    def __init__(self):
        self.coordenadas_de_borrachos = {}

    def anadir_borracho(self, borracho, coordenada):
        self.coordenadas_de_borrachos[borracho] = coordenada

    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

    def obtener_coordenadas(self, borracho):
        return self.coordenadas_de_borrachos[borracho]

Clase Coordenada:

class Coordenada:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def mover(self, delta_x, delta_y):
        return Coordenada(self.x + delta_x, self.y + delta_y)

    def distancia(self, otra_coordenada):
        delta_x = self.x - otra_coordenada.x
        delta_y = self.y - otra_coordenada.y

        return (delta_x**2 + delta_y**2)**0.5 # raiz cuadrada del cuadrado de los catetos

Camino aleatorio:

from borracho import BorrachoTradicional
from campo import Campo
from coordenada import Coordenada
from bokeh.plotting import figure, show

def caminata(campo, borracho, pasos):
    inicio = campo.obtener_coordenadas(borracho)

    for _ in range(pasos):
        campo.mover_borracho(borracho)

    return inicio.distancia(campo.obtener_coordenadas(borracho))

def simular_caminata(pasos, numero_de_intentos, tipo_de_borracho):
    borracho = tipo_de_borracho(nombre = 'David')
    origen = Coordenada(0, 0)
    distancias = []
    for _ in range(numero_de_intentos):
        campo = Campo()
        campo.anadir_borracho(borracho, origen)
        simulacion_caminata = caminata(campo, borracho, pasos)
        distancias.append(round(simulacion_caminata, 1))

    return distancias

def graficar(x, y):
    grafica = figure(title='Camino aleatorio', x_axis_label = 'pasos', y_axis_label = 'distancia')
    grafica.line(x, y, legend_label='distancia media')

    show(grafica)

def main(distancias_de_caminata, numero_de_intentos, tipo_de_borracho):
    distancias_media_por_caminata = []

    for pasos in distancias_de_caminata:    
        distancias = simular_caminata(pasos, numero_de_intentos, tipo_de_borracho)
        distancia_media = round(sum(distancias) / len(distancias), 4)
        distancia_maxima = max(distancias)
        distancia_minima = min(distancias)
        distancias_media_por_caminata.append(distancia_media)
        print(f'{tipo_de_borracho.__name__} tuvo una caminata aleatoria de {pasos} pasos')
        print(f'Media = {distancia_media}')
        print(f'Máxima = {distancia_maxima}')
        print(f'Mínima = {distancia_minima}')

    graficar(distancias_de_caminata, distancias_media_por_caminata)

if __name__ == "__main__":
    distancias_de_caminata = [10, 100, 1000, 10000]
    numero_de_intentos = 100

    main(distancias_de_caminata, numero_de_intentos, BorrachoTradicional)

Gráfica inicial sin modificación en Borracho:

Gráfica inicial con modificación en Borracho:

el mio es un borracho que va hacia el norte jajaja

def camina(self):
        return random.choice([(0, 1), (0, -1), (1.5, 0), (-1, 0)])```

depronto la gráfica se desenreda

Alfin después de ver tantas veces esto, y leer varios comentarios:

con 1000000 pasos

1 millón de pasos:


from borracho import BorrachoTradicional
from campo import Campo
from coordenada import Coordenada
from bokeh.plotting import figure, show

def caminata(campo, borracho, pasos):    
    
    inicio = campo.obtener_coordenada(borracho)
    x1=[]
    y1=[]    

    for _ in range(pasos):
        campo.mover_borracho(borracho)
        x1.append(campo.obtener_coordenada(borracho).x)
        y1.append(campo.obtener_coordenada(borracho).y)
    
    graficar(x1,y1)
    return inicio.distancia(campo.obtener_coordenada(borracho))
    

def simular_caminata(pasos, numero_de_intentos, tipo_de_borracho):
    borracho = tipo_de_borracho(nombre='David')
    origen = Coordenada(0,0)
    distancias = []

    for _ in range(numero_de_intentos):
        campo= Campo()
        campo.anadir_borracho(borracho, origen)
        simulacion_caminata = caminata(campo,borracho,pasos)
        distancias.append(round(simulacion_caminata, 1))

    return distancias

def graficar(x,y):
    grafica = figure(title='Camino aleatorio',x_axis_label='X',y_axis_label='Y')
    grafica.line(x, y, legend_label='Caminata')

    show(grafica)

def main(distancias_de_caminata,numero_de_intentos,tipo_de_borracho):

    distancia_media_por_caminata=[]
    for pasos in distancias_de_caminata:
        distancias = simular_caminata(pasos, numero_de_intentos, tipo_de_borracho)
        distancia_media = round(sum(distancias)/len(distancias),4)
        distancia_maxima = max(distancias)  
        distancia_minima = min(distancias)
        distancia_media_por_caminata.append(distancia_media)
        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}')
    #graficar(distancias_de_caminata,distancia_media_por_caminata)

if __name__== '__main__':
    
    distancias_de_caminata = [1000000]
    numero_de_intentos = 1

    main(distancias_de_caminata,numero_de_intentos, BorrachoTradicional)


![](

Hice mi propia version!! added some new features.
Si gustan pueden ir a clonares el repo y probarlo. Me haria ilusion. acepto pull requeest.

repo en github

Hola amigos,

Les comparto mi resultado obtenido para un recorrido de 10 millones de pasos así como la implementación de mi código en Python (la cual no varía mucho de varias soluciones aquí descritas). En rojo muestro el punto inicial (0,0) así como el punto final. El archivo PNG escrito con bokeh pesaba 96MB así que decidí tomarle un screenshot para poder subirlo sin problemas aquí 😅

Código implementado:

from borracho import BorrachoTradicional, BorrachoDoble
from campo import Campo
from coordenada import Coordenada
from bokeh.plotting import figure, show
from bokeh.io import export_png

def graficar(x, y):
    grafica = figure(title = 'Camino aleatorio', x_axis_label='pasos', y_axis_label='distancia media')
    grafica.line(x,y, legend_label='camino recorrido')
    
    inicio_final_x = [x[0], x[-1]]
    inicio_final_y = [y[0], y[-1]]
    grafica.circle(inicio_final_x, inicio_final_y, size=7, fill_color="red")
    export_png(grafica, filename="camino_borracho_10M.png")

def caminata(campo, borracho, pasos):
    inicio = campo.obtener_coordenada(borracho)

    for _ in range(pasos):
        campo.mover_borracho(borracho)
    
    return inicio.distancia(campo.obtener_coordenada(borracho))

def simular_caminata(pasos, tipo_de_borracho):
    borracho = tipo_de_borracho(nombre = 'David')
    origen = Coordenada(0,0)
    campo = Campo()
    campo.anadir_borracho(borracho, origen)
    arreglo_coords_x = []
    arreglo_coords_y = []

    arreglo_coords_x.append(campo.obtener_coordenada(borracho).x)
    arreglo_coords_y.append(campo.obtener_coordenada(borracho).y)

    for _ in range(pasos):
        campo.mover_borracho(borracho)
        arreglo_coords_x.append(campo.obtener_coordenada(borracho).x)
        arreglo_coords_y.append(campo.obtener_coordenada(borracho).y)
    
    return (arreglo_coords_x, arreglo_coords_y)

def main(numero_de_pasos, tipo_de_borracho):
    arreglo_x, arreglo_y = simular_caminata(numero_de_pasos, tipo_de_borracho)
    graficar(arreglo_x, arreglo_y)

if __name__ == '__main__':
    numero_de_pasos = 10000000
    main(numero_de_pasos, BorrachoTradicional)```

![](

con 1000000

 random.choice([(0,2), (0,-2), (0,1), (0,-1), (2,0), (-2,0), (1,0), (-1,0)])

Yo el único cambio que hice es darle al borracho intención de irse derechito. Asi que e duplique el peso o probabilidad de irse en (0,1), el arreglo queda:

class BorrachoConIntencion(Borracho):
	def __init__(self,nombre):
		super().__init__(nombre)
	
	def camina(self):
		return random.choice([(0,1),(0,1),(0,-1),(1,0),(-1,0)])

La gráfica de los pasos que dio refleja su intención de irse derecho:

Aumente las opciones del random choice para que el Boraacho pudiera moverse en 8 direcciones y sea más libre. Al parecer o vario mucho a cuando solo podía moverse en 4.

class BorrachoTodasDirecciones(Borracho):

    def __init__(self, nombre):
        super().__init__(nombre)

    
    def camina(self):
        return random.choice([(0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1)])

Generé otra subclase Borracho que avanza más de lo que retrocede. El crecimiento de la distancia media fue más líneal sin tener que romperse un crecimiento más acelerado.

class BorrachoAvanzaMasRetrocedeMenos(Borracho):

    def __init__(self, nombre):
        super().__init__(nombre)


    def camina(self):
        return random.choice([(0, 4), (0, -2), (4, 0), (-2, 0)])

Buenas.
Yo implementé un borracho con más probabilidad de ir hacia el norte:
class BorrachoNorte(Borracho):

def __init__(self, nombre):
    super().__init__(nombre)

def camina(self):
    return random.choice([(0, 1), (0, -1), (1, 0), (1, 0), (-1, 0)]) #Con más probabilidad de ir hacia el norte

y cambia mucho los valores medios:
BorrachoNorte caminata aleatoria de 10 pasos
Media = 3.435
Max = 8.2
Min = 0.0
BorrachoNorte caminata aleatoria de 100 pasos
Media = 20.688
Max = 47.0
Min = 3.2
BorrachoNorte caminata aleatoria de 1000 pasos
Media = 201.308
Max = 272.4
Min = 143.2
BorrachoNorte caminata aleatoria de 10000 pasos
Media = 1998.083
Max = 2205.8
Min = 1809.3

Slds

mi borracho se murió apenas ejecuté el código

Se genera el ambiente virtual.

Codigo base de la clase:

import random
from bokeh.plotting import figure, show


class Borracho:

    def __init__(self, nombre):
        self.nombre = nombre

class BorrachoTradicional(Borracho):

    def __init__(self, nombre):
        super().__init__(nombre)

    def camina(self):
        return random.choice([(0, 1), (0, -1), (1, 0), (-1, 0)])

class Campo:
    def __init__(self):
        self.coordenadas_de_borrachos = {}

    def anadir_borracho(self, borracho, coordenada):
        self.coordenadas_de_borrachos[borracho] = coordenada
    
    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

    def obtener_coordenadas(self, borracho):
        return self.coordenadas_de_borrachos[borracho]

class Coordenada:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def mover(self, delta_x, delta_y):
        return Coordenada(self.x + delta_x, self.y + delta_y)

    def distancia(self, otra_coordenada):
        delta_x = self.x - otra_coordenada.x 
        delta_y = self.y - otra_coordenada.y 

        return (delta_x**2 + delta_y**2)**0.5


def caminata(campo, borracho, pasos):
    inicio = campo.obtener_coordenadas(borracho)

    for _ in range(pasos):
        campo.mover_borracho(borracho)

    return inicio.distancia(campo.obtener_coordenadas(borracho))

def simular_caminata(pasos, numero_de_intentos, tipo_de_borracho):
    borracho = tipo_de_borracho(nombre='David')
    origen = Coordenada(0, 0)
    distancias = []

    for _ in range(numero_de_intentos):
        campo = Campo()
        campo.anadir_borracho(borracho, origen)
        simulacion_caminata = caminata(campo, borracho, pasos)
        distancias.append(round(simulacion_caminata, 1))

    return distancias

def graficar(x, y):
    grafica = figure(title='Camino aleatorio', x_axis_label='pasos', y_axis_label='distancia')
    grafica.line(x, y, legend='distancia media')

    show(grafica)

def main(distancias_de_caminata, numero_de_intentos, tipo_de_borracho):
    distancias_media_por_caminata = []


    for pasos in distancias_de_caminata:
        distancias = simular_caminata(pasos, numero_de_intentos, tipo_de_borracho)
        distancia_media = round(sum(distancias) / len(distancias), 4)
        distancia_maxima = max(distancias)
        distancia_minima = min(distancias)
        distancias_media_por_caminata.append(distancia_media)
        print(f'{tipo_de_borracho.__name__} caminata aleatoria de {pasos}')
        print(f'Media = {distancia_media}')
        print(f'Max = {distancia_maxima}')
        print(f'Min = {distancia_minima}')
    graficar(distancias_de_caminata, distancias_media_por_caminata)

if __name__ == '__main__':
    distancias_de_caminata = [10, 100, 1000, 10000]
    numero_de_intentos = 100

    main(distancias_de_caminata, numero_de_intentos, BorrachoTradicional)```

Problema:
Suponga que ud. sale de su casa a comprar un medicamento, para una persona a la cual quiere mucho,y desea volver en el m ́ınimo tiempo posible. Si no lo compra, la persona sufrir ́a un perjuicio en su salud,cosa que por supuesto ud. no desea. En la ciudad hayNfarmacias.El tiempo de viaje para ir desde la farmaciaia la farmaciajestij[s]i, j∈0, . . . , N, donde la “farmacia0” representa su casa.El medicamento que ud. desea comprar es muy escaso y es posible que no se encuentre en todas lasfarmacias. Existe una probabilidad a prioripique el medicamento est ́e en la farmaciai. La presencia delmedicamento en 2 farmacias cualesquiera son v.a. dependientes en probabilidad: si ud. visita algunasfarmacias y encuentra que el medicamento no est ́a disponible en ellas, esa informaci ́on modifica lasprobabilidades de encontrarlo en las restantes (en general disminuye la probabilidad de encontrarlo enlas que est ́an cerca de una farmacia donde no est ́a el medicamento). Vale decir, la probabilidad deencontrarlo en la farmaciaies funci ́on del itinerario previo.Entrar a una farmacia a preguntar por el medicamento toma un tiempo deτ[s].

  1. ¿Cuantas farmacias visitar ud a lo sumo?
  2. Formule un modelo de programaci on dinamica que permita decidir su itinerario de manera deminimizar el valor esperado del tiempo hasta volver a su casa con el medicamento.

Todavia no estoy muy seguro del 2, pense tomar los recorridos que menos tomaron viajes y ver cual era la primeras droguerias que era necesario visitar, cualquier aporte o mejora seria de gran ayuda 😄

# -*- coding: utf-8 -*-
"""
Created on Sat May 30 09:03:24 2020

@author: Daniel Galvis
"""
import pandas as pd
import os
from random import randint,random,uniform
from bokeh.plotting import figure,show

class Farmacia:
    def __init__(self,nombre,proba,cordx,cordy):
        self.nombre=nombre
        self.proba=proba
        self.cordx=cordx
        self.cordy=cordy
        self.visit=0
        
    def distancia(self,cordx_m,cordy_m):
        dist=((self.cordx-cordx_m)**2+(self.cordy-cordy_m)**2)**(1/2)
        return dist

class Persona:
    def __init__(self,nombre,cordx,cordy):
        self.nombre=nombre
        self.cordx=cordx
        self.cordy=cordy
        self.distancia=0
        self.farmacia='Casa'
        
    def mover(self,nombre,cordx_m,cordy_m):
        recorrido=((self.cordx-cordx_m)**2+(self.cordy-cordy_m)**2)**(1/2)
        self.distancia=self.distancia+recorrido
        self.farmacia=nombre
        self.cordx=cordx_m
        self.cordy=cordy_m
        
    def escoger(self,randomico,listafarmacias):
        listafarmacias[randomico-1].visit=1
        farmacia_pivote=listafarmacias[randomico-1]
        return farmacia_pivote.nombre,farmacia_pivote.cordx,farmacia_pivote.cordy
    
#Extraer los datos del dataframe y convertirlos en una lista con la variable clase
def leerdatos(direccion,documento):
    os.chdir(direccion)
    dataframe_farmacias=pd.read_csv(documento,sep=';',header=None)
    fil,col=dataframe_farmacias.shape
    listafarmacias=[]
    for i in range(fil):
        farmaciapiv=Farmacia(dataframe_farmacias.iloc[i,0],dataframe_farmacias.iloc[i,3],dataframe_farmacias.iloc[i,1],dataframe_farmacias.iloc[i,2])
        listafarmacias.append(farmaciapiv)
    return listafarmacias,fil


def reduccionproba(listafarmacias,probabilidad,cordx,cordy):
    for i in listafarmacias:
        if i.visit==1:
            continue
        else:
            distancia=i.distancia(cordx,cordy)
            if distancia > 10:
                continue
            else:
                i.proba=i.proba*probabilidad
    pass
        
#Función main
def main(nombre,cordinicialx,cordinicialy,listafarmacias,fil):
    contador=0
    listamovx=[]
    listamovy=[]
    persona=Persona(nombre,cordinicialx,cordinicialy)
    listamovx.append(cordinicialx)
    listamovy.append(cordinicialy)
    condicion=False
    while condicion==False:
        farmacia,cordx,cordy=persona.escoger(randint(0,fil),listafarmacias)
        if farmacia==False:
            if contador>len(listafarmaciasi):
                return None,listamov
            continue
        else:
            listamovx.append(cordx)
            listamovy.append(cordy)
            persona.mover(farmacia,cordx,cordy)
            probabilidad=listafarmacias[int(persona.farmacia[9:])-1].proba
            if random()>probabilidad:
                reduccionproba(listafarmacias,probabilidad,cordx,cordy)
                continue
            else:
                condicion=True
        contador+=1        
    listamovx.append(cordinicialx)
    listamovy.append(cordinicialy)
    persona.mover("Casa", cordinicialx, cordinicialy)
    return persona.distancia,listamovx,listamovy


def graficar(x,y,nombre,intento):
    nombre_grafica=f'Recorrido de {nombre} intento {intento}'
    grafica=figure(title=nombre_grafica,x_axis_label='Coordenada x', y_axis_label='Coordenada y')
    grafica.step(x,y, legend="Distancia media")
    show(grafica)
    
    
if __name__=='__main__':
    #__________DATOS INICIALES_______________
    nombre="Daniel"
    cordenada_inicial_x=0
    cordenada_inicia_y=0
    intentos=10000
    distancias=[]
    listamovtotalesx=[]
    listamovtotalesy=[]
    direccion="D:/Documentos/Cursos_Daniel_2020/Cursos_Python/4_Platzi_Course_dinamicayestocastica"
    documento='Farmaciasexcel.csv'
    listafarmacias,fil=leerdatos(direccion,documento)
    listafarmacias_inicial=listafarmacias
    #________________________________________
    i=0
    while i<intentos:
        listafarmacias=listafarmacias_inicial
        dist,listamovx,listamovy=main(nombre,cordenada_inicial_x,cordenada_inicia_y,listafarmacias,fil)
        distancias.append(dist)
        listamovtotalesx.append(listamovx)
        listamovtotalesy.append(listamovy)
        i+=1
        
    distanciatotal=sum(distancias)/len(distancias)
    print(f'La persona {nombre} recorrio una distancia promedio de {distanciatotal} km para encontrar su medicina')
    
    intento_a_graficar=63
    graficar(listamovtotalesx[intento_a_graficar],listamovtotalesy[intento_a_graficar],nombre,intento_a_graficar)
    
    media_de_viajes=0
    for i in listamovtotalesx:
        media_de_viajes=media_de_viajes+len(i)
        
    media_de_viajes=int(media_de_viajes/len(listamovtotalesx))
    print(f'La media de viajes es {media_de_viajes}')

Mi gráfica para los movimientos del borracho con 10mm de pasos

Dejo código del reto con comentarios:

![](

'''
Este es el programa principal, desde este punto se crearan los borracho
Se indicacara cuando se debe mover
Y se actualizaran las posiciones en el campo
Para esta aplicación es necesario crear un ambiente virtual
python3 -m venv env
Abrirlo en Windows
source env/Scripts/activate
Si usa linux Scripts se remplaza por bin
Instalar bokeh para la libreria grafica
pip instal bokeh
'''
#Para esto primero importamos nuestras clases (los programas que creamos en la calse anterior)
#Primiero se indica el nombre del archivo y luego la clase
from bokeh.plotting import figure, show, output_file
from borracho import BorrachoTradicional, BorrachoNortenio, BorrachoSurenio
from coordenada import Coordenada
from campo import Campo

#Funcion que hace que el borracho se desplace
def caminata(campo, borracho, pasos):
    #Obtenemos las coordenadas del borracho
    inicio = campo.obtenerCoordenada(borracho)
    for _ in range(pasos):
        #Esta función es la que hace que el borracho se mueva
        campo.mover_borracho(borracho)
    #Retornamos la ultima posición del borracho
    return inicio.distancia(campo.obtenerCoordenada(borracho))
    
#Inicialiazamos nuestras variables
def simular_caminata(pasos, numeroDeIntentos, tipoBorracho):
    #Crea un nuevo borracho
    borracho = tipoBorracho(nombre = 'David')
    #Creamos el origen del borracho en el campo
    origen = Coordenada(0,0)
    #Variable para guardar las distancias
    distancias = []
    #Con este ciclo simulamos una caminata en varias ocasiones un total de 100
    for _ in range(numeroDeIntentos):
        #Creamos un campo para desplazar el borracho, un campp por 
        #cada intento
        campo = Campo()
        #Añadimos el borracho al campo e indicamos cual es su posicion
        campo.anadir_borracho(borracho, origen)
        #caminata retorna un valor para cada cantidad de pasos
        #que deseamos desplazar el borracho
        simulacion_caminata = caminata(campo, borracho, pasos)
        #Cada distancia se guarda en un arreglo de distancias
        distancias.append(round(simulacion_caminata, 1))

    return distancias
    
#Función para graficar un borracho a la vez, esta comentada 
#si la activas se genera una grafica cada llamada
''' def graficar(x,y,tipo_borracho):
    #Para graficar en una ventana html
    output_file('CaminoAleatrio.html')
    #Crea la ventana de tipo grafica
    grafica = figure(title='Camino aleatorio', x_axis_label='Pasos', y_axis_label='Distancia')
    #Hace una grafica de tipo linea con los puntos X e Y
    leyenda = 'Distancia Media ' + tipo_borracho.__name__
    grafica.line(x, y, legend=leyenda)
    #Pinta la grafica en la ventana
    show(grafica) '''

#Función para graficar
def graficaSimultanea(datos1, datos2, datos3):
    x1 = list(datos1.keys())
    y1 = list(datos1.values())
    x2 = list(datos2.keys())
    y2 = list(datos2.values())
    x3 = list(datos3.keys())
    y3 = list(datos3.values())
    #Para graficar en una ventana html
    output_file('CaminoAleatrio.html')
    #Crea la ventana de tipo grafica
    grafica = figure(title='Camino aleatorio', x_axis_label='Pasos', y_axis_label='Distancia')
    #Hace una grafica de tipo linea con los puntos X e Y
    grafica.line(x1, y1, legend='Distancia Borracho Tradicional', color= 'red')
    grafica.line(x2, y2, legend='Distancia Borracho Surenio', color= 'blue')
    grafica.line(x3, y3, legend='Distancia Borracho Nortenio', color= 'orange')
    #Pinta la grafica en la ventana
    show(grafica)


#Main
def main(distancia_De_Caminata, numeroDeIntentos, tipo_borracho):
    #Este array guardara las diferentes distancias que se ejecuten
    distancia_media_por_caminata = []
    #Retorno un diccionario con los pasos y distancias recorridas
    movimientos = {}
    #Este ciclo me ayuda a hacer que el borracho se mueva
    #por las 4 distancias que deseamos se mueva
    for pasos in distancia_De_Caminata:
        #Retorna un arreglo de distancias por cada simulacion
        distancia = simular_caminata(pasos, numeroDeIntentos, tipo_borracho)
        #Medida de la media de distancia recorrida
        distanciaMedia = round(sum(distancia) / len(distancia), 4)
        distancia_media_por_caminata.append(distanciaMedia)
        #Maxima distancia
        distanciaMaxima = max(distancia)
        #Minima distancia
        distanciaMinima = min(distancia)
        #Imprimimos los resultados para nuestro borracho
        print(f'{tipo_borracho.__name__} caminata aleatoria de {pasos} pasos")')
        print(f'Media  = {distanciaMedia}')
        print(f'Maxima = {distanciaMaxima}')
        print(f'Minima = {distanciaMinima}')
        #Lleno el diccionario para graficarlo
        movimientos[pasos] = distanciaMedia
    #Si activas las funcion para graficar de una en una en esta linea se llama la función
    #graficar(distancia_De_Caminata, distancia_media_por_caminata,tipo_borracho)
    return movimientos
    

#Primero generamos las lineas de comando para que el programa
#se ejecute en la linea de comandos (la terminal)
if __name__ == '__main__':
    #Tendremos cuatro caminatas que simular
    #Cada numero del array representa el numero de pasos
    #que caminara el borracho
    distancia_De_Caminata = [10, 100, 1000, 10000]
    #Para ver una aproximacion del resultado se corre varias
    #veces esta simulacion 100
    numeroDeIntentos = 100
    #La funcion main es la que corre el programa. Has de cuenta que
    #es el play del programa, por eso recibe todos los datos necesarios
    #para crear un borracho, medir su primer posicion, actualizar al mover
    #y ubicarlo en el campo. Veamos la simulacion para 3 borrachos
    borracho1 = main(distancia_De_Caminata, numeroDeIntentos, BorrachoTradicional)
    borracho2 = main(distancia_De_Caminata, numeroDeIntentos, BorrachoSurenio)
    borracho3 = main(distancia_De_Caminata, numeroDeIntentos, BorrachoNortenio)
    #Llamo la funcion para obtener los resultados de las tres simulaciones simultaneas
    graficaSimultanea(borracho1, borracho2, borracho3)

  • Tipos de borracho
#Clase para inicializar un borracho
import random
class Borracho:
    def __init__(self, nombre):
        self.nombre = nombre
#Es la extensión que hace que un borracho se desplace entr cuatro coordenadas
class BorrachoTradicional(Borracho):
    def __init__(self, nombre):
        super().__init__(nombre)
    
    def camina(self):
        #random.choice() escoge aleatoriamente entre una estructura 
        #iterable en este caso un arreglo con cuatro coordenadas
        return random.choice([(1,0),(0,1),(-1,0),(0,-1)])

#Creo un borracho que tenga probabilidad de ir hacia el sur
class BorrachoSurenio(Borracho):
    def __init__(self, nombre):
        super().__init__(nombre)
    
    def camina(self):
        #Tiene 2/5 de posibilidad de ir hacia el sur
        return random.choice([(1,0),(0,1),(-1,0),(0,-1),(0,-1)])

#Creo un borracho que tenga probabilidad de ir hacia el norte
#Creo un borracho que tenga probabilidad de ir hacia el sur
class BorrachoNortenio(Borracho):
    def __init__(self, nombre):
        super().__init__(nombre)
    
    def camina(self):
        #Tiene 2/5 de posibilidad de ir hacia el norte
        return random.choice([(1,0),(0,1),(-1,0),(0,-1),(0,1)])

Después de analizar un rato las clases puede entender bien como funciona, recomiendo empezar a revisar las clases antes del archivo que tiene el método principal, y después la clase principal donde se encuentra el main.

Hola, Alguien me podría indicar cual es la acción equivalente de ($ cd camino_aleatorio/) de Linux. En windows 8, no he podido avanzar. Si alguien me puede ayudar estoy profundamente agradecido.

Les comparto mi ejemplo:

Resultado:

from borracho import BorrachoTradiccional
from campo import Campo
from coordenada import Coordenada
from bokeh.plotting import figure, show


def caminata(campo, borracho, pasos):
    
    inicio = campo.obtener_coordenada(borracho)

    for _ in range(pasos):
        campo.mover_borracho(borracho)

    return inicio.distancia(campo.obtener_coordenada(borracho)), campo.obtener_coordenada(borracho)


def simular_caminata(pasos, numero_de_intentos, tipo_de_borracho):
    
    borracho = tipo_de_borracho(nombre='Yerson')
    origen = Coordenada(0, 0)
    distancia = []
    coordenada = []

    # _ en el for le estamos diciendo que no vamos a usar la variable, solo nos interesa la iteración
    for _ in range(numero_de_intentos):
        campo = Campo()
        campo.anadir_borracho(borracho, origen)
        simulacion_caminata, simulacion_coordenadas = caminata(campo, borracho, pasos)
        distancia.append(round(simulacion_caminata, 1)) # que no tenga decimal
        coordenada.append((simulacion_coordenadas.x, simulacion_coordenadas.y))

    
    return distancia, coordenada


def graficar(x, y):
    grafica = figure(title='Camino de Borrachos', x_axis_label='Pasos', y_axis_label='Distancia')
    grafica.line(x, y, legend='Distanacia media')

    show(grafica)


def main(distancia_de_caminata, numero_de_intentos, tipo_de_borracho):

    # distancias_media_por_caminata = []
    coordenada_x = []
    coordenada_y = []
    
    for pasos in distancia_de_caminata:
        distancias, coordenada = simular_caminata(pasos, numero_de_intentos, tipo_de_borracho)
        distancia_media = round(sum(distancias) / len(distancias), 4) # obtener solo 3 decimales
        distancia_maxima = max(distancias)
        distancia_minima = min(distancias)

        # distancias_media_por_caminata.append(distancia_media)
        # coordenada_x.append(coordenada.x)
        # coordenada_x.append(coordenada.y)

        for x in coordenada:
            coordenada_x.append(x[0])
            coordenada_y.append(x[1])

        print(f'{tipo_de_borracho.__name__} caminata aleotoria de {pasos} pasos') #.__name__ devuelve el nombre de la clase
        print(f'Media \t=\t {distancia_media}')
        print(f'Max \t=\t {distancia_maxima}')
        print(f'Min \t=\t {distancia_minima}')

    #graficar(distancia_de_caminata, distancias_media_por_caminata)
    graficar(coordenada_x, coordenada_y)


if __name__ == '__main__':
    distancia_de_caminata = [200000] # [10, 100, 1000, 10000]
    numero_de_intentos = 1000

    main(distancia_de_caminata, numero_de_intentos, BorrachoTradiccional)

Unas clases bastante pesadas realmente, costó mucho seguir el flujo. Recuerden que hay maneras diferentes de acercarse al problema.

https://www.youtube.com/watch?v=BfS2H1y6tzQ En este enlace hay una explicación al problema de los random walks con un enfoque diferente.

Adjunto mis gráficas con 10, 100, 1000, 10000 y 100000 pasos:

Con ayuda de los aportes y del profesor, les comparto mi resultado. Es el camino de un borracho tradicional con una distancia de 10000000 (10 millones) de pasos. La profundidad es increíble y el odio de mi CPU y Ram al curso también.❤

Este es el borracho de derecha (sí, doble sentido político). Está sesgado hacia x positivo.

class BorrachoDeDerecha(Borracho):

    def __init__(self, nombre):
        super().__init__(nombre)

    def camina(self):
        return random.choice([
                (0,0.2),
                (0,-0.2),
                (0.4,0),
                (-0.2,0)
        ])

![](

Corrí los siguientes comandos en el terminal para poder ejecutar bokeh en windows:

PS D:\18.PLATZI\1.INTELIGENCIA ARTIFICIAL\PRUEBA> py -m venv env
PS D:\18.PLATZI\1.INTELIGENCIA ARTIFICIAL\PRUEBA> cd env
PS D:\18.PLATZI\1.INTELIGENCIA ARTIFICIAL\PRUEBA\env> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
PS D:\18.PLATZI\1.INTELIGENCIA ARTIFICIAL\PRUEBA\env> cd Srcripts
PS D:\18.PLATZI\1.INTELIGENCIA ARTIFICIAL\PRUEBA\env\Scripts> .\activate
(env) PS D:\18.PLATZI\1.INTELIGENCIA ARTIFICIAL\PRUEBA\env\Scripts> pip install bokeh
(env) PS D:\18.PLATZI\1.INTELIGENCIA ARTIFICIAL\PRUEBA\env\Scripts> cd…

No encontré como poner las manchas, pero hice las lineas; aquí mi reto:

![](

Si alguién esta trabajando en Deepnote le paso este código que encontré para que puedan graficar.

# Este código es para ejecutarse en deepnote
from bokeh.plotting import figure, output_file, save
from IPython.display import IFrame
from IPython.core.display import display, HTML
import tempfile

def bokeh_deepnote_show(plot):
    tmp_output_filename = tempfile.NamedTemporaryFile(suffix='.html').name
    output_file(tmp_output_filename)
    save(plot)

    f = open(tmp_output_filename, "r")
    display(HTML(f.read()))

# Ejemplo de uso
#p = figure(title="Bokeh test", plot_width=300, plot_height=300)
#p.line(x_vals, y_vals, line_width=2)
#bokeh_deepnote_show(p)

Es una buena práctica, lograr calcular el promedio, mínimo y máximo.

Espero este bien. Cuencano por Ecuador/Cuenca.

from bokeh.plotting import figure, show
from borracho import BorrachoTradicional, BorrachoCuencano
from campo import Campo
from coordenada import Coordenada
    

def graficar(x,y):
    grafica = figure(title='Camino de borracho', x_axis_label='pasos', y_axis_label='distancia')    
    grafica.line(x, y, legend_label='Distancia media' )
    show(grafica)  


def caminata(campo, pasos, borracho):
    inicio = campo.obtener_coordenada(borracho)
    for _ in range(pasos):
         campo.mover_borracho(borracho)
    return  inicio.distancia(campo.obtener_coordenada(borracho))
    
        
def simular_caminata(pasos, numero_de_intentos, borracho):
    coordenada_x_y = []
    borracho = borracho(nombre="William")
    origen = Coordenada(0,0)
    for _ in range(numero_de_intentos):
        campo = Campo()
        campo.agregar_borracho(borracho, origen)
        generador_coordenadas = caminata(campo, pasos, borracho)
        coordenada_x_y.append(generador_coordenadas)
    return coordenada_x_y
   

def main(distancias_de_caminata,numero_de_intentos,borracho):
    coordenadas_x= []
    coordenadas_y = []
    for pasos in distancias_de_caminata:
        coordenadas_aleatorias = simular_caminata(pasos, numero_de_intentos, borracho)
        distancia_maxima = max(coordenadas_aleatorias)
        distancia_minima = min(coordenadas_aleatorias)
        distancia_media = round(sum(coordenadas_aleatorias) / len(coordenadas_aleatorias), 4)
        print(f'{borracho.__name__} caminata aleatoria de {pasos}')
        print(f'La distancia media = {distancia_media}')
        print(f'La distancia maxima = {distancia_maxima}')
        print(f'La distancia minima = {distancia_minima}')
    for i in range(1, len(coordenadas_aleatorias), 2):
        coordenadas_y.append(coordenadas_aleatorias[i])
    for i in range(0, len(coordenadas_aleatorias), 2):
        coordenadas_x.append(coordenadas_aleatorias[i]) 
    graficar(coordenadas_x, coordenadas_y)


if __name__ == '__main__':
    distancias_de_caminata = [10, 100, 1000, 10000]
    numero_de_intentos = 1000
    print(""" 
    
            BORRACHO TRADICIONAL    
            
     """)
    main(distancias_de_caminata, numero_de_intentos, BorrachoTradicional)
    print(""" 
    
            BORRACHO CUENCANO      
            
        """)
    main(distancias_de_caminata, numero_de_intentos, BorrachoCuencano)
class BorrachoCojoDerecho(Borracho):

    def __init__(self, nombre):
        super().__init__(nombre)

    def camina(self):
        return random.choice([(0, 1), (0, -1), (0.5, 0), (-1, 0)])

Les comparto mis simulaciones a 2000, 20000, 200000 y 2000000 de pasos. 😬

Les comparto un código un poco más corto y para mi más facil de entender, fue creado en jupyter notebook.

import numpy as no #librerias
import matplotlib.pyplot as plt

def generate_neighborhood(x,y):
    return [
        (x+1,y),#derecha
        (x-1,y),#izquierda
        (x,y+1),#arriba
        (x,y-1)#abajo
    ]
def random_walk_2D(origin=(0,0),steps = 10):
    walk = [origin] #Iniciamos el camino en el origen (0,0)
    si = 0 
    while True:
        candidates = generate_neighborhood(*walk[-1]) #Calculamos los 4 posibles candidatos de las siguientes coordenadas en el camino
        selected = candidates[no.random.choice(len(candidates))] # Seleccionamos una coordenada aleatoriamente con el random.choice
        walk+=[selected] # Aumentamos la coordenada anterior al camino
        si += 1 #Aumentamos los pasos
        if si == steps: break
    return walk #Devolvemos el camino

walk= random_walk_2D(steps = 100)
w = no.array(walk).T    #Transponemos las coordenadas para graficar más fáciñ
plt.figure(figsize=(5,5))
plt.plot(w[0],w[1],':.')

yo igual quiero, subí mi script, aunque no estoy seguro si está del todo correcto, pero igual me tinca que si

Mi gráfica con 10,000 y con la línea con la distancia final

Amigos, en youtube encontre un corto tutorail de graficos con bokeh, me parecio interesante.

https://www.youtube.com/watch?v=2TR_6VaVSOs&t=447s

def graficar(x, y, distancia):
    figura = figure(title = 'Random Walks', 
                    x_axis_label = 'x axis',
                    y_axis_label = 'y axis')
    figura.line(x, y, legend = 'Route')

    figura.circle(x[0], y[0], color='black', size = 10, legend = 'Init')
    figura.circle(x[-1], y[-1], color='green', size = 10, legend = 'Final')
    figura.line([x[0],x[-1]], [y[0], y[-1]], color='red', line_width = 1, legend = 'Distance')
    show(figura)```

Aqui mi grafico, un compilado de distintos aportes, hay muchos muy buenos en los comentarios.

from borrachos import SnoopDog, BorrachoTradicional
from coordenada import Coordenada
from campo import Campo
import random

from bokeh.plotting import figure, show

def main(distancia, inicio, borracho):
    campo = Campo()
    campo.anadir_borracho(borracho, inicio) #poner un borracho en origen
    ejecutar_caminata(campo, borracho, distancia)

def ejecutar_caminata(campo, borracho, distancia):
    x_arreglo = []
    y_arreglo = []
    x_arreglo.append(campo.obtener_coordenada(borracho).x)
    y_arreglo.append(campo.obtener_coordenada(borracho).y)
    for _ in range(distancia):
        campo.mover_borracho(borracho) #se actualiza las coordenadas del borracho
        x_arreglo.append(campo.obtener_coordenada(borracho).x)
        y_arreglo.append(campo.obtener_coordenada(borracho).y)

    graficar(x_arreglo, y_arreglo)

def graficar(x, y):
    figura = figure(title=f'Simulacion de borracho con {distancia} pasos', x_axis_label='Axis X', y_axis_label='Axis Y', plot_width=700, plot_height=700)
    x_plot = [x[0], x[-1]] # x_inicial, x_final
    y_plot = [y[0], y[-1]]    #  y_inicial, y_final
    names = ['Start', 'End']

    colors = '#%06X' % random.randint(0, 0xFFFFFF)
    figura.line(x, y, color=colors)
    figura.circle(x_plot,y_plot,alpha=0.8, size=20)
    figura.line(x_plot, y_plot, color="firebrick")
    # labels = LabelSet(x='x', y='y', text='names', level='glyph', x_offset=5, y_offset=5, render_mode='canvas')
    # colors = '#%06X' % random.randint(0, 0xFFFFFF)
    # figura.circle(x[len(x)-1],y[len(y)-1], color=colors,line_width=10)
    print(x[len(x)-1])
    print(y[len(y)-1])
    show(figura)

if __name__ == '__main__':
    distancia = 10000
    inicio = Coordenada(0,0)
    borracho1 = SnoopDog('Enzo')
    main(distancia, inicio, borracho1)

Les dejo este código si quieren crear un borracho vaya mas hacia arriba o mas hacia abajo, mas a la isquierda o la derecha. Solo tienen que cambiar los pesos “weights”

def camina(self):
        sig_paso = [(0,1), (0,-1), (1,0),(-1,0)]
        d = random.choices(range(len(sig_paso)),weights=(40,20,20,10),k=1)
        dint = int(d[0])
        return sig_paso[dint]

No estoy entendiendo bien la variable intentos (en el caso del programa=100). Cuando hacemos caminar al borracho usamos el for:
for _ in range(numero_de_intentos): campo = Campo() campo.anadir_borracho(borracho, origen) simulacion_caminata = caminata(campo, borracho, pasos) distancias.append(round(simulacion_caminata, 1))

Cuando en realidad eso deberia estar definido por la cantidad de pasos que nos arroja la lista de distancias o no? Acaso no deberia quedar asi?
for _ in range(pasos): campo = Campo() campo.anadir_borracho(borracho, origen) simulacion_caminata = caminata(campo, borracho, pasos) distancias.append(round(simulacion_caminata,1)) print(borracho.camina()) return distancias

Si alguien me saca la duda les agredecere mucho!

No me corrió y ni idea de donde tengo el error

La conclusión de esta clase es sencilla: “Uno no sabe cómo pero siempre regresa al punto de origen aún borracho” :smil

adjunto la modificación a borracho, para obtener distintos “pesos” de probabilidad en cada opción:

# Creamos la clase BorrachoModificado que extiende de Borracho.
class BorrachoModificado(Borracho):

    def __init__(self, nombre):
        super().__init__(nombre)

    
    def camina(self):
        
        a=random.choices([(0, 1), (0, -1), (1, 0), (-1, 0)],weights=[0.1, 0.1, 0.1, 0.7])
        return(a[0])```

Agregué una coordenada extra al programa, como no se graficar en 3D con bokeh, decidí representarlo con tres graficas.
Código: https://github.com/Angrub/Caminos_aleatorios.git

Por si alguien tenía curiosidad de cómo se veian las coordenadas del borracho tradicional.

Logre modificar el código para agregar 2 borrachines, pero ambas presentan un patrón bastante parecido. Por el momento solo dejare el código de la grafica

![]()

from bokeh.models import ColumnDataSource

def graficar(x, y):
    grafica = figure(title='Camino aleatorio', x_axis_label='pasos', y_axis_label='distancia')
    source= ColumnDataSource(data=dict(x=x, y1=y[0], y2=y[1]))
    grafica.line(x, y, legend='distancia media')
    grafica.vline_stack(['y1', 'y2'], x='x', color=['blue', 'red'],  source=source)

Pues el cambio más sobresaliente que le hice al segundo objeto de la clase Borracho fue triplicar su distancia y si hay cambio en las estadísticas.

Mi borracho fue invisible

Mi borracho ultra loco luego de 10000 pasos! Fue clave la clase extra de la mentora para poder terminar de entender esto! Muchas gracias!

Y que pasa si el Borracho y Drogrado salen juntos??? 😂😂😂 100, 1000, 10000 y 100000 pasos!

Excelente la clase y los aportes en los comentarios!!! 😁

Si les da error con la lista distancias les recomiendo poner esta linea al final de la función simular_caminata

return distancias

No me corre alguien que me ayude por favor:
C:\Users\Personal>C:/Python27/ArcGIS10.5/python.exe c:/Users/Personal/camino_aleatorio.py
Traceback (most recent call last):
File “c:/Users/Personal/camino_aleatorio.py”, line 41, in <module>
main(distancias_de_caminata, numero_de_intentos, BorrachoTradicional)
File “c:/Users/Personal/camino_aleatorio.py”, line 27, in main
distancias = simular_caminata(pasos, numero_de_intentos, tipo_de_borracho)
File “c:/Users/Personal/camino_aleatorio.py”, line 14, in simular_caminata
borracho = tipo_de_borracho(nombre = ‘Fercho’)
File “c:\Users\Personal\borracho.py”, line 11, in init
super().init(nombre)
TypeError: super() takes at least 1 argument (0 given)

Start : This command cannot be run due to the error: The system cannot find the file specified.
At line:1 char:1

  • Start “file:///tmp/tmpn7esux1v.html”
  •   + CategoryInfo          : InvalidOperation: (:) [Start-Process], InvalidOperationException
      + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
    
    
    

Me sale este error cuando intento graficar el programa, alguien sabe como solucionarlo??

BorrachoFibonacci, caminara las distancias de fibonacci y un número de intentos de 10

Mi resultado con 10 millones
![bokeh_plot.png](https://static.platzi.com/media/user_upload/bokeh_plot-42dcf282-d415-43ac-8f23-19b08288b3c7.jpg

y con 15 millones

Codigos finales de la clase
1.-borracho

import random

class Borracho:

    def __init__(self, nombre):
        self.nombre = nombre

class BorrachoTradicional(Borracho):
    def __init__(self, nombre):
        super().__init__(nombre)
    
    def camina(self):
        return random.choice([(0,1),(0,-1),(1,0),(-1,0)])```
2.- coordenada


class Coordenada:

def __init__(self, x, y):
    self.x=x
    self.y=y

def mover(self, delta_x, delta_y):
    return Coordenada(self.x + delta_x, self.y + delta_y)

def distancia(self, otra_coordenada):
    delta_x=self.x - otra_coordenada.x
    delta_y=self.y - otra_coordenada.y

    return (delta_x**2 + delta_y**2 )**0.5```

3.-campo

class Campo:

    def __init__(self):
        self.coordenadas_de_borrachos = {}

    def anadir_borracho(self, borracho, coordenada):
        self.coordenadas_de_borrachos[borracho] = coordenada

    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

    def obtener_coordenada(self, borracho):
        return self.coordenadas_de_borrachos[borracho]```

4.- camino aleatorio


from borracho import BorrachoTradicional
from campo import Campo
from coordenada import Coordenada

from bokeh.plotting import figure, show

def caminata(campo, borracho, pasos):
inicio = campo.obtener_coordenada(borracho)

for _ in range(pasos):
    campo.mover_borracho(borracho)

return inicio.distancia(campo.obtener_coordenada(borracho))

def simular_caminata(pasos, numero_de_intentos, tipo_de_borracho):
borracho = tipo_de_borracho(nombre=‘David’)
origen = Coordenada(0, 0)
distancias = []

for _ in range(numero_de_intentos):
    campo = Campo()
    campo.anadir_borracho(borracho, origen)
    simulacion_caminata = caminata(campo, borracho, pasos)
    distancias.append(round(simulacion_caminata, 1))

return distancias

def graficar(x, y):
grafica = figure(title=‘Camino aleatorio’, x_axis_label=‘pasos’, y_axis_label=‘distancia’)
grafica.line(x, y, legend=‘distancia media’)

show(grafica)

def main(distancias_de_caminata, numero_de_intentos, tipo_de_borracho):
distancias_media_por_caminata = []

for pasos in distancias_de_caminata:
    distancias = simular_caminata(pasos, numero_de_intentos, tipo_de_borracho)
    distancia_media = round(sum(distancias) / len(distancias), 4)
    distancia_maxima = max(distancias)
    distancia_minima = min(distancias)
    distancias_media_por_caminata.append(distancia_media)
    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}')
graficar(distancias_de_caminata, distancias_media_por_caminata)

if name == ‘main’:
distancias_de_caminata = [10, 100, 1000, 10000]
numero_de_intentos = 100

main(distancias_de_caminata, numero_de_intentos, BorrachoTradicional)



mi resultado con 10 millones de pasos:

BorrachoRengo: tendencia de que cada vez que de un paso en ‘x’, lo da 3 veces.

import random

class Borracho:

def __init__(self,nombre):
    self.nombre = nombre

class BorrachoTradicional(Borracho):

def __init__(self,nombre):
    super().__init__(nombre)

def camina(self):
    return random.choice([(0,10),(0,-1),(10,0),(-1,0)])

minuto 1:38, para evitar el error relacionado con el self, pueden agregar el decorador @staticmethod a la funcion, ya que realmente es una funcion estatica porque no interactua de ninguna forma con la clase y no tiene mucho sentido que reciba self para no usarlo.

@staticmethod
def camina():
    return random.choice([......])