Un número feliz es un entero positivo n que verifica la siguiente про-Пьедад: se reemplaza n por la suma de los cuadrados de sus dígitos y se repite el proceso имеет к obtener ООН 1. Por ejemplo, el 7 es feliz porque:
• 7 → 7^2 = 49
• 49 → 4^2 + 9^2 = 16 + 81 = 97
• 97 → 9^2 + 7^2 = 81 + 49 = 130
• 130 → 1^2 + 3^2 + 0^2 = 1 + 9 + 0 = 10
• 10 → 1^2 + 0^2 = 1 + 0 = 1
Un número que no es feliz es infeliz. En tal caso, el proceso предшествующие полости en bucle. Por ejemplo, полости es infeliz porque el proceso en bucle el 4 (aunque el bucle никакой tiene por qué presentarse en el primer elemento de la secuencia ESTO ÚLTIMO ES IMPORTANTE):
• 4 → 4^2 = 16
• 16 → 1^2 + 6^2 = 1 + 36 = 37
• 37 → 3^2 + 7^2 = 9 + 49 = 58
• 58 → 5^2 + 8^2 = 25 + 64 = 89
• 89 → 8^2 + 9^2 = 64 + 81 = 145
• 145 → 1^2 + 4^2 + 5^2 = 1 + 16 + 25 = 42
• 42 → 4^2 + 2^2 = 16 + 4 = 20
• 20 → 2^2 + 0^2 = 4 + 0 = 4
Определите una función digitosDe :: Integer -> [Integer]
que облицовывают панелями ООН естественная devuelva ООН, Листа подставляет sus dígitos:
digitosDe :: Integer -> [Integer]
digitosDe x = reverse (digitosDe' x)
where digitosDe' x
|x < 10 = [x]
|otherwise = (x `mod` 10) : digitosDe' (x`div`10)
Определите una función sumaCuadradosDigitos :: Integer -> Integer
que облицовывают панелями un naturaldevuelva la suma de los cuadrados de sus dígitos:
sumaCuadradosDigitos :: Integer -> Integer
sumaCuadradosDigitos x = sum (map (^2) (digitosDe x))
Определите una función esFeliz :: Integer -> Bool
que определяют СИ ООН entero positivo es feliz:
esFeliz :: Integer -> Bool
esFeliz x
|sumaCuadradosDigitos x == 1 = True
|otherwise = esFeliz (sumaCuadradosDigitos x)
HE AQUÍ EL PROBLEMA: никакой sé cómo пара el bucle en el caso que se detecte que existe
Se я sugiere usar una funcion auxiliar"esFelizAc
"que используют довод "против" recursión фургон acumulador y emplear éste para almacenar los números que se obteniendo en la sucesivas iteraciones.
Договора. Давайте начинаться с немного teorГ - в. Давайте предполагать, что мы хотим сделать следующую funciГіn:
unfold :: a -> [b]
Как предложи имя, unfold
делает ее operaciГіn обратная из fold
и сходные:
fold :: [a] -> b
(Он замечает: типа fold
serГ-an sum
, product
, head
, last
... foldr
, foldl
...)
мы Можем осуществлять unfold
посредством recursiГіn применяя iterativamente одна funciГіn f
для того, чтобы он дал элементы в команде: Этой definiciГіn не хватает
unfold :: a -> [b]
unfold x = y : unfold z
where (y,z) = f x
она condiciГіn остановки, чтобы предотвращать одна recursiГіn бесконечная . То, что возможно оценивать, состоит в том, что он является совсем не работоспособным: у себя требует, чтобы получить оставшуюся часть списка перед тем, как мочь aГ±adir элемент, что будет нуждаться в достаточном количестве памяти, чтобы сохранять промежуточные результаты до конца ее operaciГіn.
Давайте Вводить аккумулятор:
unfold :: a -> [b]
unfold = unfoldAc []
unfoldAc :: [b] -> a -> [b]
unfoldAc xs x | cond x = xs
| otherwise = unfoldAc (y:xs) z
where (y,z) = f x
В первом аргументе xs
из unfoldAc
идет аккумулятор. Начнись vacГ - или и он наполняется произведенными элементами. Когда будет выполнена она condiciГіn cond
, для нее recursiГіn, и возврати то, что есть в аккумуляторе. Хорошее этой implementaciГіn состоит в том, что его не требуют, сохранять ningГєn промежуточный результат, так как все проходит как аргумент. Вот то, что известно как "optimizaciГіn tailrec " .
Давайте Видеть cГіmo изменять ты implementaciГіn digitosDe
помещая аккумулятор:
digitosDe :: Integer -> [Integer]
digitosDe = digitosDe' []
where
digitosDeAc xs x | x < 10 = x : xs
| otherwise = digitosDeAc (m : xs) d
where (d, m) = x `divMod` 10
Как видно, уходят накапливая числа, которые он вычисляет, и в порядке, который мы хотим (сначала он помещает в аккумулятор единицы, потом десятки, и т.д., и т.д.).
В любом случае, есть одна implementaciГіn mГЎs прямая (хотя менее элегантный) используя их mГ©todos чтения / написания haskell:
digitosDe :: Integer -> [Integer]
digitosDe x = [ read [c] | c <- show x ]
, Но давайте идти в случай, который занимает нас, cГіmo помещать аккумулятор в ней funciГіn esFeliz
:
esFeliz :: Integer -> Bool
esFeliz = esFelizAc []
where
esFelizAc xs x | x `elem` xs = False
| s == 1 = True
| otherwise = esFelizAc (x : xs) s
where s = sumaCuadradosDigitos x
Аккумулятор мы это используем, чтобы помещать те nГєmeros, который уже мы увидели. Если nГєmero, чтобы подтверждать уже, он был виден, возврати False
( неудачник ). Если суммы квадратов 1, возврати True
(счастливые ). Если ни одна ни другая вещь, тогда он это не помещает в аккумулятор и вновь начинается, этот раз с суммой квадратов.
Вещь, которую нужно иметь в виду, состоит в том, что весь они nГєmeros аккумулятора они nГєmeros счастливые или несчастные, segГєn был концом последовательности. Если он шел использовать много эту funciГіn, podrГ - создавать список nГєmeros счастливые и другая из неудачников, и идти llenГЎndola с ними nГєmeros, что виделись. Или же, одна funciГіn с тремя аккумуляторами. Но я это оставляю aquГ - потому что я не хочу осложнить mГЎs ответ.