It seems I'm using these a lot, so here they are:
----------------- -- table as string ----------------- function tab2str(t) local s="(" for i,v in pairs(t) do if type(i)=="number" then s=s.."["..i.."]=" else s=s..i..'=' end if type(v)=="boolean" then s=s..(v and "true" or "false") elseif type(v)=="table" then s=s..tab2str(v) else s=s..v end s=s..',' end s=sub(s,1,#s-1)--remove last comma return s..')' end ---------- -- example ---------- l={1,2,4,5,s=5} print(tab2str(l)) |
---------------- -- clone a table ---------------- function clone(t) local c={} for i,v in pairs(t) do c[i]=type(v)=="table" and clone(v) or v end return c end |
--------------------------------------------------- -- sort a table (insertion sort) -- cmp(a,b) should return true when a,b are ordered --------------------------------------------------- function insort(t,cmp) for n=2,#t do local i=n while i>1 and not cmp(t[i-1],t[i]) do t[i],t[i-1]=t[i-1],t[i] i-=1 end end end ---------- -- example ---------- function ascending_y(a,b) return a.y<=b.y end t={} for i=1,5 do add(t,{i=i,y=rnd(10)}) print(i..': '..t[i].i..' '..t[i].y) end print("----") insort(t,ascending_y) for i=1,#t do print(i..': '..t[i].i..' '..t[i].y) end |
-- note: better version by kittenm4ster, read below ------------------ -- shuffle a table ------------------ function shuffle(t) for n=1,#t*2 do -- #t*2 times seems enough local a,b=flr(1+rnd(#t)),flr(1+rnd(#t)) t[a],t[b]=t[b],t[a] end return t end ---------- -- example ---------- t={1,2,3,4} for i=1,#t do print(i..': '..t[i]) end print("----") shuffle(t) for i=1,#t do print(i..': '..t[i]) end |
------------------------------ -- random element from a table ------------------------------ function trand(t) return t[flr(1+rnd(#t))] end ---------- -- example ---------- l={1,2,3,4} print(trand(l)) |
-- note: a little overkill token-wise, read below (thanks felice!) ----------------------------------- -- stack (lifo: last in, first out) ----------------------------------- lifo={ new = function() return setmetatable({d={}},lifo) end, clear = function(m) m.d={} end, len = function(m) return #m.d end, empty = function(m) return #m.d==0 end, push = function(m,v) m.d[#m.d+1]=v end, pop = function(m) local v=m.d[#m.d] m.d[#m.d]=nil return v end } lifo.__index=lifo ---------- -- example ---------- stack = lifo.new() stack:push(10) stack:push(20) stack:push(30) while(not stack:empty()) do print(stack:pop()) end |
I think some of these would be handy as part of the pico8 api (clone,sort,shuffle...)
feel free to criticize, comment, correct mine, post yours...
Wouldn't it be easier just to create a stack as a direct table and use two functions like this?
function pop(s) local v=s[#s] s[#s]=nil return v end push=add mystack={} push(mystack,"first") push(mystack,"second") push(mystack,"third") > print(#mystack) 3 > print(pop(mystack)) third > print(pop(mystack)) second > print(pop(mystack)) first > print(pop(mystack)) [nil] |
Granted, it's not OO, but it's much simpler and less overhead. Heck, you don't really even need push
, it's just syntactic sugar.
(I'd love it if @zep included a push/pop like this in the api, but I won't hold my breath. ;) )
I like the trand() idea btw. I do that a lot by hand and never thought to add a helper for it.
fisher-yates is a better algorithm for shuffling; you only have to run it once and you get a statically unbiased shuffle, apparently (actually I know experientially; I ran a test one time ^u^)
function shuffle(t) -- do a fisher-yates shuffle for i = #t, 1, -1 do local j = flr(rnd(i)) + 1 t[i], t[j] = t[j], t[i] end end |
@Felice
I agree! most of those methods are quite mundane anyway. makes code more readable but a little overkill in the token scarce pico8 world.
@zep: adding pop() (return and remove last table element) and get() (return and remove first table element) would be ace!
function pop(s) local v=s[#s] s[#s]=nil return v end function get(s) local v=s[1] for i=2,#s do s[i-1]=s[i] end s[#s]=nil return v end stack = {} add(stack,10) add(stack,20) add(stack,30) while(#stack!=0) do print(pop(stack)) end list = {} add(list,10) add(list,20) add(list,30) while(#list!=0) do print(get(list)) end |
btw I'm quite appalled that I've been mindlessly using a stack with "put/get" instead of "push/pop".
maybe I derived this code from a fifo? I have no idea. correcting at once, introspection pending...
@kittenmaster
thanks a lot! I've been copy/pasting those 45 seconds worth of brainstorming for a while :D
[Please log in to post a comment]