Замена звездочек в строке

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

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

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

    Egor
    Участник

    У меня вопрос по Prolog:

    мне дана строка символов, и если в ней нет символа *, то строку оставить без изменения, иначе заменить символ, стоящий после первой *, на символ +.

    Как можно переделать предикат func?
    Вот мой код:

    domains 
      %c = char 
      list = char* 
    
    predicates 
      nondeterm func(list,char) 
      %nondeterm is_zwezd(char) 
    
    clauses 
      func([],' '):-!. 
      func([Head|Tail],Head):-
        Head = '*',
        func(Tail,'+'). 
    
      /*func([Head|ListTail],[Head|_]):-
        Head = '*',
        Head1 = '+', 
        func(ListTail,_). */
    goal 
      string_to_list("fdsgdgdsd *dsfdsfds fdsfsf* fdgdsfgd",List),
      func(List,_),
      list_to_string(List,Str).

    Предикаты string_to_list и list_to_string я взял отсюда: преобразования строки в список и списка в строку.

  • #3323

    Вашу задачу можно решить так:

    PREDICATES							
    	swap_star_plus(string, string)
    CLAUSES
    	swap_star_plus("", ""):-!.
    	swap_star_plus(String, Result):-
    		frontchar(String, '*', StringWithoutStar), !,
    		frontchar(StringWithoutStar, _, StringTail),
    		frontchar(StringTailWithPlus, '+', StringTail),
    		frontchar(Result, '*', StringTailWithPlus).
    	swap_star_plus(String, Result):-
    		frontchar(String, Char, StringTail),
    		swap_star_plus(StringTail, TailResult),
    		frontchar(Result, Char, TailResult).
    GOAL
      	swap_star_plus("dsgdgdsd *dsfdsfds fdsfsf* fdgdsfgd", X).

    Преобразовывать строку в список и назад не обязательно. В списке вы можете отделять от списка первый элемент и прикреплять элемент в начало списка, но тоже самое можно делать со строками с помощью стандартных предикатов frontchar.

    swap_star_plus

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

    1. запрещаем переход на третье правило с помощью отсечения;
    2. отделяем символ, следующий за звездочкой;
    3. к полученному остатку строки дописываем символ «+»;
    4. наконец, дописываем звездочку, которую мы изъяли первым шагом;

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

  • #3326

    Egor
    Участник

    Опишите когда работает 3 правило, можете пример пожалуйста привести?

    • #3328

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

      Третье правило срабатывает если в строке есть символы и первый символ не является звездочкой. Например "1+2*3-4". Это правило служит для перебора символов строки, т.е. для нашего примера оно сначала удалить из строки 1, затем + и так далее. Затем, в один момент первым символом строки окажется звездочка и выполнение не дойдет до третьего правила, оно остановится на втором.

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