Опубликован: 12.02.2014 | Доступ: свободный | Студентов: 922 / 239 | Длительность: 11:22:00
Специальности: Программист
Лекция 6:

Списки. Полиморфизм

< Лекция 5 || Лекция 6: 123 || Лекция 7 >

Упражнение 2. Определите предикаты, которые возвращают:

  1. каждый второй элемент списка;
  2. только второй элемент списка;
  3. элементы списка целых чисел, делящиеся на 3 без остатка.

В классе list, который входит в набор Prolog Foundation Classes (PFC) основных классов языка Visual Prolog имеется предикат проверки принадлежности элемента списку isMember/2 и предикат getMember_nd/1, недетерминированно возвращающий элементы списка и определенный в виде функции. В версии 7.5 языка Visual Prolog появился оператор in, который можно использовать для выполнения обеих данных операций. Например:

if 2 in [1, 2, 3] then write("2 принадлежит списку")
 else write("2 не принадлежит списку") end if, nl, nl,
        
 foreach X in [1, 2, 3] do write(X), nl end foreach.

Следующая программа посвящена предикату append, определение которого позволяет использовать его большим количеством способов, в частности:

  1. для соединения списков;
  2. для определения префикса (начального отрезка списка), который нужно присоединить к заданному суффиксу (конечному отрезку списка), чтобы получить заданный список;
  3. для определения суффикса, который нужно присоединить к заданному префиксу, чтобы получить заданный список;
  4. для поиска всех возможных разбиений на префиксы и суффиксы;
  5. для многого другого.
class predicates
    append: (A*, A*, A*) nondeterm anyflow.
    append: (A*, A*) -> A*.
clauses
    append([], L, L).    % разнообразное использование
    append([H | L1], L2, [H | L]):-
        append(L1, L2, L).

    append([], L) = L.    % соединение двух списков в один
    append([H | L1], L2) = [H | append(L1, L2)].

    run():-
        append([1, 2], [2, 3], L0),
        write(L0), nl,
        write(append([1, 2], [2, 3])), nl,

        L = [1, 2, 3, 4, 5],
        append(L1, [4, 5], L),
        write(L1), nl,
        append([1, 2, 3], L2, L),
        write(L2), nl, nl,
        append(P, S, L),
            writef("% - %\n", P, S),
        fail;

        L = [1, 2, 3, 4, 5, 6, 7],
        append(_, [X, _, _], L),
        writef("\nТретий с конца элемент списка - %", X),
        append([_, _, Y], _, L),
        writef("\nТретий с начала элемент списка - %", Y),
        fail;
        _ = readLine().
Пример 6.3. Соединение списков

Упражнение 3. Найдите с помощью предиката append:

  1. последний элемент списка;
  2. префиксы списка;
  3. суффиксы списка;
  4. список без двух последних элементов исходного списка.

В классе list определены предикаты append, которые могут иметь от двух до пяти аргументов, выполняющие операцию соединения списков. Кроме этого, имеется предикат appendList/1, который соединяет список списков элементов в один список.

В приведенной ниже программе непосредственно генерируются подсписки списка — префиксы, суффиксы и все подсписки.

class predicates
    prefix: (A*) -> A* multi.
    suffix: (A*) -> A* multi.
    sublist: (A*) -> A* nondeterm.
clauses
    prefix(_) = [].        % префикс списка
    prefix([H | T]) = [H | prefix(T)].

    suffix(L) = L.        % суффикс списка
    suffix([_| T]) = suffix(T).

    sublist([]) = [].        % подсписок списка
    sublist(L) = S:-
        S = prefix(L),
        S <> [].
    sublist([_ | L]) = sublist(L).

    run():-
        write(prefix([1, 2, 3, 4])), nl,
        fail;
        nl, write(suffix([1, 2, 3, 4])), nl,
        fail;
        nl, write(sublist([1, 2, 3, 4])), nl,
        fail;
        _ = readLine().
Пример 6.4. Подсписки списка

Упражнение 4.

  1. Сгенерируйте подсписки списка четной длины, не используя предикат вычисления длины списка.
  2. Определите детерминированный предикат, который по двум входным спискам определяет, является ли первый из них подсписком второго списка.

В приведенной ниже программе реализованы операция замены одного элемента списка другим, а также операция замены каждого n-го элемента списка заданным элементом. В определении второго предиката используется счетчик.

class predicates
    replace: (A*, A What, A With) -> A*.
    replace_nth: (A*, positive N, A With) -> A*.
    replace_nth: (A*, positive Counter, positive N, A With) -> A*.
clauses
    replace([A | T], A, B) = [B | replace(T, A, B)]:- !.
    replace([H | T], A, B) = [H | replace(T, A, B)].
    replace([], _, _) = [].

    replace_nth(L, N, A) = replace_nth(L, N, N, A):-
        N > 1,
        !.
    replace_nth(L, _, _) = L.

    replace_nth([_ | L], 1, N, A) = [A | replace_nth(L, N, N, A)]:- !.
    replace_nth([H | L], C, N, A) = [H | replace_nth(L, C - 1, N, A)].
    replace_nth([], _, _, _) = [].

    run():-
        L = [math::random(10) || _ = std::fromTo(1, 20)],
        write(L), nl,
        write(replace(L, 0, 100)), nl,
        write(replace_nth(L, 6, 333)), nl,
        _ = readLine().
Пример 6.5. Замена элементов списка

Предикат fromTo (см. определение предиката run) недетерминированно возвращает целые числа в заданных пределах. Например, цель

X = fromTo(1, 3)

имеет следующие решения:

X = 1
X = 2
X = 3
< Лекция 5 || Лекция 6: 123 || Лекция 7 >
Жаныл Айкын
Жаныл Айкын
Rustam Inatov
Rustam Inatov

Доброго времени суток, подскажите пожалуйста, visual prolog examples, pie, vip7.5 - это все, где я могу скачать? (в смысле) может быть на сайте есть какой-то архив? Увы я не нашел его.

Подскажите, пожалуйста.

С уважением, Рустам.