Menu Close

Rotaciones divisibles por 8

Las rotaciones de 928160 son 928160, 281609, 816092, 160928, 609281 y 92816 de las que 3 son divisibles por 8 (928160, 160928 y 92816).

Definir la función

   nRotacionesDivisiblesPor8 :: Integer -> Int

tal que (nRotacionesDivisiblesPor8 x) es el número de rotaciones de x divisibles por 8. Por ejemplo,

   nRotacionesDivisiblesPor8 928160       ==  3
   nRotacionesDivisiblesPor8 43262488612  ==  4
   nRotacionesDivisiblesPor8 (read (take (10^4) (cycle "248")))  ==  6666

Soluciones

-- 1ª definición
-- =============
 
nRotacionesDivisiblesPor8 :: Integer -> Int
nRotacionesDivisiblesPor8 x =
  length [y | y <- rotaciones x
            , y `mod` 8 == 0]
 
--    rotaciones 1234  ==  [1234,2341,3412,4123]
rotaciones :: Integer -> [Integer]
rotaciones x = [read ys | ys <- rotacionesLista xs]
  where xs = show x
 
--    rotacionesLista "abcd"  ==  ["abcd","bcda","cdab","dabc"]
rotacionesLista :: [a] -> [[a]]
rotacionesLista xs =
  [zs ++ ys | k <- [0 .. length xs - 1]
            , let (ys,zs) = splitAt k xs] 
 
-- 2ª definición
-- =============
 
nRotacionesDivisiblesPor8b :: Integer -> Int
nRotacionesDivisiblesPor8b x =
  length [y | y <- tresDigitosConsecutivos x
            , y `mod` 8 == 0]
 
--    tresDigitosConsecutivos 1234  ==  [123,234,341,412]
tresDigitosConsecutivos :: Integer -> [Integer]
tresDigitosConsecutivos x =
  [read (take 3 ys) | ys <- rotacionesLista (show x)]
 
-- Comparación de eficiencia
-- =========================
 
--    λ> nRotacionesDivisiblesPor8 (read (take (3*10^3) (cycle "248")))
--    2000
--    (3.59 secs, 4,449,162,144 bytes)
--    λ> nRotacionesDivisiblesPor8b (read (take (3*10^3) (cycle "248")))
--    2000
--    (0.48 secs, 593,670,656 bytes)
Posted in Medio

10 Comments

  1. angruicam1
    nRotacionesDivisiblesPor8 :: Integer -> Int
    nRotacionesDivisiblesPor8 x =
      sum [1 | n <- rotaciones x, mod n 8 == 0]
     
    rotaciones :: Integer -> [Integer]
    rotaciones x = map read $ aux (show x) []
      where aux [] _      = []
            aux (x:xs) ys = (xs ++ ysx) : aux xs ysx
              where ysx = ys ++ [x]
  2. alerodrod5
     
    nRotacionesDivisiblesPor8 :: Integer -> Int
    nRotacionesDivisiblesPor8 x = sum [1 | n<- rotaciones x, n `mod`8 ==0] 
     
    rota :: [a] -> [a]
    rota (x:xs) = xs ++ [x]
     
    rotaciones :: Integer -> [Int]
    rotaciones x = map read (take (length n) (iterate rota n))
       where n =show x
  3. pabhueacu
    nRotacionesDivisiblesPor8 :: Integer -> Int
    nRotacionesDivisiblesPor8 n
      | n < 100   = f n + f (nRot (show n))
      | otherwise = sum . map f . map read . aux . show $ n 
      where f x | x `mod` 8 == 0 = 1
                | otherwise      = 0
            aux n = aux2 $ drop (length n - 3) n ++ init n
            aux2 (x:y:z:xs) = (x:y:z:[]) : aux2 (y:z:xs)
            aux2 _          = []
            nRot (x:y) | length (x:y) == 1 = 3
                       | otherwise         = (read y)*10 + read [x]
    • angruicam1

      Buenas, considerando como tú que si un número de tres cifras o más es divisible por ocho si sus tres últimas cifras lo son, se me ocurre también esta función:

      import Data.List.Split (divvy)
       
      nRotacionesDivisiblesPor8 :: Integer -> Int
      nRotacionesDivisiblesPor8 x =
        sum [1 | n <- rotaciones8 x, n `mod` 8 == 0]
       
      -- (rotaciones8 n) calcula las tres últimas cifras
      -- de todas las rotaciones de un número de tres o
      -- más cifras, y todas las rotaciones en otro caso.
      -- Por ejemplo,
      --   λ> rotaciones8 3456
      --   [345,456,563,634]
      rotaciones8 :: Integer -> [Integer]
      rotaciones8 = map read . aux . show
        where aux [x]      = [[x]]
              aux [x,y]    = [[x,y],[y,x]]
              aux (x:y:xs) = divvy 3 1 (x:y:xs ++ [x,y])
      • angruicam1

        Podemos modificar de la siguiente forma la función nRotacionesDivisiblesPor8 para trabajar sin argumentos:

        nRotacionesDivisiblesPor8 :: Integer -> Int
        nRotacionesDivisiblesPor8 =
          length . filter ( x -> x `mod` 8 == 0) . rotaciones8
        • antgongar

          Se puede seguir eliminando argumentos ya que

          x ->  x `mod` 8 == 0

          es equivalente a

          (== 0) . (`mod` 8)
  4. luiconbel
    nRotacionesDivisiblesPor8 :: Integer -> Int
    nRotacionesDivisiblesPor8 n =
      sum [1 | x <- take k (rotaciones n) , x `mod` 8 == 0]
      where k = length (show n)
     
    rotaciones :: Integer -> [Integer]
    rotaciones n =
      [n] ++ (rotaciones ((10*(n`mod`10^(-1+k))) + (n`div`10^(-1+k))))
      where k = length (show n)
  5. agumaragu1
    nRotacionesDivisiblesPor8 :: Integer -> Int
    nRotacionesDivisiblesPor8 n = length $ filter p (rotaciones n)
      where p x = mod x 8 == 0
     
    rotaciones :: Integer -> [Integer]
    rotaciones n = take l $ iterate siguiente n'
      where siguiente m = div m 10
            n' :: Integer
            n' = read $ show (mod n 100) ++ show n
            l = length $ show n
  6. angruicam1
    import Data.Char (digitToInt)
     
    nRotacionesDivisiblesPor8 :: Integer -> Int
    nRotacionesDivisiblesPor8 =
      length
      . filter ((== 0) . (`mod` 8))
      . rotaciones8
      . abs
     
    -- (rotaciones8 n) calcula los números obtenidos al
    -- multiplicar por 4 la antepenúltima cifra de cada una
    -- de las rotaciones de un número, por 2 la penúltima y
    -- sumarlas con la última cifra. Por ejemplo,
    --   λ> rotaciones8 3456
    --   [25,32,35,34]
     
    rotaciones8 :: Integer -> [Int]
    rotaciones8 n
      | n < 10    = [fromEnum n]
      | otherwise =
        zipWith3 (((+).) . flip ((+) . (2*)) . (4*))
        (a:b:ds) (b:ds++[a]) (ds++[a,b])
      where (a:b:ds) = digitos n
     
    -- (digitos n) calcula todas las cifras de un número.
    -- Por ejemplo,
    --   λ> digitos 3456
    --   [3,4,5,6]
     
    digitos :: Integer -> [Int]
    digitos = map digitToInt . show

Escribe tu solución

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.