Ir al contenido principal

Laberinto numérico

El problema del laberinto numérico consiste en, dados un par de números, encontrar la longitud del camino más corto entre ellos usando sólo las siguientes operaciones:

  • multiplicar por 2,
  • dividir por 2 (sólo para los pares) y
  • sumar 2.

Por ejemplo, un camino mínimo

  • de 3 a 12 es [3,6,12],
  • de 12 a 3 es [12,6,3],
  • de 9 a 2 es [9,18,20,10,12,6,8,4,2] y
  • de 2 a 9 es [2,4,8,16,18,9].

Definir la función

longitudCaminoMinimo :: Int -> Int -> Int

tal que (longitudCaminoMinimo x y) es la longitud del camino mínimo desde x hasta y en el laberinto numérico.

longitudCaminoMinimo 3 12  ==  2
longitudCaminoMinimo 12 3  ==  2
longitudCaminoMinimo 9 2   ==  8
longitudCaminoMinimo 2 9   ==  5

longitudCaminoMinimo :: Int -> Int -> Int
longitudCaminoMinimo x y =
    head [n | n <- [1..], y `elem` orbita n [x]]

-- (orbita n xs) es el conjunto de números que se pueden obtener aplicando
-- como máximo n veces las operaciones a los elementos de xs. Por ejemplo,
--    orbita 0 [12]  ==  [12]
--    orbita 1 [12]  ==  [6,12,14,24]
--    orbita 2 [12]  ==  [3,6,7,8,12,14,16,24,26,28,48]
orbita :: Int -> [Int] -> [Int]
orbita 0 xs = sort xs
orbita n xs = sort (nub (ys ++ concat [sucesores x | x <- ys]))
    where ys = orbita (n-1) xs
          sucesores x | odd x     = [2*x, x+2]
                      | otherwise = [2*x, x `div` 2, x+2]