Копировать список по количеству элементов другого списка - PullRequest
0 голосов
/ 04 мая 2018

Я пытаюсь сделать это:

times([x, x], [1, 5, 9, 8], Result).

Второй список дублируется количеством элементов в первом.

Результат: [1, 5, 9, 8, 1, 5, 9, 8]

Я пробовал это, но не работает должным образом:

times( [ ], _, [ ] ) :- !.
times( [ _ | List1 ], List2, Result ) :-    append( [], List2, Result ),
                                            times( List1, List2, Result ).

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Мы можем буквально подставить второй список для каждого элемента в первом, а затем вызвать append/2 (у SWI Prolog есть один):

nreplicate( Xs, Ys, Result) :-
  maplist( subst(Ys), Xs, Zs),
  append( Zs, Result ).

subst(Ys, _, Ys).
0 голосов
/ 04 мая 2018

Во-первых, вам не нужен ваш разрез в базовом корпусе. Излишне сокращает поиск решения:

replicate([], _, []).   % The empty list is the result of replicating any list by []

Тогда ваше рекурсивное правило, replicate([_|List1], List2, Result), похоже, имеет разумный формат / заголовок. Но у вас есть проблемы с логикой в ​​организме. Если бы вы описали логику, это не имело бы смысла. В частности, вы используете Result в двух разных местах для двух разных значений, и это приведет к неожиданному сбою. Предикат просто нужно логически продумать, что он означает:

Result - это репликация List2 на [_|List1] , если SubResult - это репликация List2 на List1 и Result - результат добавления SubResult до List2.

Обратите внимание на использование здесь «подрезультата» (SubResult), который отличается от основного результата (Result). Важно, чтобы это были разные переменные.

Если вы напишите это как Пролог, вы получите:

replicate([_|List1], List2, Result) :-
    replicate(List1, List2, SubResult),
    append(List2, SubResult, Result).

Я не проверял это, но это должно в основном делать это. Вы должны попробовать это и решить любые остающиеся проблемы самостоятельно как часть вашего процесса обучения Пролога. Я также не подумал, есть ли более эффективный подход к общей проблеме, но я просто решаю ваши проблемы с вашим текущим подходом. <ч /> Еще бы использовать maplist/2 и append/2. Вы можете использовать maplist/3, чтобы получить список списков, а затем использовать append/2, чтобы получить свой результат:

replicate(List1, List2, Result) :-
    length(List1, Len),
    length(R1, Len),
    maplist(=(List2), R1),
    append(R1, Result).

<ч /> Немного подумав, это можно решить с помощью простой рекурсивной обработки списка. В этом случае вы рекурсивно объединяете заголовок результата с заголовком каждого элемента во втором списке, а затем продолжаете этот процесс для каждого элемента в первом списке.

replicate(Rep, List, Res) :-
    replicate(Rep, List, List, Res).

replicate([], _, _, []).
replicate([R|Rs], List, [X|Xs], [X|Res]) :-
    replicate([R|Rs], List, Xs, Res).
replicate([R|Rs], List, [], Res) :-
    replicate(Rs, List, List, Res).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...