Софтинка. Версия два.
Заглянув в ЖЖ обнаружил не попавший почему-то в мыло
коммент
keethraxx@lj'а по поводу
софтинки. Ну и добавил на досуге считалку корреляции.
В качестве образца используется файл который получается на выходе софтинки. Подсчёт корреляции некоего текста включается при запуске софтинки с ключом и параметром --sample образец.gnu . В этом случае софтинка не выводит спектр, а считает корреляцию между спектром из файла образец.gnu и спектром скармливаемого текста. По идее - чем ближе результат к 1, тем больше похожи спектры.
Ещё добавил возможность читать буквосочетания из файла, --pattern буквосочетания.txt
Формат такой:
Если строка начинается с # - это комментарий и строка пропускается.
Иначе, первые 2 буквы - это очередное буквосочетание.
#include <locale.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <getopt.h>
#include <math.h>
#define SLOG_COUNT (512)
char slog[SLOG_COUNT][3] = {
"ст","то","ен","но","ни","ов","на","ра","ос","пр","ро","ко","ан","ли","по","во",
"ес","ре","не","от","ол","од","ор","ть","ва","го","ер","ит","ет","ти","об","ел",
"он","та","ри","ль","ны","те","ал","ат","де","ка","ом","ис","тв","ве","ин","ие",
"ло","ми","со","ав","ог","ме","ем","ия","им","ле","ас","из","ив","ла","ак","че",
"мо","да","ии","ед","за","тр","ой","ск","ар","нн","до","ки","ам","оп","ил","ик",
"ви","бо","ма","тс","ьн","ся","ев","аз","оз","ек","ир","же","ои","бы","си","ег",
"ич","ци","вс","еп","ап","зн","ди","ад","ид","ип","сл","вы","вн","ру","ля","ые",
"ей","ое","ок","се","их","оч","вл","ож","ят","хо","эт","пе","тн","ых","ры","уд",
"чт","ио","ще","ку","аб","дн","сп","ьс","ео","ая","чи","ий","му","св","ги","ду",
"ае","йс","це","нт","ча","ше","оо","лю","сс","ют","вр","яв","жн","уп","ез","ус",
"зв","ым","ыл","мы","кр","ян","ну","ее","па","иа","еб","ую","аи","нс","са","ьк",
"га","иг","ыв","еи","еч","кт","жи","аж","ты","ый","уч","ут","ту","иб","яс","мн",
"ач","су","чн","яп","ыс","зм","бе","дл","зо","ац","сь","пи","мп","лу","дс","ах",
"ын","бр","ям","ня","ур","щи","гр","яз","ун","бщ","жд","еж","аю","ши","уж","ыт",
"нк","нь","бу","зд","тк","вп","ьв","яи","гл","йн","сн","вт","би","мс","ды","ук",
"ып","др","ул","зи","рн","вк","кл","ао","хр","ех","кс","юд","ию","аг","тп","уг",
"пл","ву","ьп","ув","бл","см","йв","йп","яо","ьт","як","мв","ьш","ьи","хи","ёт",
"иц","фи","ря","яд","ср","ум","ба","йи","рс","вв","вя","рт","хс","рм","яе","оц",
"жа","ью","оя","йт","иу","гд","ке","нц","ыи","нд","ош","йк","ущ","дв","ау","мм",
"оу","ющ","ша","рп","хп","ьм","лл","эк","зы","бс","иж","рк","уб","мк","вм","тд",
"кн","хв","ык","еа","ьо","рв","ай","уе","еш","ьз","ох","зк","кв","вд","ён","хн",
"яр","аш","ыо","фо","йм","сч","еу","лн","зу","ец","ащ","пу","ца","рг","ьд","оэ",
"зр","йо","тт","мч","йд","ял","лж","иф","ьг","ыр","кп","ыд","гу","чё","йр","иэ",
"вг","мя","юб","хк","яч","ьб","тя","ыш","чк","зе","уи","кц","ыч","ыб","ещ","лы",
"яб","оф","мб","ях","сё","юс","бн","тм","ём","вз","сы","ха","пы","уа","лс","шл",
"рь","сх","рж","рд","нг","хт","рх","сд","ух","мд","ьч","яю","ье","уш","уз","ща",
"ге","еф","аэ","фр","бъ","дя","тч","тб","мт","км","уо","мл","ьр","йб","вш","юп",
"фе","йч","тл","яу","нв","мр","юв","еэ","дё","яц","ыз","сш","дп","аа","ья","зя",
"юч","иш","дь","ху","яэ","бм","гн","кд","шн","вб","хд","йз","ящ","ъе","фа","хл",
"ёр","её","хм","дк","аф","ою","лк","лг","цы","юи","йг","вэ","бх","хг","ьл","ощ",
"зл","яг","йц","щё","оа","тз","ея","юз","аё","бя","ыу","кк","вц","нп","юо","лё",
"чу","нф","чш","йш","ьу","йэ","йа","юр","юн","юк","мг","юц","шк","пн","ыг","мз",
};
int spectrum[SLOG_COUNT];
void usage(char *name)
{
printf("Usage: %s [--verbose] [--help] [--sample file] [--pattern file] [file]\n", name);
}
int main(int argc, char *argv[]) {
char c1 = 0, c2 = 0, buf[256], *src, *prog, *sample = NULL,
*pattern = NULL;
int ret, i, verbose = 0, count = 0;
FILE *fd;
static struct option long_options[] =
{
{"pattern", required_argument, 0, 'p'},
{"sample", required_argument, 0, 's'},
{"verbose", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
setlocale(LC_ALL, "");
prog = strrchr(argv[0],'/');
if(!prog) prog = argv[0];
else prog++;
while ((ret = getopt_long (argc, argv, "p:s:vh", long_options, NULL)) != -1)
{
switch(ret)
{
case 'p': pattern = strdup(optarg); break;
case 's': sample = strdup(optarg); break;
case 'v': verbose = 1; break;
case 'h': usage(prog); return 1;
default: usage(prog); return 1;
}
}
if(verbose) fprintf(stderr, "Cleaning spectrum...\n");
for(i = 0; i < SLOG_COUNT; i++) spectrum[i] = 0;
if(pattern)
{
if(verbose) fprintf(stderr, "Reading file %s\n", pattern);
fd = fopen(pattern, "r");
if(!fd)
{
fprintf(stderr, "Error opening file %s: %s\n", pattern, strerror(errno));
return 255;
}
for(i = 0; fgets(buf,sizeof(buf),fd) && i < SLOG_COUNT;)
{
if(buf[0] != '#')
{
slog[i][0] = buf[0];
slog[i][1] = buf[1];
i++;
}
}
fclose(fd);
free(pattern);
}
if(argc > optind)
{
if(verbose) fprintf(stderr, "Reading file %s\n",argv[optind]);
fd = fopen(argv[optind],"r");
if(!fd)
{
fprintf(stderr, "Error opening file %s: %s\n", argv[optind], strerror(errno));
return 255;
}
}
else
{
if(verbose) fprintf(stderr, "Reading stdin\n");
fd = stdin;
}
while(fgets(buf,sizeof(buf),fd))
{
src = buf;
while(*src)
{
c2 = tolower(*src);
if(c1 && isalpha(c2))
{
for(i = 0; i < SLOG_COUNT; i++)
{
if(slog[i][0] == c1 && slog[i][1] == c2)
{
spectrum[i]++;
count++;
break;
}
}
}
c1 = c2;
src++;
}
}
if(fd != stdin) fclose(fd);
if(count > 0)
{
if(sample)
{double x[SLOG_COUNT], y[SLOG_COUNT], mx, my, sxx, syy, sxy;
if(verbose) fprintf(stderr, "Reading file %s\n", sample);
fd = fopen(sample, "r");
if(!fd)
{
fprintf(stderr, "Error opening file %s: %s\n", sample, strerror(errno));
return 255;
}
for(i = 0; fgets(buf,sizeof(buf),fd) && i < SLOG_COUNT;)
{
if(buf[0] != '#')
{
x[i++] = atof(buf);
}
}
fclose(fd);
free(sample);
for(i = 0; i < SLOG_COUNT; i++)
{
y[i] = (double)spectrum[i] / (double)count;
}
// Считаем корреляцию ( от LJ user keethraxx )
for(i = 0, mx = my = 0.0; i < SLOG_COUNT; i++)
{
mx += x[i];
my += y[i];
}
mx = mx / SLOG_COUNT;
my = my / SLOG_COUNT;
for(i = 0, sxx = syy = sxy = 0.0; i < SLOG_COUNT; i++)
{
sxx += (x[i] - mx) * (x[i] - mx);
syy += (y[i] - my) * (y[i] - my);
sxy += (x[i] - mx) * (y[i] - my);
}
printf("Correlation with sample: %f\n", sxy / sqrt(sxx * syy));
}
else
{
for(i = 0; i < SLOG_COUNT; i++)
{
printf("%e # %s\n", (double)spectrum[i] / (double)count, slog[i]);
}
}
}
return 0;
}