Сибирский университет потребительской кооперации
Опубликован: 04.05.2005 | Доступ: свободный | Студентов: 4322 / 1347 | Оценка: 4.45 / 4.22 | Длительность: 12:28:00
ISBN: 978-5-9556-0034-5
Лекция 11:

Строки

< Лекция 10 || Лекция 11: 1234 || Лекция 12 >

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

Запишем решение этой задачи. Начнем с того, что при помощи стандартного предиката frontstr разобьем исходную строку на две подстроки. Во вторую попадут все символы, начиная с той позиции, с которой нужно удалять символы. В первую — начало исходной строки. Вторую подстроку еще раз разделим на две подстроки. В первую подстроку поместим те символы, которые нужно удалить. В этом месте можно будет воспользоваться анонимной переменной. Во вторую подстроку попадут оставшиеся символы остатка исходной строки. Чтобы получить ответ, нам остается только соединить первую подстроку исходной строки с последней подстрокой второй подстроки. Мы получим строку, состоящую в точности из тех символов, которые и должны были остаться в итоговой строке.

Давайте запишем эти немного путаные размышления в виде предложения на Прологе.

str_delete(S,I,C,SO) :–
            I1=I–1, /* I1 — количество символов, 
                    которые должны остаться 
                    в начале строки S */
            frontstr(I1,S,S1,S2), 
                  /* S1 — первые I1 символов 
                    строки S, S2 — символы 
                    строки S, с I —го 
                    до последнего */
            frontstr(C,S2,_,S3), 
                  /* S3 — последние символы 
                    строки S2 ( или, что тоже 
                    самое, последние символы 
                    строки S */
            concat(S1,S3,SO). 
                  /* SO — строка, полученная 
                    соединением строк S1 и S3 */

Пример. Не помешает иметь в нашем хозяйстве предикат, который будет копировать часть строки. Предикат будет иметь четыре параметра. Первые три входные: первый — исходная строка, второй — позиция, начиная с которой нужно копировать символы, третий — количество копируемых символов. Четвертым — выходным — параметром будет результат копирования символов из строки, указанной в первом параметре, в количестве, указанном в третьем параметре, начиная с позиции, указанной во втором параметре.

Для решения этой задачи опять воспользуемся предикатом frontstr. Сначала получим хвост нашей строки, начиная с той позиции, c которой нужно копировать символы. Если после этого взять столько первых символов новой строки, сколько их нужно копировать, получим в точности ту подстроку исходной строки, которую требуется получить.

Зафиксируем наши рассуждения.

str_copy(S,I,C,SO) :–
              I1=I–1, /* I1 — это количество 
                       символов,  расположенных 
                       в начале строки S, которые 
                       не нужно копировать */
              frontstr(I1,S,_,S1), 
                    /* S1 — строка, состоящая 
                       из всех символов строки S, 
                       с I-го и до последнего */
              frontstr(C,S1,SO,_). 
                    /* SO — первые C символов 
                       строки S1 */

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

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

Запишем:

str_insert(S,S1,I,SO) :–
              I1=I–1, /* I1 — это количество 
                       символов, расположенных 
                       в начале строки S, после 
                       которых нужно вставить новые 
                       символы */
              frontstr(I1,S1,S1_1,S1_2), 
                    /* S1_1 — первые I1 символов 
                       строки S1, S1_2 —  остаток 
                       строки S1, с I —го и до 
                       последнего */
              concat(S1_1,S,S2), 
                    /* S2 — строка, полученная 
                       объединением строк S1_1 
                       и S */
              concat(S2,S1_2,SO). 
                    /* SO — строка, полученная 
                       слиянием строк S2 и S1_2 */

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

Для того чтобы реализовать этот предикат, нам придется разработать вспомогательный предикат, который будет означивать второй аргумент единицей (если его первый аргумент является цифрой) и нулем (в противном случае). Основной предикат будет использовать рекурсию по длине строки. Базисом будет очевидный факт, говорящий, что в пустой строке цифр нет. Непустую строку с помощью предиката frontchar разделим на первый символ и хвост. Подсчитаем количество цифр в хвосте, после чего к полученному числу добавим единицу, если первый символ — цифра, и ноль, если первый символ — не цифра.

Запишем оба предиката, вспомогательный и основной:

dig(C,1):–
      ‘0’<=C,C<=’9’,!. /* C — цифра*/
dig(_,0).
count_digit("",0):–!. /* В пустой строке цифр нет */
count_digit(S,N):–
              frontchar(S,C,S2), 
                    /* C — первый символ строки S, 
                       S2 — хвост строки S */
              dig(C,M), /* M равен единице, если C — 
                        цифра, и нулю — иначе */
              count_digit(S2,N2), 
                      /* N2 — количество цифр 
                        в строке S2*/ 
              N=N2+M. /* Количество  цифр во всей 
                       строке больше на единицу, 
                       чем количество цифр 
                       в хвосте, если первый символ 
                       строки — цифра, и равно 
                       количеству цифр в хвосте — 
                       иначе */
< Лекция 10 || Лекция 11: 1234 || Лекция 12 >
Виктор Бондарь
Виктор Бондарь

После приведения формулы вида ПНФ к виду ССФ вы получаете формулу, в безквантовой матрице которой дизъюнкт содержит оба контранрных атома:. Как тогда проводить его унификацию, если в случае замены x на f(x) весь дизъюнкт обратится в единицу?

Ольга Потапенко
Ольга Потапенко

никак не могу увидеть тексты самих лекций.