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]]
