Получить выходное значение из рекурсивной функции Prolog - PullRequest
0 голосов
/ 19 сентября 2018

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

ListA: [], ListB: [] => ResultList: []
ListA: [], ListB:[a,b,c] => ResultList: [[a],[b],[c]]
ListA: [1,2], ListB:[a,b,c] => ResultList: [[1,2,a],[1,2,b],[1,2,c]]

Я застрял с проблемой выходного значения рекурсивной функции, и вот мое кодирование:

extend_my_path([],_,_,_).
extend_my_path([H|T],OriginalPath,OrignailMewPaths,NewPaths) :-
    append(OriginalPath,[H],NewPath),
    append(OrignailMewPaths,[NewPath],NewPaths1),
    print("NewPaths1:"),print(NewPaths1), nl,
    extend_my_path(T,OriginalPath,NewPaths1,NewPaths1).

Запуск его дает следующий вывод без значения Result varable:

?- extend_my_path([a,b,c],[1,2],[],Result).
"NewPaths1:"[[1,2,a]]
"NewPaths1:"[[1,2,a],[1,2,b]]
"NewPaths1:"[[1,2,a],[1,2,b],[1,2,c]]
true.

Я хочу получить его значение как:

Result=[[1,2,a],[1,2,b],[1,2,c]]

Это высоко ценится, еслилюбой может указать причину.Спасибо.

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

Вместо того, чтобы пытаться исправить существующий код, давайте попробуем решить проблему заново.Вы показываете примеры:

ListA: [],    ListB: []      => ResultList: []
ListA: [],    ListB: [a,b,c] => ResultList: [[a],[b],[c]]
ListA: [1,2], ListB: [a,b,c] => ResultList: [[1,2,a],[1,2,b],[1,2,c]]

и

?- extend_my_path([a,b,c], [1,2], [], Result).
Result = [[1,2,a],[1,2,b],[1,2,c]]

Третий аргумент выглядит совершенно неуместным, а первый и второй аргументы меняются местами по сравнению с первым пакетом примеров,так скажем, это должно быть

?- ListA = [1,2], ListB = [a,b,c], extend_my_path( ListA, ListB, ResultList).
ResultList = [[1,2,a],[1,2,b],[1,2,c]]

Итак мы начинаем кодировать , просто перечисляя случаи, которые, как мы знаем, должны выполняться:

extend_my_path_ex( [], [], []).
extend_my_path_ex( [],    [a,b,c], [[    a],[    b],[    c]]).
extend_my_path_ex( [1,2], [a,b,c], [[1,2,a],[1,2,b],[1,2,c]]).

Обобщение дает нам

extend_my_path3( [], [], []). 
extend_my_path3( OneTwo, [A,B,C], [OneTwoA,OneTwoB,OneTwoC]):-
    append( OneTwo, [A], OneTwoA),
    append( OneTwo, [B], OneTwoB),    % ... right? all the examples produce 
    append( OneTwo, [C], OneTwoC).    %     the same answers. check it!

А что, если их было только два?

extend_my_path2( [], [], []).  
extend_my_path2( OneTwo,   [B,C],         [OneTwoB,OneTwoC]):-
    append( OneTwo, [B], OneTwoB),
    append( OneTwo, [C], OneTwoC).    % ... right? 

Так что мы можем просто переписать его синтаксически как

extend_my_path3( [], [], []). 
extend_my_path3( OneTwo, [A | [B,C]], [OneTwoA | [OneTwoB,OneTwoC] ]):-
    append(      OneTwo, [A],          OneTwoA),
    extend_my_path2( OneTwo,  [B,C],             [OneTwoB,OneTwoC]  ).

Но смотри!Что бы мы ни делали с тремя элементами, мы делаем то же самое, по существу, с двумя.

И почему мы должны ограничиваться только тремя, или двумя случаями элементов?В них нет ничего особенного.Давайте обобщим еще раз,

extend_my_path( [], [], []).
extend_my_path( OneTwo, [A | B_C], [OneTwoA | OneTwoB_OneTwoC ]):-
    append(     OneTwo, [A],        OneTwoA),
    extend_my_path( OneTwo,  B_C,             OneTwoB_OneTwoC ).

Можете ли вы взять его отсюда?

0 голосов
/ 19 сентября 2018

В этих шести строках кода я вижу некоторую путаницу.Вот некоторые подсказки, что что-то не так:

  • Ваша проблема определена в терминах трех вещей, но у вашего предиката есть четыре аргумента.Какими должны быть последние два?
  • У вас есть одноэлементная переменная NewPaths, которая является катастрофой
  • Ваш базовый случай связывает пустой список с любыми тремя другими вещами!Попробуйте: extend_my_path([], lightning, [the,sound,of,rain], "fresh coffee") это правда!Кажется, вряд ли это то, что вы намеревались.
  • Интересно, что такое «тропы Оригейла Мью» или какие «пути» здесь имеют отношение к чему-либо.Опечатки имеют значение, исправьте их!
  • Индуктивный случай заканчивается двумя копиями NewPaths1, что кажется подозрительным, потому что у нас было две очень разные переменные в начале, и, как вы видите в базовом случае, это не такнезависимо от того, что они есть.Странно!

Я думаю, что здесь произошло то, что вы решили, что единственный и правильный способ добавить что-то в список - с помощью append/3, что не соответствует действительности.Я думаю, что семантика одиночного присваивания Пролога убедила вас, что вам нужен еще один аргумент для создания пустого списка, к которому вы хотите добавить.Вы пропустили базовый сценарий для своей рекурсии, поэтому вы так и не получили разумного возвращения;сделав его широко открытым, вы хотя бы вернули себя к истине, но не дали связывания.И основная проблема здесь заключается в том, что в вашем коде нет разумного отношения .Давайте попробуем еще раз.

Вы пытаетесь написать предикат, имя и аргументы которого выглядят примерно так:

% extend_path(Path, Possibilities, NewPaths)

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

В этом случае будет ваш базовый вариантгде у вас больше нет возможностей и, следовательно, нет новых путей:

extend_path(_, [], []).

Это не говорит о том, что что-то относится к чему-либо, а говорит о «расширении пути любого префикса, когда яиз возможных возможностей пуст. "

Затем ваш индуктивный случай берет ваш первый аргумент и добавляет его к следующему элементу из вашего списка возможностей.Это входит в ваш список новых путей.

extend_path(Prefix, [Ext1|ExtRest], [Next1|NextRest]) :-
    append(Prefix, [Ext1], Next1),
    extend_path(Prefix, ExtRest, NextRest).

Это буквально говорит: «дан некоторый префикс, и что у меня есть Ext, оставленный в моем списке расширений, создаст новое расширение пути Next1, такое что:Префикс + [Ext1] - следующий. "На самом деле, это говорит немного больше, чем рекурсивный шаг.Но идея здесь состоит в том, чтобы откусить одну часть, Ext1, и сопоставить ее с одной частью результата, Next1, а затем сопоставить остальную часть ввода с остальной частью вывода.

Наконец, пожалуйста делайте не обрабатывайте одноэлементную переменную "предупреждение" как предупреждение.Это , а не , как будто Python злится на то, что вам не хватает новых строк между функциями.Синглтонные переменные почти всегда КРИТИЧЕСКИЕ ОШИБКИ, особенно для новых пользователей Prolog!Обратите на них внимание!

Надеюсь, это поможет!

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