chiark / gitweb /
*.c: General spring-clean of the coding style.
[anag] / mono.c
diff --git a/mono.c b/mono.c
index 45222405261528b01ad422c4b0bd753336f1caa5..2b6ca4a7264a36c18935f6d8c49d11d36b95b2f9 100644 (file)
--- a/mono.c
+++ b/mono.c
@@ -1,13 +1,11 @@
 /* -*-c-*-
- *
- * $Id: mono.c,v 1.2 2004/04/08 01:36:19 mdw Exp $
  *
  * Monoalphabetic matcher
  *
  * (c) 2003 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.
@@ -45,24 +43,23 @@ typedef struct node_mono {
 static int n_mono(node *nn, const char *p, size_t sz)
 {
   node_mono *n = (node_mono *)nn;
-  unsigned map[UCHAR_MAX], imap[UCHAR_MAX];
+  unsigned map[UCHAR_MAX];
   const unsigned char *q = n->p;
-  int ch, i;
+  unsigned max = 0;
+  int ch;
+
+  /* Monoalphabetic substitution preserves length. */
+  if (sz != n->len) return (0);
 
-  if (sz != n->len)
-    return (0);
-  memset(map, 0, sizeof(map));
-  memset(imap, 0, sizeof(imap));
+  /* Canonicalize this string as we did the pattern.  Fail if we find a
+   * mismatch.
+   */
+  memset(map, UCHAR_MAX, sizeof(map));
   while (*p) {
     ch = *p++;
-    i = *q++;
-    if (!map[i]) {
-      if (imap[ch])
-       return (0);
-      map[i] = ch;
-      imap[ch] = 1;
-    } else if (map[i] != ch)
-      return (0);
+    if (map[ch] >= max) map[ch] = max++;
+    if (max >= UCHAR_MAX) return (0);
+    if (*q++ != map[ch]) return (0);
   }
   return (1);
 }
@@ -72,25 +69,29 @@ static int n_mono(node *nn, const char *p, size_t sz)
 node *mono(const char *const *av)
 {
   unsigned char map[UCHAR_MAX];
-  unsigned max;
-  int ch;
-  const char *p;
+  const char *p = av[0];
   unsigned char *q;
+  unsigned max = 0;
+  int ch;
 
   node_mono *n = xmalloc(sizeof(*n));
   n->n.func = n_mono;
-  memset(map, UCHAR_MAX, sizeof(map));
-  max = 0;
-  p = av[0];
+  n->p = q = xmalloc(n->len);
   n->len = strlen(p);
-  q = xmalloc(n->len);
-  n->p = q;
+
+  /* Convert the string into the canonical representative of its equivalence
+   * class, specifically the lexically first string which is equivalent under
+   * monoalphabetic substitution.  That is: replace the first distinct
+   * character with zero, the second with one, and so on.
+   */
+  memset(map, UCHAR_MAX, sizeof(map));
   while (*p) {
     ch = *p++;
-    if (map[ch] >= max)
-      map[ch] = max++;
+    if (map[ch] >= max) map[ch] = max++;
+    assert(max < UCHAR_MAX);
     *q++ = map[ch];
   }
+
   return (&n->n);
 }