mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-20 23:51:29 -07:00
Files

This is the main bulk of this boolification work, but although it's making the largest actual change, it should also be the least disruptive to anyone interacting with this code base downstream of me, because it doesn't modify any interface between modules: all the inter-module APIs were updated one by one in the previous commits. This just cleans up the code within each individual source file to use bool in place of int where I think that makes things clearer.
89 lines
1.9 KiB
C
89 lines
1.9 KiB
C
/*
|
|
* tdq.c: implement a 'to-do queue', a simple de-duplicating to-do
|
|
* list mechanism.
|
|
*/
|
|
|
|
#include <assert.h>
|
|
|
|
#include "puzzles.h"
|
|
|
|
/*
|
|
* Implementation: a tdq consists of a circular buffer of size n
|
|
* storing the integers currently in the queue, plus an array of n
|
|
* booleans indicating whether each integer is already there.
|
|
*
|
|
* Using a circular buffer of size n to store between 0 and n items
|
|
* inclusive has an obvious failure mode: if the input and output
|
|
* pointers are the same, how do you know whether that means the
|
|
* buffer is full or empty?
|
|
*
|
|
* In this application we have a simple way to tell: in the former
|
|
* case, the flags array is all 1s, and in the latter case it's all
|
|
* 0s. So we could spot that case and check, say, flags[0].
|
|
*
|
|
* However, it's even easier to simply determine whether the queue is
|
|
* non-empty by testing flags[buffer[op]] - that way we don't even
|
|
* _have_ to compare ip against op.
|
|
*/
|
|
|
|
struct tdq {
|
|
int n;
|
|
int *queue;
|
|
int ip, op; /* in pointer, out pointer */
|
|
bool *flags;
|
|
};
|
|
|
|
tdq *tdq_new(int n)
|
|
{
|
|
int i;
|
|
tdq *tdq = snew(struct tdq);
|
|
tdq->queue = snewn(n, int);
|
|
tdq->flags = snewn(n, bool);
|
|
for (i = 0; i < n; i++) {
|
|
tdq->queue[i] = 0;
|
|
tdq->flags[i] = false;
|
|
}
|
|
tdq->n = n;
|
|
tdq->ip = tdq->op = 0;
|
|
return tdq;
|
|
}
|
|
|
|
void tdq_free(tdq *tdq)
|
|
{
|
|
sfree(tdq->queue);
|
|
sfree(tdq->flags);
|
|
sfree(tdq);
|
|
}
|
|
|
|
void tdq_add(tdq *tdq, int k)
|
|
{
|
|
assert((unsigned)k < (unsigned)tdq->n);
|
|
if (!tdq->flags[k]) {
|
|
tdq->queue[tdq->ip] = k;
|
|
tdq->flags[k] = true;
|
|
if (++tdq->ip == tdq->n)
|
|
tdq->ip = 0;
|
|
}
|
|
}
|
|
|
|
int tdq_remove(tdq *tdq)
|
|
{
|
|
int ret = tdq->queue[tdq->op];
|
|
|
|
if (!tdq->flags[ret])
|
|
return -1;
|
|
|
|
tdq->flags[ret] = false;
|
|
if (++tdq->op == tdq->n)
|
|
tdq->op = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
void tdq_fill(tdq *tdq)
|
|
{
|
|
int i;
|
|
for (i = 0; i < tdq->n; i++)
|
|
tdq_add(tdq, i);
|
|
}
|