Skip to content

Instantly share code, notes, and snippets.

@bwedding
Last active April 27, 2024 13:59
Show Gist options
  • Save bwedding/fe6c4e5429988455721ac580ac78ddca to your computer and use it in GitHub Desktop.
Save bwedding/fe6c4e5429988455721ac580ac78ddca to your computer and use it in GitHub Desktop.
1000 random tasks
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <random>
#include <functional>
#include <chrono>
using namespace std::chrono;
constexpr size_t N = 1000;
constexpr size_t OPSTODO = 50000;
template<typename Func>
struct Callables {
std::vector<Func> functions;
void add(Func func)
{
functions.push_back(func);
}
void rearrange(const std::vector<size_t>& order)
{
if (order.size() != functions.size())
{
throw std::invalid_argument("Order vector size must match functions vector size.");
}
std::vector<Func> rearranged_functions(functions.size());
for (size_t i = 0; i < order.size(); ++i)
{
if (order[i] >= functions.size())
{
throw std::out_of_range("Order index out of range.");
}
rearranged_functions[i] = functions[order[i]];
}
functions = rearranged_functions;
}
void callAll(int arg, std::vector<size_t>& order, bool print)
{
for (const auto& func : order)
{
functions[func](arg);
if (print)
{
std::cout << arg << std::endl;
}
}
}
void callAll(int arg, bool print)
{
for (const auto& func : functions)
{
func(arg);
if (print)
{
std::cout << arg << std::endl;
}
}
}
};
class ExecutionTimer
{
public:
// Use the best steady clock available
using Clock = std::conditional_t<high_resolution_clock::is_steady,
high_resolution_clock,
steady_clock>;
ExecutionTimer() = default;
inline ~ExecutionTimer()
{
std::string units = " microSeconds";
// Determine whether to print uSecs or mSecs or Secs
double count = duration_cast<microseconds>(Clock::now() - mStart).count();
if (count > 1000)
{
// Convert to milliseconds
units = " milliSeconds";
count /= 1000.0f;
if (count > 1000)
{
// Convert to seconds
units = " Seconds";
count /= 1000.0f;
}
}
std::cout
<< "Elapsed: " << count << units.data() << std::endl;
}
private:
Clock::time_point mStart = Clock::now();
};
std::vector<size_t> GenerateRandomOrder(size_t n)
{
std::vector<size_t> vec(n);
std::iota(vec.begin(), vec.end(), 0);
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(vec.begin(), vec.end(), g);
return vec;
}
void makeOperations(Callables<std::function<void(int&)>> &callables)
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> operation_dist(0, 4); // 0: add, 1: subtract, 2: multiply, 3: divide 4: negate
std::uniform_int_distribution<> value_dist(1, 100);
for (int i = 0; i < N; ++i)
{
int operation_type = operation_dist(gen);
int value = value_dist(gen);
switch (operation_type)
{
case 0:
// Addition
callables.add([value](int& x) { x += value; });
break;
case 1:
// Subtraction
callables.add([value](int& x) { x -= value; });
break;
case 2:
// Multiplication
callables.add([value](int& x) { x *= value; });
break;
case 3:
// Division
callables.add([value](int& x)
{
if (value != 0)
{
x /= value;
}
});
break;
case 4:
// Negation
callables.add([value](int& x) { x = -x; });
break;
}
}
}
int main()
{
auto order = GenerateRandomOrder(N);
Callables<std::function<void(int&)>> callables;
makeOperations(callables);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> value_dist(2, 1000);
std::cout << "Starting Arranged" << std::endl;
{
callables.rearrange(order);
ExecutionTimer timer;
for (int i = 0; i < OPSTODO; ++i)
{
int input = value_dist(gen);
callables.callAll(input, false);
}
}
std::cout << "Finished" << std::endl;
std::cout << "Starting Unarranged" << std::endl;
{
ExecutionTimer timer;
for (int i = 0; i < OPSTODO; ++i)
{
int input = value_dist(gen);
callables.callAll(input, order, false);
}
}
std::cout << "Finished" << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment