program AmigaVirtual;
{$MODE OBJFPC}
const
threshold = 0.65; //порог обучения/ответа
defsyl = 4; //длина слога по умолчанию
type
TDB = array of string; //база данных
var
DB: TDB;
//Вычисление совпадений строк, результат в диапазоне 0.0 .. 1.0
function CalcSim(A, B: string; syl: integer = defsyl): real;
//Входит ли строка B в строку S?
function IsStrInStr(B, S: string): boolean;
var
i: integer;
begin
IsStrInStr := false;
for i := 1 to Length(S) - Length(B) + 1 do
if B = Copy(S, i, Length(B)) then
begin
IsStrInStr := true;
exit;
end;
end;
//Число слогов в строке
function SylCount(S: string; syl: integer): integer;
begin
SylCount := Length(S) - syl + 1;
end;
var
Match: integer = 0;
i: integer;
C, D: string;
begin
//Если строки и так одинаковые, выходим
if A = B then
begin
CalcSim := 1;
exit;
end;
//Определяем короткую (D) и длинную (C) строки
if Length(A) > Length(B) then
begin C := A; D := B; end else
begin C := B; D := A; end;
Write(Length(D), ' ', Length(C), ' - ');
//Если наименьшая строка меньше длины слога
if Length(D) < syl then
begin
C := C + Copy(C, 1, Length(D) - 1);
if IsStrInStr(D, C) then Match := 1;
CalcSim := Match / SylCount(C, Length(D));
exit;
end;
//Добавляем символы из начала строк в их конец
C := C + Copy(C, 1, syl - 1);
D := D + Copy(D, 1, syl - 1);
//Подсчитываем количество совпадающих слогов
for i := 1 to Length(C) - syl + 1 do
if IsStrInStr(Copy(C, i, syl), D) then
inc(Match);
//Вычисляем процент совпадений
CalcSim := Match / SylCount(C, syl) ;
end;
//Загружаем БД из файла
function LoadDB: TDB;
var
buf: TDB;
begin
while not eof do
begin
SetLength(buf, Length(buf)+1);
Readln(buf[Length(buf)-1]);
end;
LoadDB := buf;
end;
//Ищем в БД максимально совпадающую с LastSent строку
//и выдаём следующую за ней строку
function NextSentence(var DB: TDB; LastSent: string; var MS: real): string;
var
Sim, MaxSim: real;
i: integer;
begin
MaxSim := 0;
for i := 0 to Length(DB) - 2 do
begin
Sim := CalcSim(DB[i], LastSent);
//Если нашли строку, которая совпадает больше
if Sim > MaxSim then
begin
MaxSim := Sim;
NextSentence := DB[i + 1];
end;
end;
//Если процент совпадения меньше порога,
//тогда записываем строку в БД
if MaxSim < threshold then
begin
NextSentence := '[SYSTEM] Нет ответа, фраза запомнена';
SetLength(DB, Length(DB) + 1);
DB[Length(DB) - 1] := LastSent;
end;
MS := MaxSim;
end;
//Сравниваем две строки между собой
//и выводим результат на экран
procedure SS(A, B: string; syl: integer = defsyl);
begin
Writeln(A + ':' + B + ' - ', (CalcSim(A, B, syl) * 100):3:2, '%');
end;
//Имитация отправки пользователем строки
procedure Say(S: string);
var
Sim: real;
begin
Writeln('Вы: ', S);
Writeln('AV: ', NextSentence(DB, S, Sim), ' (', (Sim * 100):3:2, '%)');
end;
var
i: integer;
begin
DB := LoadDB;
Say('Как дила?');
Say('Ну дык чо, о чём побазарим?');
Say('Да за жизнь нашу блатную');
Say('О чём побазарим?');
Say('Побазарим о чём?');
Say('Скажи, что такое молоко?');
Say('Молоко - это напиток.');
Say('Скажи, что такое малако?');
Say('Скажи, что такое Колыма?');
Say('Что такое Колыма?');
Writeln;
//Распечатываем БД
Writeln('---- DB dump: ----');
for i := 0 to Length(DB) - 1 do
Writeln(DB[i]);
Writeln;
SS('abcd', 'fghj');
SS('abcd', 'nm');
SS('abcd', 'abfg');
SS('abcd', 'abce');
SS('abcd', 'abcd');
SS('abed', 'abcd');
SS('abcde', 'abcfr');
SS('abcdefgh', 'abcd');
SS('abcdefgh', 'cd');
SS('abcd', 'abcde');
SS('abcdef', 'abc');
SS('abcd', 'cdab');
SS('abcdef', 'abefcd');
SS('молоко', 'малако');
SS('молоко', 'млко');
SS('молоко', 'Колыма');
SS('абвгдеёжзи', 'абв', 4);
SS('абвгдеёжzи', 'абв', 4);
SS('abcdefghij', 'abc', 4);
SS('абвгдеёжзи', 'аб', 4);
SS('абвгдеёжзи', 'а', 4);
SS('абвгдеёжзи', '', 4);
end.
cHJvZ3JhbSBBbWlnYVZpcnR1YWw7Cgp7JE1PREUgT0JKRlBDfQoKY29uc3QKIHRocmVzaG9sZCA9IDAuNjU7IC8v0L/QvtGA0L7QsyDQvtCx0YPRh9C10L3QuNGPL9C+0YLQstC10YLQsAogZGVmc3lsID0gNDsgLy/QtNC70LjQvdCwINGB0LvQvtCz0LAg0L/QviDRg9C80L7Qu9GH0LDQvdC40Y4KCnR5cGUKIFREQiA9IGFycmF5IG9mIHN0cmluZzsgLy/QsdCw0LfQsCDQtNCw0L3QvdGL0YUKCnZhcgogREI6IFREQjsKCi8v0JLRi9GH0LjRgdC70LXQvdC40LUg0YHQvtCy0L/QsNC00LXQvdC40Lkg0YHRgtGA0L7Quiwg0YDQtdC30YPQu9GM0YLQsNGCINCyINC00LjQsNC/0LDQt9C+0L3QtSAwLjAgLi4gMS4wCmZ1bmN0aW9uIENhbGNTaW0oQSwgQjogc3RyaW5nOyBzeWw6IGludGVnZXIgPSBkZWZzeWwpOiByZWFsOwoKIC8v0JLRhdC+0LTQuNGCINC70Lgg0YHRgtGA0L7QutCwIEIg0LIg0YHRgtGA0L7QutGDIFM/CiBmdW5jdGlvbiBJc1N0ckluU3RyKEIsIFM6IHN0cmluZyk6IGJvb2xlYW47CiB2YXIKICBpOiBpbnRlZ2VyOwogYmVnaW4KICBJc1N0ckluU3RyIDo9IGZhbHNlOwogIGZvciBpIDo9IDEgdG8gTGVuZ3RoKFMpIC0gTGVuZ3RoKEIpICsgMSBkbwogICBpZiBCID0gQ29weShTLCBpLCBMZW5ndGgoQikpIHRoZW4KICAgYmVnaW4KICAgIElzU3RySW5TdHIgOj0gdHJ1ZTsKICAgIGV4aXQ7CiAgIGVuZDsKIGVuZDsKCiAvL9Cn0LjRgdC70L4g0YHQu9C+0LPQvtCyINCyINGB0YLRgNC+0LrQtQogZnVuY3Rpb24gU3lsQ291bnQoUzogc3RyaW5nOyBzeWw6IGludGVnZXIpOiBpbnRlZ2VyOwogYmVnaW4KICAgU3lsQ291bnQgOj0gTGVuZ3RoKFMpIC0gc3lsICsgMTsKIGVuZDsKCnZhcgogTWF0Y2g6IGludGVnZXIgPSAwOwogaTogaW50ZWdlcjsKIEMsIEQ6IHN0cmluZzsKYmVnaW4KIC8v0JXRgdC70Lgg0YHRgtGA0L7QutC4INC4INGC0LDQuiDQvtC00LjQvdCw0LrQvtCy0YvQtSwg0LLRi9GF0L7QtNC40LwKIGlmIEEgPSBCIHRoZW4KIGJlZ2luCiAgQ2FsY1NpbSA6PSAxOwogIGV4aXQ7CiBlbmQ7CgogLy/QntC/0YDQtdC00LXQu9GP0LXQvCDQutC+0YDQvtGC0LrRg9GOIChEKSDQuCDQtNC70LjQvdC90YPRjiAoQykg0YHRgtGA0L7QutC4CiBpZiBMZW5ndGgoQSkgPiBMZW5ndGgoQikgdGhlbgogYmVnaW4gQyA6PSBBOyBEIDo9IEI7IGVuZCBlbHNlCiBiZWdpbiBDIDo9IEI7IEQgOj0gQTsgZW5kOwoKV3JpdGUoTGVuZ3RoKEQpLCAnICcsIExlbmd0aChDKSwgJyAtICcpOwoKLy/QldGB0LvQuCDQvdCw0LjQvNC10L3RjNGI0LDRjyDRgdGC0YDQvtC60LAg0LzQtdC90YzRiNC1INC00LvQuNC90Ysg0YHQu9C+0LPQsAogaWYgTGVuZ3RoKEQpIDwgc3lsIHRoZW4KIGJlZ2luCiAgQyA6PSBDICsgQ29weShDLCAxLCBMZW5ndGgoRCkgLSAxKTsKICBpZiBJc1N0ckluU3RyKEQsIEMpIHRoZW4gTWF0Y2ggOj0gMTsKICBDYWxjU2ltIDo9IE1hdGNoIC8gU3lsQ291bnQoQywgTGVuZ3RoKEQpKTsKICBleGl0OwogZW5kOwoKIC8v0JTQvtCx0LDQstC70Y/QtdC8INGB0LjQvNCy0L7Qu9GLINC40Lcg0L3QsNGH0LDQu9CwINGB0YLRgNC+0Log0LIg0LjRhSDQutC+0L3QtdGGCiBDIDo9IEMgKyBDb3B5KEMsIDEsIHN5bCAtIDEpOwogRCA6PSBEICsgQ29weShELCAxLCBzeWwgLSAxKTsKCiAvL9Cf0L7QtNGB0YfQuNGC0YvQstCw0LXQvCDQutC+0LvQuNGH0LXRgdGC0LLQviDRgdC+0LLQv9Cw0LTQsNGO0YnQuNGFINGB0LvQvtCz0L7QsgogZm9yIGkgOj0gMSB0byBMZW5ndGgoQykgLSBzeWwgKyAxIGRvCiAgaWYgSXNTdHJJblN0cihDb3B5KEMsIGksIHN5bCksIEQpIHRoZW4KICAgaW5jKE1hdGNoKTsKCiAvL9CS0YvRh9C40YHQu9GP0LXQvCDQv9GA0L7RhtC10L3RgiDRgdC+0LLQv9Cw0LTQtdC90LjQuQogQ2FsY1NpbSA6PSBNYXRjaCAvIFN5bENvdW50KEMsIHN5bCkgOwplbmQ7CgovL9CX0LDQs9GA0YPQttCw0LXQvCDQkdCUINC40Lcg0YTQsNC50LvQsApmdW5jdGlvbiBMb2FkREI6IFREQjsKdmFyCiBidWY6IFREQjsKYmVnaW4KIHdoaWxlIG5vdCBlb2YgZG8KIGJlZ2luCiAgU2V0TGVuZ3RoKGJ1ZiwgTGVuZ3RoKGJ1ZikrMSk7CiAgUmVhZGxuKGJ1ZltMZW5ndGgoYnVmKS0xXSk7CiBlbmQ7CiBMb2FkREIgOj0gYnVmOwplbmQ7CgovL9CY0YnQtdC8INCyINCR0JQg0LzQsNC60YHQuNC80LDQu9GM0L3QviDRgdC+0LLQv9Cw0LTQsNGO0YnRg9GOINGBIExhc3RTZW50INGB0YLRgNC+0LrRgwovL9C4INCy0YvQtNCw0ZHQvCDRgdC70LXQtNGD0Y7RidGD0Y4g0LfQsCDQvdC10Lkg0YHRgtGA0L7QutGDCmZ1bmN0aW9uIE5leHRTZW50ZW5jZSh2YXIgREI6IFREQjsgTGFzdFNlbnQ6IHN0cmluZzsgdmFyIE1TOiByZWFsKTogc3RyaW5nOwp2YXIKIFNpbSwgTWF4U2ltOiByZWFsOwogaTogaW50ZWdlcjsKYmVnaW4KIE1heFNpbSA6PSAwOwogZm9yIGkgOj0gMCB0byBMZW5ndGgoREIpIC0gMiBkbwogYmVnaW4KICBTaW0gOj0gQ2FsY1NpbShEQltpXSwgTGFzdFNlbnQpOwogIC8v0JXRgdC70Lgg0L3QsNGI0LvQuCDRgdGC0YDQvtC60YMsINC60L7RgtC+0YDQsNGPINGB0L7QstC/0LDQtNCw0LXRgiDQsdC+0LvRjNGI0LUKICBpZiBTaW0gPiBNYXhTaW0gdGhlbgogIGJlZ2luCiAgIE1heFNpbSA6PSBTaW07CiAgIE5leHRTZW50ZW5jZSA6PSBEQltpICsgMV07CiAgZW5kOwogZW5kOwogLy/QldGB0LvQuCDQv9GA0L7RhtC10L3RgiDRgdC+0LLQv9Cw0LTQtdC90LjRjyDQvNC10L3RjNGI0LUg0L/QvtGA0L7Qs9CwLAogLy/RgtC+0LPQtNCwINC30LDQv9C40YHRi9Cy0LDQtdC8INGB0YLRgNC+0LrRgyDQsiDQkdCUCiBpZiBNYXhTaW0gPCB0aHJlc2hvbGQgdGhlbgogYmVnaW4KICBOZXh0U2VudGVuY2UgOj0gJ1tTWVNURU1dINCd0LXRgiDQvtGC0LLQtdGC0LAsINGE0YDQsNC30LAg0LfQsNC/0L7QvNC90LXQvdCwJzsKICBTZXRMZW5ndGgoREIsIExlbmd0aChEQikgKyAxKTsKICBEQltMZW5ndGgoREIpIC0gMV0gOj0gTGFzdFNlbnQ7CiBlbmQ7CiBNUyA6PSBNYXhTaW07CmVuZDsKCi8v0KHRgNCw0LLQvdC40LLQsNC10Lwg0LTQstC1INGB0YLRgNC+0LrQuCDQvNC10LbQtNGDINGB0L7QsdC+0LkKLy/QuCDQstGL0LLQvtC00LjQvCDRgNC10LfRg9C70YzRgtCw0YIg0L3QsCDRjdC60YDQsNC9CnByb2NlZHVyZSBTUyhBLCBCOiBzdHJpbmc7IHN5bDogaW50ZWdlciA9IGRlZnN5bCk7CmJlZ2luCiBXcml0ZWxuKEEgKyAnOicgKyBCICsgJyAtICcsIChDYWxjU2ltKEEsIEIsIHN5bCkgKiAxMDApOjM6MiwgJyUnKTsKZW5kOwoKLy/QmNC80LjRgtCw0YbQuNGPINC+0YLQv9GA0LDQstC60Lgg0L/QvtC70YzQt9C+0LLQsNGC0LXQu9C10Lwg0YHRgtGA0L7QutC4CnByb2NlZHVyZSBTYXkoUzogc3RyaW5nKTsKdmFyCiBTaW06IHJlYWw7CmJlZ2luCiBXcml0ZWxuKCfQktGLOiAnLCBTKTsKIFdyaXRlbG4oJ0FWOiAnLCBOZXh0U2VudGVuY2UoREIsIFMsIFNpbSksICcgKCcsIChTaW0gKiAxMDApOjM6MiwgJyUpJyk7CmVuZDsKCnZhcgogaTogaW50ZWdlcjsKCmJlZ2luCiBEQiA6PSBMb2FkREI7CiBTYXkoJ9Ca0LDQuiDQtNC40LvQsD8nKTsKIFNheSgn0J3RgyDQtNGL0Log0YfQviwg0L4g0YfRkdC8INC/0L7QsdCw0LfQsNGA0LjQvD8nKTsKIFNheSgn0JTQsCDQt9CwINC20LjQt9C90Ywg0L3QsNGI0YMg0LHQu9Cw0YLQvdGD0Y4nKTsKIFNheSgn0J4g0YfRkdC8INC/0L7QsdCw0LfQsNGA0LjQvD8nKTsKIFNheSgn0J/QvtCx0LDQt9Cw0YDQuNC8INC+INGH0ZHQvD8nKTsKIFNheSgn0KHQutCw0LbQuCwg0YfRgtC+INGC0LDQutC+0LUg0LzQvtC70L7QutC+PycpOwogU2F5KCfQnNC+0LvQvtC60L4gLSDRjdGC0L4g0L3QsNC/0LjRgtC+0LouJyk7CiBTYXkoJ9Ch0LrQsNC20LgsINGH0YLQviDRgtCw0LrQvtC1INC80LDQu9Cw0LrQvj8nKTsKIFNheSgn0KHQutCw0LbQuCwg0YfRgtC+INGC0LDQutC+0LUg0JrQvtC70YvQvNCwPycpOwogU2F5KCfQp9GC0L4g0YLQsNC60L7QtSDQmtC+0LvRi9C80LA/Jyk7CiBXcml0ZWxuOwogLy/QoNCw0YHQv9C10YfQsNGC0YvQstCw0LXQvCDQkdCUCiBXcml0ZWxuKCctLS0tIERCIGR1bXA6IC0tLS0nKTsKIGZvciBpIDo9IDAgdG8gTGVuZ3RoKERCKSAtIDEgZG8KICBXcml0ZWxuKERCW2ldKTsKIFdyaXRlbG47CiBTUygnYWJjZCcsICdmZ2hqJyk7CiBTUygnYWJjZCcsICdubScpOwogU1MoJ2FiY2QnLCAnYWJmZycpOwogU1MoJ2FiY2QnLCAnYWJjZScpOwogU1MoJ2FiY2QnLCAnYWJjZCcpOwogU1MoJ2FiZWQnLCAnYWJjZCcpOwogU1MoJ2FiY2RlJywgJ2FiY2ZyJyk7CiBTUygnYWJjZGVmZ2gnLCAnYWJjZCcpOwogU1MoJ2FiY2RlZmdoJywgJ2NkJyk7CiBTUygnYWJjZCcsICdhYmNkZScpOwogU1MoJ2FiY2RlZicsICdhYmMnKTsKIFNTKCdhYmNkJywgJ2NkYWInKTsKIFNTKCdhYmNkZWYnLCAnYWJlZmNkJyk7CiBTUygn0LzQvtC70L7QutC+JywgJ9C80LDQu9Cw0LrQvicpOwogU1MoJ9C80L7Qu9C+0LrQvicsICfQvNC70LrQvicpOwogU1MoJ9C80L7Qu9C+0LrQvicsICfQmtC+0LvRi9C80LAnKTsKIFNTKCfQsNCx0LLQs9C00LXRkdC20LfQuCcsICfQsNCx0LInLCA0KTsKIFNTKCfQsNCx0LLQs9C00LXRkdC2etC4JywgJ9Cw0LHQsicsIDQpOwogU1MoJ2FiY2RlZmdoaWonLCAnYWJjJywgNCk7CiBTUygn0LDQsdCy0LPQtNC10ZHQttC30LgnLCAn0LDQsScsIDQpOwogU1MoJ9Cw0LHQstCz0LTQtdGR0LbQt9C4JywgJ9CwJywgNCk7CiBTUygn0LDQsdCy0LPQtNC10ZHQttC30LgnLCAnJywgNCk7CmVuZC4=