Проверка орфографии

Итак, перед нами стоит следующая задача: реализовать load, check, size и unload настолько эффективно, насколько это возможно, чтобы минимизировать TIME IN load, TIME IN check, TIME IN size, и TIME IN unload.

Возможно, не совсем понятно, что значит минимизовать. Особенно с учётом того, что эти показатели будут меняться в зависимости от того, какой словарь dictionary и текст text вы загружаете в speller. Это и есть самая соль задачи, самое сложное, но при этом — очень увлекательное затруднение. К его решению можно подойти творчески.

Разумеется, желательно минимизировать объем используемой памяти, но главное — уменьшить время выполнения. Прежде, чем погрузиться в решение, пробегитесь по следующим рекомендациям.

  • Вы не можете менять speller.c.
  • Вы можете менять dictionary.c (по сути, вы должны его менять, чтобы завершить реализацию load, check, size и unload, но при этом нельзя изменять объявления load, check, size и unload).
  • Вы можете изменять dictionary.h, но нельзя изменять объявления load, check, size и unload.
  • Вы можете менять Makefile.
  • Вы можете добавить функции в dictionary.c или в ваши собственные файлы. Только проследите, чтобы при этом ваш код успешно компилировался с помощью make.
  • Ваша реализация check должна быть нечувствительна к регистру. Другими словами, если foo есть в словаре, check должна возвращать значение true для любого слова, которые отличаются от foo только регистром символов. Все слова foo, foO, fOo, fOO, fOO, Foo, FoO, FOo и FOO нужно считать правильными.
  • Помимо регистра, ваша реализация check должна возвращать значение true для слов, которые действительно есть в dictionary. Осторожнее с часто употребляемыми словами (например, с the), если мы передали dictionary без них. Более того, разрешены только те конкретные слова, которые явно заданы в словаре dictionary, а их формы — нет. Иначе говоря, даже если foo есть в dictionary, команда check должна вернуть значение false для foo’s в случае если foo’s нет в dictionary.
  • Считайте, что check проходит строки только по символам алфавита и/или апострофам.
  • Считайте, что любой словарь в вашей программе будет структурирован точно так, как наши: лексикографически выстроен сверху вниз по одному слову в строке, и все строки заканчиваются знаком \n. Также примите, что dictionary должен содержать по крайней мере одно слово и все слова не должны быть длиннее LENGTH (эта константа определена в dictionary.h). Ни одно слово не должно повторяться и все они должны содержать строчные символы алфавита и, возможно, апострофы.
  • Ваша программа проверки правописания должна принимать на вход только text и, дополнительно, может принимать словарь dictionary. Невзирая на то, что вы, скорее всего захотите предварительно “доработать” наш словарь по умолчанию с целью определить для него лучшую хеш-функцию, вы не сможете сохранить на диск результат любой подобной доработки с тем, чтобы повторно загрузить его в память для более быстрых дальнейших вызовов.
  • Вы можете использовать хеш-функции из книг или интернета, при условии, что вы даете ссылку на оригинал любой хеш-функции, которую вы интегрируете в ваш код.

Начинаем

Вот что вам нужно сделать:

  • Реализовать load. Советуем вам подготовить словари, меньше 143 091 слов, с которыми вы будете тестировать ваш код во время разработки.
  • Реализовать check. Советуем вам подготовить несколько малых файлов для проверки правописания, перед началом. «Войну и мир», например.
  • Реализовать size.
  • Реализовать unload. Обязательно высвободите память (free), которую вы выделили под load!
  • Еще немного подсказок:

    Не забывайте, valgrind — ваш лучший приятель! Он отслеживает потерю доступа к памяти, пока ваша программа работает. Убедитесь, что аргументы в программной строке передаются, если вы хотите, чтобы функция valgrind анализировала speller, пока вы используете определенный словарь и/или текст. Лучше всего работать с небольшим текстом, в противном случае valgrind потребуется значительное количество времени.

    valgrind — leak-check=full ./speller texts/ralph.txt

    Если вы запускаете valgrind без указания text для speller, ваша реализация load и unload не будет вызываться (и анализироваться).

    Если вы не уверены, как следует интерпретировать результат valgrind, запустите help50:

    help50 valgrind — leak-check=full ./speller texts/ralph.txt

    Проверка

    Как понять, что программа выбрала верные слова с опечатками? Во-первых, вы можете посмотреть ответы в директории keys. Она находится внутри директории speller. Например, в keys/austinpowers.txt должны быть собраны все слова, которые ваша программа считает написанными неправильно.

    Или вы можете запустить программу над текстом в одном окне.

    ./speller ~cs50/pset5/texts/austinpowers.txt

    А потом запустите версию, созданную сотрудниками курса, с тем же самым текстом в другом окне, как показано ниже:

    ~cs50/pset5/speller ~cs50/pset5/texts/austinpowers.txt 

    и провести визуальное сравнение визуально, строка за строкой. Правда, такая работа очень быстро надоедает. Вместо этого лучше перенаправить результат работы программы в отдельный файл (вы уже так делали с generate в третьем задачнике):

    ./speller ~cs50/pset5/texts/austinpowers.txt > student.txt
    ~cs50/pset5/speller ~cs50/pset5/texts/austinpowers.txt > staff.txt

    Вы можете сравнить оба файла, открыв их в одном окне с помощью программы diff:

    diff -y student.txt staff.txt

    Или ещё один вариант: для экономии времени, вы можете сравнить результат работы вашей программы (предположим, что вы перенаправляете его в, например, student.txt) с одним из файлов ответов:

    diff -y student.txt ~cs50/pset5/keys/austinpowers.txt

    Если результат работы вашей программы совпадает с нашей версией, diff выведет на экран два идентичных столбца. Отличие возможно только во времени продолжительности работы, указанной внизу.

    Если столбцы будут отличаться, вы увидите знаки > или |, там, где они отличаются. Например,

    MISSPELLED WORDS                                                MISSPELLED WORDS
    
    FOTTAGE                                                         FOTTAGE
    INT                                                             INT
                                                                  > EVIL'S
    s                                                               s
                                                                  > EVIL'S
    Farbissina                                                      Farbissina

    Это означает что программа (её вывод — слева) не считает, что EVIL’s не верен, а вот наша программа считает именно так, что представляется отсутствием EVIL’s в левой колонке и присутствием его в правой.

    check50

    Чтобы проверить свой код в автоматическом режиме (правда, не полностью), вы можете выполнить следующее:

    check50 2015.fall.pset5.speller dictionary.c dictionary.h Makefile

    Обратите внимание, check50 не отслеживает утечки памяти, поэтому обязательно используйте также valgrind.

    Как понять, достаточно ли быстрая ваша версия?

    Как всегда, вы можете запустить версию, созданную сотрудниками курса, и сравнить результат её работы с вашим:

    ~cs50/pset5/speller ~cs50/pset5/texts/austinpowers.txt