// Aritmética de índices de un buffer circular: no guarda elementos, solo calcula posiciones.
#include <cstdio>

void print_positions(int capacity, int front, int size) {
    std::printf("capacidad %d, frente %d, tamaño %d:", capacity, front, size);
    for (int i = 0; i < size; i++) {
        std::printf(" e%d->%d", i, (front + i) % capacity);
    }
    std::printf("\n");
}

// A dónde va cada elemento al desenrollar, si el bloque nuevo empieza en el frente.
void print_unroll(int capacity, int front, int size) {
    std::printf("desenrollar:");
    for (int i = 0; i < size; i++) {
        std::printf(" %d->%d", (front + i) % capacity, i);
    }
    std::printf("\n");
}

// Sigue una serie de operaciones: E encola, D desencola. Solo mueve índices.
void trace(int capacity, const char* operations) {
    int front = 0;
    int size = 0;
    int next_label = 0;
    std::printf("%-3s %-9s %-7s %-6s %s\n", "op", "capacidad", "frente", "tamaño", "posición usada");
    for (const char* op = operations; *op != '\0'; op++) {
        int position;
        if (*op == 'E') {
            if (size == capacity) {
                capacity *= 2;
                front = 0;
                std::printf("%-3s %-9d %-7d %-6d (desenrolla)\n", "--", capacity, front, size);
            }
            position = (front + size) % capacity;
            size++;
            next_label++;
        } else {
            position = front;
            front = (front + 1) % capacity;
            size--;
        }
        std::printf("%-3c %-9d %-7d %-6d %d\n", *op, capacity, front, size, position);
    }
    std::printf("encolados: %d\n", next_label);
}

int main() {
    trace(4, "EEEDDEEEE");
    print_positions(8, 6, 4);
    print_positions(8, 5, 8);
    print_unroll(8, 5, 8);
    print_positions(16, 0, 8);
    return 0;
}
