RosettaCodeData/Task/Vampire-number/Pluto/vampire-number.pluto
2026-04-30 12:34:36 -04:00

75 lines
1.5 KiB
Text

local fmt = require "fmt"
require "table2"
local function ndigits(x)
local n = 0
while x > 0 do
n += 1
x //= 10
end
return n
end
local function dtally(x)
local t = 0
while x > 0 do
t += 2 ** ((x % 10) * 6)
x //= 10
end
return t
end
local tens = table.rep(15, 0)
local function init()
tens[1] = 1
for i = 2, 15 do tens[i] = tens[i - 1] * 10 end
end
local function fangs(x)
local f = {}
local nd = ndigits(x)
if nd & 1 == 1 then return f end
nd //= 2
local lo = math.max(tens[nd], (x + tens[nd + 1] - 2) // (tens[nd + 1] - 1))
local hi = math.min(x // lo, math.floor(math.sqrt(x)))
local t = dtally(x)
local a = lo
while a <= hi do
local b = x // a
local t2 = dtally(a) + dtally(b)
if a * b == x and ((a % 10) > 0 or (b % 10) > 0) and t == t2 then
f:insert(a)
end
a += 1
end
return f
end
local function showfangs(x, f)
fmt.write("%6d", x)
if #f > 1 then print() end
for f as a do fmt.print(" = %3d x %3d", a, x // a) end
end
init()
local x = 1
local n = 0
while n < 25 do
local f = fangs(x)
if #f > 0 then
n += 1
fmt.write("%2d: ", n)
showfangs(x, f)
end
x += 1
end
print()
for {16758243290880, 24959017348650, 14593825548650} as y do
local f = fangs(y)
if #f > 0 then
showfangs(y, f)
else
fmt.print("%d is not vampiric", y)
end
end