#include <iostream>
#include <stack>
using namespace std;
// parameters
struct Call {
int n;
int a, b, c, d; // local variables
int cur_loc; // location of next statement to be executed
};
int G(int n) {
Call initial_call;
initial_call.n = n;
initial_call.cur_loc = 0;
stack<Call> st;
st.push(initial_call);
int last_ret_val = 0; // Return value of last finished call
while (!st.empty()) {
Call& call = st.top();
if (call.cur_loc == 0) {
if (call.n <= 1) {
// Call finished, save return value and pop stack
last_ret_val = 1;
st.pop();
}
else {
// Make new child call F(n-1) and push to stack
Call new_call;
new_call.cur_loc = 0;
new_call.n = call.n - 1;
st.push(new_call);
// Update current location inside parent call
call.cur_loc = 1;
}
}
else if (call.cur_loc == 1) {
// Do required computations
call.a = call.n + last_ret_val;
// Make new child call F(n/2) and push to stack
Call new_call;
new_call.cur_loc = 0;
new_call.n = call.n / 2;
st.push(new_call);
// Update current location inside parent call
call.cur_loc = 2;
}
else if (call.cur_loc == 2) {
// Do required computations
call.b = call.n * last_ret_val;
call.c = call.n - 2 - (call.a + call.b) % 2;
Call new_call;
new_call.cur_loc = 0;
new_call.n = call.c;
st.push(new_call);
// Update current location inside parent call
call.cur_loc = 3;
}
else if (call.cur_loc == 3) {
// Do required computations
call.d = last_ret_val;
// Call finished, save return value and pop stack
last_ret_val = call.a + call.b + call.d;
st.pop();
}
}
return last_ret_val;
}
int main()
{
cout << "Result: " << G(3) << endl;
return 0;
}