Lua 1640 (1558 không phân luồng)
Phiên bản luồng, đánh gôn (1640 ký tự):
L=loadstring L(([[z=table p=z.insert P=z.remove W=io.write t="><^v/\\|_#x+-*,%=)(!?:~$@&r}{gponi;[].m"C=t.char B=t.byte F=t.match M=setmetatable Q=getfenv R=setfenv I=io.read w="@h1,0@h-1,0@h0,-1@h0,1@h-Y,-X@hY,X|X=-X|Y=-Y@h-X,-Y|z=math.random(1,4)R(f[('><^v'):sub(z,z)],Q())()|@c@a+@a)|@c-@a+@a)|@c@a*@a)|z=@a@pz~=0 @b@c@a/z)@rerror'Div by 0'@d|y=@az=@a@cz%y)|@c@a==@a@n1@g0)|@c@a>@a@n1@g0)|@c@a<@a@n1@g0)|@i|@p#s==0@gs[#s]==0 @b@i@d|@cs[#s])|@a|z=#s s[z@k-1]=s[z-1@k]|z=#s s[z@k-1@k-2]=s[z-1@k-2@k]|@pr @b@cr)r=N @rr=@a@d|z={}@o=1,#s@qz[#s-k+1]=s[k]@ds=z|@c1,@a)|@cP(s,1))|z=@a@cc[@a][z])|z,w=@a,@ac[@a][w]=z|W(C(@a))|W(@a)|z=I(1)while F(z,'%s')@qz=I(1)@d@cB(z))|os.exit()|T.N=1|P(T,I)@o=I,#T@qT[k].I=k@d|s=s==S@nl@gS|z=s==S@nl@gS @o=#s,1,-1@qp(z,P(s,1))@d|"z=1 f={}@o in t:gmatch"."@q_,z,s=w:find("|(.-)|",z)f[k]=L(s)@dT={m@j)@i @py>#c @by=0 @fy<0 @by=#c@d@px>#c[y]@nX==1 @bx=0 @fx<0 @bx=#c[y]@d@d,n@jx,y,X,Y)z=M({I=#T+1,l={},X=X@g1,Y=Y@g0,x=x@g0,y=y@g0},{__index=_G})z.s=z.l T[z.I]=z@d}c={}S={}T.n(-1)fh=arg[1]@nio.open(arg[1])@gio.stdin y=0 for l in fh:lines()@qc[y]=M({},{__index@j)return 32@d})@o=1,#l@qz=l:sub(k,k) @pnot i @b@pF(z@l@bi=z@d@pF(z,"[^\n\r]")@b@m@d@r@pz==i @bi=N@d@m@d@dy=y+1@dwhile #T>0@qfor I=1,#T@qt=T[I]R(1,t)R(T.m,t)()n,o=X,Y q=C(c[y][x])@pi @b@pF(q@l@bi=N @r@cc[y][x])@d@fF(q@l @bi=q @fF(q,"%x")@b@ctonumber(q,16))@fF(q,"[^ ]")@bsetfenv(f[q],t)()@d@d@pT.N@n(n~=X@go~=Y)@bT.n(x,y,X,Y)T.N=N X,Y=n,o@d@d]]):gsub("@(.)",{a="P(s)",b="then ",c="p(s,",d=" end ",f="elseif ",g=" or ",h="|X,Y=",i="x,y=x+X,y+Y",j="=function(",k="],s[z",l=[[,"['\"]")]],m="c[y][k-1]=B(z)",n=" and ",o="for k",p="if ",q=" do ",r="else "}))()
Phiên bản phân luồng thực hiện một số hack khó chịu với setfenv và getfenv để loại bỏ nhu cầu lập chỉ mục cho các luồng khác nhau.
Phiên bản luồng có thể đọc được:
-- http://codegolf.stackexchange.com/questions/1595/interpret-fish
z=table
p=z.insert -- push
P=z.remove -- pop
W=io.write
t="><^v/\\|_#x+-*,%=)(!?:~$@&r}{gponi;[].m" -- all tokens
C=t.char
B=t.byte
F=t.match
M=setmetatable
Q=getfenv
R=setfenv
I=io.read
--w=("@d1,0@d-1,0@d0,-1@d0,1@d-Y,-X@dY,X|X=-X|Y=-Y@d-X,-Y|z=math.random(1,4)R(f[('><^v'):sub(z,z)],Q())()|@b@a+@a)|@b-@a+@a)|@b@a*@a)|z=@aif z~=0@i@b@a/z)else error'Div by 0'end|y=@az=@a@bz%y)|@b@a==@a @c@b@a>@a@c@b@a<@a@c@h|if #s==0 or s[#s]==0@i@h end|@bs[#s])|@a@gs[z-1]=@e]@g@e-2]=@e-2],s[z]|if r@i@br)r=N else r=@aend|z={}for k=1,#s do z[#s-k+1]=s[k]end s=z|@b1,@a)|@bP(s,1))|z=@a@bc[@a][z])|z,w=@a,@ac[@a][w]=z|W(C(@a))|W(@a)|z=I(1)while F(z,'%s')do z=I(1)end @bB(z))|os.exit()|T.N=1|P(T,I)for k=I,#T do T[k].I=k end|s@f|z@f for k=#s,1,-1 do p(z,P(s,1))end|"):gsub("@(.)",{a="P(s)",b="p(s,",c="and 1 or 0)|",d="|X,Y=",e="s[z-1],s[z",f="=s==S and l or S",g="|z=#s s[z],",h="x,y=x+X,y+Y",i=" then "})
w="|X,Y=1,0|X,Y=-1,0|X,Y=0,-1|X,Y=0,1|X,Y=-Y,-X|X,Y=Y,X|X=-X|Y=-Y|X,Y=-X,-Y|z=math.random(1,4)R(f[('><^v'):sub(z,z)],Q())()|p(s,P(s)+P(s))|p(s,-P(s)+P(s))|p(s,P(s)*P(s))|z=P(s)if z~=0 then p(s,P(s)/z)else error'Div by 0'end|y=P(s)z=P(s)p(s,z%y)|p(s,P(s)==P(s) and 1 or 0)|p(s,P(s)>P(s)and 1 or 0)|p(s,P(s)<P(s)and 1 or 0)|x,y=x+X,y+Y|if #s==0 or s[#s]==0 then x,y=x+X,y+Y end|p(s,s[#s])|P(s)|z=#s s[z],s[z-1]=s[z-1],s[z]|z=#s s[z],s[z-1],s[z-2]=s[z-1],s[z-2],s[z]|if r then p(s,r)r=N else r=P(s)end|z={}for k=1,#s do z[#s-k+1]=s[k]end s=z|p(s,1,P(s))|p(s,P(s,1))|z=P(s)p(s,c[P(s)][z])|z,w=P(s),P(s)c[P(s)][w]=z|W(C(P(s)))|W(P(s))|z=I(1)while F(z,'%s')do z=I(1)end p(s,B(z))|os.exit()|T.N=1|P(T,I)for k=I,#T do T[k].I=k end|s=s==S and l or S|z=s==S and l or S for k=#s,1,-1 do p(z,P(s,1))end|"
z=1
f={}
for k in t:gmatch"." do -- will contain the tokens
_,z,s=w:find("|(.-)|",z)
f[k]=loadstring(s)
end
T={ -- table of threads
--N = new thread to be created.
m=function()
x,y=x+X,y+Y
if y > #c then
y=0
elseif y<0 then
y=#c
end
if x>#c[y] and X==1 then
x=0
elseif x<0 then
x=#c[y]
end
end,
n=function(x,y,X,Y)
z=M({
I=#T+1, -- keep number id
l={}, -- local stack
X=X or 1, -- 1 for +x, -1 for -x, 0 for y/-y
Y=Y or 0, -- 1 for +y, -1 for -y, 0 for x/-x
x=x or 0, -- X of IP
y=y or 0, -- Y of IP
-- i, -- will contain type of quote when reading in a string --TODO keep local
-- r, -- registry --TODO make global
},{__index=_G}) -- Enable lookup of functions in global table.
z.s=z.l -- current stack is local stack
T[z.I]=z -- add at next index
end
}
c={} -- codebox IP wraps around -- TODO make codebox global in code
S={} -- global stack
-- codebox layout
-- -----> +x
-- @ |line of text -- wrap around to second line
-- |second line of text. -- negative indices can be used for variables
-- |
-- V +Y
-- y first coord, x second
-- wrap around rows if nil row
-- wrap around cols if nil char.
T.n(-1)
-- compile to codebox
fh= arg[1] and io.open(arg[1]) or io.stdin -- use file or stdin
y=0
for l in fh:lines() do
c[y]=M({},{__index=function()return 32 end})--default to space
for k=1,#l do
z=l:sub(k,k)
if not i then -- normal mode
if F(z,"['\"]") then i=z end
if F(z,"[^\n\r]")then --filter out only newlines
c[y][k-1]=B(z)
end -- any spacing allowed.
else
if z==i then i=N end-- verbatim string mode
c[y][k-1]=B(z)
end
end
y=y+1
end
io.stdout:setvbuf("no") -- direct output
while #T>0 do
for I=1,#T do
t=T[I]
R(1,t)
R(T.m,t)()
n,o=X,Y -- keep old directions for new thread detection
q=C(c[y][x])
if i then -- stringparsing mode
if F(q,"['\"]") then -- end-quote
i=N
else
p(s,c[y][x]) -- push contents of box, then advance
end
elseif F(q,"['\"]") then -- start-quote
i=q
elseif F(q,"%x") then -- parsing a number
p(s,tonumber(q,16))
elseif F(q,"[^ ]") then
assert(setfenv(f[q],t))
f[q]() -- call, feed with state/thread
end
end
if T.N and (n~=X or o~=Y) then
-- create new thread
T.n(x,y,X,Y)
T.N=N
X,Y=n,o -- restore directions of parent
end
end
Phiên bản Nonthreading, được đánh gôn (1558 ký tự, nhưng có thể được thu nhỏ hơn một chút nếu phiên bản không phân luồng sẽ là tiêu chí):
T=table p=T.insert P=T.remove I=io.read W=io.write A=assert t="><^v/\\|_#x+-*,%=)(!?:~$@&r}{gponi;"M=t.match B=t.byte C=t.char f={"X,Y=1,0","X,Y=-1,0","X,Y=0,-1","X,Y=0,1","X,Y=-Y,-X","X,Y=Y,X","X=-X","Y=-Y","X,Y=-X,-Y","z=math.random(1,4)f[('><^v'):sub(z,z)]()","p(s,P(s)+P(s))","p(s,-P(s)+P(s))","p(s,P(s)*P(s))","p(s,(1/P(s) or error'Div by 0')*P(s))","y=P(s)z=P(s)p(s,z%y)","p(s,P(s)==P(s) and 1 or 0)","p(s,P(s)>P(s) and 1 or 0)","p(s,P(s)<P(s) and 1 or 0)","x,y=x+X,y+Y","if #s==0 or s[#s]==0 then f['!']()end","p(s,s[#s])","P(s)","z=#s s[z],s[z-1]=s[z-1],s[z]","z=#s s[z],s[z-1],s[z-2]=s[z-1],s[z-2],s[z]","if r then p(s,r)r=N else r=P(s)end","z={}for k=1,#s do z[#s-k+1]=s[k]end s=z","p(s,1,P(s))","p(s,P(s,1))","z=P(s) p(c[P(s)][z])","z,w=P(s),P(s) c[P(s)][w]=z","W(C(P(s)))","W(P(s))","z=I(1) while M(z,'%s')do z=I(1)end p(s,B(z))","os.exit()"}z=1 for k in t:gmatch"."do f[k]=A(loadstring(f[z]))z=z+1 end c={}s={}X=1 Y=0 x=0 y=0 m=function(s)x,y=x+X,y+Y if y>#c then y=0 elseif y<0 then y=#c end if x>#c[y]and X==1 then x=0 elseif x<0 then x=#c[y]end end F=arg[1]and io.open(arg[1])or io.stdin l=0 for line in F:lines()do c[l]=setmetatable({},{__index=function()return 0 end})for k=1,#line do z=line:sub(k,k)if not i then if M(z,"['\"]")then i=z end if M(z,"[^\n\r]")then c[l][k-1]=B(z)end else if z==i then i=N end c[l][k-1]=B(z)end end l=l+1 end while 1 do q=C(c[y][x])if i then if M(q,"['\"]")then i=N else p(s,c[y][x])end else if M(q,"['\"]")then i=q elseif M(q,"%x")then p(s,tonumber(q,16)) elseif M(q,"[^ %z]")then A(f[q])f[q]()end end m()end
Phiên bản dễ đọc:
-- http://codegolf.stackexchange.com/questions/1595/interpret-fish
--
-- TODO's
-- threading instructions:
-- * [ start thread at next change in direction.
-- * ] end thread
-- * . switch between global and local stack
-- * m copy global to local stack
--
p=table.insert -- push
P=table.remove -- pop
t=table.concat{
"><^v", -- Direction DONE
"/\\|_#", -- Mirror DONE
"x", -- random direction DONE
"+-*,%", -- arithm. DONE
"=)(", -- pops A and B of the stack if A==B then push 1 else push 0,same for greater than, lesser than. (result on stack) -- DONE
"!", -- skip next DONE
"?", -- if s[#s]==0 then skip next, else continue DONE
":", -- duplicate top DONE
"~", -- remove top DONE
"$", -- rotate top 2 values DONE
"@", -- rotate top 3 values DONE
"&", -- poptop to registry or read from registry DONE
"r", -- reverse stack DONE
"}{", -- shift stack right, (or up)/ shift stack left (or down) DONE
"g", -- pops A,B push values at B,A in the codebox on the stack DONE
"p", -- pops A,B,C from stack, and change value at C,B to A DONE
"o", -- pops from stack and output character DONE
"n", -- pops from stack, outputs number DONE
"i", -- take 1 char of input, and push the ASCII value on stack DONE
";", -- os.exit() DONE
--[["[", -- start new thread at next direction change
"]", -- end thread
".", -- switch between global and local stack
"m", -- Copy global stack to local one --]]
}
f={
"s.dx,s.dy=1,0","s.dx,s.dy=-1,0","s.dx,s.dy=0,-1","s.dx,s.dy=0,1",
"s.dx,s.dy=-s.dy,-s.dx","s.dx,s.dy=s.dy,s.dx","s.dx=-s.dx","s.dy=-s.dy","s.dx,s.dy=-s.dx,-s.dy",
"z=math.random(1,4)f[('><^v'):sub(z,z)]()",
"p(s.s,P(s.s)+P(s.s))","p(s.s,-P(s.s)+P(s.s))","p(s.s,P(s.s)*P(s.s))","p(s.s,(1/P(s.s) or error'Div by 0')*P(s.s))","y=P(s.s)z=P(s.s)p(s.s,z%y)",
"p(s.s,P(s.s)==P(s.s) and 1 or 0)",
"p(s.s,P(s.s)>P(s.s) and 1 or 0)",
"p(s.s,P(s.s)<P(s.s) and 1 or 0)",
"s.x,s.y=s.x+s.dx,s.y+s.dy",
"if #s.s==0 or s.s[#s.s]==0 then f['!']()end",
"p(s.s,s.s[#s.s])",
"P(s.s)",
"z=#s.s s.s[z],s.s[z-1]=s.s[z-1],s.s[z]",
"z=#s.s s.s[z],s.s[z-1],s.s[z-2]=s.s[z-1],s.s[z-2],s.s[z]",
"if s.r then p(s.s,s.r)s.r=nil else s.r=P(s.s)end",
"z={}for k=1,#s.s do z[#s.s-k+1]=s.s[k]end s.s=z",
"p(s.s,1,P(s.s))",
"p(s.s,P(s.s,1))",
"z=P(s.s) p(s.s,s.c[P(s.s)][z])",
"z,w=P(s.s),P(s.s) s.c[P()][w]=z",
"io.write(string.char(P(s.s)))",
"io.write(P(s.s))",
"z=io.read(1) while z:match'%s'do z=io.read(1)end p(s.s,z:byte())",
"os.exit()"
}
z=1
for k in t:gmatch"." do -- will contain the tokens
f[k]=assert(loadstring(f[z]))
z=z+1
end
s={ -- state
c={}, -- codebox IP wraps around
s={}, -- stack
dx=1, -- 1 for +x, -1 for -x, 0 for y/-y
dy=0, -- 1 for +y, -1 for -y, 0 for x/-x
x=0, -- X of IP
y=0, -- Y of IP
-- i, -- will contain type of quote when reading in a string
-- r, -- registry
-- codebox implementation
-- codebox layout
--
--
-- -----> +x
-- @ |line of text -- wrap around to second line
-- |second line of text. -- negative indices can be used for variables
-- |
-- V +Y
-- y first coord, x second
-- wrap around rows if nil row
-- wrap around cols if nil char.
move=function(s)
s.x,s.y=s.x+s.dx,s.y+s.dy
if s.y > #s.c then
s.y=0
elseif s.y<0 then
s.y=#s.c
end
if s.x>#s.c[s.y] and s.dx==1 then
s.x=0
elseif s.x<0 then
s.x=#s.c[s.y]
end
end
}
-- compile to codebox
fh= arg[1] and io.open(arg[1]) or io.stdin -- use file or stdin
y=0
for line in fh:lines() do
s.c[y]=setmetatable({},{__index=function() return 0 end})
for k=1,#line do
z=line:sub(k,k)
--print(y,k,"|"..z.."|")
if not s.i then -- normal mode
if z:match"['\"]" then s.i=z end
if z:match"[^\n\r]"then --filter out only newlines
s.c[y][k-1]=string.byte(z)
end -- any spacing allowed.
else -- verbatim string mode
if z==s.i then s.i=nil end
s.c[y][k-1]=string.byte(z)
end
end
y=y+1
end
io.stdout:setvbuf("no") -- direct output
function dbg()
print("\nIP",s.y,s.x)
print("command",string.char(s.c[s.y][s.x]))
print("codebox:",#s.c)
for y=0,#s.c do
print("\tline",y)
io.write"\t"
for x=0,#s.c[y] do
--io.write(string.char(s.c[y][x]),",\t")
io.write(tostring(s.c[y][x]),",\t")
end
io.write"\n"
end
print("stack:")
for k,v in pairs(s.s) do print("",k,v) end
end
function run()
while 1 do
r,e = pcall(string.char,s.c[s.y][s.x]) -- look up command in codebox
if not r then print("Error happened reading command",s.c[s.y][s.x])
dbg()
end
q=string.char(s.c[s.y][s.x])
--print(s.y,s.x,q)
if s.i then -- stringparsing mode
if q:match"['\"]" then -- end-quote
s.i=nil
else
p(s.s,s.c[s.y][s.x]) -- push contents of box, then advance
end
else -- not in string parsing mode
if q:match"['\"]" then -- start-quote
s.i=q
elseif q:match"%x" then -- parsing a number
p(s.s,tonumber(q,16))
elseif q:match"[^ %z]" then
assert(f[q])
r,e= pcall(f[q]) -- call
if not r then print("Error calling function for "..q..": \n",e) -- error happened, clarify
end
end
end
s:move() -- move the IP
end
end
r,e=pcall(run)
if not r then print("Error occured:",e)
dbg()
end
Không đặt kết quả tiếp theo là kết quả, vì sử dụng nén trực tiếp không phải là mục tiêu tôi đoán;). Sử dụng murgaLua (hoặc bất kỳ phiên bản Lua nào có lzlib và luaSocket (để giải mã base64)), với số lượng ma thuật là 1333:
L=loadstring L(zlib.decompress(mime.unb64("eJxtVW1z4jYQ/iuqaYp0yD587fQDzaadS+c6zPQyd4lnjgw4DC8ieACZyE6wDeS3d1fCB6H3AbTa12ff5Ary0Xip2BqqINGZMjn7gqRRq/RFsW+QpMHGJLliOXhXlw8v7weD3bBRtPx38gIE/+nPzuvPf/1i9tvHdaqTP/pxsPKuIQ8m85FhH5EYl2j8CYnVKJ/M2WfIVL5S+ciF/QqPKp8p/cJuSWCpLgU1ajRlG/B2PXkPoWzb06+JtvTDA+FO/176PUvdSzwBL8R0sp5EqgIEMA/MSE/TFQ/lb+KWz/q8SUk1RSd7HvNKViKWX7kQXOzWPJNfeCZa9Oeu/tmdqHfuWgGdyYxVr9Bm+VxpVmu8r4RaZoopY1LT/Dt5YeOStZtKT3eltXK2pF5dlEfPYNkM8bKQpYa1j6Ir+vuR4PJcUMgSilZPlq37HaJrZIDwUJT1G1kMNdQTLUa4yJ3VEDtyiNk1MjSpYuRWfhiDO+gW/09ojw+nOnhzqojAHItjhIEbZmtjbK4UuoLtfoYAF9h09DtNWYVA/EXLRl3EqMMyqCzEUL7phQy/N4I4kz5RMcZFrtxYvjWoBZsY/Xzj19x6EUjWvezyUGzmCc7nJxyK5kXWFATE8gkAuf/IK9RNs0AVSY7zEgU3EGK5ItkVLoGubESUQISwgy4sbGkzwBbc2a4uqRF3GO6Mw5x5gxL0Q/KwRhSHBMmHV0HIZnWhWKJZ3nm06+UFHqoPZSUz2HRmiZ5yb8cDX+w8nO0ZAoF/XaFZBNsVzJ71JE9SzcXpCGCbyqvGxHWqxCGhHhHzsl3zUEpOkFmgZr+MCX4PEJcbqKNRURsVYBXJjJGx1MfwGF3iquIqfObbLjSiViiXmKDsQY9qEtJi25GWBRSOKKG0xF5uh0PMVBUw/GcvqgDHI1hi1augix2mUPsJ+rrDXxRo7odiNoeReeyHFjU+Nulaae44Al0iJ8unicudarykGs/mnWWiVcZpFigTwnoS/FhLo/Jno9mvH2xs8X2cl3acYWkfm4VcCKqfTnOWuArhjebN6zcHXuwJx3MZHGUPAz0wtZRg9Be0kTSOpGfXid4hgNorLRlKfqCLP6xiK7SUG/hGdNUmmAS6S6DtCOcQ9bvxLT6bOT6bUbDCkwstU8CusSe45tZ7EdMTeJrN03k2h4V3C+pMathnBjX6pzfCi+LgijzkqX5ejZVBQfi7EG+cPLA66OG7gq/9U2xx17mjLm4tbR7Xr27Q0le4d1Y0KvVY0m7fMPqWYMrsYP4fCvRCgw==")))()