Шекспир

  • Автор темы a9x
  • Дата начала
A

a9x

Гость
#1
Задание: написать программу, которая считывает txt файл - Шекспир во оригинале на английском, и считает слова, которые Шекспир употребил в произведении - все слова, кроме тех, которые повторяются. Главное - чтобы прога считала слова в разных формах с окончаниями -ing, -ed, -ies и тд - за одно слово. Я написал программу, которая считает слова, и те, которые повторяются - считает за одно слово. Помогите пож с разными формами.
Например слова change, changed - считать за одно слово.
Вот моя прога
Код:
procedure TForm1.Button1Click(Sender: TObject);
const
// Все, что считается разделителем
Separator = ['''', '"', '&', '.', ',', ':', ';', '!', '?', '-', ' ', #9, #10, #13];
var
sL, sLtxt: TStringList;
i: integer;
f: TextFile;
s: string;
begin
sL := TStringList.Create;	 // Создаем переменную для хранения слов
sL.Sorted :=true;			 // Назначаем ей св-ва Сортировать
sL.Duplicates := dupIgnore;	// и игнорировать дубликаты
AssignFile(f,'Otello.txt');		// Связываем f с текстовым файлом
Reset(f);					 // Начало файла
while not EOF(f) do			// Пока не дойдем до конца
begin
ReadLn(f,s);				 // Читаем строку
for i := 1 to Length(s) do  // Если есть кавычка ('), заменяем на пробел
if s[i] = '''' then s[i] := ' ';
ExtractStrings(Separator, [' '], PAnsiChar(s), sL); // и записываем их в sL
end;
ListBox1.Items.Assign(sL);	 // Выводим результат в ЛистБокс
sL.Free;					  // Освобождаем память от ненужных больше переменных
CloseFile(f);				 // Закрываем файл
ShowMessage(IntToStr(ListBox1.Count)); // Показываем кол-во найденных слов

end;
end.
 

sinkopa

Well-Known Member
17.06.2009
344
9
#2
Задание: написать программу, которая считывает txt файл - Шекспир во оригинале на английском, и считает слова, которые Шекспир употребил в произведении - все слова, кроме тех, которые повторяются. Главное - чтобы прога считала слова в разных формах с окончаниями -ing, -ed, -ies и тд - за одно слово. Я написал программу, которая считает слова, и те, которые повторяются - считает за одно слово. Помогите пож с разными формами.
Например слова change, changed - считать за одно слово.
Это вопрос скорее по английскому языку... :rolleyes:
Вот. передоделал Ваш код...
Предложения, замечания в комментариях...
Код:
uses
StrUtils;

procedure TForm1.Button1Click(Sender: TObject);
const
// Все, что считается разделителем
Separator = ['''', '"', '&', '.', ',', ':', ';', '!', '?', '-', ' ', #9, #10, #13];
var
sL, sLtxt: TStringList;
i,j,sLen: integer;
f: TextFile;
s: string;
begin
sL := TStringList.Create;	 // Создаем переменную для хранения слов
sL.Sorted :=true;			 // Назначаем ей св-ва Сортировать
sL.Duplicates := dupIgnore;	// и игнорировать дубликаты

// Поскольку потоковые операции быстрее чем файловые,
// вместо AssignFile(f,'Otello.txt'); Reset(f) и ReadLn(f,s)
// предлагаю использовать следующее:
sLtxt := TStringList.Create;	 // Создаем переменную для загрузки текстового файла
sLtxt.LoadFromFile('Otello.txt'); // Загружаем текст

for i := 0 to sLtxt.Count-1 do
begin
s := Trim(AnsiLowerCase(sLtxt[i])); // Читаем строку !!! в нижнем регистре !!!
// иначе слова будут дублироваться
// например: "This" и "this" получится два разных слова
if (s = '') then Continue; // пустые пропускаем

for j := 1 to Length(s) do		 // !!! Не уверен что это правильно... этот код
if s[j] = '''' then s[j] := ' '; // поделит такие слова как "It's", "I've" на два слова

ExtractStrings(Separator, [' '], PAnsiChar(s), sL); // и записываем их в sL
end;

sLtxt.Clear;
// вынимаем из sL трансформы c окончаниями
// -ing, -ed, -ies -es -s
for i := sL.Count-1 downto 0 do
begin
s := sL[i];
if (	AnsiEndsStr('ing', s) // change -> changing
or AnsiEndsStr('ed', s ) // press -> pressed
or AnsiEndsStr('ies', s) // dictionary -> dictionaries.
or AnsiEndsStr('es', s)  // box -> boxes
or AnsiEndsStr('s', s)	// day --> days
) then
begin
sLtxt.Add(s); // переносим в sLtxt
sL.Delete(i);
end;
end;

// обрабатываем трансформы
for i := 0 to sLtxt.Count-1 do
begin
s := sLtxt[i];	 // взяли слово
sLen := Length(s); // получили длину

// вычисляем длину корня слова
if AnsiEndsStr('ing', s) then
Dec(sLen,3)
else if AnsiEndsStr('ies',s ) then
Dec(sLen,3)
else if AnsiEndsStr('es', s ) then
Dec(sLen,2)
else if AnsiEndsStr('ed', s ) then
Dec(sLen,2)
else if AnsiEndsStr('s', s ) then
Dec(sLen,1);

if (sLen < 2) then // Это не корень базовой формы слова, возвращаем слово в sL
sL.Add(s)
else
begin
SetLength(s,sLen); // отрезаем окончание (укорачиваем для длины слова)

// пытаемся найти в sL одну из словоформ
if	( sL.IndexOf(s) < 0 )		 // базовая форма "day", "press" и тп.
and ( sL.IndexOf(s+'e')  < 0 )  // базовая форма "change" и тп.
and ( sL.IndexOf(s+'y')  < 0 )  // базовая форма "dictionary" и тп.
and ( sL.IndexOf(s+'ed') < 0 )  // трансформ "pressed", "changed" и тп.
and ( sL.IndexOf(s+'ies') < 0 )  // трансформ "dictionaries" и тп.
and ( sL.IndexOf(s+'ing') < 0 )  // трансформ "pressing", "changing" и тп.
and ( sL.IndexOf(s+'s')  < 0 )  // трансформ "days", "boys" и тп.
then
begin
// Если не нашлось ни одного из вариантов - возвращаем слово в sL
sL.Add(sLtxt[i])
end;
end;
end;
sLtxt.Clear;

ListBox1.Items.Assign(sL);	 // Выводим результат в ЛистБокс
sL.Free;					  // Освобождаем память от ненужных больше переменных
sLtxt.Free;
ShowMessage(IntToStr(ListBox1.Count)); // Показываем кол-во найденных слов
end;