Haskell, 61 bytes
import Data.Numbers.Primes
until=<<((==)=<<)$sum.primeFactors
Explanation
until=<<((==)=<<)
takes a function f
and applies it to input x
until a fix point is reached, that is f x
equals x
. primeFactors
returns the list of prime factors of a number, sum
yields the sum of a list of numbers.
But wait, why does until=<<((==)=<<)
the until=<<((==)=<<)
the job and looks so weird?
If we assume f=sum.primeFactors
, a more natural definition would be until(\x->f x==x)f
, because until
takes a predicate (a function which returns a boolean), a function which has the same input and return type (e.g. Int -> Int
) and value of this type, and then applies the function to the value until the predicate is fulfilled.
until(\x->f x==x)f
is the same as until(\x->(==)(f x)x)f
, and as it holds that g (h x) x
is the same as (g=<<h)x
, we get until(\x->((==)=<<f)x)f
. After Eta conversion, this becomes until((==)=<<f)f
. But if we now treat (==)=<<
as a function which is applied to f
, we can see that until(((==)=<<)f)f
is again of the form g (h x) x
, with g=until
, h=((==)=<<)
and x=f
, so it can be rewritten to (until=<<((==)=<<))f
. Using the $
operator to get rid of the outer parentheses and substituting f
with sum.primeFactors
yields the solution from above.