We have been restricted us to not use a loop in a program as a programming challenge.
Restrictions:
You can not use while, for, goto and recursion.
The restrictions are pretty daunting. I couldn't really think of any proper solution.
So I opted for this one which is achieved by modifying the return address.
Could this be any better?
#include <unistd.h>
#include <sys/mman.h>
#include <iostream>
#include <cstring>
void the__(){}
void magic__(){}
void loop__(){}
void function__(){}
void here__(){}
template <typename T>
struct for_
{
bool started = false;
void* fix = nullptr;
void(*body)(T&) = nullptr;
for_(void(*body)(T&))
: body(body)
{
auto do_for__ = uintptr_t(do_for_);
uint64_t magic[] = {5243466812662057800, 6135086863767628931ull, 10416984888688609608ull, 144};
mprotect((void*)(do_for__-do_for__%4096), 4096, 7);
std::memcpy((void*)(do_for__+135), magic, 25);
}
static void do_for_(T& ctx)
{
void** p = (void**)((char*)&p+16);
if (!ctx.started)
{
if (!ctx) return;
ctx.started = true;
ctx.fix = *p;
*p = (void*)do_for_;
}
ctx.body(ctx);
ctx.next();
if (ctx)
{
the__();
magic__();
loop__();
function__();
here__();
}
else
{
*p = ctx.fix;
}
}
};
struct For0ToN : for_<For0ToN>
{
For0ToN(int N, void(*f)(For0ToN&))
: for_<For0ToN>(f)
, N(N)
{
do_for_(*this);
}
operator bool() {return i < N;}
operator int() {return i;}
void next() {i++;}
int count() {return i;}
int i = 0, N = 0;
};
int main()
{
For0ToN(10, +[](For0ToN& i)
{
std::cout << int(i) << ": ";
For0ToN(i.count(), +[](For0ToN& i)
{
std::cout << int(i) << ". ";
});
std::cout << "\n";
});
std::cout << "done\n";
return 0;
}
The code is demonstrated here: https://coliru.stacked-crooked.com/a/3dd77ade501ac748
You could use longjmp. Here's an example from cppreference:
#include <csetjmp>
#include <iostream>
std::jmp_buf jump_buffer;
[[noreturn]] void a(int count)
{
std::cout << "a(" << count << ") called\n";
std::longjmp(jump_buffer, count+1); // setjmp() will return count+1
}
int main() {
// loop from 0-9
volatile int count = 0; // local variables must be volatile for setjmp
if (setjmp(jump_buffer) != 10) {
a(count++); // This will cause setjmp() to exit
}
}
Question is unclear but 1 alternative of the loop is std::transform()
Template metaprogramming is common way of avoiding writing explicit loop in code. This work gets done by compiler. Check this for examples of factorial and bubble sort implementation without writing explicit loops. You can check this stack overflow post as well.
Does it count if I hide recursion into function objects and create a finite state machine?
struct state
{
size_t current_column;
size_t current_row;
size_t max_column;
size_t max_row;
};
typedef function<void(state&)> action_t;
struct do_item
{
do_item(ostream& ss, action_t* move_next)
: ss_(ss), move_next_(move_next) {}
void operator()(state& s)
{
if (s.current_row == s.max_row)
{
ss_ << "done";
return;
}
if (0 == s.current_column)
{
ss_ << s.current_row << ':';
}
if (s.max_column == s.current_column)
{
ss_ << '\n';
s.current_column = 0;
++s.current_row;
s.max_column = s.current_row;
}
else
{
ss_ << ' ' << s.current_column << '.';
++s.current_column;
}
(*move_next_)(s);
}
ostream& ss_;
action_t* move_next_;
};
static string no_loops_challenge(size_t n)
{
stringstream ss;
state s = {0, 0, 0, n};
action_t move_next;
do_item action(ss, &move_next);
move_next = action;
action(s);
return ss.str();
}
Here's a solution using range-v3 that should satisfy all the constraints:
namespace rv = ranges::views;
ranges::for_each(rv::iota(0, 10), [](int i) {
std::cout << i << ": ";
ranges::copy(rv::iota(0, i),
ranges::ostream_iterator<int>(std::cout, ". "));
std::cout << "\n";
});
Here's a demo.
Related
I'm trying to count vowels in a book "War and Peace" by Lev Tolstoi with 4 different methods:
Using Count_if/find
Using Count_if/for
for/find
4.for/for
The programm also calculates time it takes for every method to get the number of vowels. I'm using a russian version of the book as a reference so all the vowels are taken from cyrillic alphabet. Here is the code:
#include <chrono>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <Windows.h>
#include <string>
#include <fstream>
#include <iterator>
class Timer
{
private:
using clock_t = std::chrono::high_resolution_clock;
using second_t = std::chrono::duration<double, std::ratio<1> >;
std::string m_name;
std::chrono::time_point<clock_t> m_beg;
double elapsed() const
{
return std::chrono::duration_cast<second_t>(clock_t::now()
- m_beg).count();
}
public:
Timer() : m_beg(clock_t::now()) { }
Timer(std::string name) : m_name(name), m_beg(clock_t::now()) { }
void start(std::string name) {
m_name = name;
m_beg = clock_t::now();
}
void print() const {
std::cout << m_name << ":\t" << elapsed() * 1000 << " ms" << '\n';
}
};
const std::string vowels = "аеёиоуыэюяАЕЁИОУЫЭЮЯ";
bool containVowel(const std::string& s, const char& a)
{
for (size_t i = 0; i < s.size(); i++)
{
if (a == s[i])
{
return true;
}
return false;
}
}
void ForFor(std::ifstream& ifs, std::string& ww)
{
size_t count = 0;
Timer t1("for for");
while (ifs >> ww)
{
for (size_t i = 0; i < ww.size(); i++)
{
if (containVowel(vowels, ww[i]))
{
count++;
}
}
}
t1.print();
std::cout << count << std::endl;
}
//bool findVowel(char c)
//{
// return vowels.find(c) != std::string::npos;
//}
void CountIfFind(std::ifstream& ifs, std::string& ww) // not sure what is the way to cout count here...
{
Timer t("count_if/find");
while (ifs >> ww)
{
size_t count = std::count_if(ww.begin(), ww.end(), [&](char c) {return vowels.find(c) != std::string::npos; });
}
t.print();
}
void CountIfFor(std::ifstream& ifs, std::string& ww) // not sure what is the way to cout count here...
{
Timer t("count_if/for");
while (ifs >> ww)
{
for (size_t i = 0; i < vowels.size(); i++)
{
auto count = std::count_if(ww.begin(), ww.end(), [&](char c) {return c == vowels[i]; });
}
}
t.print();
}
void ForFind(std::ifstream& ifs, std::string& ww)
{
char c{};
int count = 0;
Timer t("for/find");
while (ifs >> ww)
{
for (size_t i = 0; i < ww.size(); i++)
{
if (vowels.find(c) != std::string::npos)
{
count++;
}
}
}
t.print();
std::cout << count << std::endl;
}
int main()
{
setlocale(LC_ALL, "ru");
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
std::ifstream ifs;
ifs.open("Толстой Лев. Война и мир. Книга 1 - royallib.ru.txt");
if (ifs.is_open())
{
std::string ww;
ForFor(ifs, ww);
CountIfFind(ifs,ww);
CountIfFor(ifs,ww);
ForFind(ifs, ww);
ifs.close();
}
else
{
std::cout << "Can't open the file!" << std::endl;
}
}
Function ForFor works just fine but 3 other don't work (they don't show count but show time though). I'm guessing there is a problem with parsing the file, though I'm not sure because of my inexperience.
Will be hoping for your help!) Thank you all, in advance.
EDIT:Ok so now I'm sure the issue is in while(ifs>>ww). ForFor was the first function in the main so it worked, I tried commenting it and the next one CountIfFind started working. But when I delete while in every function and use it in main like: while(ifs>>ww) {ForFor(ww); CountIfFind(ww); CountIfFor(ww); ForFind(ww);} It doesn't work at all... How do I fix it?
So here is the correct way to do it:
class Timer
{
private:
using clock_t = std::chrono::high_resolution_clock;
using second_t = std::chrono::duration<double, std::ratio<1> >;
std::string m_name;
std::chrono::time_point<clock_t> m_beg;
double elapsed() const
{
return std::chrono::duration_cast<second_t>(clock_t::now()
- m_beg).count();
}
public:
Timer() : m_beg(clock_t::now()) { }
Timer(std::string name) : m_name(name), m_beg(clock_t::now()) { }
void start(std::string name) {
m_name = name;
m_beg = clock_t::now();
}
void print() const {
std::cout << m_name << ":\t" << elapsed() * 1000 << " ms" << '\n';
}
};
const std::string vowels = "аеёиоуыэюяАЕЁИОУЫЭЮЯ";
size_t ForFor(std::string& ww)
{
size_t count = 0;
Timer t1("for for");
for(const auto& ch : ww)
{
for (const auto& vow : vowels)
{
if (ch == vow)
{
++count;
break;
}
}
}
t1.print();
return count;
}
size_t CountIfFind(std::string& ww)
{
Timer t("count_if/find");
size_t count = std::count_if(ww.begin(), ww.end(), [ & ](char c) {return vowels.find(c) != std::string::npos; });
t.print();
return count;
}
size_t CountIfFor(std::string& ww)
{
Timer t("count_if/for");
size_t count = std::count_if(ww.begin(), ww.end(), [&](const char& c1)
{
for (const auto& ch : vowels)
{
if (c1 == ch)
{
return true;
}
}
return false;
});
t.print();
return count;
}
size_t ForFind(std::string& ww)
{
char c{};
size_t count = 0;
Timer t("for/find");
for (const auto& ch :ww)
{
if (vowels.find(ch) != std::string::npos)
{
++count;
}
}
t.print();
return count;
}
int main()
{SetConsoleCP(1251);
SetConsoleOutputCP(1251);
std::ifstream file("Толстой Лев. Война и мир. Книга 1 - royallib.ru.txt");
file.seekg(0, std::ios::end);
size_t size = file.tellg();
file.seekg(0);
std::string s(size, ' ');
file.read(&s[0], size);
std::cout << CountIfFind(s) << std::endl;
std::cout << ForFor(s) << std::endl;
std::cout << ForFind(s) << std::endl;
std::cout << CountIfFor(s) << std:: endl;
}
In my daily work, I usually write my code like this:
int ret = 0;
ret = func1();
if(ret != 0) {
return ret;
}
ret = func2();
if(ret != 0) {
return ret;
}
But this means I need to complete a lot of "if(ret!=0){return ret;}",Is there a more C++ elegant implementation to complete the function jump?
By the way, we are not allowed to use exception.
The shown code seems to be logically equivalent to:
int ret;
if ((ret=func1()) || (ret=func2()))
return ret;
Tack on as many additional function calls as you wish, in the obvious manner.
Another possibility is to perform a for range loop over a set of functions:
for (auto& ff: {func1, func2, func3}) {
Output:
in func1
in func2
in func3
3
Code:
#include <iostream>
int func1() {
std::cout << "in func1\n";
return 0;
}
int func2() {
std::cout << "in func2\n";
return 0;
}
int func3() {
std::cout << "in func3\n";
return 3;
}
int foo () {
for (auto& ff: {func1, func2, func3}) {
int ret;
if ((ret=ff()) != 0) {
return ret;
}
}
return 0;
}
int main() {
std::cout << foo() << "\n";
}
In a comment, you asked the question on how to make it work with member functions.
It seems more tricky, in particular because the compiler has difficulty to guess
the proper type of the initializer_list.
This is one way to solve it.
#include <iostream>
class Obj {
public:
int func1() {
std::cout << "in func1\n";
return 0;
}
int func2() {
std::cout << "in func2\n";
return 0;
}
int func3() {
std::cout << "in func3\n";
return 3;
}
int foo () {
for (auto ff: {&func1, &func2, &func3}) {
int ret;
if ((ret=(this->*ff)()) != 0) {
return ret;
}
}
return 0;
}
};
int main() {
Obj var;
std::cout << var.foo() << "\n";
}
#include <iostream>
#include <functional>
struct Status{
int status;
template<typename Func, typename... Args>
Status& invoke(Func&& func, Args&&... args){
if (!status)
status = std::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
return *this;
};
int value() const noexcept{
return status;
}
};
int func1(){
std::cout << "call func 1" << std::endl;
return 0;
}
int func2(int a){
std::cout << "call func 2 with " << a << std::endl;
return a;
}
int func3(float x){
std::cout << "call func 3 with " << x << std::endl;
return 1;
}
int foo(){
std::cout << "call foo" << std::endl;
return Status{}.invoke(func1).invoke(func2, 0).invoke(func3, 0).value();
}
int bar(){
std::cout << "call bar" << std::endl;
return Status{}.invoke(func2, 3).invoke(func1).invoke(func3, 0).value();
}
int main(){
int a;
a = foo();
std::cout << "foo return " << a << std::endl;
a = bar();
std::cout << "bar return " << a << std::endl;
return 0;
}
it shows:
call foo
call func 1
call func 2 with 0
call func 3 with 0
foo return 1
call bar
call func 2 with 3
bar return 3
I don't think it's the best way to do that, but it's elegant enough, in my mind. you can serialize all functions and apply short-circuit evaluation (that's why invoke is needed). or you can write it as a command style:
int foo(){
return Status{}
.invoke(func1)
.invoke(func2, 0)
.invoke(func3, 3)
.value();
}
by the way, if you want to know more about this, you can refer to Monad in Haskell.
By using a fold expression and an if statement with initialization you can write the following variadic function template that takes an arbitrary number of pointers to such functions as non-type template arguments:
template<int(...Funcs)()> // equivalent to template<int(*...Funcs)()>
int overall_func() {
if (int ret; (... || (ret = Funcs())))
return ret;
return 0;
}
This way, you factor out all the calls to those functions, the corresponding return value assignments, and their individual checks. Eventually, it boils down to a single check and a single return statement:
if (int ret = overall_func<func1, func2, func3>(); ret)
return ret;
This is regardless of the number of functions to call.
C++, as a descendant of C, has the same short-hand method for assignment and checking together:
int ret;
if ((ret = func1()) != 0) return ret;
if ((ret = func2()) != 0) return ret;
This works because a = something is itself an expression whose value is a.
If you wanted to type even less code for each call-and-check, you could opt for a macro, but that's probably overkill (I wouldn't do it myself), but I'll show it just in case you're interested:
#define RNZ(x) if ((ret = x) != 0) return ret
int ret;
RNZ(func1());
RNZ(func2());
It's possible to do the following code with C++:
myFunction(myArray, positionInsideMyArray) = myValue.
cout << myFunction[positionInsideMyArray] << endl; // Display muValue
How can I do that with C++?
To make my question more clear, With one value the following code work correctly,
I want to do the same thing but using an Array parameter.
int& myFunction(int &x){
return x;
}
this is the main function:
int x;
myFunction(x) = myValue;
cout << x << endl; // This will display myValue
#include <iostream>
int &myFunction(int *arr, size_t pos) { return arr[pos]; }
int main() {
using std::cout;
int myArray[30];
size_t positionInsideMyArray = 5;
myFunction(myArray, positionInsideMyArray) = 17.;
cout << myArray[positionInsideMyArray] << "\n"; // Display muValue
}
or with error checking:
#include <stdexcept>
template<size_t N>
inline int &myFunction(int (&arr)[N], size_t pos)
{
if (pos >= N)
throw std::runtime_error("Index out of bounds");
return arr[pos];
}
myFunction(myArray, positionInsideMyArray) = myValue.
cout << myFunction[positionInsideMyArray] << endl;
With functions alone, the second line is not possible; you'll need a class.
However, that the second call remembers myArray from the
first makes the whole semantics a bit strange...
A rough idea (no complete class, only for int-arrays):
class TheFunc
{
int *arr;
int &operator() (int *arr, size_t pos)
{
this->arr = arr;
return arr[pos];
}
int &operator[] (size_t pos)
{
return arr[pos];
}
};
...
TheFunc myFunction;
myFunction(myArray, positionInsideMyArray) = myValue.
cout << myFunction[positionInsideMyArray] << endl;
A different, more robust version, where the array it set separately:
class TheFunc
{
int *arr;
TheFunc(int *arr)
{
this->arr = arr;
}
int &operator() (size_t pos)
{
return arr[pos];
}
int &operator[] (size_t pos)
{
return arr[pos];
}
};
...
TheFunc myFunction(myArray);
myFunction(positionInsideMyArray) = myValue.
cout << myFunction[positionInsideMyArray] << endl;
I have a member function that prints a snapshot of a boost::fibonacci_heap
virtual void printSnapshot(std::ostream& ss) {
Heap heap(this->heap);
double prev_price = DBL_MAX;
while(heap.size() > 0) {
const Order& order = heap.top();
if(order.price != prev_price) {
if(prev_price != DBL_MAX) ss << std::endl;
ss << order.price << " | ";
}
ss << order.quantity << " ";
prev_price = order.price;
heap.pop();
}
ss << std::endl;
}
I call this member function in another member function, which does
while(std::getline(stream, line)) {
... // do something on this->heap.
this->printSnapshot(std::cout);
}
Since the heap is created through a copy constructor at the beginning of "printSnapshot", then "printSnapshot" should change this->heap. However, this program leads to segment fault, while the following does not:
while(std::getline(stream, line)) {
... // do something on this->heap.
// this->printSnapshot(std::cout);
}
Now, if we add a const keyword to the definition of printSnapshot, i.e.
virtual void printSnapshot(std::ostream& ss) const {
Heap heap(this->heap);
double prev_price = DBL_MAX;
while(heap.size() > 0) {
const Order& order = heap.top();
if(order.price != prev_price) {
if(prev_price != DBL_MAX) ss << std::endl;
ss << order.price << " | ";
}
ss << order.quantity << " ";
prev_price = order.price;
heap.pop();
}
ss << std::endl;
}
The segment fault disappears. How could this be explained?
The constructor of fibonacci_heap that takes a lvalue reference (non-const) apparently doesn't do the right things.
It's not documented what it should do: http://www.boost.org/doc/libs/1_55_0/doc/html/boost/heap/fibonacci_heap.html#idp21129704-bb
I assume this might be a reportable bug. I'll look into this a bit.
UPDATE Surprisingly the behaviour of this constructor is apparently equivalent to move-construction:
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
/// \copydoc boost::heap::priority_queue::priority_queue(priority_queue &&)
fibonacci_heap(fibonacci_heap && rhs):
super_t(std::move(rhs)), top_element(rhs.top_element)
{
roots.splice(roots.begin(), rhs.roots);
rhs.top_element = NULL;
}
fibonacci_heap(fibonacci_heap & rhs):
super_t(rhs), top_element(rhs.top_element)
{
roots.splice(roots.begin(), rhs.roots);
rhs.top_element = NULL;
}
The latter has the weird side-effect of simply removing all roots from the original (intrusive) list. This looks like a clear-cut bug.
Simply removing this constructor makes the code work.
The essential workaround is to avoid the lvalue-ref constructor:
Heap cloned(static_cast<Heap const&>(this->heap));
Meanwhile here's a self-contained reproducer:
#include <boost/heap/fibonacci_heap.hpp>
#include <iostream>
#include <random>
namespace {
#undef DBL_MAX
static double DBL_MAX = std::numeric_limits<double>::max();
std::mt19937 rng;
//std::uniform_real_distribution<double> dist(100, 4000);
std::discrete_distribution<int> dist({1,1,1,1,1,1});
static auto price_gen = [&] {
static double values[] = {52.40, 12.30, 87.10, 388., 0.10, 23.40};
return values[dist(rng)];
};
}
struct Order {
double price = price_gen();
unsigned quantity = rand() % 4 + 1;
double subtotal() const { return price * quantity; }
bool operator<(Order const& other) const { return subtotal() < other.subtotal(); }
};
using Heap = boost::heap::fibonacci_heap<Order>;
struct Y {
virtual void printSnapshot(std::ostream &ss) {
//Heap cloned(static_cast<Heap const&>(this->heap));
Heap cloned(this->heap);
double prev_price = DBL_MAX;
while (cloned.size() > 0) {
const Order &order = cloned.top();
if (order.price != prev_price) {
if (prev_price != DBL_MAX)
ss << std::endl;
ss << order.price << " | ";
}
ss << order.quantity << " ";
prev_price = order.price;
cloned.pop();
}
ss << std::endl;
}
void generateOrders() {
for (int i=0; i<3; ++i) {
heap.push({});
}
}
Heap heap;
};
int main() {
Y y;
for(int i=0; i<10; ++i) {
y.generateOrders();
y.printSnapshot(std::cout);
}
}
I have the following class that tries to work on huge arrays where initialising, reading, writing and deleting are all O(1):
#include <cstdlib>
#include <iostream>
using namespace std;
template<class T> class Init_array {
public:
explicit Init_array(size_t n, const T &val = T()) :
data(static_cast<T *>(malloc(sizeof(T) * n))), default_value(val),
valid(static_cast<size_t *>(malloc(sizeof(size_t) * n))),
x_check(static_cast<size_t *>(malloc(sizeof(size_t) * n))),
count() {
}
~Init_array() {
free(data);
free(valid);
free(x_check);
}
bool is_valid(size_t index) const {
// assume daemons do not fly out of the nose accessing uninitialised size_t
return valid[index] < count && x_check[valid[index]] == index;
}
T &operator[](size_t index) {
if (!is_valid(index)) {
valid[index] = count;
x_check[count] = index;
++count;
new(data + index) T(default_value);
}
return data[index];
}
const T &operator[](size_t index) const {
if (!is_valid[index]) {
return default_value;
} else {
return data[index];
}
}
void erase(size_t index) {
x_check[valid[index]] = x_check[count - 1];
valid[x_check[count - 1]] = valid[index];
--count;
}
private:
T *data;
const T default_value;
size_t *valid;
size_t *x_check;
size_t count;
};
int main() {
Init_array<int> x(1ll << 30); // 20 GiB RAM needed
cout << x[3827749] << '\n';
const size_t test_index = 23829073;
x[test_index] = 123456;
const size_t another_test_index = 212748399;
x[another_test_index] = 888888;
cout << x[test_index] << '\n';
cout << x[another_test_index] << '\n';
x.erase(test_index);
cout << x[test_index] << endl;
}
However, the line after the comment is technically undefined behaviour because it will try to read uninitialised values. I am afraid that it will crash on some machines. Is it possible to make the class free of undefined behaviour, while retaining everything as O(1)?