Вариант 2. Экспертная система.
Создайте простую экспертную систему, которая классифицирует что-либо в зависимости от ответов пользователя на вопросы. Примерами подобных систем могут быть программа поиска причин неисправности или классификации объектов по категориям.
Данная экспертная система будет определять животное из трех возможных: муравей, зебра и золотая рыбка. Система будет использовать таблицу, содержащую вопросы и действия, которые необходимо предпринять при ответах да и нет. Пример: Это живет в воде? Если да, то золотая рыбка. Если нет, то это черное? Если да, то муравей, если нет, то зебра.
Такая таблица может быть представлена типом data Table = Decision String | Question String Table Table, где Decision d означает выдать решение d, а Question q y n означает задать вопрос q, и следовать инструкциям в таблице y или n в зависимости от ответа.
Определите функцию decide :: Table -> IO (), которая следуя инструкциям из таблицы, задает пользователю вопросы и в зависимости от его ответа задает дальнейшие вопросы или выводит результат.
Для создания таблицы нам необходимы вопросы о каждом из животных и ответы на них. Их можно представить в виде списка, где каждое решение связано с вопросом и соответствующим ему ответом. Например:
facts :: Facts
facts =
[("Это муравей",
[("Это меньше карандаша", True),
("Это черное", True),
("Это живет в воде", False)]),
("Это зебра",
[("Это меньше карандаша", False),
("Это живет в воде", False),
("Это полосатое", True),
("Это черное", False)]),
("Это золотая рыбка",
[("Это меньше карандаша", True),
("Это полосатое", True),
("Это черное", False),
("Это живет в воде", True)])]
Определите функцию restrict :: String -> Bool -> Facts -> Facts, которая по вопросу, ответу и списку возможных фактов возвращает список тех фактов, которые данный ответ НЕ исключает. Заметьте, что некоторые факты могут не относиться к вопросу, поэтому они не исключаются любым ответом. Примеры:
restrict "Это полосатое" False facts ==
[("Это муравей",
[("Это меньше карандаша", True),
("Это черное", True),
("Это живет в воде", False)])]
restrict "Это черное" True facts ==
[("Это муравей",
[("Это меньше карандаша", True),
("Это живет в воде", False)])]
Определите функцию table :: Facts -> Table, которая строит таблицу решений по набору фактов. Необходимо обеспечить получение решения за минимальное количество вопросов. В примере для идентификации животного требуется максимум 2 вопроса, хотя по каждому животному известно три или четыре факта. Хорошей стратегией для этого является задание вопроса, который при любом ответе минимизирует количество возможных решений. В данном случае первый вопрос «Это живет в воде» гарантирует, что независимо от ответа остается максимум две возможности. Напротив, вопрос «Это полосатое» при ответе да не исключает ни одного животного (муравьи не полосатые, но этого факта в базе нет).
Напишите программу, реализующую данную функциональность. Предусмотрите возможность загрузки фактов из текстовых файлов.