debruijn

De Bruijn Sequence generator
git clone https://git.sinitax.com/sinitax/debruijn
Log | Files | Refs | LICENSE | sfeed.txt

debruijn.c (1738B)


      1#include <string.h>
      2#include <stdio.h>
      3#include <stdlib.h>
      4#include <stdbool.h>
      5#include <stdarg.h>
      6
      7/* De Bruijn sequence generation based on Burrows-Wheeler transform */
      8
      9static void
     10die(const char *fmt, ...)
     11{
     12	va_list ap;
     13
     14	va_start(ap, fmt);
     15	fprintf(stderr, "debruijn: ");
     16	vfprintf(stderr, fmt, ap);
     17	if (*fmt && fmt[strlen(fmt)-1] == ':') {
     18		fputc(' ', stderr);
     19		perror(NULL);
     20	} else {
     21		fputc('\n', stderr);
     22	}
     23	va_end(ap);
     24
     25	exit(1);
     26}
     27
     28static void
     29gen(bool *visited, const char *alph, size_t k, size_t n, size_t len, size_t cnt)
     30{
     31	size_t i, si, so, plen, out;
     32
     33	plen = len / k;
     34	out = 0;
     35	memset(visited, 0, len);
     36	for (i = 0; i < len; i++) {
     37		if (visited[i]) continue;
     38		so = i;
     39		do {
     40			si = so;
     41
     42			putchar(alph[si / plen]);
     43			if (++out == cnt) return;
     44			visited[si] = true;
     45
     46			/* (sorted -> unsorted) translation */
     47			so = (si % plen) * k + si / plen;
     48		} while (!visited[so]);
     49	}
     50}
     51
     52int
     53main(int argc, const char **argv)
     54{
     55	const char **arg;
     56	const char *alph_arg, *n_arg;
     57	size_t i, k, n, len;
     58	bool all, *visited;
     59
     60	all = false;
     61	alph_arg = n_arg = NULL;
     62	for (arg = argv + 1; *arg; arg++) {
     63		if (!strcmp(*arg, "-h") || !strcmp(*arg, "--help")) {
     64			break;
     65		} else if (!strcmp(*arg, "-a")) {
     66			all = true;
     67		} else if (!alph_arg) {
     68			alph_arg = *arg;
     69		} else if (!n_arg) {
     70			n_arg = *arg;
     71		} else {
     72			break;
     73		}
     74	}
     75
     76	if (*arg || !alph_arg || !n_arg) {
     77		fprintf(stderr, "Usage: debruijn ALPH N\n");
     78		return 1;
     79	}
     80
     81	k = strlen(alph_arg);
     82	n = strtoull(n_arg, NULL, 10);
     83	if (!k || !n) die("invalid args");
     84
     85	for (len = 1, i = 0; i < n; i++) len *= k;
     86	visited = malloc(len);
     87	if (!visited) die("malloc:");
     88
     89	gen(visited, alph_arg, k, n, len, len);
     90	if (all) gen(visited, alph_arg, k, n, len, k - 1);
     91}