проверка списка на prolog
От: fsssl_dm  
Дата: 18.03.07 16:51
Оценка:
Есть небольшое задание: написать предикат проверки списка. Список имеет следующий вид:
[a,a,a,a,…,a,b,…,b]

Предполагается использование Arity Prolog, но, наверное, это не имеет особого значения.

Я написал вот что (не работает):

check([H|T]):- identity(T,H).

identity([H|T],H):- identity(T, H).
identity([H|[HT|T]],HT):- identity_(T,HT).

identity_([], _).
identity_([H|T], H):- identity_(T, H).


P.S. Никак не могу забыть про императивный стиль программирования.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: проверка списка на prolog
От: palm mute  
Дата: 18.03.07 17:29
Оценка: 3 (1)
Здравствуйте, fsssl_dm, Вы писали:

_>Есть небольшое задание: написать предикат проверки списка. Список имеет следующий вид:

_>
_>[a,a,a,a,…,a,b,…,b]
_>

_>Предполагается использование Arity Prolog, но, наверное, это не имеет особого значения.

Честно говоря, не совсем понятно, что нужно сделать, под вид [a,a,a,a,…,a,b,…,b] можно подогнать много ограничений (например, список заканчивается чередующейся последовательностью a,b,a,b,a,...). Если телепатия меня не подвела, и список должен начинаться с непустой последовательности элементов X любой длины, а заканчиваться непустой последовательностью элементов Y любой длины, причем X<>Y, то можно так (работает на SWI-Prolog. DISCLAIMER: на Прологе и пишу крайне редко и не более 10 строчек, код предоставлен AS IS):
many(X, [], []) :- nonvar(X).
many(X, [Y|Ys], [Y|Ys]) :- nonvar(X), not(X=Y).
many(X, [X|Xs], Ys) :- many(X, Xs, Ys).


check(Xs) :- many(X, Xs, Ys), many(Y, Ys, []), not(X=Y).


_>P.S. Никак не могу забыть про императивный стиль программирования.

Это просто, надо просто не думать о белой обезьяне
Re: проверка списка на prolog
От: oziro Нигерия  
Дата: 18.03.07 21:59
Оценка: 3 (1)
Здравствуйте, fsssl_dm, Вы писали:
_>Есть небольшое задание: написать предикат проверки списка. Список имеет следующий вид:

Я вот что придумал.
    % 1. пролетаем первую часть одинаковых букв
first(A, [A|T]) :- 
        first(A, T). 

    % 2. начинается вторая часть уже других одинаковых букв,
    % при этом А запоминается, что бы исключить [a,a,...,a]

first(A, [B|T]) :- 
        not(A=B),second(A, B, T).    

    % 3. пролетаем вторую часть            
second(A, B, [B|T]) :- 
        not(A=B),second(A, B, T).        

    % 4. конецц
second(A, B, []) :- 
        not(A=B).    

    % 0. процедура проверки списка на соотвесттвие шаблону
    %[a, a,... , a, b, b,... ,b]
check(L) :- 
        first(_,L).

Вроде работает. SWI-Prolog.

Т.к. пролог использую ооооочень редко, не могли бы знающие люди прокомментировать мой код. Например мне не очень нра вятся not(A=B), однако если это не поставить во 2 предложении — работает неправильно (на наборе [a,a,...,a]). А раз уж поставил в одном месте, то поставил и в остальных, где А != В
Re[2]: проверка списка на prolog
От: oziro Нигерия  
Дата: 18.03.07 22:05
Оценка:
ОписАлся.
O>...однако если это не поставить во 2 предложении ...
в 4 предложении!
Хотя если поменять местами 2 и 1 то и тут будет необходимость в A!=B, а ведь от перестановки предложений не должен меняться декларативный смысл программы, как я понимаю
Re[2]: проверка списка на prolog
От: Кодт Россия  
Дата: 19.03.07 13:57
Оценка: 4 (1)
Здравствуйте, oziro, Вы писали:

O>Здравствуйте, fsssl_dm, Вы писали:


Можно немножко упростить. second не нуждается в знании A.
А поскольку проверка на равенство уже выполнялась в первой кляузе ( ), то достаточно сделать отсечку вместо повторной проверки с not.
test([A|T]) :- first(A, T).

first(A, [A|T]) :- !, first(A, T).
first(A, [B|T]) :- second(B, T).

second(B, [B|T]) :- second(B, T).
second(B, []) .
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[2]: проверка списка на prolog
От: Аноним  
Дата: 19.03.07 14:14
Оценка: +1
Здравствуйте, oziro, Вы писали:

От большинства not можно избавиться. Код такой:
first(A, [A|T]) :- 
        first(A, T).

first(A, [B|T]) :- 
        second(A, B, T).    

second(A, B, [B|T]) :- 
        second(A, B, T).

second(A, B, []) :-
    not(A = B).

check(L) :- 
        first(_,L).
Re[3]: проверка списка на prolog
От: oziro Нигерия  
Дата: 19.03.07 14:15
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Можно немножко упростить. second не нуждается в знании A.

К>А поскольку проверка на равенство уже выполнялась в первой кляузе ( ), то достаточно сделать отсечку вместо повторной проверки с not.

Да, спасибо большое, никак я отсечкой не научусь нормально пользоваться, read only

С учетом пожеланий swi-prolog'a (варнинги на неиспользуемые переменные):
test([A|T]) :- first(A, T).

first(A, [A|T]) :- !, first(A, T).
first(_, [B|T]) :- second(B, T).

second(B, [B|T]) :- second(B, T).
second(_, []) .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.