В этой лекции мы займемся изучением
Знакомство со спецификой обработки
Начнем со встроенного предиката str_len, который предназначен для определения
Первый, наиболее естественный вариант использования этого предиката, когда первый аргумент связан, а второй свободен. В этом случае во второй аргумент будет помещено количество символов в первом аргументе.
Второй, также ожидаемый для стандартного "прологовского" предиката вариант использования этого предиката, когда оба аргумента связаны. В этом случае предикат будет успешен, если
И, наконец, третий, не столь распространенный вариант использования, в случае, когда второй аргумент связан, а первый — свободен. В этой ситуации первый аргумент будет означен
Следующий стандартный предикат concat предназначен, вообще говоря, для соединения двух
Первый вариант, когда связаны первые два аргумента. В этом случае третий аргумент будет означен
Второй вариант, когда связанными оказались первый и третий аргументы. В этой ситуации второй аргумент будет означен
Третий вариант аналогичен второму, за исключением того, что связанными аргументами оказываются второй и третий, а свободным — первый. В этом случае, естественно, первый аргумент будет означен
И, наконец, четвертый вариант возникает, когда все три аргумента означены. Предикат будет успешен, если при соединении первого аргумента со вторым получится третий аргумент, и неуспешен — в противном случае.
Следующие три встроенных предиката предназначены для "разделки"
Предикат frontchar служит для разделения исходной
Первый вариант, когда первый аргумент связан, а второй и третий — свободны. В этом случае второй аргумент будет означен первым символом
Второй, также часто используемый вариант этого предиката, когда наоборот, первый аргумент свободен, а второй и третий — связаны. В этом случае в первый аргумент попадет
Третий вариант получается, когда первый и второй аргументы означены, а третий нет. В этой ситуации в третий аргумент будут переписаны все символы первого аргумента, начиная со второго, в случае, если первый символ первого аргумента совпадает со вторым аргументом. В противном случае предикат терпит неудачу.
Четвертый вариант похож на третий, но свободен второй аргумент, а связаны — первый и третий. В этом случае второй аргумент означивается первым символом первого аргумента, если оставшиеся символы первого аргумента образуют в точности третий аргумент. Иначе предикат будет неуспешен.
И, наконец, пятый вариант использования этого предиката возникает, когда все три его аргументы означены. В этом случае он будет истинен, если
Предикат frontstr обобщает предикат frontchar в том смысле, что он тоже позволяет "откусить" от данной
Если количество символов, указанных в первом параметре предиката frontstr, превышает
И, наконец, предикат fronttoken также дробит исходную
Первый вариант, когда первый аргумент связан, а второй и третий — свободны. В этом случае второй аргумент будет означен первым атомом
Второй вариант использования этого предиката — когда, наоборот, первый аргумент свободен, а второй и третий — связаны. В таком случае этот предикат работает точно так же, как и
Третий вариант получается, когда первый и второй аргументы означены, а третий нет. В этой ситуации в третий аргумент будут переписаны все символы первого аргумента, остающиеся после удаления первого атома, в случае, если первый атом первого аргумента совпадает со вторым аргументом. В противном случае предикат терпит неудачу.
Четвертый вариант подобен третьему, но свободен второй аргумент, а связаны первый и третий. В этом случае второй аргумент означивается первым атомом первого аргумента, если оставшиеся символы первого аргумента совпадают со
И, наконец, пятый вариант использования этого предиката возникает, когда все три его аргументы означены. В этом случае он будет истинным, если
Для полноты картины следует еще упомянуть о предикате isname, который истинен, если его строковый аргумент является идентификатором, и ложен в противном случае.
Пример. Теперь попробуем применить рассмотренные предикаты. Создадим предикат, который будет преобразовывать
Решение, как всегда, будет рекурсивным. Базис: пустой frontchar разобьем
Запишем эту идею:
str_list("",[]). /* пустой строке соответствует
пустой список */
str_list(S,[H|T]):–
frontchar(S,H,S1),
/* H — первый символ строки S,
S1 — остаток строки */
str_list(S1,T).
/* T — список, состоящий
из символов, входящих
в строку S1*/
Пример. Теперь попробуем немного модифицировать описанный предикат так, чтобы он преобразовывал
Отличаться предыдущее решение будет заменой предиката frontchar на предикат fronttoken. Да еще надо не забыть в разделе описания предикатов заменить домен второго параметра со списка символов на список
Запишем эту идею:
str_a_list("",[]). /* пустой строке по-прежнему
соответствует пустой список */
str_a_list(S,[H|T]):–
fronttoken(S,H,S1),
/* H — первый атом строки S,
S1 — остаток строки */
str_a_list(S1,T).
/* T — список, состоящий
из атомов, входящих
в строку S1*/
Кстати, этот же предикат можно задействовать для создания списка слов, входящих в
Пример. Разработаем предикат, который будет преобразовывать список символов в
Базис рекурсии: пустому списку соответствует пустая frontchar, приписывать к первому элементу списка
Запишем эту идею:
list_str([],""). /* пустой строке соответствует
пустой список */
list_str([H|T],S):–
list_str(T,S1),
/* S1 — строка, образованная
элементами списка T */
frontchar(S,H,S1).
/* S — строка, полученная
дописыванием строки S1
к первому элементу списка H */
Пример. Создадим предикат, который по
Решение, как обычно, будет рекурсивным. Рекурсия по frontchar.
char_count("",_,0). /* Любой символ не встречается
в пустой строке ни разу*/
char_count(S,C,N):–
frontchar(S,C,S1),!,
/* символ C оказался первым символом
строки S, в S1 — оставшиеся
символы строки S */
char_count(S1,C,N1),
/* N1 — количество вхождений
символа C в строку S1 */
N=N1+1.
/* N — количество вхождений
символа C в строку S получается
из количества вхождений символа C
в строку S1 добавлением единицы */
char_count(S,C,N):–
frontchar(S,_,S1),
/* первым символом строки S
оказался символ, отличный
от исходного символа C, в S1 —
оставшиеся символы строки S */
char_count(S1,C,N).
/* в этом случае количество
вхождений символа C в строку S
совпадает с количеством
вхождений символа C
в строку S1 */
Пример. Попробуем разработать предикат, который по символу и
Не самая легкая задачка, но мы с ней справимся. Можно, конечно, записать в качестве базиса, что в пустой
Вначале с помощью предиката frontchar разделим исходную
В противном случае, если первым символом исходной
Давайте попробуем записать эти рассуждения.
str_pos(C,S,1):–
frontchar(S,C,_),!.
/* Искомый символ C оказался первым
символом данной строки S */
str_pos(C,S,N) :–
frontchar(S,_,S1),
/* S1 — состоит из всех символов
строки S, кроме первого, который
отличается от искомого символа C */
str_pos(C,S1,N1),
/* N1 — это позиция, в которой
символ C встречается первый раз
в хвосте S1 или ноль*/
N1<>0,!, /* если позиция вхождения
символа C в строку S1 не равна
нулю, то есть если он встречается
в строке S1, /
N=N1+1. /* то, увеличив позицию его
вхождения на единицу, мы получим
позицию его вхождения в исходную
строку */
str_pos(_,_,0). /* искомый символ не входит в данную
строку */
Пример. Создадим предикат, который будет заменять в
Решение, как обычно, будет рекурсивным. Если frontchar на первый символ и
Возможны два варианта. Либо первый символ исходной
В первом случае заменим все вхождения первого символа вторым символом в хвосте исходной frontchar, приклеим полученную
Во втором случае, когда первый символ исходной
str_replace("",_,_,""):–!. /* из пустой строки можно
получить только пустую
строку */
str_replace(S,C,C1,SO):–
frontchar(S,C,S1),!,
/* заменяемый символ C оказался
первым символом строки S,
S1 — остаток строки S */
str_replace(S1,C,C1,S2),
/* S2 — результат замены
в строке S1 всех вхождений
символа C на символ C1 */
frontchar(SO,C1,S2).
/* SO — результат склейки
символа C1 и строки S2 */
str_replace(S,C,C1,SO):–
frontchar(S,C2,S1),
/* разделяем исходную строку S
на первый символ C2
и строку S2, образованную
всеми символами строки S,
кроме первого */
str_replace(S1,C,C1,S2),
/* S2 — результат замены
в строке S1 всех вхождений
символа C на символ C1 */
frontchar(SO,C1,S2).
/* SO — результат соединения
символа C1 и строки S2 */
Если нам понадобится предикат, который будет заменять не все вхождения первого символа на второй, а только первое вхождение первого символа, то нужно просто из первого правила удалить вызов предиката .
Пример. Разработаем предикат, который будет удалять часть
Запишем решение этой задачи. Начнем с того, что при помощи стандартного предиката 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. Сначала получим хвост нашей
Зафиксируем наши рассуждения.
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. /* Количество цифр во всей
строке больше на единицу,
чем количество цифр
в хвосте, если первый символ
строки — цифра, и равно
количеству цифр в хвосте —
иначе */
В этой лекции мы займемся изучением
Знакомство со спецификой обработки
Начнем со встроенного предиката str_len, который предназначен для определения
Первый, наиболее естественный вариант использования этого предиката, когда первый аргумент связан, а второй свободен. В этом случае во второй аргумент будет помещено количество символов в первом аргументе.
Второй, также ожидаемый для стандартного "прологовского" предиката вариант использования этого предиката, когда оба аргумента связаны. В этом случае предикат будет успешен, если
И, наконец, третий, не столь распространенный вариант использования, в случае, когда второй аргумент связан, а первый — свободен. В этой ситуации первый аргумент будет означен
Следующий стандартный предикат concat предназначен, вообще говоря, для соединения двух
Первый вариант, когда связаны первые два аргумента. В этом случае третий аргумент будет означен
Второй вариант, когда связанными оказались первый и третий аргументы. В этой ситуации второй аргумент будет означен
Третий вариант аналогичен второму, за исключением того, что связанными аргументами оказываются второй и третий, а свободным — первый. В этом случае, естественно, первый аргумент будет означен
И, наконец, четвертый вариант возникает, когда все три аргумента означены. Предикат будет успешен, если при соединении первого аргумента со вторым получится третий аргумент, и неуспешен — в противном случае.
Следующие три встроенных предиката предназначены для "разделки"
Предикат frontchar служит для разделения исходной
Первый вариант, когда первый аргумент связан, а второй и третий — свободны. В этом случае второй аргумент будет означен первым символом
Второй, также часто используемый вариант этого предиката, когда наоборот, первый аргумент свободен, а второй и третий — связаны. В этом случае в первый аргумент попадет
Третий вариант получается, когда первый и второй аргументы означены, а третий нет. В этой ситуации в третий аргумент будут переписаны все символы первого аргумента, начиная со второго, в случае, если первый символ первого аргумента совпадает со вторым аргументом. В противном случае предикат терпит неудачу.
Четвертый вариант похож на третий, но свободен второй аргумент, а связаны — первый и третий. В этом случае второй аргумент означивается первым символом первого аргумента, если оставшиеся символы первого аргумента образуют в точности третий аргумент. Иначе предикат будет неуспешен.
И, наконец, пятый вариант использования этого предиката возникает, когда все три его аргументы означены. В этом случае он будет истинен, если
Предикат frontstr обобщает предикат frontchar в том смысле, что он тоже позволяет "откусить" от данной
Если количество символов, указанных в первом параметре предиката frontstr, превышает
И, наконец, предикат fronttoken также дробит исходную
Первый вариант, когда первый аргумент связан, а второй и третий — свободны. В этом случае второй аргумент будет означен первым атомом
Второй вариант использования этого предиката — когда, наоборот, первый аргумент свободен, а второй и третий — связаны. В таком случае этот предикат работает точно так же, как и
Третий вариант получается, когда первый и второй аргументы означены, а третий нет. В этой ситуации в третий аргумент будут переписаны все символы первого аргумента, остающиеся после удаления первого атома, в случае, если первый атом первого аргумента совпадает со вторым аргументом. В противном случае предикат терпит неудачу.
Четвертый вариант подобен третьему, но свободен второй аргумент, а связаны первый и третий. В этом случае второй аргумент означивается первым атомом первого аргумента, если оставшиеся символы первого аргумента совпадают со
И, наконец, пятый вариант использования этого предиката возникает, когда все три его аргументы означены. В этом случае он будет истинным, если
Для полноты картины следует еще упомянуть о предикате isname, который истинен, если его строковый аргумент является идентификатором, и ложен в противном случае.
Пример. Теперь попробуем применить рассмотренные предикаты. Создадим предикат, который будет преобразовывать
Решение, как всегда, будет рекурсивным. Базис: пустой frontchar разобьем
Запишем эту идею:
str_list("",[]). /* пустой строке соответствует
пустой список */
str_list(S,[H|T]):–
frontchar(S,H,S1),
/* H — первый символ строки S,
S1 — остаток строки */
str_list(S1,T).
/* T — список, состоящий
из символов, входящих
в строку S1*/
Пример. Теперь попробуем немного модифицировать описанный предикат так, чтобы он преобразовывал
Отличаться предыдущее решение будет заменой предиката frontchar на предикат fronttoken. Да еще надо не забыть в разделе описания предикатов заменить домен второго параметра со списка символов на список
Запишем эту идею:
str_a_list("",[]). /* пустой строке по-прежнему
соответствует пустой список */
str_a_list(S,[H|T]):–
fronttoken(S,H,S1),
/* H — первый атом строки S,
S1 — остаток строки */
str_a_list(S1,T).
/* T — список, состоящий
из атомов, входящих
в строку S1*/
Кстати, этот же предикат можно задействовать для создания списка слов, входящих в
Пример. Разработаем предикат, который будет преобразовывать список символов в
Базис рекурсии: пустому списку соответствует пустая frontchar, приписывать к первому элементу списка
Запишем эту идею:
list_str([],""). /* пустой строке соответствует
пустой список */
list_str([H|T],S):–
list_str(T,S1),
/* S1 — строка, образованная
элементами списка T */
frontchar(S,H,S1).
/* S — строка, полученная
дописыванием строки S1
к первому элементу списка H */
Пример. Создадим предикат, который по
Решение, как обычно, будет рекурсивным. Рекурсия по frontchar.
char_count("",_,0). /* Любой символ не встречается
в пустой строке ни разу*/
char_count(S,C,N):–
frontchar(S,C,S1),!,
/* символ C оказался первым символом
строки S, в S1 — оставшиеся
символы строки S */
char_count(S1,C,N1),
/* N1 — количество вхождений
символа C в строку S1 */
N=N1+1.
/* N — количество вхождений
символа C в строку S получается
из количества вхождений символа C
в строку S1 добавлением единицы */
char_count(S,C,N):–
frontchar(S,_,S1),
/* первым символом строки S
оказался символ, отличный
от исходного символа C, в S1 —
оставшиеся символы строки S */
char_count(S1,C,N).
/* в этом случае количество
вхождений символа C в строку S
совпадает с количеством
вхождений символа C
в строку S1 */
Пример. Попробуем разработать предикат, который по символу и
Не самая легкая задачка, но мы с ней справимся. Можно, конечно, записать в качестве базиса, что в пустой
Вначале с помощью предиката frontchar разделим исходную
В противном случае, если первым символом исходной
Давайте попробуем записать эти рассуждения.
str_pos(C,S,1):–
frontchar(S,C,_),!.
/* Искомый символ C оказался первым
символом данной строки S */
str_pos(C,S,N) :–
frontchar(S,_,S1),
/* S1 — состоит из всех символов
строки S, кроме первого, который
отличается от искомого символа C */
str_pos(C,S1,N1),
/* N1 — это позиция, в которой
символ C встречается первый раз
в хвосте S1 или ноль*/
N1<>0,!, /* если позиция вхождения
символа C в строку S1 не равна
нулю, то есть если он встречается
в строке S1, /
N=N1+1. /* то, увеличив позицию его
вхождения на единицу, мы получим
позицию его вхождения в исходную
строку */
str_pos(_,_,0). /* искомый символ не входит в данную
строку */
Пример. Создадим предикат, который будет заменять в
Решение, как обычно, будет рекурсивным. Если frontchar на первый символ и
Возможны два варианта. Либо первый символ исходной
В первом случае заменим все вхождения первого символа вторым символом в хвосте исходной frontchar, приклеим полученную
Во втором случае, когда первый символ исходной
str_replace("",_,_,""):–!. /* из пустой строки можно
получить только пустую
строку */
str_replace(S,C,C1,SO):–
frontchar(S,C,S1),!,
/* заменяемый символ C оказался
первым символом строки S,
S1 — остаток строки S */
str_replace(S1,C,C1,S2),
/* S2 — результат замены
в строке S1 всех вхождений
символа C на символ C1 */
frontchar(SO,C1,S2).
/* SO — результат склейки
символа C1 и строки S2 */
str_replace(S,C,C1,SO):–
frontchar(S,C2,S1),
/* разделяем исходную строку S
на первый символ C2
и строку S2, образованную
всеми символами строки S,
кроме первого */
str_replace(S1,C,C1,S2),
/* S2 — результат замены
в строке S1 всех вхождений
символа C на символ C1 */
frontchar(SO,C1,S2).
/* SO — результат соединения
символа C1 и строки S2 */
Если нам понадобится предикат, который будет заменять не все вхождения первого символа на второй, а только первое вхождение первого символа, то нужно просто из первого правила удалить вызов предиката .
Пример. Разработаем предикат, который будет удалять часть
Запишем решение этой задачи. Начнем с того, что при помощи стандартного предиката 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. Сначала получим хвост нашей
Зафиксируем наши рассуждения.
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. /* Количество цифр во всей
строке больше на единицу,
чем количество цифр
в хвосте, если первый символ
строки — цифра, и равно
количеству цифр в хвосте —
иначе */
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.