массивы — Упрощение C ++ для цикла

на данный момент у меня есть следующий код:

for(int i = 0; i < 4; i++){
cout << rowNo[i] << endl;
}

for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
cout << rowNo[i] << '.';
cout << rowNo[j] << endl;
}
}

for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
for(int k = 0; k < 4; k++){
cout << rowNo[i] << '.';
cout << rowNo[j] << '.';
cout << rowNo[k] << endl;
}
}
}

for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
for(int k = 0; k < 4; k++){
for(int l = 0; l < 4; l++){
cout << rowNo[i] << '.';
cout << rowNo[j] << '.';
cout << rowNo[k] << '.';
cout << rowNo[l] << endl;
}
}
}
}

Где rowNo [] — массив {1,2,3,4}

И мне было интересно две вещи:

  1. Можно ли это упростить, так что, возможно, поместить в какой-то рекурсивный цикл?
  2. После этого можно ли это сделать для массива размером N?

3

Решение

Вы на самом деле пытаетесь напечатать число, закодированное в base4 с цифрой {1, 2, 3, 4}. Чтобы достичь этого, вам нужно только определить функцию, которая будет увеличиваться на единицу. Я предлагаю общее решение с точки зрения количества номеров для печати и базы.
Как и другие, я использую число для обозначения "empty digit"и я использую ноль, что довольно удобно.

Полный исходный код:

#include <iostream>
#include <vector>

bool increment_basep(std::vector<int>& number, int p)
{
int i = 0;
while(i < number.size() && number[i] == p)
{
number[i] = 1;
++i;
}
if(i >= number.size())
return false;

++number[i];
return true;
}

void print_vect(std::vector<int>& number)
{
for(int i = number.size() -1 ; i >= 0; --i)
{
if(number[i] != 0)
std::cout << number[i];
}
std::cout << std::endl;
}

int main() {
int n = 4;
int p = 4;
std::vector<int> num4(n);
std::fill(num4.begin(), num4.end(), 0);

while(increment_basep(num4, p))
{
print_vect(num4);
}
return 0;
}

Приращение возвращает, независимо от того, было ли вычисление переполнено. Когда мы переполняемся, мы знаем, что нам нужно остановиться.

1

Другие решения

Вы ищете Cartesian_product

С

bool increment(std::vector<std::size_t>& v, std::size_t maxSize)
{
for (auto it = v.rbegin(); it != v.rend(); ++it) {
++*it;
if (*it != maxSize) {
return true;
}
*it = 0;
}
return false;
}

тогда вы можете сделать:

void print_cartesian_product(const std::vector<int>&v, int n)
{
std::vector<std::size_t> indexes(n);

do {
print(v, indexes);
} while (increment(indexes, v.size()));

}

демонстрация

3

Первое решение, которое приходит мне в голову, состоит в том, чтобы в каждом цикле помещать буфер и, наконец, печатать все буферы.
Я думаю, что есть и другие гениальные методы

for(int i = 0; i < 4; i++){
put in buffer1 rowNo[i]
for(int j = 0; j < 4; j++){
put in buffer2 rowNo[i],rowNo[j]
for(int k = 0; k < 4; k++){
put in buffer3 rowNo[i],rowNo[j],rowNo[k]
for(int l = 0; l < 4; l++){
put in buffer4 rowNo[i],rowNo[j],rowNo[k],rowNo[l],endl.
}
}
}
}
print(buffer1);
print(buffer2);
print(buffer3);
print(buffer4);
1

Ниже приведен самый простой код, который я придумал. Там должен быть более прямой способ сделать это, хотя …

Он в основном вводит «призрачный» индекс -1, соответствующий пустому месту в числе. Тернарные операторы в условиях циклов существуют, чтобы избежать дубликатов.

int main()
{
int N = 4;
int rowNo[4] = {1, 2, 3, 4};

for (int i = -1; i < N; i++)
for (int j = (i > -1 ? 0 : -1); j < N; j++)
for (int k = (j > -1 ? 0 : -1); k < N; k++)
for (int l = (k > -1 ? 0 : -1); l < N; l++)
{
if (i > -1) std::cout << rowNo[i] << '.';
if (j > -1) std::cout << rowNo[j] << '.';
if (k > -1) std::cout << rowNo[k] << '.';
if (l > -1) std::cout << rowNo[l];
std::cout << std::endl;
}
}

Конечно, его можно обобщить до произвольного массива, возможно, с помощью некоторого скрипта генерации кода.

0