tail recursion optimization - c++

how to make tail recursion optimization enabled, when function more and vals call each other?
now, when I set n = 5, but when I set n = 50000000, it will occur error.
using Cb = std::function<void(bool, int)>;
using Read = std::function<void(bool, Cb)>;
using Sink = std::function<void(Read&)>;
using Through = std::function<Read(Read&)>;
int main() {
int n = 5;
Read vals = [&](bool abort, Cb cb) {
if (n-- <= 0) {
return;
}
cb(false, n); // call `more` function
};
Sink logInt = [&](Read &read) {
Cb more;
more = [&](bool abort, int val) {
cout << val << endl;
read(false, more); // call `vals` function
};
read(false, more);
};
logInt(vals);
return 0;
}
whole real code example

Related

Getting Permutations with Repetitions in this special way

I have a list of {a,b} and i need all possible combinatations where say n=3.
so:
[a,b,a],
[b,a,b]
[a,a,a]
[b,b,b]
etc.
Is there a name of such a problem
My current solution just uses random sampling and is very inefficient:
void set_generator(const vector<int>& vec, int n){
map<string, vector<int>> imap;
int rcount = 0;
while(1){
string ms = "";
vector<int> mset;
for(int i=0; i<n; i++){
int sampled_int = vec[rand() % vec.size()];
ms += std::to_string(sampled_int);
mset.emplace_back(sampled_int);
}
if(rcount > 100)
break;
if(imap.count(ms)){
rcount += 1;
//cout << "*" << endl;
continue;
}
rcount = 0;
imap[ms] = mset;
cout << ms << endl;
}
}
set_generator({1,2},3);
Let us call b the size of the input vector.
The problem consists in generating all numbers from 0 to b^n - 1, in base b.
A simple solution increments the elements of an array one by one, each from 0 to b-1.
This is performed by the function increment in the code hereafter.
Output:
111
211
121
221
112
212
122
222
The code:
#include <iostream>
#include <vector>
#include <string>
#include <map>
void set_generator_op (const std::vector<int>& vec, int n){
std::map<std::string, std::vector<int>> imap;
int rcount = 0;
while(1){
std::string ms = "";
std::vector<int> mset;
for(int i=0; i<n; i++){
int sampled_int = vec[rand() % vec.size()];
ms += std::to_string(sampled_int);
mset.emplace_back(sampled_int);
}
if(rcount > 100)
break;
if(imap.count(ms)){
rcount += 1;
//cout << "*" << endl;
continue;
}
rcount = 0;
imap[ms] = mset;
std::cout << ms << "\n";
}
}
// incrementation of a array of int, in base "base"
// return false if max is already attained
bool increment (std::vector<int>& cpt, int base) {
int n = cpt.size();
for (int i = 0; i < n; ++i) {
cpt[i]++;
if (cpt[i] != base) {
return true;
}
cpt[i] = 0;
}
return false;
}
void set_generator_new (const std::vector<int>& vec, int n){
int base = vec.size();
std::vector<int> cpt (n, 0);
while (true) {
std::string permut = "";
for (auto &k: cpt) {
permut += std::to_string (vec[k]);
}
std::cout << permut << "\n";
if (!increment(cpt, base)) return;
}
}
int main() {
set_generator_op ({1,2},3);
std::cout << "\n";
set_generator_new ({1,2},3);
}
Following advices of Jarod42, I have
suppressed the useless conversion to a string
used a more elegant do ... while instead of the while true
inversed the iterators for printing the result
Moreover, I have created a templated version of the program.
New output:
111
112
121
122
211
212
221
222
aaa
aab
aba
abb
baa
bab
bba
bbb
And the new code:
#include <iostream>
#include <vector>
#include <string>
#include <map>
// incrementation of a array of int, in base "base"
// return false if max is already attained
bool increment (std::vector<int>& cpt, int base) {
int n = cpt.size();
for (int i = 0; i < n; ++i) {
cpt[i]++;
if (cpt[i] != base) {
return true;
}
cpt[i] = 0;
}
return false;
}
template <typename T>
void set_generator_new (const std::vector<T>& vec, int n){
int base = vec.size();
std::vector<int> cpt (n, 0);
do {
for (auto it = cpt.rbegin(); it != cpt.rend(); ++it) {
std::cout << vec[*it];
}
std::cout << "\n";
} while (increment(cpt, base));
}
int main() {
set_generator_new<int> ({1,2}, 3);
std::cout << "\n";
set_generator_new<char> ({'a','b'}, 3);
}
Besides the concrete answer for integer usage, I want to provide a generic way I needed during test case construction for scenarios with a wide spread of various parameter variations. Maybe it's helpful to you too, at least for similar scenarios.
#include <vector>
#include <memory>
class SingleParameterToVaryBase
{
public:
virtual bool varyNext() = 0;
virtual void reset() = 0;
};
template <typename _DataType, typename _ParamVariationContType>
class SingleParameterToVary : public SingleParameterToVaryBase
{
public:
SingleParameterToVary(
_DataType& param,
const _ParamVariationContType& valuesToVary) :
mParameter(param)
, mVariations(valuesToVary)
{
if (mVariations.empty())
throw std::logic_error("Empty variation container for parameter");
reset();
}
// Step to next parameter value, return false if end of value vector is reached
virtual bool varyNext() override
{
++mCurrentIt;
const bool finished = mCurrentIt == mVariations.cend();
if (finished)
{
return false;
}
else
{
mParameter = *mCurrentIt;
return true;
}
}
virtual void reset() override
{
mCurrentIt = mVariations.cbegin();
mParameter = *mCurrentIt;
}
private:
typedef typename _ParamVariationContType::const_iterator ConstIteratorType;
// Iterator to the actual values this parameter can yield
ConstIteratorType mCurrentIt;
_ParamVariationContType mVariations;
// Reference to the parameter itself
_DataType& mParameter;
};
class GenericParameterVariator
{
public:
GenericParameterVariator() : mFinished(false)
{
reset();
}
template <typename _ParameterType, typename _ParameterVariationsType>
void registerParameterToVary(
_ParameterType& param,
const _ParameterVariationsType& paramVariations)
{
mParametersToVary.push_back(
std::make_unique<SingleParameterToVary<_ParameterType, _ParameterVariationsType>>(
param, paramVariations));
}
const bool isFinished() const { return mFinished; }
void reset()
{
mFinished = false;
mNumTotalCombinationsVisited = 0;
for (const auto& upParameter : mParametersToVary)
upParameter->reset();
}
// Step into next state if possible
bool createNextParameterPermutation()
{
if (mFinished || mParametersToVary.empty())
return false;
auto itPToVary = mParametersToVary.begin();
while (itPToVary != mParametersToVary.end())
{
const auto& upParameter = *itPToVary;
// If we are the very first configuration at all, do not vary.
const bool variedSomething = mNumTotalCombinationsVisited == 0 ? true : upParameter->varyNext();
++mNumTotalCombinationsVisited;
if (!variedSomething)
{
// If we were not able to vary the last parameter in our list, we are finished.
if (std::next(itPToVary) == mParametersToVary.end())
{
mFinished = true;
return false;
}
++itPToVary;
continue;
}
else
{
if (itPToVary != mParametersToVary.begin())
{
// Reset all parameters before this one
auto itBackwd = itPToVary;
do
{
--itBackwd;
(*itBackwd)->reset();
} while (itBackwd != mParametersToVary.begin());
}
return true;
}
}
return true;
}
private:
// Linearized parameter set
std::vector<std::unique_ptr<SingleParameterToVaryBase>> mParametersToVary;
bool mFinished;
size_t mNumTotalCombinationsVisited;
};
Possible usage:
GenericParameterVariator paramVariator;
size_t param1;
int param2;
char param3;
paramVariator.registerParameterToVary(param1, std::vector<size_t>{ 1, 2 });
paramVariator.registerParameterToVary(param2, std::vector<int>{ -1, -2 });
paramVariator.registerParameterToVary(param3, std::vector<char>{ 'a', 'b' });
std::vector<std::tuple<size_t, int, char>> visitedCombinations;
while (paramVariator.createNextParameterPermutation())
visitedCombinations.push_back(std::make_tuple(param1, param2, param3));
Generates:
(1, -1, 'a')
(2, -1, 'a')
(1, -2, 'a')
(2, -2, 'a')
(1, -1, 'b')
(2, -1, 'b')
(1, -2, 'b')
(2, -2, 'b')
For sure, this can be further optimized/specialized. For instance you can simply add a hashing scheme and/or an avoid functor if you want to avoid effective repetitions. Also, since the parameters are held as references, one might consider to protect the generator from possible error-prone usage via deleting copy/assignement constructors and operators.
Time complexity is within the theoretical permutation complexity range.

Assert Failing and I don't know why c++

from the main.cpp
assert error is here
if(!((CPU1.peek()).isExecuting())) {
cout << "Running: " << CPU1.peek().running << endl;
(CPU1.peek()).execute();
cout << "Running: " << CPU1.peek().running << endl;
assert((CPU1.peek()).isExecuting());
((PCB)CPU1.peek()).setStart(slice);
((PCB)CPU1.peek()).setWait(slice-((PCB)CPU1.peek()).getArrival());
averageWait1 += ((PCB)CPU1.peek()).getWait();
cpu1PCBTotal++;
length1 = ((PCB)CPU1.peek()).getLength();
}
PCB.h
class PCB
{
private:
/**
* this process ID
*/
int pid;
/**
* the nice (priority) value of this process
*/
int priority;
/**
* running status 0=idle 1=running
*/
int running;
public:
/**
* Creates a simulated job with default values for its parameters.
*/
PCB()
{
priority = 19;
running = 0;
arrived = 0;
length = 0;
}
PCB(int id, int pval, int run, int arr, int len)
{
pid = id;
priority = pval;
running = run;
arrived = arr;
length = len;
}
bool isExecuting() const
{
return (running == 1);
}
void execute()
{
running = 1;
}
heap.cpp
template <typename E>
Heap<E>::Heap()
{
// compiler-generated code .. no need to implement this
}
template <typename E>
Heap<E>::~Heap()
{
while(tree.size() > 0)
tree.pop_back();
}
template <typename E>
bool Heap<E>::isEmpty() const
{
return tree.size() == 0;
}
template<typename E>
void Heap<E>::insert(E item)
{
tree.push_back(item);
int place = size()-1;
int parent = (place-1)/2;
while(parent >= 0 && tree[place] > tree[parent]) {
swap(place, parent);
place = parent;
parent = (place-1)/2;
}
}
template<typename E>
E Heap<E>::remove() throw (HeapException)
{
E root = tree[0];
tree[0] = tree[size()-1];
tree.pop_back();
reheapify(0);
return root;
}
template<typename E>
const E& Heap<E>::peek() const throw (HeapException)
{
return tree[0];
}
template<typename E>
int Heap<E>::size()const
{
return tree.size();
}
template<typename E>
void Heap<E>::swap(int place, int parent)
{
E temp = tree[place];
tree[place] = tree[parent];
tree[parent] = temp;
}
template<typename E>
void Heap<E>::reheapify(int root)
{
int l = root*2+1;
int r = root*2+2;
if(l < size()-1) {
if(r < size()-1)
if(tree[root] < tree[r]) {
swap(root, r);
reheapify(r);
}
if(tree[root] < tree[l]) {
swap(root, l);
reheapify(l);
}
}
}
The assertion is failing, and I have no idea why... Please help, thanks
Top is main function, bottom is PCB.h; CPU class is a Heap
Originally typecasted CPU1.peek() because it gave me the error "passing 'const PCB' as 'this' argument discards qualifiers" So I guess I needs help calling CPU1.peek().execute()

Node.js C++ Addon - Setting a certain index of an array

I'm trying to create a Node.js C++ Addon that generates the Fibonacci sequence to compare its speed with a normal Node.js module, but I'm having trouble setting a certain index of an array. I've got this so far:
#include <node.h>
namespace demo {
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::Value;
using v8::Number;
using v8::Array;
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
int next, first = 0, second = 0, c = 0, n = args[0]->NumberValue();
Local<Array> arr = Array::New(isolate, n);
for (; c < n; c++) {
if ( c <= 1 ) next = c;
else {
next = first + second;
first = second;
second = next;
}
// How to set arr[c]?????
}
args.GetReturnValue().Set(arr);
}
void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "fib", Method);
}
NODE_MODULE(addon, init)
}
On line 26, how should I set arr[c]? v8:Array doesn't provide a subscript operator.
how should I set arr[c]? v8:Array doesn't provide a subscript operator.
It doesn't, but v8::Array already inherits the function member Set from v8::Object, with an overload that takes an integer (uint32_t) for the key. Use it to populate each element of the array:
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
int next, first = 0, second = 0, c = 0, n = args[0]->NumberValue();
Local<Array> arr = Array::New(isolate, n);
int i = 0;
for (; c < n; c++) {
if ( c <= 1 ) next = c;
else {
next = first + second;
first = second;
second = next;
}
arr->Set(i++, Number::New(isolate, next));
}
args.GetReturnValue().Set(arr);
}

For loop and vectors causing trouble

I am trying to create a for loop that runs through a vector, pushes something into a queue, updates all appropriate elements of the struct of the vector and then loops again until the vector is empty.
The problem I am having is that the function to run through my for loop does not seem to be updating my vector elements, I am getting the same output even though I know it should be changing.
Here is the link to a gist of the project https://gist.github.com/sgodfrey321/6cffd85896432b2942aa , it just has a lot of filler, I had to input alot of stuff by hand so it is kinda messy.
So to start with I pass my vector to the function in a while loop
void queueNodes(vector<vertex>& list, queue<vertex>& q);
as such
int counter = 0;
while (counter < 11) {
queueNodes(nodes, q);
counter++;
}
the while loop is to make sure that I run through the vector enough times. Now in the function I check to see if incomingEdges of the struct is 0 and if it is I push it into the queue and update the next door incomingEdges:
void queueNodes(vector<vertex>& nodes, queue<vertex>& q) {
for (auto i : nodes) {
cout << endl << i.vertexName << " ";
if (i.incomingEdges == 0) {
i.nextDoorTop->incomingEdges--;
i.nextDoorMiddle->incomingEdges--;
i.nextDoorBottom->incomingEdges--;
q.push(i);
cout << "foo";
} else {
cout << "bar";
}
}
Now I would expect that when I use the function again with the updated vector I would see a change in output as updating the next door incomingEdges would cause some to trigger the condition I am looking for. I have written outputs that show the next door incomingEdges are in fact decreasing however I can not seem to use the updated vector in the function call.
Do I need to return the vector somehow? I am sure that I am calling the function incorrectly, but does anyone have any ideas?
Thank You
edit: forgot to pass by reference the queue!
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct vertex {
char vertexName;
int incomingEdges;
vertex* nextDoorTop;
vertex* nextDoorMiddle;
vertex* nextDoorBottom;
};
void queueNodes(vector<vertex>& nodes);
int main() {
vertex s, A, G, D, B, H, E, C, I, F, t;
s.vertexName = 's';
s.incomingEdges = 0;
s.nextDoorTop = &A;
s.nextDoorMiddle = &D;
s.nextDoorBottom = &G;
A.vertexName = 'A';
A.incomingEdges = 2;
A.nextDoorTop = &B;
A.nextDoorMiddle = &E;
G.vertexName = 'G';
G.incomingEdges = 1;
G.nextDoorTop = &D;
G.nextDoorMiddle = &E;
G.nextDoorBottom = &H;
D.vertexName = 'D';
D.incomingEdges = 2;
D.nextDoorMiddle = &E;
B.vertexName = 'B';
B.incomingEdges = 1;
B.nextDoorTop = &C;
H.vertexName = 'H';
H.incomingEdges = 1;
H.nextDoorTop = &E;
H.nextDoorMiddle = &I;
E.vertexName = 'E';
E.incomingEdges = 4;
E.nextDoorTop = &C;
E.nextDoorMiddle = &F;
E.nextDoorBottom = &I;
C.vertexName = 'C';
C.incomingEdges = 3;
C.nextDoorMiddle = &t;
I.vertexName = 'I';
I.incomingEdges = 2;
I.nextDoorTop = &F;
I.nextDoorMiddle = &t;
F.vertexName = 'F';
F.incomingEdges = 2;
F.nextDoorMiddle = &t;
t.vertexName = 't';
t.incomingEdges = 3;
vector<vertex> nodes { s, A, G, D, B, H, E, C, I, F, t };
cout << "Vertex Name: " << " Number Of Edges: " << endl;
for (auto i : nodes) {
cout << i.vertexName << " " << i.incomingEdges << " "
<< endl;
}
int counter = 0;
while (counter < 11) {
queueNodes(nodes);
counter++;
}
return 0;
}
void queueNodes(vector<vertex>& nodes) {
for (auto& i : nodes) {
cout << endl << i.vertexName << " ";
if (i.incomingEdges == 0) {
i.nextDoorTop->incomingEdges--;
i.nextDoorMiddle->incomingEdges--;
i.nextDoorBottom->incomingEdges--;
cout << "foo";
} else {
cout << "bar";
}
}
}

Why I am getting zero output for all the values in array?

I got this implementation for maximum matching off the net and is trying to give its input through main class. But I am getting zero for all the places in match. What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <queue>
using namespace std;
void add_edge(int u, int v);
void edmonds();
struct edge {
int v, nx;
};
const int MAXN = 1000, MAXE = 2000;
edge graph[MAXE];
int last[MAXN], match[MAXN], px[MAXN], base[MAXN], N, M, edges;
bool used[MAXN], blossom[MAXN], lused[MAXN];
int main ()
{
// return 0;
add_edge(1,4);
add_edge(1,5);
add_edge(1,6);
add_edge(2,5);
add_edge(2,7);
add_edge(3,4);
add_edge(4,1);
add_edge(4,3);
add_edge(5,1);
add_edge(5,2);
add_edge(6,1);
add_edge(7,2);
edmonds();
cout << match[0];
cout << match[1];
cout << match[2];
cout << match[3];
cout << match[4];
cout << match[5];
cout << match[6];
}
inline void add_edge(int u, int v) {
graph[edges] = (edge) {v, last[u]};
last[u] = edges++;
graph[edges] = (edge) {u, last[v]};
last[v] = edges++;
}
void mark_path(int v, int b, int children) {
while (base[v] != b) {
blossom[base[v]] = blossom[base[match[v]]] = true;
px[v] = children;
children = match[v];
v = px[match[v]];
}
}
int lca(int a, int b) {
memset(lused, 0, N);
while (1) {
lused[a = base[a]] = true;
if (match[a] == -1)
break;
a = px[match[a]];
}
while (1) {
b = base[b];
if (lused[b])
return b;
b = px[match[b]];
}
}
int find_path(int root) {
memset(used, 0, N);
memset(px, -1, sizeof(int) * N);
for (int i = 0; i < N; ++i)
base[i] = i;
used[root] = true;
queue<int> q;
q.push(root);
register int v, e, to, i;
while (!q.empty()) {
v = q.front(); q.pop();
for (e = last[v]; e >= 0; e = graph[e].nx) {
to = graph[e].v;
if (base[v] == base[to] || match[v] == to)
continue;
if (to == root || (match[to] != -1 && px[match[to]] != -1)) {
int curbase = lca(v, to);
memset(blossom, 0, N);
mark_path(v, curbase, to);
mark_path(to, curbase, v);
for (i = 0; i < N; ++i)
if (blossom[base[i]]) {
base[i] = curbase;
if (!used[i]) {
used[i] = true;
q.push(i);
}
}
} else if (px[to] == -1) {
px[to] = v;
if (match[to] == -1)
return to;
to = match[to];
used[to] = true;
q.push(to);
}
}
}
return -1;
}
void build_pre_matching() {
register int u, e, v;
for (u = 0; u < N; ++u)
if (match[u] == -1)
for (e = last[u]; e >= 0; e = graph[e].nx) {
v = graph[e].v;
if (match[v] == -1) {
match[u] = v;
match[v] = u;
break;
}
}
}
void edmonds() {
memset(match, 0xff, sizeof(int) * N);
build_pre_matching();
register int i, v, pv, ppv;
for (i = 0; i < N; ++i)
if (match[i] == -1) {
v = find_path(i);
while (v != -1) {
pv = px[v], ppv = match[pv];
match[v] = pv, match[pv] = v;
v = ppv;
}
}
}
You set elements of match in two locations: In build_pre_matching() and in edmonds(). In both of these cases, no change will happen if match[x] for some index x isn't -1. The only other place elements of match get a value is during static initialization where the values get zero initialized. Since the initial value is zero and the values are only ever changed if at least one of them happens to be -1, I would expect that the values retain the value 0.
You might want to use something like
std::fill(std::begin(match), std::end(match), -1);
at a strategic location since you seem to assume that the values are initially -1. Of course, you also should consider the idea of not using global variables because this doesn't scale and works really badly in a multi-threaded program.