Achilles numbers
editable example
Click the pencil to open this in an editor, change it, and run it in your browser. The same solution is posted on Rosetta Code.
ghul
use IO.Std.write_line
use Collections.LIST
use Collections.List
use Collections.Iterable
use Ghul.Pipes
factorize(n: int) -> List[(prime: int, exponent: int)] is
let factors = LIST[(prime: int, exponent: int)]()
let remaining mut = n
let prime mut = 2
while prime * prime <= remaining do
let exponent mut = 0
while remaining % prime == 0 do
remaining = remaining / prime
exponent = exponent + 1
od
if exponent > 0 then
factors.add((prime, exponent))
fi
prime = prime + 1
od
if remaining > 1 then
factors.add((remaining, 1))
fi
return factors
si
gcd(a: int, b: int) -> int =>
if b == 0 then a else gcd(b, a % b) fi
power(base: int, exponent: int) -> int =>
if exponent == 0 then 1 else base * power(base, exponent - 1) fi
is_achilles(n: int) -> bool =>
let factors = factorize(n) in
factors.count > 0 /\
(factors |> all(factor => factor.exponent >= 2)) /\
(factors |> map(factor => factor.exponent) |> reduce(0, gcd)) == 1
totient(n: int) -> int =>
factorize(n)
|> reduce(1, (total, factor) =>
total *
power(factor.prime, factor.exponent - 1) *
(factor.prime - 1))
achilles_numbers() -> Pipe[int] is
let n mut = 1
do
if is_achilles(n) then
yield n
fi
n = n + 1
od
si
show(heading: string, numbers: Iterable[int]) is
write_line(heading)
for row in numbers |> chunk(10) do
write_line(row |> map(n => "{n,7}") |> join(""))
od
write_line("")
si
show("first 50 Achilles numbers:", achilles_numbers() |> take(50))
show(
"first 20 strong Achilles numbers:",
achilles_numbers() |> filter(n => is_achilles(totient(n))) |> take(20)
)
for digits in 2::5 do
let total =
(power(10, digits - 1)..power(10, digits))
|> filter(is_achilles)
|> count()
write_line("Achilles numbers with {digits} digits: {total}")
od
[impure-function-argument] argument must be a pure function
[impure-function-argument] argument must be a pure function
first 50 Achilles numbers:
72 108 200 288 392 432 500 648 675 800
864 968 972 1125 1152 1323 1352 1372 1568 1800
1944 2000 2312 2592 2700 2888 3087 3200 3267 3456
3528 3872 3888 4000 4232 4500 4563 4608 5000 5292
5324 5400 5408 5488 6075 6125 6272 6728 6912 7200
first 20 strong Achilles numbers:
500 864 1944 2000 2592 3456 5000 10125 10368 12348
12500 16875 19652 19773 30375 31104 32000 33275 37044 40500
Achilles numbers with 2 digits: 1
Achilles numbers with 3 digits: 12
Achilles numbers with 4 digits: 47
Achilles numbers with 5 digits: 192