Изменение количества параметров и унификация - PullRequest
0 голосов
/ 04 декабря 2018

У меня проблема с получением правильного вывода.Я получаю свой результат, как вы можете видеть в след.Но я не могу понять, горячо, чтобы остановить это в определенный момент.Он должен вычислить сказанное по формуле и просто записать результат в список и уменьшить значение D и повторять, что пока он не достигнет 0, а не выполнить 0.

t(R, L) :- t(R, R, L).

t(D, R, [Ti|L]) :- D >= 1, !,
                 Ti is D * ((D + 1) / 2),
                 D1 is D - 1,
                 t(D1, R, [Ti|L]).

, ввод равен t (2, L).

Call: (8) t(2, _1804) ? creep
Call: (9) t(2, 2, _1804) ? creep
Call: (10) 2>=1 ? creep
Exit: (10) 2>=1 ? creep
Call: (10) _2052 is 2*((2+1)/2) ? creep
Exit: (10) 3.0 is 2*((2+1)/2) ? creep
Call: (10) _2064 is 2+ -1 ? creep
Exit: (10) 1 is 2+ -1 ? creep
Call: (10) t(1, 2, [3.0|_1804]) ? creep
Call: (11) 1>=1 ? creep
Exit: (11) 1>=1 ? creep
Call: (11) _2088 is 1*((1+1)/2) ? creep
Exit: (11) 1 is 1*((1+1)/2) ? creep
Call: (11) _2094 is 1+ -1 ? creep
Exit: (11) 0 is 1+ -1 ? creep
Call: (11) t(0, 2, [1, 3.0|_1804]) ? creep
Call: (12) 0>=1 ? creep
Fail: (12) 0>=1 ? creep
**Fail: (11) t(0, 2, [1, 3.0|_1804]) ? creep**
Fail: (10) t(1, 2, [3.0|_1804]) ? creep
Fail: (9) t(2, 2, _1804) ? creep
Fail: (8) t(2, _1804) ? creep
false.

Выход должен быть L = [1,3] на основе этой формулы Ti равен D * ((D + 1) / 2) как есть на отмеченной линиив след, но это не так.Он должен остановиться, когда он достигает D = 0, но это не так.

Я попытался все это остановить, создав кейс для 0, но он не работает.

t(0, []) :- !.
t(0, _, _) :- !.
t(_, _, R, L) :- R < 1, !.

1 Ответ

0 голосов
/ 04 декабря 2018

Проблема в том, что вы никогда не говорили Прологу, что делать в случае D=0.Таким образом, Пролог продолжает уменьшать значение D до тех пор, пока D >= 1 больше не будет успешным, и это означает, что вы достигли точки " fail ".Затем Prolog начнет возврат, пока не найдет точку возврата, или здесь он размотает весь стек вызовов и сообщит об ошибке.

Даже если вам удастся реализовать условие остановки, это не достаточно, так как в вашем предикате вы используете [Ti|L] в качестве параметра и рекурсивно вызываете с [Ti|L].Это означает, что рекурсивный вызов будет стремиться установить элемент в списке, тот же элемент (!), И если значения будут другими, это снова приведет к ошибке.

Поскольку вы построили список справа налево, вы можете использовать аккумулятор, который начинается с пустого списка и каждый раз добавляет элемент к списку в рекурсивном вызове.Условие останова затем объединяет аккумулятор с результатом.

t(R, L) :-
    t(R, <b>[]</b>, L).

t(0, <b>R</b>, <b>R</b>).
t(D, <b>L</b>, <b>R</b>) :-
    D >= 1, !,
    Ti is D * ((D + 1) / 2),
    D1 is D - 1,
    t(D1, <b>[Ti|L]</b>, <b>R</b>).

Это затем дает ожидаемое:

?- t(2, L).
L = [1, 3.0] ;
false.

Обратите внимание, что вы можете сделать вышеупомянутое более эффективным, работая влево-направо, и используйте аккумулятор, который суммирует индексы.

Например:

t(N, R) :-
    t(1, 1, N, R).

t(I, _, N, []) :-
    I > N.
t(I, A, N, [A|T]) :-
    I =< N,
    I1 is I+1,
    A1 is A + I1,
    t(I1, A1, N, T).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...