Collatz en base 6

Un programa para operar sobre la conjetura de Collatz en base seis. No implementa la multiplicación por tres; en lugar de eso multiplica por seis y divide por dos. Un posible cambio podría ser retirar la división por dos y sustituirla por multiplicar por tres y dividir entre seis. Otra cosa que posiblemente hay que mejorar es retirar las colas de ceros que se acumulan; aunque el número de ceros puede dar información adicional.

Nótese que en ningún momento empleo números en el sentido convencional del término.

data Base6 = C0 | C1 | C2 | C3 | C4 | C5 deriving (Eq)
instance Show Base6 where
    show C0 = "0"
    show C1 = "1"
    show C2 = "2"
    show C3 = "3"
    show C4 = "4"
    show C5 = "5"
 
type IntBase6 = [Base6]
 
convierte :: Integer -> IntBase6
convierte x
    | x == 0 = []
    | mod x 6 == 0 = C0 : convierte (div x 6)
    | mod x 6 == 1 = C1 : convierte (div x 6)
    | mod x 6 == 2 = C2 : convierte (div x 6)
    | mod x 6 == 3 = C3 : convierte (div x 6)
    | mod x 6 == 4 = C4 : convierte (div x 6)
    | mod x 6 == 5 = C5 : convierte (div x 6)
 
porseis :: IntBase6 -> IntBase6
porseis x = C0 : x
 
-- vagamente equivalente a un "right shift"
rsh :: Base6 -> Base6
rsh C0 = C0
rsh C2 = C1
rsh C4 = C2
rsh _ = error "rsh; mal parametro"
 
-- Suponemos que x es x+6
rsh2 :: Base6 -> Base6
rsh2 C0 = C3
rsh2 C2 = C4
rsh2 C4 = C5
rsh2 _ = error "rsh2; mal parametro"
 
dec :: IntBase6 -> IntBase6
dec (x:xs) =
    if x == C0 then C5:(dec xs)
    else (dec1 x):xs where
        dec1 :: Base6 -> Base6
        dec1 C1 = C0
        dec1 C2 = C1
        dec1 C3 = C2
        dec1 C4 = C3
        dec1 C5 = C4
 
par :: Base6 -> Bool
par C0 = True
par C2 = True
par C4 = True
par C1 = False
par C3 = False
par C5 = False
 
entredos :: IntBase6 -> IntBase6
entredos [] = []
entredos [x] = [(rsh x)]
entredos (x:y:xs)
    | par y = (rsh x) : entredos (y:xs)
    | (not.par) y = (rsh2 x) : entredos (dec (y:xs))
 
masuno :: IntBase6 -> IntBase6
masuno [] = [C1]
masuno (x:xs) =
    if x == C5 then C0:(masuno xs)
    else (inc1 x):xs where
        inc1 :: Base6 -> Base6
        inc1 C0 = C1
        inc1 C1 = C2
        inc1 C2 = C3
        inc1 C3 = C4
        inc1 C4 = C5
 
op :: IntBase6 -> IntBase6
op (x:xs)
    | par x = (entredos (x:xs))
    | (not.par) x = (entredos.masuno.entredos.porseis) (x:xs)
 
esuno :: IntBase6 -> Bool
esuno (x:xs) = and [(x == C1), (escero xs)] where
    escero :: IntBase6 -> Bool
    escero [] = True
    escero (y:ys) = and [(y == C0), (escero ys)]
 
collatz :: IntBase6 -> [IntBase6]
collatz x
    | esuno x = []
    | otherwise = (op x):(collatz (op x))

Ejemplo:

*Main> collatz (convierte 19)
[[5,4,0],[2,1,1,0],[4,3,0,0],[5,1,0,0],[5,2,0,0,0],[2,4,0,0,0,0],[1,2,0,0,0,0],[2,3,0,0,0,0,0],[4,1,0,0,0,0,0],[5,0,0,0,0,0,0],[2,1,0,0,0,0,0,0],[4,0,0,0,0,0,0,0],[2,0,0,0,0,0,0,0],[1,0,0,0,0,0,0,0]]

Powered by Drupal, an open source content management system