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]




