2014-11-04 4 views
-1

Я пытаюсь добавить число к каждому элементу в списке и подсписок. Список также содержит дерево (функтор не может быть числовым, только листья могут быть числовыми).Добавить число для каждого элемента в списке

% Checking if element in a list is a tree 
istree(H) :- istree(_,F). 
istree(_,F) :- isforest(F). 
isforest([]). 
isforest([T|Ts]) :- istree(T), isforest(Ts). 

Когда я пытаюсь выполнить запрос, он терпит неудачу. Любая помощь будет оценена по достоинству.

+3

Там опечатка в пункте 'istree (H): - istree (_, F) .'. Система Prolog, вероятно, напечатала предупреждение об одноэлементных переменных в этом разделе. –

+0

Я тестировал этот фрагмент кода и отлично работает. Он показывает true, если данный термин является многодорожечным деревом. Можете ли вы сказать мне, где еще я могу ошибиться. – abc

+0

Конечно, это правда! Вы вызываете предикат 'istree/2' с переменной во втором аргументе, что означает вызов' isforest/1' с переменным аргументом. –

ответ

1

Ваша проблема утверждение

Я пытаюсь добавить номер к каждому элементу в списке и подсписков. Список также содержит дерево (функтор не может быть числовым, только листья могут быть числовыми).

Вы не указали как представлены ваши «деревья». Однако это довольно простая проблема обхода. Вы можете сделать что-то очень общее, так, что будет принимать любой произвольный пролог срока и увеличиваете все числа, найденные в:

increment(X , Y , Z) :- number(X) , ! , Z is X+Y) . 
increment(X , Y , Z) :- var(X)  , ! , Z = X . 
increment(X , Y , Z) :- atomic(X) , ! . Z = X . % atomic terms, including the empty list, remain unchanged. 
increment(X , Y , Z) :- compound(X) , ! ,   % otherwise, we have a compound term, including a non-empty list... 
    X =.. [Functor|Args] ,       % - decompose the compound term into its functor and argument list 
    increment(Args,Y,Args1) ,       % - increment the argument list 
    Z =.. [Functor|Args1] ,       % - assemble the new, incremented compound term 
    .             % Easy! 

Вам не нужны в явной форме тестов для списков, как пустой список только атом '[]' и непустой список [Head|Tail] является просто синтаксическим сахаром для прологового термина '.'(Head,Tail), при этом соглашение состоит в том, что Tail является либо пустым списком ([]), либо другим непустым списком.

Однако, вы можете хотите явный тест для списков, поскольку я подозреваю, что многие (большинство?) Прологи имеют специальные реализации списков, чтобы повысить производительность.

Если вы хотите ограничить ваш increment/3 только списки, вы могли бы сделать что-то вроде этого, где increment/3 траверсы списка и применяете преобразование к каждому найденному элементу в пределах:

increment([]  , _ , [] ) :- 
increment([X|Xs] , Y , [Z|Zs]) :- 
    transform(X ,Y , Z ) , 
    increment(Xs ,Y , Zs) 
    . 

transform(X,Y,Z) :- var(X)  , ! , Z = X . 
transform(X,Y,Z) :- number(X) , ! , Z is X+Y . 
transform(X,Y,Z) :- is_list(X) , ! , increment(X,Y,Z) . 
transform(X,Y,Z) :- atomic(X) , ! , Z = Z . 
transform(X,Y,Z) :- compound(X) , ! , 
    X =.. [F|As] ,  % - decompose the compound term into its functor and list of arguments 
    increment(As,Y,A1) , % - increment the argument list 
    Z =.. [F|A1]   % - assemble the incremented compount term 
    .     % Easy! 

is_list/1 является встроенным предикат для SWI Prolog. Если у вашего пролога нет его, тривиально сворачивать самостоятельно. Вот две реализации.

Это исчерпывающий тест на список. Он проверяет полное рекурсивное определение списка: список представляет собой либо атом [], либо непустой список [H|T], где T сам является списком. Это реализация используется SWI Prolog:

is_list( X ) :- var(X) , ! , fail . % variables are not lists 
is_list( [] ) .      % the empty list 
is_list([_|T]) :- is_list(T) .  % a non-empty list has a tail that is itself a list 

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

is_list( X ) :- var(X) , ! , fail . % variables are not lists 
is_list( [] ) .      % the empty list 
is_list( [_|_]) .      % a non-empty list 
1

Мне нравится идея взаимной рекурсии между istree/1 и isforest/1. Если вы хотите обеспечить соблюдение прав собственности, вы, вероятно, захотите получить такой код:

istree([]). 
istree([H|T]) :- 
    (number(H) ; istree(H)), 
    istree(T). 

Здесь нет взаимной рекурсии.

Ваш istree/1/istree/2 код довольно широкий. Я бы не стал так беспокоиться об этих двух статьях, кроме того, что вы указали @PauloMoura, что вы думаете, что код «отлично работает», когда на самом деле он ничего не будет делать. Он будет принимать что угодно, не производя никаких привязок. Сообщения об ошибках из Пролога об одноэлементных переменных должны приниматься как ужасные, критические ошибки, которые должны быть адресованы должно быть. Попробуйте следовать логике с помощью предиката istree/1. Между H и F нет никакой связи. Пролог скажет yes, потому что istree(_,F) удается позвонить по телефону isforest(F), а затем привязать F = [], но это отбрасывается обратно в istree/1, потому что нет никакой связи между H и F. Подумайте. Ни в коем случае он не «отлично работает» - он ничего не делает. Вы можете заменить его true.

Ваш isforest/1 выглядит довольно хорошо, он просто предполагает, что есть законный istree/1 для звонка. Если бы я хотел, чтобы вписываться в взаимную теме рекурсии, я мог бы попробовать это:

istree(E) :- number(E). 
istree([H|T]) :- isforest([H|T]). 

Ничего из этого не получает вас очень близко к добавлению числа к каждому элементу списка и подспискам, которые вы упоминаете это ВАШЕ задача. Я предполагаю, что вы имеете в виду это арифметически, так что, например, addToTree([1,[2],3], 3, [4,[5],6]) объединит. Для этого я хотел бы сделать это:

% base case: empty list 
addToTree([], _, []). 

% case 1: head is a number 
addToTree([H|T], N, [HN|Rest]) :- 
    number(H), 
    HN is H+N, 
    addToTree(T, N, Rest). 

% case 2: head is a list 
addToTree([H|T], N, [NH|Rest]) :- 
    is_list(H), 
    addToTree(H, N, NH), 
    addToTree(T, N, Rest). 
Смежные вопросы