/* -*-c-*-
- *
- * $Id: trackword.c,v 1.1 2001/02/04 17:14:42 mdw Exp $
*
* Matches trackwords
*
* (c) 2001 Mark Wooding
*/
-/*----- Licensing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
*
* This file is part of Anag: a simple wordgame helper.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* Anag is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with Anag; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: trackword.c,v $
- * Revision 1.1 2001/02/04 17:14:42 mdw
- * Initial checkin
- *
- */
-
/*----- Header files ------------------------------------------------------*/
#include "anag.h"
/*----- Data structures ---------------------------------------------------*/
-enum { N, NE, E, SE, S, SW, W, NW, NDIR };
+#define NDIR 9
typedef struct tcell {
struct tcell *hop[NDIR];
{
long i, q;
- /* --- Initial guess is half the input length --- */
-
- for (i = q = a; q; q >>= 2)
- i >>= 1;
-
- /* --- Do the main series iteration --- */
+ /* Initial guess is half the input length. */
+ for (i = q = a; q; q >>= 2) i >>= 1;
+ /* Do the main series iteration. */
for (;;) {
- q = i * i - a;
- if (!q || (q < 0 && -q <= 2 * i))
- return (i);
- q /= 2 * i;
- if (!q)
- i--;
- else
- i -= q;
+ q = i*i - a;
+ if (q > -2*i && q <= 0) return (i);
+ q /= 2*i;
+ if (!q) i--;
+ else i -= q;
}
}
static int track(tcell *c, const char *p)
{
- int i;
+ tcell **cc;
+
+ if (*p++ != c->ch) return (0);
+ if (!*p) return (1);
- if (*p++ != c->ch)
- return (0);
- if (!*p)
- return (1);
c->f = 1;
- for (i = 0; i < NDIR; i++) {
- if (!c->hop[i] || c->hop[i]->f)
- continue;
- if (track(c->hop[i], p)) {
- c->f = 0;
- return (1);
- }
+ for (cc = c->hop; *cc; cc++) {
+ if ((*cc)->f) continue;
+ if (track(*cc, p)) { c->f = 0; return (1); }
}
c->f = 0;
+
return (0);
}
node_track *n = (node_track *)nn;
tcell *c;
- if (!*p)
- return (1);
- for (c = n->c; c->ch; c++) {
- if (track(c, p))
- return (1);
- }
+ if (!*p) return (1);
+ for (c = n->c; c->ch; c++)
+ if (track(c, p)) return (1);
return (0);
}
unsigned i, j;
const char *p = av[0], *q, *l;
size_t sz = strlen(p);
- tcell *c;
-
- /* --- Work out the dimensions --- */
+ tcell *c, **cc, **ccc;
+ /* Work out the dimensions. */
x = strcspn(p, "/");
if (!p[x]) {
x = isqrt(sz);
- if (x * x != sz)
+ if (x*x != sz)
die("bad trackword `%s': not square, and no line markers", p);
y = x;
}
- if (!x)
- die("bad trackword `%s': no columns", p);
+ if (!x) die("bad trackword `%s': no columns", p);
y = 0;
l = p + sz;
q = p;
for (;;) {
- if (*q == '/')
- q++;
- if (!*q)
- break;
+ if (*q == '/') q++;
+ if (!*q) break;
if (l - q < x)
die("bad trackword `%s': inconsistent line lengths", p);
q += x;
y++;
}
- if (!y)
- die("bad trackword `%s': no rows", p);
-
- /* --- Build the match node --- */
+ if (!y) die("bad trackword `%s': no rows", p);
+ /* Build the match node. */
n = xmalloc(sizeof(*n));
n->n.func = n_track;
n->x = x; n->y = y;
- n->c = xmalloc((x * y + 1) * sizeof(tcell));
+ n->c = xmalloc((x*y + 1)*sizeof(tcell));
q = p;
c = n->c;
for (j = 0; j < y; j++) {
- if (*q == '/')
- q++;
+ if (*q == '/') q++;
for (i = 0; i < x; i++) {
c->ch = *q++;
c->f = 0;
+ cc = c->hop;
#define NOK (j > 0)
#define SOK (j < y - 1)
#define WOK (i > 0)
#define EOK (i < x - 1)
- c->hop[N] = NOK ? c - x : 0;
- c->hop[S] = SOK ? c + x : 0;
- c->hop[W] = WOK ? c - 1 : 0;
- c->hop[E] = EOK ? c + 1 : 0;
+ if (NOK) *cc++ = c - x;
+ if (SOK) *cc++ = c + x;
+ if (WOK) *cc++ = c - 1;
+ if (EOK) *cc++ = c + 1;
- c->hop[NW] = NOK && WOK ? c - x - 1 : 0;
- c->hop[NE] = NOK && EOK ? c - x + 1 : 0;
- c->hop[SW] = SOK && WOK ? c + x - 1 : 0;
- c->hop[SE] = SOK && EOK ? c + x + 1 : 0;
+ if (NOK && WOK) *cc++ = c - x - 1;
+ if (NOK && EOK) *cc++ = c - x + 1;
+ if (SOK && WOK) *cc++ = c + x - 1;
+ if (SOK && EOK) *cc++ = c + x + 1;
#undef NOK
#undef SOK
#undef WOK
#undef EOK
+ *cc++ = 0;
c++;
}
}
c->ch = 0;
- /* --- Done --- */
-
- c = n->c;
- for (j = 0; j < y; j++) {
- for (i = 0; i < x; i++) {
- printf("%c ", c->ch);
- c++;
- }
- fputc('\n', stdout);
+ /* Now prune out bogus links. */
+ for (c = n->c; c->ch; c++) {
+ ccc = c->hop;
+ for (cc = c->hop; *cc; cc++)
+ if (isalpha((unsigned char)(*cc)->ch)) *ccc++ = *cc;
+ *ccc++ = 0;
}
+ /* Done. */
return (&n->n);
}