Войти в систему

Home
    - Создать дневник
    - Написать в дневник
       - Подробный режим

LJ.Rossia.org
    - Новости сайта
    - Общие настройки
    - Sitemap
    - Оплата
    - ljr-fif

Редактировать...
    - Настройки
    - Список друзей
    - Дневник
    - Картинки
    - Пароль
    - Вид дневника

Сообщества

Настроить S2

Помощь
    - Забыли пароль?
    - FAQ
    - Тех. поддержка



Пишет deadbeef ([info]deadbeef)
@ 2004-11-21 07:10:00


Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Вот, сотворил. Может полезно будет.
Сотворил простейшую и кратчайшую программку, которая может помочь людям русским, в одном мутном деле.
Иногда, возникает подозрение, что под разными именами в инете пишет один и тот же человек. Это подозрение бывает достаточно сложно проверить, однако и на такую хитрую задницу с лабиринтом, найдётся русский лом.


Нижеприведённая программка делает очень простую вещь - считает, сколько в тексте есть разных буквосочетаний. Из соображений скорости и простоты она учитывает только 512 наиболее распространённых в русском языке буквосочетаний. На выходе получаем простой список из 512 относительных величин в экспоненциальном формате - количество буквосочетаний одного типа отнесённое к общему количеству буквосочетаний. Теперь остаётся только загнать этот список в какую-нибудь программку для построения графиков, чтобы она нарисовала нам спектр текста (я пользую gnuplot).
А главное, и самое интересное, что этот самый спектр текста будет почти одинаков для разных текстов одного автора и будет отличаться для текстов разных авторов. Нарисовав в одном графике спектры для двух текстов, мы без особого труда можем определить, принадлежат ли тексты разным людям, или они были написаны одним человеком (ну или нелюдем). Тексты, правда, должны быть достаточно длинными, чтобы дать спектр действительно характерный для изучаемого автора - книга, например, или собранные в один файл сотни комментариев.

Вот, например, участок спектра с 100-го по 200-е буквосочетания для двух разных кусков Лукьяненки:
Image

А вот, тот же участок для Лукьяненки и Неведимова (Лукьяненка - красный):
Image

Посмотрев на картинки, разобраться, что на первой картинке - автор один, а на второй - авторы разные, не так уж и сложно.


#include <locale.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <getopt.h>

#define SLOG_COUNT  (512)

char *slog[SLOG_COUNT] = {
"ст","то","ен","но","ни","ов","на","ра","ос","пр","ро","ко","ан","ли","по","во",
"ес","ре","не","от","ол","од","ор","ть","ва","го","ер","ит","ет","ти","об","ел",
"он","та","ри","ль","ны","те","ал","ат","де","ка","ом","ис","тв","ве","ин","ие",
"ло","ми","со","ав","ог","ме","ем","ия","им","ле","ас","из","ив","ла","ак","че",
"мо","да","ии","ед","за","тр","ой","ск","ар","нн","до","ки","ам","оп","ил","ик",
"ви","бо","ма","тс","ьн","ся","ев","аз","оз","ек","ир","же","ои","бы","си","ег",
"ич","ци","вс","еп","ап","зн","ди","ад","ид","ип","сл","вы","вн","ру","ля","ые",
"ей","ое","ок","се","их","оч","вл","ож","ят","хо","эт","пе","тн","ых","ры","уд",
"чт","ио","ще","ку","аб","дн","сп","ьс","ео","ая","чи","ий","му","св","ги","ду",
"ае","йс","це","нт","ча","ше","оо","лю","сс","ют","вр","яв","жн","уп","ез","ус",
"зв","ым","ыл","мы","кр","ян","ну","ее","па","иа","еб","ую","аи","нс","са","ьк",
"га","иг","ыв","еи","еч","кт","жи","аж","ты","ый","уч","ут","ту","иб","яс","мн",
"ач","су","чн","яп","ыс","зм","бе","дл","зо","ац","сь","пи","мп","лу","дс","ах",
"ын","бр","ям","ня","ур","щи","гр","яз","ун","бщ","жд","еж","аю","ши","уж","ыт",
"нк","нь","бу","зд","тк","вп","ьв","яи","гл","йн","сн","вт","би","мс","ды","ук",
"ып","др","ул","зи","рн","вк","кл","ао","хр","ех","кс","юд","ию","аг","тп","уг",
"пл","ву","ьп","ув","бл","см","йв","йп","яо","ьт","як","мв","ьш","ьи","хи","ёт",
"иц","фи","ря","яд","ср","ум","ба","йи","рс","вв","вя","рт","хс","рм","яе","оц",
"жа","ью","оя","йт","иу","гд","ке","нц","ыи","нд","ош","йк","ущ","дв","ау","мм",
"оу","ющ","ша","рп","хп","ьм","лл","эк","зы","бс","иж","рк","уб","мк","вм","тд",
"кн","хв","ык","еа","ьо","рв","ай","уе","еш","ьз","ох","зк","кв","вд","ён","хн",
"яр","аш","ыо","фо","йм","сч","еу","лн","зу","ец","ащ","пу","ца","рг","ьд","оэ",
"зр","йо","тт","мч","йд","ял","лж","иф","ьг","ыр","кп","ыд","гу","чё","йр","иэ",
"вг","мя","юб","хк","яч","ьб","тя","ыш","чк","зе","уи","кц","ыч","ыб","ещ","лы",
"яб","оф","мб","ях","сё","юс","бн","тм","ём","вз","сы","ха","пы","уа","лс","шл",
"рь","сх","рж","рд","нг","хт","рх","сд","ух","мд","ьч","яю","ье","уш","уз","ща",
"ге","еф","аэ","фр","бъ","дя","тч","тб","мт","км","уо","мл","ьр","йб","вш","юп",
"фе","йч","тл","яу","нв","мр","юв","еэ","дё","яц","ыз","сш","дп","аа","ья","зя",
"юч","иш","дь","ху","яэ","бм","гн","кд","шн","вб","хд","йз","ящ","ъе","фа","хл",
"ёр","её","хм","дк","аф","ою","лк","лг","цы","юи","йг","вэ","бх","хг","ьл","ощ",
"зл","яг","йц","щё","оа","тз","ея","юз","аё","бя","ыу","кк","вц","нп","юо","лё",
"чу","нф","чш","йш","ьу","йэ","йа","юр","юн","юк","мг","юц","шк","пн","ыг","мз",
};

int spectrum[SLOG_COUNT];

void usage(char *name)
{
	printf("Usage: %s [--verbose] [--help] [file]\n", name);
}
   
int main(int argc, char *argv[]) {
 char                   c1 = 0, c2 = 0, buf[256], *src, *prog;
 int                    ret, i, verbose = 0, count = 0;
 FILE			*fd;
 static struct option   long_options[] =
 {
   {"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, "vh", long_options, NULL)) != -1)
	{
		switch(ret)
		{
			case 'v': verbose = 1; break;
			case 'h': usage(prog); break;
			default: usage(prog); return 1;
		}
	}

	if(verbose) printf("Cleaning spectrum...\n");

	for(i = 0; i < SLOG_COUNT; i++) spectrum[i] = 0;

	if(argc > optind)
	{
		if(verbose) printf("Reading file %s\n",argv[optind]);
		fd = fopen(argv[optind],"r");
	}
	else
	{
		if(verbose) printf("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(count > 0) 
	{
		for(i = 0; i < SLOG_COUNT; i++)
		{
			printf("%e # %s\n", (double)spectrum[i] / (double)count, slog[i]);
		}
	}

	if(fd != stdin) fclose(fd);

	return 0;
}


Вот собственно и всё.

Программка читает либо стандартный ввод, либо файл, если он указан в качестве аргумента. Выдаёт результат на терминал, ну или куда там перенаправишь - в файл, например. А можно сразу скормить рисовалке графиков.

Клоны могут отдыхать.
Лицензия - GNU, автор - я.



(Читать комментарии) - (Добавить комментарий)

Re: Reply to your comment...
[info]vchk@lj
2004-11-24 21:59 (ссылка)
С сортировкой до сих пор регулярно проблемы встречаются. Например, у многих зарубежных хостеров стоит mysql<4.1, настроенный на работу с кодировкой latin1.

Дык это проблемы тех, кто пользуется услугами таких хостеров и не знает как пользоваться
SET SESSION character_set_server = 'koi8_ru';
SET SESSION collation_server = 'koi8_ru';

Ну или там 'cp1251'...

KOI8-R ничуть не хуже сортируется по ORDER BY.
Если конечно доки читать...

Теперь, пожалуйста, приведите мне пример mta, который до сих пор отрезает старший бит и при этом установлен на более чем двухстах серверах.

Ну да, конечно. Вы-то и не собирались показать мне 200 серверов где стоит совсем допотопный mysql который аж collation_server не понимает. А я тут с вами буду делиться допотопными MTA, которые так давно не апгрейдились, что до сих пор 7-й бит режут. ЩАЗ. Слишком глупый способ нарыть себе нахаляву дырок/открытых релеев. Идиотов ищите по другим журналам.

Определитесь уж ;-)

Я-то определился. CP1251 - я не использую, потому что она разработана микрософтом. Это для меня достаточное условие, чтобы гнушаться этой кодировкой.

Про стандарты:
Не надо выдавать регистрацию MIME-charset'a за принятие кодировки стандартом. Я завтра напишу свою кодировку и с таким же успехом зарегистрирую ей имечко для MIME-charset'а.

Хотя, если хочется совсем уж по стандартам — есть ISO-8859-5 и ГОСТ-19768-87. В обеих, кстати, буквы идут по алфавиту.
Да, эти годятся.

А какие могут быть санкции в случае других кодировок, интересно?
Никто не будет пользовать изменённую кодировку, потому что стандарт-то остался неизменным.

Тянет на сценарий для фильма про хакеров.

Тянет в лучшем случае на слабенькое описание того, чем на самом деле микрософт непрерывно занимается.

(Ответить) (Уровень выше) (Ветвь дискуссии)

Re: Reply to your comment...
[info]mivlad@lj
2004-11-24 22:36 (ссылка)
> Дык это проблемы тех, кто пользуется
> услугами таких хостеров и не знает как
> пользоваться SET SESSION character_set_server = 'koi8_ru';
> SET SESSION collation_server = 'koi8_ru';

Сервер может вообще ничего не знать о такой кодировке. Зарубежный, например.

> KOI8-R ничуть не хуже сортируется по ORDER BY.
> Если конечно доки читать...

Спасибо, я в курсе. Только вот не всегда есть возможность эти доки применить.

> делиться допотопными MTA, которые так
> давно не апгрейдились, что до сих пор 7-й
> бит режут. ЩАЗ. Слишком глупый способ
> нарыть себе нахаляву дырок/открытых
> релеев. Идиотов ищите по другим
> журналам.

:-)

> Определитесь уж ;-)
> Я-то определился. CP1251 - я не использую,
> потому что она разработана микрософтом.
> Это для меня достаточное условие, чтобы
> гнушаться этой кодировкой.

Ага. Так бы сразу и сказали. В соседней записи вы определились совсем по другому. Двойные стандарты — это удобно.

А вы в курсе, что MS является членом W3C и принимает активное участие в разработке web-стандартов? Как у вас, от смотрения в браузер аллергия не начинается? Нет? Ну что ж, даже и не двойные, значит.

> Тянет в лучшем случае на слабенькое
> описание того, чем на самом деле
> микрософт непрерывно занимается.

Согласен, MS делает много гадостей. Очень много. Но на моё мнение о кодировках это не влияет. Потому что я уже давно не мыслю на уровне «Фу-кака-брось_каку».

(Ответить) (Уровень выше) (Ветвь дискуссии)

Re: Reply to your comment...
[info]vchk@lj
2004-11-24 23:08 (ссылка)
Сервер может вообще ничего не знать о такой кодировке. Зарубежный, например.

Ну да. Какие-нибудь русофобы специально при сборке включили опцию --without-charset
Стоит ли пользоваться таким хостингом?

Ага. Так бы сразу и сказали. В соседней записи вы определились совсем по другому. Двойные стандарты — это удобно.

Я вообще-то с самого начала совершенно открыто заявил о своей позиции относительно продуктов мелкософта.
Никаких двойных стандартов. Это я Вам определится предлагал, ибо непонятно поначалу было - то ли Вы за "свободу и равенство", то ли заняли определённую сторону.

А вы в курсе, что MS является членом W3C и принимает активное участие в разработке web-стандартов?

Да, дофига чего наразрабатывала MS. Причём сама это всё выполнять не собирается вовсе. :)

Как у вас, от смотрения в браузер аллергия не начинается? Нет? Ну что ж, даже и не двойные, значит.

Ну я ж не в IE смотрю - почему у меня должна быть аллергия?

(Ответить) (Уровень выше)


(Читать комментарии) -