Atribuyen a Edison la frase: “I will not say I failed 1000 times, I will say that I discovered there are 1000 ways that can cause failure.” Pues yo he estado haciendo lo mismo en los ratos libres de estos ajetreados días... +

#AdventOfCode2021 #AdventOfCode
Por las noches mientras veía alguna peli del Prime time he estado programando mi particular acercamiento al problema 15 haciendo stiching de soluciones para encontrar la solución completa al #AoC +
La dificultad no provenía del Floyd Warshall sino de como pegar las soluciones entre si propagando los costos del tal manera que no me sorprendian los fallos, hasta que aburrido/estancado pensé programar el dijkstra para tener la solución y comparar el devenir de cada código.. +
Hay mil sitios de donde coger el código, yo preferí ver si mi antiguo libro de algoritmica aún daba la talla. Y efectivamente en la pag. 90 encontré este clasico de los algoritmos voraces y la gestión de grafos.. ImageImage
Asi que me decidí a implementarlo de la forma mas simple posible usando simples listas (ni conjuntos ni colas de prioridad..)
Aun asi comparado con el Floyd es un poco mas complejo pero poco más, aunque me ha permitido probar por 1º vez una lambda con capturas en Python: ImageImageImage
Asi que rehice el cuerpo de la parte 1 para usar el dijkstra y sacar la solución antes de volver a mi aventura con el Floyd.. Image
Asi que probé con el test y funcionó sin muchos problemas.. Image
Incluso probé un par de grid mas que tenia para pruebas y todo parecía bien.. ImageImage
Asi que lo usé con fichero del puzzle. Parecía ir bien asi que me aventure a pasar la solucion a la página del advent of code.. ImageImage
Pues resulta que no resuelve el puzle! 😅 Curioso, no? Eventualmente daré con ello, mientras seré un imitador de Edison...

Diviértanse (yo lo hago)

#AdventOfCode2021 #AdventOfCode Image
BTW: Pylance se ha vuelto muy lento o quizás es el intellisense del @code . ¿Alguien tienen experiencias similares?
Encontré que me he olvidado de ordenar los nodos por la distancia usando key= itemgetter(2). Sutil diferencia que necesitó de 5 ficheros mas de test y comparando desde (0,0) con (h-1, h-1) siendo h la altura del mapa... Image
probamos de nuevo con el fichero del puzzle. Esta vez añadí la representacion gráfica del camino... ImageImageImage
Claramente con el algoritmo Dijkstra y si uno no está espeso la cosa está hecha (ya se encargó él de tener la claridad de mente). Voy a ver que piden en la 2º parte si no piden mucho volveré a ver si acabo mi aproximación con el Floyd (ya por curiosidad) Image
La 2da parte te piden extender la lista 2D A derecha y hacia abajo 5 veces y ha sido bastante fácil sin embargo a la hora de atacar el mapa completo 500x500 nodos que hecho de no usar una cola de prioridad ni montículo le está pasando factura a mi implementación de dijkstra …
Y el hecho principalmente de iniciar con la lista completa de nodos hace que tenga que hacer 6 millones de ordenaciones de una lista que en su tamaño máximo tiene 250k nodos (Y que se recrea cada vez combinándose con el coste acumulado actual para cada nodo )
Aquí la opción más rápida aparte de incorporar un montículo sería no poblar la lista inicial de nodos con todos ellos sino incrementalmente con los vecinos del nodo actual. Esto los elimina del procesamiento hasta que no sean “descubiertos”.
Tras mas de 1 hora y media corriendo, abortamos la ejecución y nos proponemos implementar algunos de estos cambios...
Primeramente añadimos un set para recordar que vertices/nodos hemos vistado ya... Image
La lista de nodos se poblará solamente con el nodo inicial Image
Cada nodo/vértice visitado se añade en el conjunto de visitados + Image
los candidatos se se eligen entre los vecinos (arriba, abajo, derecha e izquierda) SIEMPRE que no sean nodos que ya han sido visitados + Image
Finalmente si el vecino/candidato no está ya en la lista de vertices a procesar se añade a ella. Image
Aqui vemos la nueva función llamada dijkstra_fast(...) en toda su gloria.. Image
La extension a 5 veces el tamaño no ha sido dificil, solo hay que llevar la cuenta de en cual tesela estamos y en que posicion relativa a la tesela original.. Image
Comprobamos con el ejemplo que funciona correctamente, ademas podemos observar ya que el tiempo de ejecución ha disminuido obstensiblemente.. ¿Tanto? veremos luego.. ImageImage
Probamos en con el puzle ahora de tamaño 500x500 . dijkstra(...) tardó mas de 1 hora 30 mins sin llegar a acabar, ¿cuánto nos tomará ahora con dijkstra_fast(...)? La salida queda descolocada por el tamaño del mapa 2D pero podemos observar que en menos de 2 mins hemos terminado.. ImageImage
Hemos reducido el procesamiento en la lista de nodo al "frente de onda" minorando el procesamiento en la costosa lista de nodos.
Este ha sido uno de los puzles mas instructivos y aún tengo ideas en la recamara para probar con él..

Diviértanse!

#AdventOfCode #AdventOfCode2021 Image
Ja ja ya puedo decir eso de...

I just completed "Chiton" - Day 15 - Advent of Code 2021 adventofcode.com/2021/day/15 #AdventOfCode
No quería quedarme con la espinita de no probar un montículo o "heap". Heapq permite convertir una lista en un monticulo directamente así que cambiando tres lineas tenemos la version del algorithmo que resuelve la 2da parte el día 15 en unos 8 segundos.. Image
Me preguntaba si sería posible añadir el mismo nodo con distintos costes en el montículo y si esto afectaría al algoritmo asi q eliminé el chequeo añadiendo los vecinos con mejor coste directamente a "nodes".
Todos los test pasan y el fichero del puzle se procesa en 2 segundos.. Image
¿Porqué me recreo aqui? por que este algorithmo de busqueda no informada es la puerta al A-Estrella. Tan solo añadir a donde queremos ir con una heurística admisible y tenemos practicamente el A*. Seguro q a los roboteros de
@UAHrobotics
les gustará juguetear con esto..
Bueno pues ya que stoy no me voy a quedar con las ganas de contar la versión recursiva y lo que es mejor el estilo de continuaciones llamada en inglés por su siglas:CPS "Continuation Passing Style"

¿quereis conocerlo? Pues seguimos el hilo...

#AdventOfCode #adventofcode2021
Recordermos la ultima version iterativa del Dijkstra "Shortest Path" que hacúa uso de un Heap o montículo...
Amen de alguna prueba con arrays voy a tranformar esta version en una recursiva con el siempre manido esquema worker/wrapper... Image
El worker queda definido en _dijkstra(...) con la estructura típica recursiva: Caso base + caso general.
El wrapper prepara los datos necesarios y recoge los frutos del trabajo de worker. Image
No ha costado mucho trabajo... Ejecutamos el fichero de test con la parte2 del día 15 y ...

Opps! tras unos 1000 niveles de anidamiento obtenemos una excepción de excesivo anidamiento recursivo..

¿como podemos librarnos de esto? Image
La idea es anidar un número asequible de llamadas , digamos 100 veces y abortar "prematuramente" trasladando la responsabilidad de seguir con el cálculo al call site. Pero claro el top level debe recoger el estado de todo lo que haciamos y replicar la llamada 101...
Podriamos crear una lambda que capture el estado actual de la siguiente llamada recursiva y así el call site no tiene porque saber nada de nuestro estado interno, simplemente debe ejecutar la lambda para proseguir con el cálculo. Esto es lo q se llama en el argot una continuación Image
modificamos el worker para llevar la cuenta del nivel de anidamiento:
- devolver una excepción en caso de maximo nivel de anidamiento que contiene una lambda que al evaluarse ejecutará la sigueinte llamada recursiva que hubieramos hecho si no hubieramos excedido el limite.. Image
En caso de terminar la computación con exito devolver a su vez una lambda que al evaluarse devuelve el resultado. Esto no es estrictamente necesario pero lo hacemos de cara a homogenizar la interfaz del worker de cara a lo que ve al call site (el wrapper) Image
Por su puesto la llamada recursiva que hace el worker sigue siendo igual con la pequeá diferencia de que llevamos la cuenta de cuantos niveles de anidamiento... Image
Modificamos ahora el wrapper para que evalues las continuaciones en el caso normal en el caso de excepción y extraiga los datos finalmente... A continuación veremos en detalle cada cambio. Image
primero debemos convertir la primera llamada al worker en una continuacion, ya que el warpper ahora sólo entiende de evaluar continuaciones y no simples llamadas a funciones. En #Haskell diriamos que hemos liftado o elevado la funcion _dijkstra(...) al contexto de continuaciones Image
El wrapper usa un while para controlar la evaluacion y protege con un try la evaluación de la continuacion, esto nos permitirá actuar en consecuencia según la continuación eleve una excepción o no.. Image
En caso de excepción MaxDepth (creada ad-hoc para nuestro esquema) obtenemos las continuación contenida en la excepción y dejamos que el bucle while repita la evaluación... Image
En caso de ejecución correcta result contiene la continuación final (recordad que _dijkstra(...) ahora solo devuelve continuaciones) asi pues la evaluamos para desempaquetar el resultado final (sea quel que sea) y lo devolvemos al call site. Image
probamos con el test de la segunda parte y vemos que funciona perfectamente. sabiendo que el limite que pusimos eran 100 anidamientos hemos devuelto el control en 10 excepciones y reanuado el proceso evaluando 10 lambdas y finalmente una mas para devolver el resultado. ImageImage
Esta claro que con 10 continuaciones el sobrecoste ha sido minimo ( y podriamos haber puesto 500 de límite reduciendo el proceso muchos mas). Al probar con el ejemplo completo del día 15 vemos que el tiempo de proceso sigue en la figura de los 2 segundos.. ImageImage
En fin, hay mucho más en el #AdventOfCode que perder el culo por sacar el resultado lo mas rápido posible. Para la mayoria de nosotros es una oportunidad para aprender mas allá de la zona de confort, no la desaprovecheis!!

Diviértanse!

#AdventOfCode #adventofcode2021

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with The Code Maverick

The Code Maverick Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @maverick_code

16 Dec
I just completed "Extended Polymerization" - Day 14 - Advent of Code 2021 adventofcode.com/2021/day/14 #AdventOfCode

Este tiene un parecido a Lanter Fish en su crecimiento rápido en la 2º parte que obliga a un replanteamiento..

*SPOILERS *SPOILERS*

#AdventOfCode #AdventOfCode2021
El parser: secuencia de parsers "polymerP" y "newlineP >> rulesP" que capturan tanto la plantilla como las reglas. Creamos todos los subparser necesarios. Leed la función desde el final hacia arriba y veréis la "estructura"
la parte 1 "del tirón". Leemos las reglas y preparamos un diccionario.. BB -> C. En cada paso de polimerización convertimos el pólimero en pares(zip) y aplicamos la conversión a cada par según el dict. El resultado crece rápidamente por lo que abreviamos la salida si len > 60
Read 21 tweets
15 Dec
I just completed "Transparent Origami" - Day 13 - Advent of Code 2021 adventofcode.com/2021/day/13 #AdventOfCode
El parser como siempre: construimos partes como número, coordenada etc.. Aquí la novedad es instructionP que parsea un "fold" y devuelve un lambda que realiza el doblado propiamente dicho "lambda a: fold(a, x, y)" donde x y son el eje e y la fila ó columna respectivamente.
para construir la hoja desde las coordenadas suminstradas tenemos la función data_to_sheet bastante directa (reseñar que hay que averiguar primero la dimensión de las lista de listas)
Read 12 tweets
14 Dec
I just completed "Passage Pathing" - Day 12 - Advent of Code 2021 adventofcode.com/2021/day/12 #AdventOfCode

Bueno al final un generador me ha salvado de hacer una burrada aunque la versión no ha quedado demasiado fea...

*SPOILERS* * SPOILERS*

#AdventOfCode #adventofCode2021
Bueno empecemos por el parser...
Preparamos un diccionario con las conexiones entre nodos (si a -> b entonces b -> a tambien) y luego llamamos a la función traverse que devuelve un generador de rutas que usamos para contabilizar la respuesta y mostrar las rutas al asuario.
Read 12 tweets
10 Dec
I just completed "Syntax Scoring" - Day 10 - Advent of Code 2021 adventofcode.com/2021/day/10 #AdventOfCode

Luego os lo cuento...

*SPOILERS* *SPOILERS*

#AdventOfCode2021 #adventofcode
El parser!! No me canso de quitarme problemas leyendo la entrada con un poco de cuidado (incluso he tratado de correr el fichero de un puzle con el código de otro y esto ayuda a que nada que no tenga que pasar "pase"...
Leemos todos los "chunks" y de aquellos corruptos calculos su "score" an base al caracter que no cuadraba en el lexing.. Usamos un dict para las puntuaciones +
Read 15 tweets
10 Dec
I just completed "Smoke Basin" - Day 9 - Advent of Code 2021 adventofcode.com/2021/day/9 #AdventOfCode
problemas de lectura comprensiva? yo, a veces, lo que me ha llevado a darme de bruces con el puzle (habiendo pasado el test) hasta que quité las diagonales que nadie me habia pedido 🤨

Veamos...

*SPOILERS* *SPOILERS*

#AdventOfCode2021 #adventofcode
El parser. aprovechamos para probar estrategias de sanitización como por ejemplo leer la primera linea y adaptar el parser al vuelo para que las demas sean exactamente de la misma longitud +
Read 15 tweets
8 Dec
I just completed "Seven Segment Search" - Day 8 - Advent of Code 2021 adventofcode.com/2021/day/8 #AdventOfCode
Otro trabajo "guarro" y que conste que quise hacerlo de una forma elegante pero acabé haciéndolo en plan "el juego de la imitación" buscando el "Heil JS!" y esperando pacientemente a que la "bomba" cuadrase todo..

Veamos..

*SPOILERS* *SPOILERS*

#AdventOfCode #AdventOfCode2021
el parser como siempre para leer todo sin errores que ya bastante lío nos van a formar los amigos de Advent of Code..
Read 16 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us on Twitter!

:(