Задача на Visual Prolog. Проверка на наличие слов

      Комментарии к записи Задача на Visual Prolog. Проверка на наличие слов отключены

В этой теме 2 ответа, 2 участника, последнее обновление  Васильев Владимир Сергеевич 10 мес., 2 нед. назад.

  • Автор
    Сообщения
  • #2838

    Nika
    Участник

    Имеется задача:

    Дана строка, содержащая английский текст. Проверьте есть ли в ней слова, начинающиеся с буквы “b”.

    Вот её решение:

    predicates
      check_text(string,char,char)
      check(string,char)
    
    clauses
      check_text(S,’ ‘,L):- 
        frontchar(S,L,_), !.
      check_text(S,P,L):- 
        P<>’ ‘,
        frontchar(S,Q,R), 
        check_text(R,Q,L).
    
      check(T,L):- 
        frontchar(T,A,_), 
        check_text(T,A,L).
    goal 
      check (“stringb bot”, M).

    Работает правильно, можно только вас попросить объяснить её решение?

  • #2848

    Я не могу объяснить ее решение, т.к. мне не понятно даже что передается в вашу функцию. Функция проверки, на мой взгляд, должна принимать строку, но у вас она что-то еще возвращает.

    Функция check зачем-то отделяет от строки первый символ и передает его в check_text вместе с исходной строкой.

    Функция check_text никак не может решать вашу задачу, т.к. в ней нигде не встречается даже упоминание о букве «b», которая фигурирует в условии задачи.

    Например, если я подам на вход вашей функции строку " hello world" — то результатом будет истина, хотя никаких слов, начинающихся с «b» в моей строке нет.

    Ваша программа сработает так:

    1. в секции goal вызывается check(" hello world", M);
    2. функция check вычислит T = " hello world", A = ' '. Вызовет check_text(" hello world", ' ', L);
    3. в предикате check_text выполнится первое правило, т.к. второй аргумент успешно сопоставится с пробелом, а от исходной строки можно отделить один символ (что сделает frontchar). Причем, остаток строки будет выкинут, ведь третьим аргументом записана анонимная переменная. Итого, функция check_text вернет L = ' ';
    4. вернемся в функцию check со значением L = ' ';
    5. вернемся в goal и выведем true (т.к. решение найдено) и M = ‘ ‘.

    Поясните, каким образом это все связано с вашей задачей? — Почему Вы решили, что это правильное решение?

  • #2849

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

    1. пробелов между словами может быть несколько;
    2. пробелы могут стоять в начале строки;
    3. пробелы могут стоять в конце строки (это отдельная проблема);
    4. слова могут разделяться не только пробелами, но и символами перевода строки или табуляциями, например;

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

    find_first_simbol_words([HeadWord|TailWords]):-
      frontchar(HeadWord, "b", _), !;
      find_first_simbol_words(TailWords).

    Т.е. мы перебираем слова из списка до тех пор, пока первой буквой очередного слова не окажется нужный нам символ. Если список кончится, то мы не сможем выполнить его разделение на голову и хвост, а значит предикат (как и положено по заданию) завершится неудачей.

    Ну а если же вам нужно топорное решение — то ищите в строке сочетание пробел + нужный вам символ для решения задачи:

    find_first_simbol_words(String):-
      frontchar(Space, " ", StringWithoutSpace),
      frontchar(StringWithoutSpace, "b", _TailString), !.
    find_first_simbol_words(String):-
      frontchar(Space, _HeadSymbol, StringWithoutHead),
      find_first_simbol_words(StringWithoutHead).

    Алгоритм тоже очень прост:

    • если первый символ строки пробел, а второй — нужная вам буква, то функция завершается успешно;
    • в противном случае первый символ отбрасывается, а остальная часть строки обрабатывается рекурсивно;
    • если строка кончится, то вызов frontchar для нее завершится неудачей и функция (как и следует, т.к. в пустой строке нет слов, соответствующих условию) тоже завершится неудачей.

    Ну а ваши поделки из первого поста мне вообще не понятны. Я даже не знаю с какой стороны начинать читать этот код и какой алгоритм мог пытаться реализовать его автор.

Для ответа в этой теме необходимо авторизоваться.