¿Cómo contaría manualmente en papel? Verificaría el último dígito. Si es 0, lo configura en 1. Si ya es 1, lo vuelve a establecer en 0 y continúa con el siguiente dígito. Entonces es un proceso recursivo.
El siguiente programa genera todas las combinaciones posibles mediante la mutación de una secuencia:
#include <iostream>
template <typename Iter>
bool next(Iter begin, Iter end)
{
if (begin == end) // changed all digits
{ // so we are back to zero
return false; // that was the last number
}
--end;
if ((*end & 1) == 0) // even number is treated as zero
{
++*end; // increase to one
return true; // still more numbers to come
}
else // odd number is treated as one
{
--*end; // decrease to zero
return next(begin, end); // RECURSE!
}
}
int main()
{
char test[] = "0000";
do
{
std::cout << test << std::endl;
} while (next(test + 0, test + 4));
}
El programa funciona con cualquier secuencia de cualquier tipo. Si necesita todas las combinaciones posibles al mismo tiempo, simplemente colóquelas en una colección en lugar de imprimirlas. Por supuesto, necesita un tipo de elemento diferente, porque no puede poner matrices C en un vector. Vamos a usar un vector de cadenas:
#include <string>
#include <vector>
int main()
{
std::vector<std::string> combinations;
std::string test = "0000";
do
{
combinations.push_back(test);
} while (next(test.begin(), test.end()));
// now the vector contains all pssible combinations
}
Si no te gusta la recursividad, aquí es una solución iterativa equivalente:
template <typename Iter>
bool next(Iter begin, Iter end)
{
while (begin != end) // we're not done yet
{
--end;
if ((*end & 1) == 0) // even number is treated as zero
{
++*end; // increase to one
return true; // still more numbers to come
}
else // odd number is treated as one
{
--*end; // decrease to zero and loop
}
}
return false; // that was the last number
}
@Fred si sé una respuesta Lisp y C# respuesta se me permite añadir "[Lisp]" y "[C#]" o deberíamos simplemente reemplazar todos los de "[independiente del idioma]"? –
@Johannes: Me encantaría ver las soluciones LISP y C# :-) Agregué la etiqueta C++ porque Nils publicó la pregunta en el chat C++, así que supuse que estaba interesado en una solución C++. Y agregué la etiqueta Haskell para que los programadores reales de Haskell pudieran mejorar mi solución Haskell. – fredoverflow