SlideShare una empresa de Scribd logo
1 de 8
Descargar para leer sin conexión
/**
* @mainpage
* @anchor mainpage
* @brief
* @details
* @copyright Russell John Childs, PhD, 2017
* @author Russell John Childs, PhD
* @date 2017-03-20
*
* This file contains
* class: Call
*
* Functions: recursive_combinations, iterative_combinations,
* recursive_permutations, iterative_permutations
*
*
* Problem statement:
* You have a recursive routine that needs to be replaced with iteration.
* To avoid potential error, the class "Call" may be used to replace recursion
* with iteration whilst keeping the structure of the function intact. This is
* useful for problems that are more easily solved through recurrence relations,
* which makes recursion a more natural, but problematic approach in C++.
* The class "Call" allows for direct conversion to iteration by using
* std::stack instead of a call stack, as in the following example:
*
* @code
*void iterative_perms(const std::vector<unsigned>& in, unsigned recurse)
*{
* //Args to be pushed to stack
* struct Args{unsigned recurse; std::set<unsigned>::iterator* iter;
* unsigned i;};
* //Vector of indices not yet "used up" in permuation sequence
* static std::set<unsigned> remaining(in.begin(), in.end());
* //Vector containing the permutation
* static std::vector<unsigned> indices(in.size());
* //Termination sequence
* static std::vector<unsigned> term(in.rbegin(), in.rend());
*
* auto iter = remaining.begin();
* //Iterate until recursion termination condition hit
* while (Call<Args>::done({ recurse }, [&]{return indices != term; }) )
* {
* // Create object to push and pop args for each iteration
* Call<Args> call;
* //Loop over all unused indices to generate next index in permutation
* while ( iter != remaining.end() )
* {
* //Add next index to permutation
* unsigned i = *iter;
* indices[call().recurse] = i;
* //If complete permuation then print
* if (call().recurse == in.size() - 1)
* {
* for (auto index : indices) std::cout << index << " ";
* std::cout << std::endl;
* ++iter;
* }
* //If incomplete, recurse
* else
* {
* //Ctor is done at top of "recurse"
* auto ctor = [&](){ remaining.erase(call().i);
* (*call().iter) = remaining.begin();};
* //recurse
* call({ call().recurse + 1, &iter, i}, ctor);
* //Dtor is done after recurse returns
* call.dtor([&call](){*call().iter =
* remaining.insert(call().i).first; ++(*call().iter); });
* }
* }
* }
*}
* @endcode
*
* Notes: The class "Call" has been partially tested using combinatorics. It is
* found to be significantly faster when iteration replaces recursion using
* "Call". There is an expected overhead and timings for a Release build show
* that using "Call" takes 50% longer than std::next_permutation for 9!
* permuations. This may be due to the overhead of using a stack or may be due
* to the algorithm I devised for generating permutations.
*
* Compiled and tested under Linux Mint, using g++ 4.8.
*
* g++ options: -O0 -g3 -Wall -O0 -fopenmp -mavx -m64 -g -Wall -c
* -fmessage-length=0 -fno-omit-frame-pointer --fast-math
* -std=c++11 -I/opt/intel/vtune_amplifier_xe_2013/include/
*
* Linker options: -Wl,--no-as-needed -fopenmp
* -L/opt/intel/vtune_amplifier_xe_2013/lib64/
*
* Cmd line options: -lpthread -latomic -littnotify -ldl
*
* Documentation: Doxygen comments for interfaces, normal for impl.
*
* @file iteration.cpp
* @see
* @ref mainpage
*/
#include <vector>
#include <set>
#include <stack>
#include <memory>
#include <iostream>
#include <functional>
#include <chrono>
#include <algorithm>
/**
* addtogroup Recursion
* @{
*/
namespace Recursion
{
/** Dummy function acting as ctor/dtor
*
*/
void default_cdtor(void){}
/**
* @tparam T - struct containing function arguments to be pushed to stack
* @tparam Ctor - a void(*)(void) func acting as ctor
* @tparam Dtor - a void(*)(void) func acting as dtor
*/
template<typename T, typename Ctor = std::function<void(void)>,
typename Dtor = std::function<void(void)> >
struct Call
{
/**
* Holds stack of function arguments, ctors, dtors used to implement:
*
* pre-code - executed in ctor
*
* recursive-call(args...) - pushed to std::stack
*
* post-code - executed in dtor
*/
struct Func
{
/**
* Default ctor
*/
Func() :
m_ctor(&default_cdtor),
m_dtor(&default_cdtor)
{
}
/**
* Dtor
*/
~Func()
{
}
/**
* @return A stack of function arguments, ctors, dtors
*/
static std::stack<std::unique_ptr<Func>>& stack( void )
{
static std::stack<std::unique_ptr<Func>> ret_val;
return ret_val;
}
T m_t;
Ctor m_ctor;
Dtor m_dtor;
};
/**
* Default ctor
*
*/
Call()
{
}
/**
* Dtor
*/
~Call()
{
//Call dtor, pop "call" off stack
if (m_func.stack().empty() == false)
{
m_func.stack().top()->m_dtor();
m_func.stack().pop();
}
}
/**
* @param ctor {Ctor} - stores ctor to stack
*/
void ctor(Ctor ctor)
{
m_func.stack().top()->m_ctor = ctor;
}
/**
* @param dtor {Dtor} - stores dtor to stack
*/
void dtor(Dtor dtor)
{
m_func.stack().top()->m_dtor = dtor;
}
/**
* Dummy termination condition
*/
static bool default_done(){ return false; }
/**
* @tparam Pred - bool(*)(...) condition for recursion termination
* @param t {const T&} - struct of function args to be pushed to stack
* @param pred {Pred} - condition for recursion termination
* @return bool - true iff recursion should terminate
*/
template<typename Pred>
static bool done(const T& t, Pred pred)
{
//Push function args to stack
static bool init = true;
if (init == true)
{
Func::stack().push(std::unique_ptr<Func>(new Func));
Func::stack().top()->m_t = t;
}
//Return true iff recursion termination should occur
bool ret_val = (init == false && Func::stack().empty()==true) || pred();
init = false;
return ret_val;
}
/**
* @param t {const T& } - function args to be pushed to stack
*/
static bool done(const T& t)
{
return done(t, &default_done);
}
/**
* @param t {T} - function args to be pushed to stack
* @param ctor {std::function<void(void)> } - ctor to be pushed to stack
*/
void operator()(T t, std::function<void(void)> ctor = default_cdtor)
{
//Push "call" to stack and then execute ctor
m_func.stack().push(std::unique_ptr<Func>(new Func));
m_func.stack().top()->m_t = t;
m_func.stack().top()->m_ctor = ctor;
ctor();
}
/**
* @return - function args from top of stack
*/
T& operator()()
{
return m_func.stack().top()->m_t;
}
/**
* @return - true iff stack is empty
*/
static bool empty()
{
return Func::stack().empty();
}
Func m_func;
};
}
/**
* @}
*/
/**
* addtogroup Tests
* @{
*/
namespace Tests
{
/**
* @param in {const std::vector<unsigned>&} - vectors of indices
* @param k {unsigned} - k in n choose k
* @param pos {unsigned} - length of sequence so far
* @param recurse {unsigned} - recursion depth
*
* Enumerates k out of n indices recursively. This code is O(k*n_choose_k).
*/
void recursive_combinations(const std::vector<unsigned>& in, unsigned k,
unsigned pos=0, unsigned recurse=0)
{
using namespace Recursion;
//Indices of combination & termination sequence
static std::vector<unsigned> indices(k);
static std::vector<unsigned> term(in.begin()+k, in.end());
//Loop from current length of sequence to end of input vector
for (unsigned i = pos; i < in.size()-(k-recurse-1); ++i)
{
//Add current index
indices[recurse] = i;
//If complete combination then print
if (recurse == k-1 || indices == term)
{
for (auto index : indices) std::cout << index << " ";
std::cout << std::endl;
}
//If not complete then recurse
else
{
recursive_combinations(in, k, i + 1, recurse + 1);
}
}
}
/**
* @param in {const std::vector<unsigned>&} - vectors of indices
* @param k {unsigned} - k in n choose k
* @param pos {unsigned} - length of sequence so far
* @param recurse {unsigned} - recursion depth
*
* Enumerates k out of n indices iteratively. This code is O(k*n_choose_k).
*/
void iterative_combinations(const std::vector<unsigned>& in, unsigned k,
unsigned pos=0, unsigned recurse = 0)
{
using namespace Recursion;
//Function args that would normally be pushed to stack
struct Args{ unsigned k; unsigned pos; unsigned recurse; };
//Indices of combination
static std::vector<unsigned> indices(k);
//Loop while stack non-empty
while (Call<Args>::done({ k, pos, recurse }) == false)
{
//Create object to push args to stack and pop them at end of iteration
Call<Args> call;
//Loop from current length of sequence to end of input vector
for (unsigned i=call().pos; i < in.size()-(k - call().recurse - 1); ++i)
{
//Add current index
indices[call().recurse] = i;
//If complete combination then print
if (call().recurse == k - 1)
{
for (auto index : indices) std::cout << index << " ";
std::cout << std::endl;
}
//If not complete then recurse
else
{
call({ k, ++call().pos, call().recurse + 1 });
}
}
}
}
/**
* @param in {const std::vector<unsigned>&} - vectors of indices
* @param recurse {unsigned} - recursion depth
*
* Enumerates all permutations recursively. This code is O(n*n!).
*/
void recursive_permutations(const std::vector<unsigned>& in, unsigned recurse=0)
{
using namespace Recursion;
//Vector of indices not yet "used up" in permuation sequence
static std::set<unsigned> remaining(in.begin(), in.end());
//Vector containing the permutation
static std::vector<unsigned> indices(in.size());
//Termination sequence
static std::vector<unsigned> term(in.rbegin(), in.rend());
//Loop over all unused indices to generate next index in permutation
for (auto iter = remaining.begin(); iter != remaining.end(); ++iter)
{
//Add next index to permutation
unsigned i = *iter;
indices[recurse] = i;
//If complete permuation then print
if (recurse == in.size()-1 || indices == term)
{
for (auto index : indices) std::cout << index << " ";
std::cout << std::endl;
}
//If incomplete, recurse
else
{
remaining.erase(i);
recursive_permutations(in, recurse + 1);
iter = remaining.insert(i).first;
}
}
}
/**
* @param in {const std::vector<unsigned>&} - vectors of indices
* @param recurse {unsigned} - recursion depth
*
* Enumerates all permutations iteratively. This code is O(n*n!).
*/
void iterative_permutations(const std::vector<unsigned>& in, unsigned recurse=0)
{
using namespace Recursion;
//Args to be pushed to stack
struct Args{unsigned recurse; std::set<unsigned>::iterator* iter;
unsigned i;};
//Vector of indices not yet "used up" in permuation sequence
static std::set<unsigned> remaining(in.begin(), in.end());
//Vector containing the permutation
static std::vector<unsigned> indices(in.size());
//Termination sequence
static std::vector<unsigned> term(in.rbegin(), in.rend());
auto iter = remaining.begin();
//Iterate until recursion termination condition hit
while (Call<Args>::done({ recurse }, [&]{return indices != term; }) )
{
// Create object to push and pop args for each iteration
Call<Args> call;
//Loop over all unused indices to generate next index in permutation
while ( iter != remaining.end() )
{
//Add next index to permutation
unsigned i = *iter;
indices[call().recurse] = i;
//If complete permuation then print
if (call().recurse == in.size() - 1)
{
for (auto index : indices) std::cout << index << " ";
std::cout << std::endl;
++iter;
}
//If incomplete, recurse
else
{
//Ctor is done at top of "recurse"
auto ctor = [&](){ remaining.erase(call().i);
(*call().iter) = remaining.begin();};
//recurse
call({ call().recurse + 1, &iter, i}, ctor);
//Dtor is done after recurse returns
call.dtor([&call](){*call().iter =
remaining.insert(call().i).first; ++(*call().iter); });
}
}
}
}
}
/**
* @}
*/
int main(void)
{
using namespace Tests;
using namespace std::chrono;
bool is_test_recursive = false;
std::vector<unsigned> in({ 0, 1, 2, 3, 4, 5 });
unsigned k = 3;
std::cout << "Generating " << k << " out of " << in.size()
<< " combinations: " << std::endl;
is_test_recursive ? recursive_combinations(in,k) :
iterative_combinations(in,k);
std::vector<unsigned> recursive({ 0, 1, 2, 3});
std::vector<unsigned> iterative({ 0, 1, 2, 3, 4, 5, 6, 7, 8 });
auto vec = is_test_recursive ? recursive : iterative;
std::cout << "Generating all permutations of " << vec.size()
<< " indices using class "Call": " << std::endl;
steady_clock::time_point begin, end;
begin=steady_clock::now();
is_test_recursive ? recursive_permutations(recursive) :
iterative_permutations(iterative);
end=steady_clock::now();
auto time_for_call = duration_cast<microseconds>(end - begin).count();
std::cout << "Class "Call" took: "
<< time_for_call << std::endl;
std::cout << "Generating all permutations of " << vec.size()
<< " indices using std::next_permuation: " << std::endl;
begin=steady_clock::now();
while(std::next_permutation(iterative.begin(), iterative.end()))
{
for(auto& i : iterative) std::cout << i << " ";
std::cout << std::endl;
}
end=steady_clock::now();
std::cout << "Class "Call" took: "
<< time_for_call << std::endl;
auto next_perm = duration_cast<microseconds>(end - begin).count();
std::cout << "std::next_permuation took: "
<< next_perm<< std::endl;
std::cout << "Time for Class "Call" / time for std::next_permutation: "
<< (double)time_for_call/(double)next_perm << std::endl;
return 0;
}

Más contenido relacionado

La actualidad más candente

Arrry structure Stacks in data structure
Arrry structure Stacks  in data structureArrry structure Stacks  in data structure
Arrry structure Stacks in data structurelodhran-hayat
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with PythonHan Lee
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...ssuserd6b1fd
 
Алексей Кутумов, Вектор с нуля
Алексей Кутумов, Вектор с нуляАлексей Кутумов, Вектор с нуля
Алексей Кутумов, Вектор с нуляSergey Platonov
 
Advance C++notes
Advance C++notesAdvance C++notes
Advance C++notesRajiv Gupta
 
Advance features of C++
Advance features of C++Advance features of C++
Advance features of C++vidyamittal
 
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...Sergey Platonov
 
OOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerOOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerMario Fusco
 
2 BytesC++ course_2014_c9_ pointers and dynamic arrays
2 BytesC++ course_2014_c9_ pointers and dynamic arrays 2 BytesC++ course_2014_c9_ pointers and dynamic arrays
2 BytesC++ course_2014_c9_ pointers and dynamic arrays kinan keshkeh
 

La actualidad más candente (20)

Arrry structure Stacks in data structure
Arrry structure Stacks  in data structureArrry structure Stacks  in data structure
Arrry structure Stacks in data structure
 
Computer Programming- Lecture 4
Computer Programming- Lecture 4Computer Programming- Lecture 4
Computer Programming- Lecture 4
 
Imugi: Compiler made with Python
Imugi: Compiler made with PythonImugi: Compiler made with Python
Imugi: Compiler made with Python
 
functions of C++
functions of C++functions of C++
functions of C++
 
Link list
Link listLink list
Link list
 
C++ L01-Variables
C++ L01-VariablesC++ L01-Variables
C++ L01-Variables
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
 
Алексей Кутумов, Вектор с нуля
Алексей Кутумов, Вектор с нуляАлексей Кутумов, Вектор с нуля
Алексей Кутумов, Вектор с нуля
 
Constructor,destructors cpp
Constructor,destructors cppConstructor,destructors cpp
Constructor,destructors cpp
 
C++ L08-Classes Part1
C++ L08-Classes Part1C++ L08-Classes Part1
C++ L08-Classes Part1
 
Advance C++notes
Advance C++notesAdvance C++notes
Advance C++notes
 
Lecture 12: Classes and Files
Lecture 12: Classes and FilesLecture 12: Classes and Files
Lecture 12: Classes and Files
 
Advance features of C++
Advance features of C++Advance features of C++
Advance features of C++
 
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
 
C++11 & C++14
C++11 & C++14C++11 & C++14
C++11 & C++14
 
Computer Programming- Lecture 6
Computer Programming- Lecture 6Computer Programming- Lecture 6
Computer Programming- Lecture 6
 
Memory management in c++
Memory management in c++Memory management in c++
Memory management in c++
 
C++11 - STL Additions
C++11 - STL AdditionsC++11 - STL Additions
C++11 - STL Additions
 
OOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerOOP and FP - Become a Better Programmer
OOP and FP - Become a Better Programmer
 
2 BytesC++ course_2014_c9_ pointers and dynamic arrays
2 BytesC++ course_2014_c9_ pointers and dynamic arrays 2 BytesC++ course_2014_c9_ pointers and dynamic arrays
2 BytesC++ course_2014_c9_ pointers and dynamic arrays
 

Destacado

Shared_memory_hash_table
Shared_memory_hash_tableShared_memory_hash_table
Shared_memory_hash_tableRussell Childs
 
Design pattern to avoid downcasting
Design pattern to avoid downcastingDesign pattern to avoid downcasting
Design pattern to avoid downcastingRussell Childs
 
IBM Kinexa Prove It! C programming test results.
IBM Kinexa Prove It! C programming test results.IBM Kinexa Prove It! C programming test results.
IBM Kinexa Prove It! C programming test results.Russell Childs
 
Full resume dr_russell_john_childs_2016
Full resume dr_russell_john_childs_2016Full resume dr_russell_john_childs_2016
Full resume dr_russell_john_childs_2016Russell Childs
 
Dirac demo (quantum mechanics with C++). Please note: There is a problem with...
Dirac demo (quantum mechanics with C++). Please note: There is a problem with...Dirac demo (quantum mechanics with C++). Please note: There is a problem with...
Dirac demo (quantum mechanics with C++). Please note: There is a problem with...Russell Childs
 

Destacado (6)

Shared_memory_hash_table
Shared_memory_hash_tableShared_memory_hash_table
Shared_memory_hash_table
 
Design pattern to avoid downcasting
Design pattern to avoid downcastingDesign pattern to avoid downcasting
Design pattern to avoid downcasting
 
Interview C++11 code
Interview C++11 codeInterview C++11 code
Interview C++11 code
 
IBM Kinexa Prove It! C programming test results.
IBM Kinexa Prove It! C programming test results.IBM Kinexa Prove It! C programming test results.
IBM Kinexa Prove It! C programming test results.
 
Full resume dr_russell_john_childs_2016
Full resume dr_russell_john_childs_2016Full resume dr_russell_john_childs_2016
Full resume dr_russell_john_childs_2016
 
Dirac demo (quantum mechanics with C++). Please note: There is a problem with...
Dirac demo (quantum mechanics with C++). Please note: There is a problem with...Dirac demo (quantum mechanics with C++). Please note: There is a problem with...
Dirac demo (quantum mechanics with C++). Please note: There is a problem with...
 

Similar a Recursion to iteration automation.

Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01Abdul Samee
 
Were writing code for a project that dynamically allocates an arra.pdf
Were writing code for a project that dynamically allocates an arra.pdfWere writing code for a project that dynamically allocates an arra.pdf
Were writing code for a project that dynamically allocates an arra.pdffsenterprises
 
Lecture#6 functions in c++
Lecture#6 functions in c++Lecture#6 functions in c++
Lecture#6 functions in c++NUST Stuff
 
golang_refcard.pdf
golang_refcard.pdfgolang_refcard.pdf
golang_refcard.pdfSpam92
 
C++ Nested loops, matrix and fuctions.pdf
C++ Nested loops, matrix and fuctions.pdfC++ Nested loops, matrix and fuctions.pdf
C++ Nested loops, matrix and fuctions.pdfyamew16788
 
in c languageTo determine the maximum string length, we need to .pdf
in c languageTo determine the maximum string length, we need to .pdfin c languageTo determine the maximum string length, we need to .pdf
in c languageTo determine the maximum string length, we need to .pdfstopgolook
 
C++ FUNCTIONS-1.pptx
C++ FUNCTIONS-1.pptxC++ FUNCTIONS-1.pptx
C++ FUNCTIONS-1.pptxShashiShash2
 
Algorithms devised for a google interview
Algorithms devised for a google interviewAlgorithms devised for a google interview
Algorithms devised for a google interviewRussell Childs
 
Write a program that converts an infix expression into an equivalent.pdf
Write a program that converts an infix expression into an equivalent.pdfWrite a program that converts an infix expression into an equivalent.pdf
Write a program that converts an infix expression into an equivalent.pdfmohdjakirfb
 
1- The design of a singly-linked list below is a picture of the functi (1).pdf
1- The design of a singly-linked list below is a picture of the functi (1).pdf1- The design of a singly-linked list below is a picture of the functi (1).pdf
1- The design of a singly-linked list below is a picture of the functi (1).pdfafgt2012
 
@author Derek Harter @cwid 123 45 678 @class .docx
@author Derek Harter  @cwid   123 45 678  @class  .docx@author Derek Harter  @cwid   123 45 678  @class  .docx
@author Derek Harter @cwid 123 45 678 @class .docxadkinspaige22
 
filesHeap.h#ifndef HEAP_H#define HEAP_H#includ.docx
filesHeap.h#ifndef HEAP_H#define HEAP_H#includ.docxfilesHeap.h#ifndef HEAP_H#define HEAP_H#includ.docx
filesHeap.h#ifndef HEAP_H#define HEAP_H#includ.docxssuser454af01
 
Unit 4
Unit 4Unit 4
Unit 4siddr
 
Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)ujihisa
 

Similar a Recursion to iteration automation. (20)

Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01
 
Were writing code for a project that dynamically allocates an arra.pdf
Were writing code for a project that dynamically allocates an arra.pdfWere writing code for a project that dynamically allocates an arra.pdf
Were writing code for a project that dynamically allocates an arra.pdf
 
Chapter 4
Chapter 4Chapter 4
Chapter 4
 
Templates
TemplatesTemplates
Templates
 
Namespaces
NamespacesNamespaces
Namespaces
 
Lecture#6 functions in c++
Lecture#6 functions in c++Lecture#6 functions in c++
Lecture#6 functions in c++
 
golang_refcard.pdf
golang_refcard.pdfgolang_refcard.pdf
golang_refcard.pdf
 
C++ Nested loops, matrix and fuctions.pdf
C++ Nested loops, matrix and fuctions.pdfC++ Nested loops, matrix and fuctions.pdf
C++ Nested loops, matrix and fuctions.pdf
 
in c languageTo determine the maximum string length, we need to .pdf
in c languageTo determine the maximum string length, we need to .pdfin c languageTo determine the maximum string length, we need to .pdf
in c languageTo determine the maximum string length, we need to .pdf
 
C++ FUNCTIONS-1.pptx
C++ FUNCTIONS-1.pptxC++ FUNCTIONS-1.pptx
C++ FUNCTIONS-1.pptx
 
C++ FUNCTIONS-1.pptx
C++ FUNCTIONS-1.pptxC++ FUNCTIONS-1.pptx
C++ FUNCTIONS-1.pptx
 
C++ L05-Functions
C++ L05-FunctionsC++ L05-Functions
C++ L05-Functions
 
Algorithms devised for a google interview
Algorithms devised for a google interviewAlgorithms devised for a google interview
Algorithms devised for a google interview
 
C++ Functions.ppt
C++ Functions.pptC++ Functions.ppt
C++ Functions.ppt
 
Write a program that converts an infix expression into an equivalent.pdf
Write a program that converts an infix expression into an equivalent.pdfWrite a program that converts an infix expression into an equivalent.pdf
Write a program that converts an infix expression into an equivalent.pdf
 
1- The design of a singly-linked list below is a picture of the functi (1).pdf
1- The design of a singly-linked list below is a picture of the functi (1).pdf1- The design of a singly-linked list below is a picture of the functi (1).pdf
1- The design of a singly-linked list below is a picture of the functi (1).pdf
 
@author Derek Harter @cwid 123 45 678 @class .docx
@author Derek Harter  @cwid   123 45 678  @class  .docx@author Derek Harter  @cwid   123 45 678  @class  .docx
@author Derek Harter @cwid 123 45 678 @class .docx
 
filesHeap.h#ifndef HEAP_H#define HEAP_H#includ.docx
filesHeap.h#ifndef HEAP_H#define HEAP_H#includ.docxfilesHeap.h#ifndef HEAP_H#define HEAP_H#includ.docx
filesHeap.h#ifndef HEAP_H#define HEAP_H#includ.docx
 
Unit 4
Unit 4Unit 4
Unit 4
 
Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)Hacking parse.y (RubyKansai38)
Hacking parse.y (RubyKansai38)
 

Más de Russell Childs

spinor_quantum_simulator_user_guide_.pdf
spinor_quantum_simulator_user_guide_.pdfspinor_quantum_simulator_user_guide_.pdf
spinor_quantum_simulator_user_guide_.pdfRussell Childs
 
Feature extraction using adiabatic theorem
Feature extraction using adiabatic theoremFeature extraction using adiabatic theorem
Feature extraction using adiabatic theoremRussell Childs
 
Feature extraction using adiabatic theorem
Feature extraction using adiabatic theoremFeature extraction using adiabatic theorem
Feature extraction using adiabatic theoremRussell Childs
 
Wavelets_and_multiresolution_in_two_pages
Wavelets_and_multiresolution_in_two_pagesWavelets_and_multiresolution_in_two_pages
Wavelets_and_multiresolution_in_two_pagesRussell Childs
 
Simple shared mutex UML
Simple shared mutex UMLSimple shared mutex UML
Simple shared mutex UMLRussell Childs
 
Full_resume_Dr_Russell_John_Childs
Full_resume_Dr_Russell_John_ChildsFull_resume_Dr_Russell_John_Childs
Full_resume_Dr_Russell_John_ChildsRussell Childs
 
Dynamic programming burglar_problem
Dynamic programming burglar_problemDynamic programming burglar_problem
Dynamic programming burglar_problemRussell Childs
 
Multithreaded sockets c++11
Multithreaded sockets c++11Multithreaded sockets c++11
Multithreaded sockets c++11Russell Childs
 
IBM Kinexa Prove It! C++ programming test results.
IBM Kinexa Prove It! C++ programming test results.IBM Kinexa Prove It! C++ programming test results.
IBM Kinexa Prove It! C++ programming test results.Russell Childs
 
2 mathematical challenge_analysis_design_and_results
2 mathematical challenge_analysis_design_and_results2 mathematical challenge_analysis_design_and_results
2 mathematical challenge_analysis_design_and_resultsRussell Childs
 
1 mathematical challenge_problem
1 mathematical challenge_problem1 mathematical challenge_problem
1 mathematical challenge_problemRussell Childs
 

Más de Russell Childs (20)

spinor_quantum_simulator_user_guide_.pdf
spinor_quantum_simulator_user_guide_.pdfspinor_quantum_simulator_user_guide_.pdf
spinor_quantum_simulator_user_guide_.pdf
 
String searching o_n
String searching o_nString searching o_n
String searching o_n
 
String searching o_n
String searching o_nString searching o_n
String searching o_n
 
String searching o_n
String searching o_nString searching o_n
String searching o_n
 
String searching
String searchingString searching
String searching
 
Permute
PermutePermute
Permute
 
Permute
PermutePermute
Permute
 
Feature extraction using adiabatic theorem
Feature extraction using adiabatic theoremFeature extraction using adiabatic theorem
Feature extraction using adiabatic theorem
 
Feature extraction using adiabatic theorem
Feature extraction using adiabatic theoremFeature extraction using adiabatic theorem
Feature extraction using adiabatic theorem
 
Wavelets_and_multiresolution_in_two_pages
Wavelets_and_multiresolution_in_two_pagesWavelets_and_multiresolution_in_two_pages
Wavelets_and_multiresolution_in_two_pages
 
Relativity 2
Relativity 2Relativity 2
Relativity 2
 
Simple shared mutex UML
Simple shared mutex UMLSimple shared mutex UML
Simple shared mutex UML
 
Interview uml design
Interview uml designInterview uml design
Interview uml design
 
Full_resume_Dr_Russell_John_Childs
Full_resume_Dr_Russell_John_ChildsFull_resume_Dr_Russell_John_Childs
Full_resume_Dr_Russell_John_Childs
 
Dynamic programming burglar_problem
Dynamic programming burglar_problemDynamic programming burglar_problem
Dynamic programming burglar_problem
 
K d tree_cpp
K d tree_cppK d tree_cpp
K d tree_cpp
 
Multithreaded sockets c++11
Multithreaded sockets c++11Multithreaded sockets c++11
Multithreaded sockets c++11
 
IBM Kinexa Prove It! C++ programming test results.
IBM Kinexa Prove It! C++ programming test results.IBM Kinexa Prove It! C++ programming test results.
IBM Kinexa Prove It! C++ programming test results.
 
2 mathematical challenge_analysis_design_and_results
2 mathematical challenge_analysis_design_and_results2 mathematical challenge_analysis_design_and_results
2 mathematical challenge_analysis_design_and_results
 
1 mathematical challenge_problem
1 mathematical challenge_problem1 mathematical challenge_problem
1 mathematical challenge_problem
 

Último

introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfayushiqss
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is insideshinachiaurasa2
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024Mind IT Systems
 
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456KiaraTiradoMicha
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxalwaysnagaraju26
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfonteinmasabamasaba
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedDelhi Call girls
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 

Último (20)

introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 

Recursion to iteration automation.

  • 1. /** * @mainpage * @anchor mainpage * @brief * @details * @copyright Russell John Childs, PhD, 2017 * @author Russell John Childs, PhD * @date 2017-03-20 * * This file contains * class: Call * * Functions: recursive_combinations, iterative_combinations, * recursive_permutations, iterative_permutations * * * Problem statement: * You have a recursive routine that needs to be replaced with iteration. * To avoid potential error, the class "Call" may be used to replace recursion * with iteration whilst keeping the structure of the function intact. This is * useful for problems that are more easily solved through recurrence relations, * which makes recursion a more natural, but problematic approach in C++. * The class "Call" allows for direct conversion to iteration by using * std::stack instead of a call stack, as in the following example: * * @code *void iterative_perms(const std::vector<unsigned>& in, unsigned recurse) *{ * //Args to be pushed to stack * struct Args{unsigned recurse; std::set<unsigned>::iterator* iter; * unsigned i;}; * //Vector of indices not yet "used up" in permuation sequence * static std::set<unsigned> remaining(in.begin(), in.end()); * //Vector containing the permutation * static std::vector<unsigned> indices(in.size()); * //Termination sequence * static std::vector<unsigned> term(in.rbegin(), in.rend()); * * auto iter = remaining.begin(); * //Iterate until recursion termination condition hit * while (Call<Args>::done({ recurse }, [&]{return indices != term; }) ) * { * // Create object to push and pop args for each iteration * Call<Args> call; * //Loop over all unused indices to generate next index in permutation * while ( iter != remaining.end() ) * { * //Add next index to permutation * unsigned i = *iter; * indices[call().recurse] = i; * //If complete permuation then print * if (call().recurse == in.size() - 1) * { * for (auto index : indices) std::cout << index << " "; * std::cout << std::endl; * ++iter; * } * //If incomplete, recurse * else * { * //Ctor is done at top of "recurse" * auto ctor = [&](){ remaining.erase(call().i); * (*call().iter) = remaining.begin();}; * //recurse
  • 2. * call({ call().recurse + 1, &iter, i}, ctor); * //Dtor is done after recurse returns * call.dtor([&call](){*call().iter = * remaining.insert(call().i).first; ++(*call().iter); }); * } * } * } *} * @endcode * * Notes: The class "Call" has been partially tested using combinatorics. It is * found to be significantly faster when iteration replaces recursion using * "Call". There is an expected overhead and timings for a Release build show * that using "Call" takes 50% longer than std::next_permutation for 9! * permuations. This may be due to the overhead of using a stack or may be due * to the algorithm I devised for generating permutations. * * Compiled and tested under Linux Mint, using g++ 4.8. * * g++ options: -O0 -g3 -Wall -O0 -fopenmp -mavx -m64 -g -Wall -c * -fmessage-length=0 -fno-omit-frame-pointer --fast-math * -std=c++11 -I/opt/intel/vtune_amplifier_xe_2013/include/ * * Linker options: -Wl,--no-as-needed -fopenmp * -L/opt/intel/vtune_amplifier_xe_2013/lib64/ * * Cmd line options: -lpthread -latomic -littnotify -ldl * * Documentation: Doxygen comments for interfaces, normal for impl. * * @file iteration.cpp * @see * @ref mainpage */ #include <vector> #include <set> #include <stack> #include <memory> #include <iostream> #include <functional> #include <chrono> #include <algorithm> /** * addtogroup Recursion * @{ */ namespace Recursion { /** Dummy function acting as ctor/dtor * */ void default_cdtor(void){} /** * @tparam T - struct containing function arguments to be pushed to stack * @tparam Ctor - a void(*)(void) func acting as ctor * @tparam Dtor - a void(*)(void) func acting as dtor */ template<typename T, typename Ctor = std::function<void(void)>, typename Dtor = std::function<void(void)> > struct Call {
  • 3. /** * Holds stack of function arguments, ctors, dtors used to implement: * * pre-code - executed in ctor * * recursive-call(args...) - pushed to std::stack * * post-code - executed in dtor */ struct Func { /** * Default ctor */ Func() : m_ctor(&default_cdtor), m_dtor(&default_cdtor) { } /** * Dtor */ ~Func() { } /** * @return A stack of function arguments, ctors, dtors */ static std::stack<std::unique_ptr<Func>>& stack( void ) { static std::stack<std::unique_ptr<Func>> ret_val; return ret_val; } T m_t; Ctor m_ctor; Dtor m_dtor; }; /** * Default ctor * */ Call() { } /** * Dtor */ ~Call() { //Call dtor, pop "call" off stack if (m_func.stack().empty() == false) { m_func.stack().top()->m_dtor(); m_func.stack().pop(); } } /** * @param ctor {Ctor} - stores ctor to stack
  • 4. */ void ctor(Ctor ctor) { m_func.stack().top()->m_ctor = ctor; } /** * @param dtor {Dtor} - stores dtor to stack */ void dtor(Dtor dtor) { m_func.stack().top()->m_dtor = dtor; } /** * Dummy termination condition */ static bool default_done(){ return false; } /** * @tparam Pred - bool(*)(...) condition for recursion termination * @param t {const T&} - struct of function args to be pushed to stack * @param pred {Pred} - condition for recursion termination * @return bool - true iff recursion should terminate */ template<typename Pred> static bool done(const T& t, Pred pred) { //Push function args to stack static bool init = true; if (init == true) { Func::stack().push(std::unique_ptr<Func>(new Func)); Func::stack().top()->m_t = t; } //Return true iff recursion termination should occur bool ret_val = (init == false && Func::stack().empty()==true) || pred(); init = false; return ret_val; } /** * @param t {const T& } - function args to be pushed to stack */ static bool done(const T& t) { return done(t, &default_done); } /** * @param t {T} - function args to be pushed to stack * @param ctor {std::function<void(void)> } - ctor to be pushed to stack */ void operator()(T t, std::function<void(void)> ctor = default_cdtor) { //Push "call" to stack and then execute ctor m_func.stack().push(std::unique_ptr<Func>(new Func)); m_func.stack().top()->m_t = t; m_func.stack().top()->m_ctor = ctor; ctor(); }
  • 5. /** * @return - function args from top of stack */ T& operator()() { return m_func.stack().top()->m_t; } /** * @return - true iff stack is empty */ static bool empty() { return Func::stack().empty(); } Func m_func; }; } /** * @} */ /** * addtogroup Tests * @{ */ namespace Tests { /** * @param in {const std::vector<unsigned>&} - vectors of indices * @param k {unsigned} - k in n choose k * @param pos {unsigned} - length of sequence so far * @param recurse {unsigned} - recursion depth * * Enumerates k out of n indices recursively. This code is O(k*n_choose_k). */ void recursive_combinations(const std::vector<unsigned>& in, unsigned k, unsigned pos=0, unsigned recurse=0) { using namespace Recursion; //Indices of combination & termination sequence static std::vector<unsigned> indices(k); static std::vector<unsigned> term(in.begin()+k, in.end()); //Loop from current length of sequence to end of input vector for (unsigned i = pos; i < in.size()-(k-recurse-1); ++i) { //Add current index indices[recurse] = i; //If complete combination then print if (recurse == k-1 || indices == term) { for (auto index : indices) std::cout << index << " "; std::cout << std::endl; } //If not complete then recurse else { recursive_combinations(in, k, i + 1, recurse + 1); } } }
  • 6. /** * @param in {const std::vector<unsigned>&} - vectors of indices * @param k {unsigned} - k in n choose k * @param pos {unsigned} - length of sequence so far * @param recurse {unsigned} - recursion depth * * Enumerates k out of n indices iteratively. This code is O(k*n_choose_k). */ void iterative_combinations(const std::vector<unsigned>& in, unsigned k, unsigned pos=0, unsigned recurse = 0) { using namespace Recursion; //Function args that would normally be pushed to stack struct Args{ unsigned k; unsigned pos; unsigned recurse; }; //Indices of combination static std::vector<unsigned> indices(k); //Loop while stack non-empty while (Call<Args>::done({ k, pos, recurse }) == false) { //Create object to push args to stack and pop them at end of iteration Call<Args> call; //Loop from current length of sequence to end of input vector for (unsigned i=call().pos; i < in.size()-(k - call().recurse - 1); ++i) { //Add current index indices[call().recurse] = i; //If complete combination then print if (call().recurse == k - 1) { for (auto index : indices) std::cout << index << " "; std::cout << std::endl; } //If not complete then recurse else { call({ k, ++call().pos, call().recurse + 1 }); } } } } /** * @param in {const std::vector<unsigned>&} - vectors of indices * @param recurse {unsigned} - recursion depth * * Enumerates all permutations recursively. This code is O(n*n!). */ void recursive_permutations(const std::vector<unsigned>& in, unsigned recurse=0) { using namespace Recursion; //Vector of indices not yet "used up" in permuation sequence static std::set<unsigned> remaining(in.begin(), in.end()); //Vector containing the permutation static std::vector<unsigned> indices(in.size()); //Termination sequence static std::vector<unsigned> term(in.rbegin(), in.rend()); //Loop over all unused indices to generate next index in permutation for (auto iter = remaining.begin(); iter != remaining.end(); ++iter) { //Add next index to permutation
  • 7. unsigned i = *iter; indices[recurse] = i; //If complete permuation then print if (recurse == in.size()-1 || indices == term) { for (auto index : indices) std::cout << index << " "; std::cout << std::endl; } //If incomplete, recurse else { remaining.erase(i); recursive_permutations(in, recurse + 1); iter = remaining.insert(i).first; } } } /** * @param in {const std::vector<unsigned>&} - vectors of indices * @param recurse {unsigned} - recursion depth * * Enumerates all permutations iteratively. This code is O(n*n!). */ void iterative_permutations(const std::vector<unsigned>& in, unsigned recurse=0) { using namespace Recursion; //Args to be pushed to stack struct Args{unsigned recurse; std::set<unsigned>::iterator* iter; unsigned i;}; //Vector of indices not yet "used up" in permuation sequence static std::set<unsigned> remaining(in.begin(), in.end()); //Vector containing the permutation static std::vector<unsigned> indices(in.size()); //Termination sequence static std::vector<unsigned> term(in.rbegin(), in.rend()); auto iter = remaining.begin(); //Iterate until recursion termination condition hit while (Call<Args>::done({ recurse }, [&]{return indices != term; }) ) { // Create object to push and pop args for each iteration Call<Args> call; //Loop over all unused indices to generate next index in permutation while ( iter != remaining.end() ) { //Add next index to permutation unsigned i = *iter; indices[call().recurse] = i; //If complete permuation then print if (call().recurse == in.size() - 1) { for (auto index : indices) std::cout << index << " "; std::cout << std::endl; ++iter; } //If incomplete, recurse else { //Ctor is done at top of "recurse" auto ctor = [&](){ remaining.erase(call().i); (*call().iter) = remaining.begin();}; //recurse
  • 8. call({ call().recurse + 1, &iter, i}, ctor); //Dtor is done after recurse returns call.dtor([&call](){*call().iter = remaining.insert(call().i).first; ++(*call().iter); }); } } } } } /** * @} */ int main(void) { using namespace Tests; using namespace std::chrono; bool is_test_recursive = false; std::vector<unsigned> in({ 0, 1, 2, 3, 4, 5 }); unsigned k = 3; std::cout << "Generating " << k << " out of " << in.size() << " combinations: " << std::endl; is_test_recursive ? recursive_combinations(in,k) : iterative_combinations(in,k); std::vector<unsigned> recursive({ 0, 1, 2, 3}); std::vector<unsigned> iterative({ 0, 1, 2, 3, 4, 5, 6, 7, 8 }); auto vec = is_test_recursive ? recursive : iterative; std::cout << "Generating all permutations of " << vec.size() << " indices using class "Call": " << std::endl; steady_clock::time_point begin, end; begin=steady_clock::now(); is_test_recursive ? recursive_permutations(recursive) : iterative_permutations(iterative); end=steady_clock::now(); auto time_for_call = duration_cast<microseconds>(end - begin).count(); std::cout << "Class "Call" took: " << time_for_call << std::endl; std::cout << "Generating all permutations of " << vec.size() << " indices using std::next_permuation: " << std::endl; begin=steady_clock::now(); while(std::next_permutation(iterative.begin(), iterative.end())) { for(auto& i : iterative) std::cout << i << " "; std::cout << std::endl; } end=steady_clock::now(); std::cout << "Class "Call" took: " << time_for_call << std::endl; auto next_perm = duration_cast<microseconds>(end - begin).count(); std::cout << "std::next_permuation took: " << next_perm<< std::endl; std::cout << "Time for Class "Call" / time for std::next_permutation: " << (double)time_for_call/(double)next_perm << std::endl; return 0; }