lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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