

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 = (block1)*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


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

