2009-11-20 3 views
0

Прежде всего позвольте мне сказать, что это часть упражнения класса, данное как домашнее задание. Но все задание гораздо более активное, чем тема этого вопроса. Итак ..Работа со списками в Прологе

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

isumrow([], [], Iresult) :- 
    Iresult is 0. 
isumrow([Hi1row | Ti1row], [Hi2row | Ti2row], Iresult) :- 
    if((Hi1row - Hi2row), IsumDiff, Hi1row), 
    NewIresult is IsumDiff + Iresult, 
    isumrow(Ti1row, Ti2row, NewIresult), 
    Iresult is NewIresult. 

if(Diff, Iresult, Entry) :- 
    Diff > 0,      

    Iresult is Entry. 

if(_, Iresult, _) :- 
    Iresult is 0. 

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

+0

Какой из них вам нужно вычислить: сумму (макс (A [я], B [я]) для г в 1..len (A)) или sum (max (A [i] -B [i], 0) для i в 1..len (A))? – liori

+0

(BTW, вы чрезмерно употребляете 'is'. Вам нужно' is' рассчитать сумму и разницу, она не нужна для простых назначений. – liori

+0

Я не уверен, что я понимаю ваш вопрос. Если у меня есть два списка, List 1 является [ 0,0,0,1], а List 2 - [0,0,3,0]. Мне нужно выполнить поиск по списку, пока не найду соответствующий элемент в списке 1, который больше, чем список List 2. В этом случае это произойдет с 1> 0. Предикат «if» возвращает это значение, которое больше (1), которое добавляется к текущему итогу. В этом итоге общее число, которое мне нужно вернуть в конце. –

ответ

0

Я попытаюсь представить как можно меньше изменений для вашего кода.

Одна вещь, которая определенно неверна, - это то, где вы пытаетесь вычислить разницу. Prolog выполняет арифметические вычисления только при использовании оператора is. Код:

if((Hi1row - Hi2row), IsumDiff, Hi1row), 

это просто передавая выражение вида (X-Y) в if предиката, а не его расчета. Позже внутри if вы не вычисляете разницу, но пытаетесь сравнить выражение с нолем ... что не удается, потому что вы можете сравнивать числа только с числами, а не с выражениями, а Diff получает назначение.

Это будет работать, если вы перезаписать первое предложение о, если следующим образом (даже если вы должны также избавиться от этой is здесь):

if((X-Y), Iresult, Entry) :- 
    X > Y, 
    Iresult is Entry. 

Таким образом, ваш if предикат получит X и Y из чтобы иметь возможность сравнивать их.

Кроме того, вам нужно избегать предиката if, чтобы получить два возможных ответа. Ваш второй пункт if будет вызываться, даже если X> Y: в процессе возврата. Самый простой способ - положить ! в конце первого предложения. Это означает: «До сих пор я принимаю первое решение в этой программе, и я не хочу возвращаться отсюда, чтобы найти любые другие решения». Положение будет изменено на:

if((X-Y), Iresult, Entry) :- 
    X > Y, 
    Iresult is Entry, 
    !. 

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

if((X-Y), Iresult, Entry) :- 
    X > Y,           
    Iresult is Entry. 

if((X-Y), Iresult, _) :- 
    X =< Y, 
    Iresult is 0. 

Тогда вы уверены, что если X> Y, то второе предложение не удастся.

После этих изменений ваш код должен работать ... Сообщите об этом, если это не так. Это все равно будет не очень пролого-иш; это немного слишком многословно.


Edit:

Хорошо, я напишу его простым способом:

sum_if_bigger([], [], 0). 
sum_if_bigger([A|L1], [B|L2], Result) :- 
     sum_if_bigger(L1, L2, Partial), 
     Result is Partial + max(0, A-B). 

...или в хвостовой рекурсии образом:

sum_if_bigger_tr(L1, L2, R) :- 
     sum_if_bigger_tr(L1, L2, 0, R). 
sum_if_bigger_tr([], [], R, R). 
sum_if_bigger_tr([A|L1], [B|L2], Partial, Result) :- 
     NewPartial is Partial + max(0, A-B), 
     sum_if_bigger_tr(L1, L2, NewPartial, Result). 
+0

Я понимаю ваши изменения и реализовал их, но я до сих пор не получаю желаемых результатов. Я не настроен на использование этого кода, который я написал, поэтому, если есть лучшие или более чистые способы реализации этого процесса, я открыт для идей. В принципе, у меня есть 2 списка списков, которые мне нужно сравнить. Как я сказал ранее, если соответствующий элемент в списке 1 больше, чем я добавлю этот элемент к текущему итогу. Это то, что мне нужно для остальной части моей программы. Опять же, я не прошу вас решить мою проблему, но я не думаю, что я понимаю концепцию пролога правильно. –

+0

Не могли бы вы предоставить альтернативный способ решить эту проблему или показать некоторые примеры? Спасибо –

+0

Кстати, вы можете попытаться понять, как работает код (как ваш, так и мой), используя 'trace/0'. Просто введите 'trace.' в приглашении swipl, запустите запрос и нажмите enter, чтобы сделать шаг за шагом. Используйте «notrace.», чтобы остановить трассировку. – liori

1
isumrow([], [], Iresult) :- 
    Iresult is 0. 

isumrow([Hi1row | Ti1row], [Hi2row | Ti2row], Iresult) :- 
    if((Hi1row - Hi2row), IsumDiff, Hi1row),    
    NewIresult is IsumDiff + Iresult, 
    isumrow(Ti1row, Ti2row, NewIresult), 
    Iresult is NewIresult. 

if(Diff, Iresult, Entry) :- 
    Diff > 0,            
    Iresult is Entry. 

if(_, Iresult, _) :- 
    Iresult is 0.