Шекспир

Тема в разделе "Pascal and Delphi", создана пользователем a9x, 1 дек 2012.

  1. a9x

    a9x Гость

    Задание: написать программу, которая считывает txt файл - Шекспир во оригинале на английском, и считает слова, которые Шекспир употребил в произведении - все слова, кроме тех, которые повторяются. Главное - чтобы прога считала слова в разных формах с окончаниями -ing, -ed, -ies и тд - за одно слово. Я написал программу, которая считает слова, и те, которые повторяются - считает за одно слово. Помогите пож с разными формами.
    Например слова change, changed - считать за одно слово.
    Вот моя прога
    Код (Delphi):
    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.
     
  2. sinkopa

    sinkopa Well-Known Member

    Регистрация:
    17 июн 2009
    Сообщения:
    344
    Симпатии:
    9
    Это вопрос скорее по английскому языку... :rolleyes:
    Вот. передоделал Ваш код...
    Предложения, замечания в комментариях...
    Код (Delphi):
    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;
     
  3. Proger23

    Proger23 New Member

    Регистрация:
    13 мар 2013
    Сообщения:
    1
    Симпатии:
    0
    Спасибо, очень помогло
     

Поделиться этой страницей