#include "mysteries.h"

#include <algorithm>

void mystery_a(long long n, Work& work) {
    for (long long i = 1; i < n; i *= 2) {
        for (long long j = 0; j < i; j++) {
            work.step();
        }
    }
}

void mystery_b(long long n, Work& work) {
    long long left = n;
    while (left > 0) {
        work.step();
        left /= 2;
    }
}

void mystery_c(long long n, Work& work) {
    for (long long i = n; i > 0; i -= 2) {
        for (long long j = 0; j < i; j++) {
            work.step();
        }
    }
}

void mystery_d(long long n, Work& work) {
    long long limit = std::min(n, 4096LL);
    for (long long i = 0; i < limit; i++) {
        work.step();
    }
}

void mystery_e(long long n, Work& work) {
    if (n <= 1) {
        work.step();
        return;
    }
    for (long long i = 0; i < n; i++) {
        work.step();
    }
    mystery_e(n / 2, work);
    mystery_e(n / 2, work);
}

void mystery_f(long long n, Work& work) {
    work.step();
    if (n == 0) {
        return;
    }
    mystery_f(n - 1, work);
    mystery_f(n - 1, work);
}

std::vector<Mystery> all_mysteries() {
    return {
        {"mystery_a", mystery_a, 1 << 12, 9},
        {"mystery_b", mystery_b, 1 << 8, 11},
        {"mystery_c", mystery_c, 1 << 7, 7},
        {"mystery_d", mystery_d, 1 << 8, 11},
        {"mystery_e", mystery_e, 1 << 8, 9},
        {"mystery_f", mystery_f, 3, 4},
    };
}
