/*
codeword - Newspaper codeword solver
Copyright (C) 2018 Ian Cowburn (ianc@noddybox.co.uk)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see .
*/
#include
#include
#include
#include
#include
typedef struct
{
int is_letter;
int number;
char letter;
} Character;
static void PrepLine(char *p)
{
size_t l = strlen(p);
size_t f;
while (l && p[l-1] == '\n')
{
p[--l] = 0;
}
for(f = 0; f < l; f++)
{
p[f] = tolower((unsigned char)p[f]);
}
}
static void Error(const char *p)
{
perror(p);
exit(EXIT_FAILURE);
}
static int ContainsLetter(char c, const Character *chars, int no_chars)
{
int f;
for(f=0; f < no_chars; f++)
{
if (chars[f].is_letter && chars[f].letter == c)
{
return 1;
}
}
return 0;
}
static int CheckLettersAndLength(const char *buff,
const Character *chars,
int no_chars)
{
size_t l = strlen(buff);
int f;
if (l != no_chars)
{
return 0;
}
for(f=0; f < no_chars; f++)
{
if (chars[f].is_letter &&
(chars[f].letter != buff[f]))
{
return 0;
}
}
return 1;
}
static int CheckNumbers(const char *buff, const Character *chars, int no_chars)
{
int f;
int n;
char code[27] = {0};
for(f = 0; f < no_chars; f++)
{
if (!chars[f].is_letter)
{
int i = chars[f].number - 1;
if (ContainsLetter(buff[f], chars, no_chars))
{
return 0;
}
if (code[i] && code[i] != buff[f])
{
return 0;
}
for(n = 0; n < 27; n++)
{
if (n != i && code[n] == buff[f])
{
return 0;
}
}
code[i] = buff[f];
}
}
return 1;
}
int main(int argc, char *argv[])
{
int no_chars;
Character *chars;
int f;
FILE *fp;
char buff[1024];
if (argc < 3)
{
fprintf(stderr, "usage: %s wordlist ...\n", argv[0]);
exit(EXIT_FAILURE);
}
no_chars = argc - 2;
chars = malloc(sizeof *chars * no_chars);
if (!chars)
{
Error("malloc");
}
for(f = 0; f < no_chars; f++)
{
int i;
i = atoi(argv[f+2]);
if (i < 1 || i > 27)
{
chars[f].is_letter = 1;
chars[f].letter = tolower((unsigned char)argv[f+2][0]);
chars[f].number = 0;
}
else
{
chars[f].is_letter = 0;
chars[f].number = i;
chars[f].letter = 0;
}
}
fp = fopen(argv[1], "r");
if (!fp)
{
Error(argv[1]);
}
while(fgets(buff, sizeof buff, fp))
{
PrepLine(buff);
if (CheckLettersAndLength(buff, chars, no_chars) &&
CheckNumbers(buff, chars, no_chars))
{
printf("%s\n", buff);
}
}
return EXIT_SUCCESS;
}