Я хочу преобразовать эти циклы в рекурсивные. Есть ли способ конвертировать эти циклы в рекурсивные - PullRequest
0 голосов
/ 22 мая 2019

Я использовал 4 вложенных цикла.Я хочу преобразовать эти циклы в рекурсивные.Есть ли способ преобразовать эти циклы в рекурсивные?

#include<iostream>
using namespace std;
int main()
{
for(int i=0;i<2;i++)
{
       for(int k=0;k<2;k++)
       {
               for(int t=0;t<2;t++)
               {
                       for(int p=0;p<2;p++)
                       {
                                cout<<i<<k<<t<<p<<endl;
                       }
                }
        }
}
}

Ответы [ 4 ]

1 голос
/ 22 мая 2019

Вы можете сделать что-то вроде:

void foo_rec(int i, int k, int t, int p)
{
    std::cout << i << k << t << p << std::endl;
    if (++p == 2) {
        p = 0;
        if (++t == 2) {
            t = 0;
            if (++k == 2) {
                k = 0;
                ++i;
            }
        }
    }
    if (i < 2) {
        foo_rec(i, k, t, p);
    }
}

void foo()
{
    foo_rec(0, 0, 0, 0);
}

Демо

1 голос
/ 22 мая 2019

Мне известно, что ваш вопрос касается преобразования ваших пирамидальных (вложенных) циклов в рекурсивную функцию (плохая идея из-за потенциального переполнения стека), но представленный код показывает таблицу истинности.

Это то, что вам нужно?

Если это так, есть гораздо более простой способ добиться того же результата, используя побитовые >> сдвиги и побитовый & оператор.

#include <iostream>

int main()
{
    for ( int i = 0 ; i < 16 ; i++ )
    {
        bool a = ( i >> 3 ) & true;
        bool b = ( i >> 2 ) & true;
        bool c = ( i >> 1 ) & true;
        bool d = ( i >> 0 ) & true;

        std::cout << a << b << c <<  d << std::endl;
    }
}

Результат:

0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111

Пример кода в сети: https://rextester.com/YAKJL54176

И есть еще более простой способ (@ Jarod42), если вы используете библиотеку std::bitset.

#include <iostream>
#include <bitset>

int main()
{
    for (int i = 0; i != 16; ++i)
    {
        std::cout << std::bitset<4>(i) << "\n";
    }
}

Результаты такие же, как указано выше.

Пример кода онлайн: https://rextester.com/VBKO8875

0 голосов
/ 22 мая 2019

Есть ли способ преобразовать эти циклы в рекурсивные?

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

Возможно, вы ищете руководство по шаблону?Так как же выглядит простой рекурсивный цикл?

Вы пометили этот пост как C ++, так что здесь мое предложение использует функторы, которые являются упрощенным классом.Компилятор использования этих функторов предоставил значения по умолчанию для ctor и dtor, которые ничего не делают (быстро).

Ниже, в функторе "Functor_TailRecursion_t", каждый цикл for сообщения был заменен рекурсивной функцией, именемкоторый отражает цикл for из оригинального поста.Таким образом, void r_k () {...} "выполняет цикл for (int k = 0; k <2; k ++) {...}. </p>

  • Обратите внимание, что каждыйфункций Functor не передают никаких параметров ... кроме скрытого параметра this. Это уменьшает автоматическое использование памяти при глубоких рекурсиях (которых в этом примере нет).

  • Примечаниечто все рекурсивные функции 'Functor' являются хвостовой рекурсией. Компилятор может оптимизировать хвостовую рекурсию для итеративной производительности, хотя я не проверял этот код.

  • Помните, что хотя компиляторБлагодаря встроенным функциям небольшого класса рекурсивные вызовы предотвратят это.

Удачи в ваших усилиях.

 #include <iostream>
 using std::cout, std::endl, std::flush;

 #ifndef                 DTB_PCKLRT_HH
 #include "../../bag/src/dtb_pclkrt.hh"
 using DTB::PClk_t;
 #endif


 // postfunction (extracted from main)
 void function_NestedForLoops()
 {
    for(int i=0;i<2;i++)
    {
       for(int k=0;k<2;k++)
       {
          for(int t=0;t<2;t++)
          {
             for(int p=0;p<2;p++)
             {
                cout<<i<<k<<t<<p<<endl;
             }
          }
       }
    }
 } // void function_NestedForLoops()


 // functor, tail recursion
 class Functor_TailRecursion_t
 {
    int i {0}, k {0}, t {0}, p {0};  // value-initialization
 public:
    void operator()() { r_i(); }     // enter recursion

 private:
    void r_i() { if (!(i < 2)) { i = 0; return; } r_k();  ++i;  r_i(); }

    void r_k() { if (!(k < 2)) { k = 0; return; } r_t();  ++k;  r_k(); }

    void r_t() { if (!(t < 2)) { t = 0; return; } r_p();  ++t;  r_t(); }

    void r_p() { if (!(p < 2)) { p = 0; return; } show(); ++p;  r_p(); }

    void show() { cout << "\n  " << i << k << t << p << flush; };
 }; // class Functor_TailRecursion_t



 class F808_t // ctor and dtor: compiler provided (do-nothing) defaults
 {
    PClk_t  pclk; // posix clock access
 public:
    int  operator()()
       {
          int retVal = 0;
          uint64_t start_ns = pclk.ns();

          cout << "\n\nfunction, nested for loops:\n";
          function_NestedForLoops();

          cout << "\n  functor, tail recursion: ";
          Functor_TailRecursion_t()();

          auto  duration_ns = pclk.ns() - start_ns;
          cout << "\n\n  F808_t::operator()() duration   " << duration_ns
               << " ns    (" <<  __cplusplus  << ")" << std::endl;
          return retVal;
       }

 }; // class F808_t


 int main(int, char**) { return F808_t()(); }
0 голосов
/ 22 мая 2019

Вы можете, но это очень надуманный пример, который на самом деле не должен быть рекурсивным.Вам нужно подумать о том, как это сделать - одну рекурсивную функцию для всего лота или пару меньших?

Если вы используете одну рекурсивную функцию для всего лота, то знайте размер своего стека.Здесь глубина 2 ^ 4 или 16 уровней.Это, вероятно, нормально, но что, если k должно быть 0..100 вместо 0..1?

PS, чтобы подкрепить мою точку зрения: код в исходном вопросе намного яснее, чем код, представленный вдругие 2 ответа.Я не сомневаюсь, что они работают, но если вам не нужно думать о них в течение нескольких секунд, чтобы выяснить, что они делают, вы справляетесь лучше меня ;-)

...