Глава 3

3. 1 (a) конк( L1, [ _, _, _ ], L)
(b)    конк( [ _, _, _ ], L1, L),
                        % Удалить 3 первые элемента L
        конк( L2, [ _, _, _ ], L1)
                        % Удалить 3 последние элемента L1
Вот более короткий вариант, предложенный I. Tvrdy:       
        конк( [ _, _, _ | L2], [ _, _, _ ], L)

3. 2 (а)    последний( Элемент, Список) :-
        конк( _, [Элемент], Список).

(b)    последний( Элемент, [Элемент]).
        последиий( Элемент, [Первый | Остальные]):-
        последний( Элемент, Остальные).

3. 3 четнаядлина( [ ] ).
четнаядлина( [Первый | Остальные] ) :-
    нечетнаядлина( Остальные).
нечетнаядлина( [ _ ] ).
нечетнаядлина( [Первый | Остальные] ) :-
    четнаядлина( Остальные).

3. 4 обращение( [ ], [ ]).
обращение( [Первый | Остальные], ОбращСпис): -
    обращение( Остальные, ОбращСписОстальных),
конк( О6ращСписОстальных, [Первый], ОбращСпис).

3. 5 % Такой предикат легко определить при помощи отношения обратить
палиндром( Список) :-
    обратить( Список, Список).
% Вот другое решение, не использующее обратить
палиндром1( [ ] ).
палиндром1( [ _ ] ).


палиндром1 [Первый | Остальные] ) :-
    конк( Середина, [Первый], Остальные),
    палиндром1( Середина).

3. 6 сдвиг( [Первый | Остальные], Сдвинут) :-
    конк( Остальные, [Первый], Сдвинут).

3. 7 перевод( [ ], [ ]).
перевод( [Голова | Хвост], [Голова1 | Хвост1]) :-
    означает( Голова, Голова1),
    перевод( Хвост, Хвост1).

3. 8 подмножество( [ ], [ ] ).
подмножество( [Первый | Остальные], [Первый | Подмн]):-
                                % Оставить первый элемент в подмножестве
    подмножество( Остальные, Подмн).
подмножество( [Первый | Остальные], Подмн) :-
                                % Убрать первый элемент из подмножества
    подмножество( Остальные, Подмн).

3. 9 разбиениесписка( [ ], [ ], [ ]).                           % Разбивать нечего
разбиениесписка( [X], [X], [ ]).
                            % Разбиение одноэлементного списка
разбиениесписка( [X, Y | Список], [Х | Список1],
                                [Y | Список2]) :-
    разбиениесписка( Список, Список1, Список2).

3. 10 можетзавладеть( состояние( _, _, _, имеет), [ ] ).
                                % Ничего не надо делать
можетзавладеть( Состояние, [Действие | Действия]):-
    ход( Состояние, Действие, НовоеСостояние),
                                % Первое действие
    можетзавладеть( НовоеСостояние, Действия).
                                % Оставшиеся действия

3. 11 линеаризация( [Голова | Хвост], ЛинейныйСписок ) :-
                                % Линеаризация непустого списка
    линеаризация( Голова, ЛинейнаяГолова ),
    линеаризация( Хвост, ЛинейныйХвост ),
    конк( ЛинейнаяГолова, ЛинейныйХвост,
        ЛинейныйСписок ).
линеаризация( [ ], [ ] ).                  % Линеаризация пустого списка
линеаризация( X, [X] ).
                            % Линеаризация объекта, не являющегося списком
% Замечание: при попытке получить от этой программы более
% одного варианта решения выдается бессмыслица

3. 12 Терм1 = играет_в( джимми, и( футбол, сквош) )
Терм2 = играет_в( сьюзан, и( теннис,
                                    и( баскетбол, волейбол) ) )

3. 13 :- ор( 300, xfx, работает)
:- ор( 200, xfx, в)
:- ор( 100, xfx, нашем)

3. 14 (a)    А = 1 + 0
(b)    В = 1 + 1 + 0
(c)    С = 1 + 1 + 1 + 1 + 0
(d)    D = 1 + 1 + 0 + 1

3. 15 :- ор( 100, xfx, входит_в)
:- ор( 300, fx, конкатенация_списков)
:- ор( 200, xfx, дает)
:- ор( 100, xfx, и)
:- ор( 300, fx, удаление_элемента)
:- ор( 100, xfx, из_списка)                         % Принадлежность к списку
Элемент входит_в [Элемент | Список].
Элемент входит_в [Первый | СписокОстальных] :-
Элемент входит_в СписокОстальных.
% Конкатенация списков
конкатенация_списков [ ] и Список дает Список.
конкатенация_списков [X | L1] и L2 дает [X | L3] :-
    конкатенация_списков L1 и L2 дает L3.
% Удаление элемента из списка
удаление_элемента Элемент иэ_списка
            [Элемент | ОстальныеЭлементы]
            дает ОстальныеЭлементы.
удаление_элемента Элемент из_списка
        [Первый | ОстальныеЭлементы]
        дает [Первый | НовСписОстЭлементов] :-
    удаление_элемента Элемент из_списка
            ОстальныеЭлементы дает НовСписОстЭлементов.

3. 16 max( X, Y, X) :-
    X >= Y.
max( X, Y, Y) :-
    X <Y.

3. 17 максспис( [X], X).
                            % Максимум в одноэлементном списке
максспис( [X, Y | Остальные], Мах) :-
                            % В списке есть по крайней мере два элемента?
    максспис( [Y | Остальные], МаксОстальные),
    mах( X, МаксОстальные, Мах).
                            % Мах наибольшее из чисел X и МаксОстальные

3. 18 сумспис( [ ], 0).
сумспис( [Первый | Остальные], Сумма) :-
    сумспис( Остальные, СуммаОстальных),
    Сумма is Первый + СуммаОстальных.

3. 19 упорядоченный ([ ]).
                        % Одноэлементный список является упорядоченным
упорядоченный( [X, Y | Остальные] :-
    X =< Y,
    упорядоченный( [Y | Остальные] ).

3. 20 подсумма( [ ], 0, [ ]).
подсумма( [N | Список], Сумма, [N | Подмн]) :-
                    % N принадлежит подмножеству
    Сумма1 is Сумма - N,
    подсумма( Список, Сумма1, Подмн).
подсумма( [N | Список], Сумма, Подмн) :-
                    % N не принадлежит подмножеству
    подсумма( Список, Сумма, Подмн).

3. 21 между( N1, N2, N1) :-
    N1 =< N2.
между( N1, N2, X) :-
    N1 < N2,
    HoвoeNl is N1 + 1,
    между( HoвoeNl, N2, X).

3. 22 :- ор( 900, fx, если).
:- ор( 800, xfx, то).
:- ор( 700, xfx, иначе).
:- ор( 600, xfx, :=).
если Вел1 > Вел2 то Перем := Вел3
                                иначе ЧтоУгодно :-
    Вел1 > Вел2,
    Перем = Вел3.
если Вел1 > Вел2 то ЧтоУгодно
                                иначе Перем := Вел4 :-
    Вел1 =< Вел2,
    Перем = Вел4.