RosettaCodeData/Task/Arithmetic-Rational/Lua/arithmetic-rational.lua

59 lines
1.8 KiB
Lua

function gcd(a,b) return a == 0 and b or gcd(b % a, a) end
do
local function coerce(a, b)
if type(a) == "number" then return rational(a, 1), b end
if type(b) == "number" then return a, rational(b, 1) end
return a, b
end
rational = setmetatable({
__add = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.den + a.den * b.num, a.den * b.den)
end,
__sub = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.den - a.den * b.num, a.den * b.den)
end,
__mul = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.num, a.den * b.den)
end,
__div = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.den, a.den * b.num)
end,
__pow = function(a, b)
if type(a) == "number" then return a ^ (b.num / b.den) end
return rational(a.num ^ b, a.den ^ b) --runs into a problem if these aren't integers
end,
__concat = function(a, b)
if getmetatable(a) == rational then return a.num .. "/" .. a.den .. b end
return a .. b.num .. "/" .. b.den
end,
__unm = function(a) return rational(-a.num, -a.den) end}, {
__call = function(z, a, b) return setmetatable({num = a / gcd(a, b),den = b / gcd(a, b)}, z) end} )
end
print(rational(2, 3) + rational(3, 5) - rational(1, 10) .. "") --> 7/6
print((rational(4, 5) * rational(5, 9)) ^ rational(1, 2) .. "") --> 2/3
print(rational(45, 60) / rational(5, 2) .. "") --> 3/10
print(5 + rational(1, 3) .. "") --> 16/3
function findperfs(n)
local ret = {}
for i = 1, n do
sum = rational(1, i)
for fac = 2, i^.5 do
if i % fac == 0 then
sum = sum + rational(1, fac) + rational(fac, i)
end
end
if sum.den == sum.num then
ret[#ret + 1] = i
end
end
return table.concat(ret, '\n')
end
print(findperfs(2^19))