/* C11. bounded stack and circular queue. */
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#define CAP 4

typedef struct { int data[CAP]; size_t size; } Stack;
typedef struct { int data[CAP]; size_t front, size; } Queue;
static bool push(Stack *s, int value)
{
    if (s->size == CAP) return false;
    s->data[s->size++] = value;
    return true;
}
static bool pop(Stack *s, int *out)
{
    if (s->size == 0) return false;
    *out = s->data[--s->size];
    return true;
}
static bool peek(const Stack *s, int *out)
{
    if (s->size == 0) return false;
    *out = s->data[s->size - 1];
    return true;
}
static bool enqueue(Queue *q, int value)
{
    if (q->size == CAP) return false;
    size_t rear = (q->front + q->size) % CAP;
    q->data[rear] = value;
    ++q->size;
    return true;
}
static bool dequeue(Queue *q, int *out)
{
    if (q->size == 0) return false;
    *out = q->data[q->front];
    q->front = (q->front + 1) % CAP;
    --q->size;
    return true;
}
int main(void)
{
    Stack s = {{0}, 0}; Queue q = {{0}, 0, 0}; int value = 0;
    assert(!pop(&s, &value) && !peek(&s, &value));
    for (int i = 1; i <= CAP; ++i) assert(push(&s, i));
    assert(!push(&s, 5)); assert(peek(&s, &value) && value == 4);
    printf("Stack:");
    for (int i = CAP; i > 0; --i) {
        assert(pop(&s, &value) && value == i); printf(" %d", value);
    }
    putchar('\n'); assert(!pop(&s, &value));
    assert(!dequeue(&q, &value));
    for (int i = 1; i <= CAP; ++i) assert(enqueue(&q, i));
    assert(!enqueue(&q, 5));
    assert(dequeue(&q, &value) && value == 1);
    assert(dequeue(&q, &value) && value == 2);
    assert(enqueue(&q, 5) && enqueue(&q, 6));
    printf("Queue after wraparound:");
    for (int i = 3; i <= 6; ++i) {
        assert(dequeue(&q, &value) && value == i); printf(" %d", value);
    }
    putchar('\n'); assert(!dequeue(&q, &value));
    for (int i = 0; i < 100; ++i) {
        assert(enqueue(&q, i)); assert(dequeue(&q, &value) && value == i);
    }
    puts("stack/queue tests passed");
    return 0;
}
