# factorial table expansion

3 messages
Open this post in threaded view
|

## factorial table expansion

 ```I'm a novice trying to generate factorial table expansion as described below. I am able to do this with many nested for loops, but I seem unable to do this in the proper spirit of lua table and iteration techniques (e.g. the permutations generater in PiL 9.1). The idea is to turn a table of tables like this: factors={ side = { left = -1, right = 1 }, duration = { short = 200, med = 500, long = 800 }, validity = { valid = 1, invalid = 0 } } into a table containing one table for every possible combination of factor levels, for the above example a table of 2*3*2 entries: conditions = { { left, short, valid }, { left, short, invalid }, { left, med, valid }, { left, med, invalid }, { left, long, valid }, { left, long, invalid }, { right, short, valid }, { right, short, invalid }, { right, med, valid }, { right, med, invalid }, { right, long, valid }, { right, long, invalid }, } My code below should illustrate what I mean about not being in the spirit of lua! I'd very much appreciate ideas about how to improve this novice effort! Rob ----- function icount(t) local k, v local i = 0 for k, v in pairs(t) do if v then i = i+1 end end return i end function createdesign(design, repsPerBlock, nblocks) local repsPerBlock = repsPerBlock or 1 local nblocks = nblocks or 1 local nconds = 1 local nlvls = {} local conds = {} local nfactor = icount(design) for f,lvls in pairs(design) do if lvls then nlvls[f] = icount(lvls) nconds = nconds * nlvls[f] end end blocksize = nconds*repsPerBlock ntrials = blocksize * nblocks for i = 1, ntrials do conds[i] = {} end ncycles = 1 for f, lvls in pairs(design) do nlevels = icount(lvls) trlsPerCyc = blocksize/ncycles nreps = trlsPerCyc/nlevels trialsthisblock = 0 while( trialsthisblock < blocksize) do for cycle = 1, ncycles do for level in pairs(lvls) do for rep = 1, nreps do for block = 1, nblocks do trialno = (block-1)*blocksize + trialsthisblock+1 value = level print(trialno,value) conds[trialno][f] = value end -- block trialsthisblock = trialsthisblock+1 end -- rep end -- level end -- cycle ncycles = ncycles * nlevels end -- trialsthisblock end -- factor return conds end -- This mail sent through http://webmail.bangor.ac.uk ```
 ```Ah, okay, you are computing a cartesian product of some sets. There's a snazzy, functional programming way of doing it using a 'fold' and just a simple pairwise cartesian product function. Here is the code -- if it is Greek to you, let me know and I can try to explain it better: -- some utility functions, boorrrring! local yield = coroutine.yield local function yieldAll(coro) for e in coro do yield(e) end end function makeTable(iterator) local t = {}; for e in iterator do t[#t+1] = e end return t end function flatten(obj) return coroutine.wrap(function() if type(obj)~="table" then yield(obj) else for _,e in ipairs(obj) do yieldAll(flatten(e)) end end end) end -- Okay, now the meat of it: function fold(tab, operator) local seed = tab[1] for i=2,#tab do seed = operator(seed, tab[i]) end return seed end function cartesian(t1, t2) local c = {} for _,i in ipairs(t1) do for _,j in ipairs(t2) do c[#c+1] = {i,j} end end return c end --- Example use local groups = { {'a','b'}, {1,2,3}, {'p','q','r'} } -- add as many as you want local product = fold(groups, cartesian) for _,p in ipairs(product) do local t = makeTable(flatten(p)) --> e.g. {a,2,q} print(unpack(t)) end And voila! the output: a 1 p a 1 q a 1 r a 2 p a 2 q a 2 r a 3 p a 3 q a 3 r b 1 p b 1 q b 1 r b 2 p b 2 q b 2 r b 3 p b 3 q b 3 r Best, Paul ```
 In reply to this post by R.A.Ward ```On Sun Apr 2, 2006 20:06, Paul Chuisano wrote: >Ah, okay, you are computing a cartesian product of some sets. There's >a snazzy, functional programming way of doing it using a 'fold' and >just a simple pairwise cartesian product function. Here is the code -- >if it is Greek to you, let me know and I can try to explain it better: That looks brilliant. It will take me some time to understand it, but I'm looking forward to that. Thanks! Rob ```