64 lines
1.5 KiB
Lua
64 lines
1.5 KiB
Lua
--- Permutation operations.
|
|
--
|
|
-- Dependencies: `pl.utils`, `pl.tablex`
|
|
-- @module pl.permute
|
|
local tablex = require 'pl.tablex'
|
|
local utils = require 'pl.utils'
|
|
local copy = tablex.deepcopy
|
|
local append = table.insert
|
|
local coroutine = coroutine
|
|
local resume = coroutine.resume
|
|
local assert_arg = utils.assert_arg
|
|
|
|
|
|
local permute = {}
|
|
|
|
-- PiL, 9.3
|
|
|
|
local permgen
|
|
permgen = function (a, n, fn)
|
|
if n == 0 then
|
|
fn(a)
|
|
else
|
|
for i=1,n do
|
|
-- put i-th element as the last one
|
|
a[n], a[i] = a[i], a[n]
|
|
|
|
-- generate all permutations of the other elements
|
|
permgen(a, n - 1, fn)
|
|
|
|
-- restore i-th element
|
|
a[n], a[i] = a[i], a[n]
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
--- an iterator over all permutations of the elements of a list.
|
|
-- Please note that the same list is returned each time, so do not keep references!
|
|
-- @param a list-like table
|
|
-- @return an iterator which provides the next permutation as a list
|
|
function permute.iter (a)
|
|
assert_arg(1,a,'table')
|
|
local n = #a
|
|
local co = coroutine.create(function () permgen(a, n, coroutine.yield) end)
|
|
return function () -- iterator
|
|
local code, res = resume(co)
|
|
return res
|
|
end
|
|
end
|
|
|
|
--- construct a table containing all the permutations of a list.
|
|
-- @param a list-like table
|
|
-- @return a table of tables
|
|
-- @usage permute.table {1,2,3} --> {{2,3,1},{3,2,1},{3,1,2},{1,3,2},{2,1,3},{1,2,3}}
|
|
function permute.table (a)
|
|
assert_arg(1,a,'table')
|
|
local res = {}
|
|
local n = #a
|
|
permgen(a,n,function(t) append(res,copy(t)) end)
|
|
return res
|
|
end
|
|
|
|
return permute
|