Advent of Code 2020

¿Dónde me apunto?

https://adventofcode.com/

Normas

  • Cada día se desbloquea un problema nuevo
  • Programas en el lenguaje que te da la gana
  • Utilizas las técnicas que te da la gana
  • Le dedicas el tiempo que te da la gana
  • Cada problema tiene una caja de texto para meter la solución (suelen ser números o alguna cadena de texto pequeña)

Leaderboard privado para el pique sano

NSFW

Las respuestas se postean en Spoiler + code

JonaN
Día 15
ciza

Me he puesto a hacerlo ahora, hago la primera parte, todo OK. Esperaba cualquier cosa para la segunda parte y digo, pf si esto lo ejecuta la primera parte tambien.

spoiler
1 respuesta
B

#782 Yo creo que estaba pensado para que hicieras la primera partr metiendo los elementos en una lista y mirándola entera a cada query y luego tuvieras que cambiarlo para meter la segunda parte a tiempo.

MartiONE

Igual es un poco tonteria pero me he acabado haciendo un defaultdict mapeando los indices para no ir recorriendo toda la lista una y otra vez, me ha quedado decente:

spoiler
2 respuestas
B

#784 Yo creo que la solución esperada es lo que has hecho tú o un equivalente, porque comprobar la lista entera con n = 3 * 10 ** 7 te puede tardar siglos.

BeheritSp

#784 No sabía que existían los defaultdicts, muy interesante

S

Menos mas que estos ultimos estan siendo faciles, asi puedo aprovechar para hacer todos los del finde que me entro toda la pereza y hasta entonces los llevaba todos al dia :sweat_smile:

Cuanto os tarda la parte 2 de hoy? Estoy utilizando maps para guardame la informacion y no tener que ir lista arriba, lista abajo, pero aun asi me tarda unos 5s, que aunque no es mucho no se porque se me antoja demasiado teniendo en cuenta que la complejidad es lineal xD

1 respuesta
QuitCat

#787 Diría que me tardó 3-4 seg. Creo que esta bien, aunque sea O(n) estamos hablando de 30 millones de iteraciones. Pensé que en algún momento podía repetirse el ciclo pero no lo comprobé

1 respuesta
B

#788 Quizá hay algun input que sí, pero yo diría que los números crecen al haber cada vez más números distintos y mayor distancia entre índices

eZpit

Mi idea para intentar optimizar el de hoy era buscar si había algún loop. Ninguno lo habéis probado entonces?

1 respuesta
B

#790 Yo lo he considerado, pero entre que he visto ejemplos en los que de haber loops tendrian que ser de periodos muy largos y que el unico input que se me ocurre que tenga un bucle facil de ver es cualquier cosa acabado con dos unos he descartado esa posibilidad, ademas que 3 * 10 ** 7 me parecia una cota que entraba dentro de lo aceptable para algo lineal.

Fyn4r

Listo, entre que estos días ando con curro y la nueva temporada de iracing me queda poco tiempo para dedicarle, menos mal que el de hoy era fácil.

La segunda parte entiendo que se puede mejorar, pero creo que más o menos lo hicimos todos igual, tampoco le lleva más de unos segundos y el hecho de utilizar la función de la primera siempre está bien xd

B

Si usamos de input inicial 0,1 tenemos lo que se llama la secuencia de Van Eck. Para esa secuencia esta demostrado que hay un numero infinito de ceros, que por su propia naturaleza no pueden ser consecutivos, por lo que significa que estaremos viendo infinitos numeros diferentes, asi que no puede haber loops. La proof esta en el link, es facil de seguir

http://oeis.org/A181391

1 1 respuesta
Fyn4r

#793 aprendo más contigo en una tarde haciendo estas mierdas que en 3 años de tesis

1
R

Pues a mi en el día 15, la segunda parte se me va a 10-15 segundos, y es lineal.

parte1
parte2

Pongo las dos partes por costumbre, pero solo cambia el valor limite del bucle xD

B

Dia 16, el enunciado de la segunda parte es bastante pobre, se supone que tienes que dar por sentado que la solución es única. Por el resto, no está mal como problema, dejo el link a github porque en spoiler y code se ve muy mal, hay lineas demasiado largas

https://github.com/srgrr/aoc20202/blob/main/16/main.py

Menos mal que me dio por mirar los indices candidatos antes de seguir programando y vi el pastel, porque si no iba a intentar resolverlo codificando el problema a SAT o algo asi xdddd

1 respuesta
JonaN

#796 No sólo tienes que dar por sentado que es única, sino que han sido tan amables de hacerlo de forma que

spoiler

Me he vuelto LOCO porque estaba multiplicando las posiciones entre sí, y no los valores correspondientes a esas posiciones en mi ticket. Sabía que la solución estaba bien, no entendía qué estaba pasando.

Dejo código chapucero de la parte 2

Día 16
2 respuestas
B

#797 Sí, además eso.

Igualmente este problema en el caso general es un bipartite matching diría, por lo que es resoluble en tiempo polinómico, pero tambien un buen coñazo de implementar si no usas alguna lib de grafos.

https://www.google.com/amp/s/www.geeksforgeeks.org/maximum-bipartite-matching/amp/

Y de hecho si lo codificas con sat o integer linear programming los solvers se lo instacrujen porque estan bastante optimizados para los problemas de flujos

2 respuestas
JonaN

#798 donde tú ves bipartire matching y lib de grafos yo veo 5 nested loops

1 respuesta
B

#799 pos también esberda

QuitCat

Entretenido el de hoy.
Creo que este año son más fáciles que el año pasado. He ojeado alguno de 2019 a estas alturas, y ni me he enterado del enunciado

1 respuesta
B

#801 En general por lo que veo la mayoría de problemas son fáciles porque tienen un input asequible, pero dan mucho mas de sí por si quieres liarte, supongo que está hecho para que la gente no abandone y se vea motivada a seguir participando, cosa que no me parece mal.

Por ejemplo el problema de hoy en el caso general (o sea, un input en el que no tienes garantías de unicidad y que además no puedes resolverlo de forma unívoca fácilmente) es muy interesante, y hay algunos de los anteriores con soluciones rápidas bastante más difíciles que la "suficiente" para pasar el input.

S

#798 Ahora que lo has dicho esta claro que tipo de problema es. Para la parte 2 del dia 8 implemente el algoritmo de Edmonds-Karp por lo que solo tendria que haberlo adaptado un poco, pero ni me he dado cuenta de que era un grafo bipartido. Por el otro lado, creo que me habria costado mas adaptar el codigo que hacerlo con los loops :joy:

@fyn4r añademe a la lista, user en el AoC y en github es Daverlo

1 respuesta
B
#803Seyfel:

Para la parte 2 del dia 8 implemente el algoritmo de Edmonds-Karp

Cómo planteaste ese problema como un maxflow? La única solución rápida que vino a mi cabeza fue plantearlo como una programación dinámica en la que calculabas si podías llegar a la instrucción final partiendo de una determinada instrucción pudiendo (o no) cambiar una instrucción.

https://github.com/srgrr/aoc20202/blob/main/8/main_dp.py

Lo que vine a explicar en #595

1 respuesta
S

#804 Mas que maxflow lo plantee como mincut. Monte un grafo donde los nodos son las instrucciones y hay una arista a->b si b se ejecuta despues de a (ya sea porque es la siguiente o porque hay un jump). En ese grafo habran minimo dos "componentes" una que contiene la primera instruccion y otra la ultima.

En el grafo incluyo tambien las aristas "complementarias", que son las que habrian si se cambia un noop por un jump y viceversa. Por la definicion del problema, al añadir estas aristas, ya deberia haber un camino entre la primera y la ultima instruccion. Poniendo las aristas complementarias con capacidad 1 y el resto 100, me aseguro que el mincut solo contenga aristas complementarias.

Esa es la teoria, pero... en la practica no funciono como me esperaba. Pensaba que el mincut contendria solo la solucion correcta, pero no cai en que si habia un camino alternativo cambiando varias instrucciones tambien formarian parte del mincut. Como ya lo tenia implementado simplemente lo hice por fuerza bruta en el conjunto reducido que devuelve.

https://github.com/Daverlo/aoc-2020/blob/master/src/days/day8/main.go

2 1 respuesta
B

#805 editado: no recordba que había potenciales loops infinitos en el programa que te daban, olvida mi paja mental.

eZpit

Bueno día 16 done, sin pena ni gloria, a base de pico y pala, ya que como habéis dicho el enunciado deja que desear.

He empezado asumiendo que no habría posiciones que cuadrasen en varias reglas, y me ha petado el assert de solo 6 "departure" fields. Debuggeando un poco he visto enseguida lo que comentaba #797, siempre hay una regla que solo encaja en una posición. Con un loop que de varias pasadas hasta ir encontrando la regla más restrictiva va que chuta.

1 1 respuesta
MartiONE

#807 Igual, he acabado de trabajar y entrenar y lo he resuelto con mas pena que gloria hackeandolo de una manera que me ha dado vergüenza

R

Día 16. La segunda parte se me ha compliicado un poco, no terminaba por no ordenar.

https://github.com/NovelleP/AdventOfCode2020/tree/main/day16

eZpit

El Día 15 pt 2 me dejó mosca porque es con diferencia lo más lento hasta ahora. He cambiando el hashmap por un vector inicializado con un tamaño que permita acceso directo (2020/30M elementos, que pa eso tenemos memoria xD) y ha mejorado algo la cosa:

  • pt1: 74.230 us -> 3.9391 us (18x)
  • pt2: 2.4865 s -> 562.26 ms (4,5x)

Especialmente en debug, el hashmap era super lento y no lo podia soportar xD