создание списка элементов, умноженных на n - PullRequest
1 голос
/ 16 апреля 2020

Итак, моя проблема в том, что у меня есть предикат, который представляет собой repeatte_el (El, N, L), в котором El является элементом, N - количество повторений, а L - список, содержащий этот элемент, повторенный N раз.

Моя проблема в том, что вместо того, чтобы повторять элемент, он дает false, и я не понимаю, почему.

Пример:

Мой вывод:

?- repete_el(a,3,L).
false

Правильный вывод:

?- repete_el(a,3,L).
L = [a,a,a].

Программа:

repete_el(El,0,[]) :- !.

repete_el(El,N,L) :- repete_el(El,N,L,[],N).

repete_el(El,N,L,L2) :- length(L2,C),
                        C =< N,
                        append(L2,[N],NL),
                        repete_el(El,N,L,NL).

Кстати, я могу сделать это только итеративно.

Ответы [ 2 ]

3 голосов
/ 16 апреля 2020

Вы можете использовать стандартный предикат findall/3 и де-факто стандартный предикат between/3. Например:

| ?- findall(a, between(1,5,_), List).
List = [a, a, a, a, a]
yes
1 голос
/ 16 апреля 2020

Причина, по которой это не сработает, состоит в том, что в момент вызова repete_el/4, L2 является свободной переменной, поэтому length(L2, C) начнет строить все виды списков с длинами. Затем вы делаете рекурсивный вызов для списка NL с одним дополнительным элементом, и вам требуется, чтобы этот список снова имел длину C (которая снова должна быть меньше N). Но в конечном итоге C будет больше, чем N, и, следовательно, предикат потерпит неудачу.

Вы можете написать такой предикат как:

repete_el(_, 0, []).  %% (1)
repete_el(X, N, [X|T]) :-        %% (2)
    N > 0,
    N1 is N-1,
    repete_el(X, N1, T).

Здесь мы таким образом говорим:

(1) Список, в котором мы повторяем элемент 0 раз, является пустым списком; и (2) список, в котором мы повторяем X, N раз, с N больше 0, это список, который начинается с X и заканчивается списком, в котором мы повторяем X, N-1 раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...