Execute a Markov algorithm: Difference between revisions

→‎{{header|C}}: more strict, hopefully easier to read, code
m (omissions)
(→‎{{header|C}}: more strict, hopefully easier to read, code)
Line 661:
 
=={{header|C}}==
 
<lang c>#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> // requires C99
#include <string.h>
#include <assertunistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
 
typedef struct { char * s; size_t alloc_len; } string;
#define MAX_RULE_LEN 1024
#define MAX_STR_LEN 1024
 
typedef struct rulestruct {
char *pat, *repl;
const char *trigger;
int terminate;
const char *replacement;
bool terminal;
struct rulestruct *next;
} rule_t;
 
typedef struct {
int n;
rule_t *rules;
char *buf;
} ruleset_t;
 
void ruleset_del(ruleset_t *r)
rule_t *free_rule(rule_t *r)
{
if (r->rules) free(r->rules);
if ( r == NULL ) return NULL;
if (r->buf) free(r->triggerbuf);
free(r->replacement);
rule_t *next = r->next;
free(r);
return next;
}
 
string * str_new(char *s)
void free_rulelist(rule_t *head)
{
int l = strlen(s);
rule_t *n = head;
string *str = malloc(sizeof(string));
while( n != NULL ) n = free_rule(n);
str->s = malloc(l + 1);
strcpy(str->s, s);
str->alloc_len = l + 1;
return str;
}
 
void readrulesstr_append(FILEstring *fstr, rule_tchar **rulesets, int len)
{
int l = strlen(str->s);
char buffer[MAX_RULE_LEN];
if (len == -1) len = strlen(s);
rule_t *t, *prev;
 
int i, j;
if (str->alloc_len < l + len + 1) {
size_t l;
str->alloc_len = l + len + 1;
str->s = realloc(str->s, str->alloc_len);
*ruleset = prev = NULL;
}
for(l=1; fgets(buffer, MAX_RULE_LEN, f) != NULL; l++ )
memcpy(str->s + l, s, len);
{
str->s[l + len] = '\0';
if ( buffer[0] == '#' ) continue; // not a rule but a comment
t = malloc(sizeof(rule_t)); assert( t != NULL );
memset(t, 0, sizeof(rule_t)); // just to be sure, in case of failure, to avoid
// freeing unallocated memory
// skip blank lines (there cannot be leading spaces...!)
if ( (buffer[0] == '\n') || (buffer[0] == '\r') ) continue;
// it's a rule: let's move until the first " -> "
char *map = strstr(buffer, " -> ");
if ( map == NULL )
{
fprintf(stderr, "rule set syntax error line %d\n", l);
free_rule(t);
return;
}
i = map - buffer + 4; // skip " -> "
j = map - buffer - 1;
while( (buffer[j] == ' ') || (buffer[j] == '\t') ) j--;
buffer[j+1] = 0;
t->trigger = strdup(buffer); assert( t->trigger != NULL );
//skip whitespaces after ->
for( ; (buffer[i] == '\t') || (buffer[i] == ' '); i++) ;
if ( buffer[i] == '.' )
{
t->terminal = true; i++; // terminal rule
} else {
t->terminal = false; // or not
}
j = i; // store this position and let's find the end
i += strlen(buffer+j);
for( i--; (buffer[i] == '\n') || (buffer[i] == '\r') ; i--) ;
buffer[i+1] = 0;
t->replacement = strdup(buffer+j); assert(t->replacement != NULL);
if ( prev == NULL )
{
*ruleset = t;
} else {
prev->next = t;
}
prev = t;
}
}
 
//* eachswap linecontent of thedest fileand issrc, aand truncate src "string" */
void markovstr_transfer(FILEstring *fdest, rule_tstring *rulesrc)
{
size_t tlen = dest->alloc_len;
char buffer[2][MAX_STR_LEN]; // double to allow state changing and no overlapping
dest->alloc_len = src->alloc_len;
int bi;
src->alloc_len = tlen;
rule_t *r;
char *d;
const char *p, *bp;
bool repldone;
size_t s;
 
char *ts = dest->s;
while( ( fgets(buffer[0], MAX_STR_LEN, f) != NULL ) )
dest->s = src->s;
{
bi src->s = 0ts;
src->s[0] = '\0';
}
 
void str_del(string *s)
do
{
{
if (s->s) free(s->s);
repldone = false;
free(s);
for( r = rule; r != NULL; r = r->next, bi++)
}
{
 
bp = buffer[bi%2];
void str_markov(string *str, ruleset_t *r)
d = buffer[(bi+1)%2];
{
if ( (p = strstr(bp, r->trigger)) != NULL )
int i, j, sl, pl;
{
int schanged = p0, -done = bp0;
string *tmp = str_new("");
memcpy(d, bp, s);
 
d += s;
while (!done) {
strcpy(d, r->replacement);
changed = 0;
d += strlen(r->replacement);
for (i = 0; !done && !changed && i < r->n; i++) {
strcpy(d, bp + strlen(r->trigger) + s);
pl = if strlen( r->terminal rules[i].pat) { ;
sl = strlen(str->s);
repldone = false;
for (j = 0; j < sl; j++) {
bi++; // let be bi the current (last) buffer
if (strncmp(str->s + j, r->rules[i].pat, pl))
break;
continue;
}
str_append(tmp, str->s, j);
repldone = true; // a repl. was done
str_append(tmp, r->rules[i].repl, -1);
r = rule; // since a repl. was done, let's "reset" r
str_append(tmp, str->s + j + pl, -1);
} else {
 
bi--; // stay on the same buffer
str_transfer(str, tmp);
changed = 1;
 
if (r->rules[i].terminate)
done = 1;
break;
}
}
if (!changed) break;
}
str_del(tmp);
}
return;
} while( repldone );
}
puts(buffer[(bi)%2]);
}
 
ruleset_t* read_rules(char *name)
int main()
{
struct stat s;
FILE *rulefile_h = NULL;
char *buf;
FILE *stringfile_h = NULL;
size_t i, j, k, tmp;
rule_t *rulelist;
rule_t *rules = 0;
int n = 0; /* number of rules */
 
int fd = open(name, O_RDONLY);
if ( argc < 3 ) {
if (fd == -1) return 0;
printf("Usage: %s rulefile stringfile\n", argv[0]);
exit(EXIT_FAILURE);
}
rulefile_h = fopen(argv[1], "r"); assert( rulefile_h != NULL );
stringfile_h = fopen(argv[2], "r"); assert( stringfile_h != NULL );
 
fstat(fd, &s);
readrules(rulefile_h, &rulelist); assert( rulelist != NULL );
buf = malloc(s.st_size + 2);
markov(stringfile_h, rulelist);
read(fd, buf, s.st_size);
buf[s.st_size] = '\n';
buf[s.st_size + 1] = '\0';
close(fd);
 
for (i = j = 0; buf[i] != '\0'; i++) {
if (buf[i] != '\n') continue;
 
/* skip comments */
if (buf[j] == '#' || i == j) {
j = i + 1;
continue;
}
 
/* find the '->' */
for (k = j + 1; k < i - 3; k++)
if (isspace(buf[k]) && !strncmp(buf + k + 1, "->", 2))
break;
 
if (k >= i - 3) {
printf("parse error: no -> in %.*s\n", i - j, buf + j);
break;
}
 
/* left side: backtrack through whitespaces */
for (tmp = k; tmp > j && isspace(buf[--tmp]); );
if (tmp < j) {
printf("left side blank? %.*s\n", i - j, buf + j);
break;
}
buf[++tmp] = '\0';
 
/* right side */
for (k += 3; k < i && isspace(buf[++k]););
buf[i] = '\0';
 
rules = realloc(rules, sizeof(rule_t) * (1 + n));
rules[n].pat = buf + j;
 
if (buf[k] == '.') {
rules[n].terminate = 1;
rules[n].repl = buf + k + 1;
} else {
rules[n].terminate = 0;
rules[n].repl = buf + k;
}
n++;
 
j = i + 1;
}
 
ruleset_t *r = malloc(sizeof(ruleset_t));
r->buf = buf;
r->rules = rules;
r->n = n;
return r;
}
 
int test_rules(char *s, char *file)
{
ruleset_t * r = read_rules(file);
if (!r) return 0;
printf("Rules from '%s' ok\n", file);
 
string *ss = str_new(s);
printf("text: %s\n", ss->s);
 
str_markov(ss, r);
printf("markoved: %s\n", ss->s);
 
str_del(ss);
ruleset_del(r);
 
return printf("\n");
}
 
int main()
{
test_rules("I bought a B of As from T S.", "rule1");
test_rules("I bought a B of As from T S.", "rule2");
test_rules("I bought a B of As W my Bgage from T S.", "rule3");
test_rules("_1111*11111_", "rule4");
 
return 0;
// dump rules
}</lang>output<lang>Rules from 'rule1' ok
/*
text: I bought a B of As from T S.
rule_t *h = rulelist;
markoved: I bought a bag of apples from my brother.
while( h != NULL )
{
printf("%s -> %s%s\n", h->trigger, h->replacement, h->terminal ? " [TERMINATING RULE]" : "");
h = h->next;
}
*/
 
Rules from 'rule2' ok
free_rulelist(rulelist);
text: I bought a B of As from T S.
markoved: I bought a bag of apples from T shop.
 
Rules from 'rule3' ok
fclose(rulefile_h); fclose(stringfile_h);
text: I bought a B of As W my Bgage from T S.
markoved: I bought a bag of apples with my money from T shop.
 
Rules from 'rule4' ok
return EXIT_SUCCESS;
text: _1111*11111_
}</lang>
markoved: 11111111111111111111
</lang>
 
=={{header|C++}}==
Anonymous user