Advent of code

Día 14

HashMap y Recursividad

Advent of code

El Advent of Code es una página web donde cada día del mes de diciembre van descubriendo un problema para que la gente haga un algoritmo que lo resuelva.

14 de diciembre de 2020

El de este día mezcla HashMaps y recursividad

Parte 1

Dan una serie de direcciones y unos valores a escribir en ellas.

Los valores sufren una transformación y se almacenan, al final hay que hacer la suma de los valores almacenados en la memoria.

Escrituras repetidas

Se puede escribir varias veces en una posición de memoria y solo nos interesa el último valor escrito → No podemos ir sumando conforme leemos.

2^36 posiciones de memoria

Para que no usemos la fuerza bruta y hagamos un array con todas las posiciones de memoria nos dicen que éstas son de 36 bits.

Es imposible que hagamos un array de 68.719.476.736 posiciones (68 gigas).

hashmap

Tenemos pocos valores en un espacio de direccionamiento muy amplio.

El caso ideal para usar un hashmap.

Haremos un put(posición, valor) y al final sumaremos los valores recorriendo todo el hashmap.

Parte 2

Múltiples escrituras

Múltiples escrituras

Las direcciones de memoria no están definidas del todo.

Si nos dan una direccion como 01010xc01010x000xx11 que tiene 4 x significa que tendremos que escribir en 2^4 = 16 posiciones de memoria diferentes, con todas las combinaciones de 1s y 0s para cada x.

En alguna dirección tenemos que cambiar hasta 10 x, eso son 2^10 = 1024 escrituras.

ejemplo con 2x

Estrategia

  • Buscar una X
  • Si no hay estamos ya en una posición final → escribir en hashmap
  • Si la hay dividimos en dos fragmentos hacemos dos llamadas recursivas una con la X cambiada por 0 y otra con la X cambiada por 1
  • Repetir hasta que no queden X

Implementación

Lo he hecho en Java pq es un lenguaje con el que me encuentro cómodo.

Se podía haber hecho en cualquier otro lenguaje (C, Python, Perl, Basic, Pascal, Javascript...), pero me he quedado con éste.

Código - 1

Llamada inicial

Aún no hay cambiado nada

Llamada recursiva

Hacer pasadas

Resumen

  • Fichero de entrada → 560 líneas
  • Escrituras tras desdoblamientos → 77.520
  • Posiciones de memoria diferentes → 73.339
  • ∑(valores) → 3.369.767.240.513

Muy importante: Trabajar con el tipo long y no integer para que no se desborde el resultado.

Optimización

He medido cuantos milisegundos le cuesta hacer los cálculos y le ha costado 31 milisegundos, por lo que he decidido no optimizarlo.

Contacto

¿Quieres contactar conmigo?

@xblasco.com (blueSky)

@xblasco (twitter)

Vuelta al índice

índice

Web Analytics