Алгоритм генерации всех возможных массивов единиц и нулей заданной длины
Как я могу генерировать все возможные комбинации битов в массиве битов длины n. Если я начну со всех нулей в моем массиве, то есть n возможностей разместить первый бит, и для этих n возможностей есть n-1 возможностей разместить второй бит.. блок все N битов установлены в один. Но пока мне не удалось его запрограммировать.
также многие люди указали, что я могу сделать это, считая от 0 до (2^n)-1 и печатая число в двоичном формате. Это будет простой способ решить проблему, однако в этом случае я просто позволяю машине считать, а не говорить ей, где разместить их. Я делаю это для обучения, поэтому я хотел бы знать, как запрограммировать подход к размещению.
6 ответов
как бы вы посчитали вручную на бумаге? Вы бы проверили последнюю цифру. Если это 0, вы устанавливаете его в 1. Если он уже равен 1, вы устанавливаете его обратно в 0 и продолжаете со следующей цифрой. Так что это рекурсивный процесс.
следующая программа генерирует все возможные комбинации, мутации в последовательности:
#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));
}
программа работает с любой последовательностью любого типа. Если вам нужны все возможные комбинации одновременно, просто поместите их в коллекцию вместо печати их. Конечно, вам нужен другой тип элемента, потому что вы не можете поместить массивы C в вектор. Давайте используем вектор строк:
#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
}
Если вам не нравится рекурсия, вот эквивалентное итеративное решение:
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
}
такие проблемы тривиально решаются функционально. Чтобы найти решения длины n, вы сначала находите решения длины n-1, а затем добавляете " 0 " и " 1 " к этим решениям, удваивая пространство решений.
вот простая рекурсивная программа Haskell:
comb 0 = [[]]
comb n =
let rest = comb (n-1)
in map ('0':) rest
++ map ('1':) rest
и вот тест:
> comb 3
["000","001","010","011","100","101","110","111"]
" истинно " рекурсивный подход в C++:
#include <iostream>
#include <string>
void print_digits(int n, std::string const& prefix = "") {
if (!n) {
std::cout << prefix << std::endl;
return;
}
print_digits(n-1, prefix + '0');
print_digits(n-1, prefix + '1');
}
int main(int, char**) {
print_digits(4);
}
оптимальное решение здесь:
http://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
вот мой ответ. Преимущество в том, что все комбинации сохраняются в двухмерном массиве, но недостатком является то, что вы можете использовать его только для жала длиной до 17 цифр!!
#include <iostream>
using namespace std;
int main()
{
long long n,i1=0,i2=0, i=1, j, k=2, z=1;
cin >> n;
while (i<n){
k = 2*k;
i++;
}
bool a[k][n], t = false;
j = n-1;
i1=0;
i2 = 0;
z = 1;
while (j>=0){
if(j!=n-1){
z=z*2;
}
i2++;
t = false;
i = 0;
while (i<k){
i1 = 0;
while (i1<z){
if(t==false){
a[i][j]=false;
}
else {
a[i][j]= true;
}
i1++;
i++;
}
if(t==false){
t = true;
}else {
t = false;
}
}
j--;
}
i = 0;
j = 0;
while (i<k){
j = 0;
while (j<n){
cout << a[i][j];
j++;
}
cout << endl;
i++;
}
return 0;
}
FredOverflow в целом прав.
однако для 1s & 0s вам лучше просто увеличить целое число от 0:
int need_digits = 10
unsigned int i=0
while (! i>>need_digits){
# convert to binary form: shift & check, make an array, or cast to string, anything.
}
... я думаю,вам не понадобится больше 32 бит, или вам придется связать несколько целых чисел.. и придерживайтесь предыдущего ответа:)