For some experiment I’m conducting, I needed to generate all permutations given a number of slots and a number of symbols. I also didn’t want to use built-in libraries like Python or other languages have to generate them, so I picked Lua to avoid being tempted to do so (and because its a cool language).
Now there are Lua implementations to do this, for example on Rosetta Code but the all examples I’ve seen either use recursion or appeared oversized.
I wrote the following non-recursive function in Lua to generate permutations given as input a number of slots and a number of symbols.
-- generate permutations -- input a, b (a number of slots, b number of symbols) function permutations(a,b) if a==0 then return end local taken = {} local slots = {} for i=1,a do slots[i]=0 end for i=1,b do taken[i]=false end local index = 1 while index > 0 do repeat repeat slots[index] = slots[index] + 1 until slots[index] > b or not taken[slots[index]] if slots[index] > b then slots[index] = 0 index = index - 1 if index > 0 then taken[slots[index]] = false end break else taken[slots[index]] = true end if index == a then for i=1,a do io.write( slots[i] ) io.write( " " ) end io.write( "n") taken[slots[index]] = false break end index = index + 1 until true end end
The following is in generator form:
function perm( sl, sy ) local permutations = function( a,b ) if a==0 then return end local taken = {} local slots = {} for i=1,a do slots[i]=0 end for i=1,b do taken[i]=false end local index = 1 while index > 0 do repeat repeat slots[index] = slots[index] + 1 until slots[index] > b or not taken[slots[index]] if slots[index] > b then slots[index] = 0 index = index - 1 if index > 0 then taken[slots[index]] = false end break else taken[slots[index]] = true end if index == a then coroutine.yield(slots) taken[slots[index]] = false break end index = index + 1 until true end end return coroutine.wrap(function () permutations(sl, sy) end) end function test(a,b) ci = perm(a,b) a = ci() while a~=nil do for i=1,#a do io.write( a[i] ) io.write( " " ) end io.write( "n") a = ci() end end
This method can probably be improved since it goes over all possible combinations (both repeating and non-repeating) and in the process filters out the repeating ones.