Log In  


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...

7


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.


1

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]