Lua,876字节
function I(a)a.s=a.s:gsub("(%d)(9*)$",function(n,k)return tostring(tonumber(n)+1)..("0"):rep(#k)end)end function D(a)a.s=a.s:gsub("(%d)(0*)$",function(n,k)return tostring(tonumber(n)-1)..("9"):rep(#k)end):gsub("^0+(%d)","%1")end function m(a,b)local A=K(a)local B=K(b)while V(0,B)do D(A)D(B)end return A end function M(a,b)local A=K(a)local B=K(b)while V(m(B,1),A)do A=m(A,B)end return A end function l(n)return#n.s end function p(a)local A=K(a)local i=K(2)while V(i,A)do if V(M(A,i),1)then return false end I(i)end return true end function V(b,a)A=K(a)B=K(b)if l(A)>l(B)then return true end if l(B)>l(A)then return false end for i=1,l(A)do c=A.s:sub(i,i)j=B.s:sub(i,i)if c>j then return true elseif c<j then return false end end return false end function K(n)if(type(n)=='table')then return{s=n.s}end return{s=tostring(n)}end P=K(io.read("*n"))repeat I(P)until p(P)print(P.s)
与其他语言不同,Lua确实具有最大整数大小。一旦数字大于2 32,事情就会停止正常工作,Lua开始尝试估算而不是精确值。
因此,我必须实现一种存储数字的新方法,特别是,我将它们存储为Base10字符串,因为Lua除了内存的大小外,对字符串没有大小限制。
我觉得这个答案对问题的精神更重要,因为它必须实现任意精度的整数,以及一个素数测试。
解释
-- String Math
_num = {}
_num.__index = _num
-- Increase a by one.
-- This works by grabbing ([0-9])999...$ from the string.
-- Then, increases the first digit in that match, and changes all the nines to zero.
-- "13", only the "3" is matched, and it increases to 1.
-- "19", firstly the 1 is turned to a 2, and then the 9 is changed to a 0.
-- "9" however, the 9 is the last digit matched, so it changes to "10"
function _num.inc(a)
a.str = a.str:gsub("(%d)(9*)$",function(num,nines)
return tostring(tonumber(num)+1)..("0"):rep(#nines)
end)
end
-- Decrease a by one
-- Much like inc, however, uses ([0-9])0...$ instead.
-- Decrements ([0-9]) by one and sets 0... to 9...
-- "13" only the "3" is matched, and it decreases by one.
-- "10", the "1" is matched by the ([0-9]), and the 0 is matched by the 0..., which gives 09, which is clipped to 9.
function _num.dec(a)
a.str = a.str:gsub("(%d)(0*)$",function(num,zeros)
return tostring(tonumber(num)-1)..("9"):rep(#zeros)
end) :gsub("^0+(%d)","%1")
end
-- Adds a and b
-- Makes A and B, so that the original values aren't modified.
-- B is then decremented until it hits 0, and A is incremented.
-- A is then returned.
function _num.__add(a,b)
local A = str_num(a)
local B = str_num(b)
while B > 0 do
A:inc()
B:dec()
end
return A
end
-- Subs b from a
-- Works just like Addition, yet Dec's A instead of Incs.
function _num.__sub(a,b)
local A = str_num(a)
local B = str_num(b)
while B > 0 do
A:dec()
B:dec()
end
return A
end
-- A % B
-- Makes A and B from a and b
-- Constantly subtracts B from A until A is less than B
function _num.__mod(a,b)
local A = str_num(a)
local B = str_num(b)
while A >= B do
A = A - B
end
return A
end
-- #a
-- Useful for golfiness
function _num.__len(n)
return #n.str
end
-- Primacy Testing
-- Generates A from a and i from 2.
-- Whilst i is less than A, i is incremented by one, and if A % i == 0, then it's not a prime, and we return false.
-- Once that finishes, we return true.
function _num.isprime(a)
local A = str_num(a)
local i = str_num(2)
while i < A do
if A%i < 1 then
return false
end
i:inc()
end
return true
end
-- b < a
-- A and B are generated from a and b
-- Fristly, if the length of A and B aren't equal, then that result is output.
-- Otherwise, each character is searched from left to right, the moment they are unequal, the difference is output.
-- If all the characters match, then it's equal. Return false.
function _num.__lt(b,a)
A=str_num(a)
B=str_num(b)
if #A > #B then
return true
end
if #B > #A then
return false
end
for i=1, #A.str do
As = A.str:sub(i,i)
Bs = B.str:sub(i,i)
if As > Bs then
return true
elseif As < Bs then
return false
end
end
return false
end
-- b <= a
-- Same as b < a, but returns true on equality.
function _num.__le(b,a)
A=str_num(a)
B=str_num(b)
if #A > #B then
return true
end
if #B > #A then
return false
end
for i=1, #A.str do
As = A.str:sub(i,i)
Bs = B.str:sub(i,i)
if As > Bs then
return true
elseif As < Bs then
return false
end
end
return true
end
-- Just straight up returns it's string component. Endlessly faster than the int equivalent, mostly because it never is anything _but_ the string form.
function _num.__tostring(a)
return a.str
end
-- Just set up the metatable...
function str_num(n)
if(type(n)=='table')then
return setmetatable({str = n.str}, _num)
end
return setmetatable({str = tostring(n)}, _num)
end
-- Generate a new str_num from STDIN
Prime = str_num(io.read("*n"))
-- This is handy, because it will call Prime:inc() atleast once, and stop at the next prime number it finds.
-- Basically, if it weren't for all that overhead of making the math possible, that's all this would be.
repeat
Prime:inc()
until Prime:isprime()
print(Prime)
尽管上面使用了Metatables,而不是像实际答案这样的常规函数,但实际效果却更小。