2014-12-05 2 views
1

Учитывая такой запрос:Проверьте список состоит из N экземпляров X (X повторить N раз)

containsN(4,2,Z). 

я должен получить: Z = [2,2,2,2].

или

containsN(4,W,[3,3,3,3]) 

я должен получить: W = 3.

Итак, другими словами, для первого примера мне нужно 4 экземпляра 2 в списке связанного с Z.

Для второго примера мне нужен элемент в списке, примененный 4 раза, связанный с W.

Моя попытка до сих пор приводит к бесконечному циклу:

containsN(Y,W,Z) :- contains_helper(Y,W,Z). 

contains_helper(0,_,_). 
contains_helper(Y,W,[H|T]) :- W = H, Y0 is Y - 1, contains_helper(Y0,W,T). 

Идея заключается в том, что я называю вспомогательную функцию, чтобы я мог проверять элементы Z один за другим. Когда счетчик достигает 0, я знаю, что список истинен, потому что для каждой итерации H = W. Однако я получаю бесконечный цикл.

+1

Ваш код работает очень хорошо (при условии, что 'fill_helper'' 'contains_helper'). Какой вход вызывает бесконечный цикл? –

+0

Когда вы достигнете '0', вы также знаете, что список должен быть пустым. Для хелперного предиката нет причин. «W = H» может быть ограничено перемещением унификации в голове предложения: 'contains_helper (Y, W, [W | T]): - ...'. –

+0

Кроме того, вы должны проверить, больше ли 'Y' больше 0 (и, возможно, после этого вырезается). В качестве альтернативы, разрежьте основной футляр (список пуст/счетчик 0). Это устраняет проблемы с циклом. –

ответ

2

Если вы хотите предикат быть как можно более общим (и я переименовал его в repeat/3)

?- repeat(X, N, L). 
N = 0, L = [] ; 
N = 1, L = [X] ; 
... 

Вы можете использовать хорошие свойства из length/2, как это:

% True when L is a list with N repeats of X 
repeat(X, N, L) :- 
    length(L, N), 
    maplist(=(X), L). 

Здесь , length(L, N) может проверять длину списка или генерировать список требуемой длины или генерировать списки увеличивающейся длины при обратном трассировке.

maplist(=(X), L) будет успешным, если каждый элемент списка L унифицируется с переменной X. Вы могли бы написать как:

foo([], _). 
foo([X|Xs], X) :- 
    foo(Xs, X). 

, но я не думаю, что это необходимо.