RosettaCodeData/Task/Smith-numbers/CLU/smith-numbers.clu
2023-07-01 13:44:08 -04:00

62 lines
1.6 KiB
Text

% Get all digits of a number
digits = iter (n: int) yields (int)
while n > 0 do
yield(n // 10)
n := n / 10
end
end digits
% Get all prime factors of a number
prime_factors = iter (n: int) yields (int)
% Take factors of 2 out first (the compiler should optimize)
while n // 2 = 0 do yield(2) n := n/2 end
% Next try odd factors
fac: int := 3
while fac <= n do
while n // fac = 0 do
yield(fac)
n := n/fac
end
fac := fac + 2
end
end prime_factors
% See if a number is a Smith number
smith = proc (n: int) returns (bool)
dsum: int := 0
fac_dsum: int := 0
% Find the sum of the digits
for d: int in digits(n) do dsum := dsum + d end
% Find the sum of the digits of all factors
nfac: int := 0
for fac: int in prime_factors(n) do
nfac := nfac + 1
for d: int in digits(fac) do fac_dsum := fac_dsum + d end
end
% The number is a Smith number if these two are equal,
% and the number is not prime (has more than one factor)
return(fac_dsum = dsum cand nfac > 1)
end smith
% Yield all Smith numbers up to a limit
smiths = iter (max: int) yields (int)
for i: int in int$from_to(1, max-1) do
if smith(i) then yield(i) end
end
end smiths
% Display all Smith numbers below 10,000
start_up = proc ()
po: stream := stream$primary_output()
count: int := 0
for s: int in smiths(10000) do
stream$putright(po, int$unparse(s), 5)
count := count + 1
if count // 16 = 0 then stream$putl(po, "") end
end
stream$putl(po, "\nFound " || int$unparse(count) || " Smith numbers.")
end start_up