RosettaCodeData/Task/Kaprekar-numbers/Elixir/kaprekar-numbers.elixir
2015-11-18 06:14:39 +00:00

44 lines
1.3 KiB
Text

defmodule KaprekarNumber do
def check(n), do: check(n, 10)
def check(1,_base), do: {"1", ""}
def check(n, base) when rem(n*(n-1), (base-1)) != 0, do: false # casting out nine
def check(n, base) do
square = Integer.to_string(n*n, base)
check(n, base, square, 1, String.length(square)-1)
end
defp check(_, _, _, _, 0), do: false
defp check(n, base, square, i, remainder) do
{a, b} = String.split_at(square, i)
if String.to_integer(b, base) == 0 do
false
else
sum = String.to_integer(a, base) + String.to_integer(b, base)
if n == sum, do: {a, b}, else: check(n, base, square, i+1, remainder-1)
end
end
end
Enum.each(1..9_999, fn n ->
if result = KaprekarNumber.check(n) do
{a, b} = result
:io.fwrite "~6w ~8s ~s + ~s~n", [n, a<>b, a, b]
end
end)
# Extra credit
count = Enum.reduce(1..999_999, 0, fn n,acc ->
if KaprekarNumber.check(n), do: acc + 1, else: acc
end)
IO.puts "\n#{count} kaprekar numbers under 1,000,000"
# Extra extra credit
base = 17
IO.puts "\nbase #{base} kaprekar numbers under 1,000,000(base10)"
Enum.each(1..999_999, fn n ->
if result = KaprekarNumber.check(n, base) do
{a, b} = result
:io.fwrite "~7w ~5s ~9s ~s + ~s~n", [n, Integer.to_string(n,base), a<>b, a, b]
end
end)