Рекурсивное решение выглядит так:
function Enumerate(len, rem)
if rem = 0 then return [0]^len
if len < rem then return {}
if len = rem then return {[1]^rem}
return ({[0]} & Enumerate(len - 1, rem))
union
({[1]} & Enumerate(len - 1, rem - 1))
Обозначение [1]^rem
означает вектор длины rem
, содержащий только 1
; оператор &
возвращает все векторы, полученные путем объединения векторов из RHS, в векторы в LHS. Это короткое замыкание, когда он обнаруживает, что решения не могут быть получены, или когда существует только одно возможное решение, но вы можете удалить это, чтобы напечатать все перестановки и просто проверить их. Пример выполнения:
Enumerate(4, 3) = {[0,1,1,1],[1,0,1,1],[1,1,0,1],[1,1,1,0]}
4 < 3? no
4 = 3? no
[0] & Enumerate(3, 3) = [0] & [1,1,1] = [0,1,1,1]
3 = 0? no
3 < 3? no
3 = 3? yes, return [1,1,1]
[1] & Enumerate(3, 2) = [1] & ([0,1,1],[1,0,1],[1,1,0]| = {[1,0,1,1],[1,1,0,1],[1,1,1,0]}
2 = 0? no
3 < 2? no
3 = 3? no
[0] & Enumerate(2, 2) = [0] & [1,1] = [0,1,1]
2 = 0? no
2 < 2? no
2 = 2? yes, return [1,1]
[1] & Enumerate(2, 1) = [1] & {[0,1],[1,0]) = {[1,0,1],[1,1,0]}
1 = 0? no
2 < 1? no
2 = 1? no
[0] & Enumerate(1, 1) = [0] & [1] = [0,1]
1 = 0? no
1 < 1? no
1 = 1? yes, return [1]
[1] & Enumerate(1, 0) = [1] & [0] = [1,0]
0 = 0? yes, return [0]
Если вы хотите, чтобы это было итеративным, а не рекурсивным, добавьте структуру данных стека и явно управляйте стеком в цикле while, пока стек не пуст.
Если вы хотите, чтобы положение каждого решения в упорядоченном пространстве всех решений - просто интерпретируйте вектор как последовательность цифр двоичного числа len-цифры и добавьте единицу. Таким образом, [0,1,1,1] становится (0111) b = (7) d + 1 = (8) d = 8.