Пролог - Добавить голову в новый список для каждого рекурсивного прогона? - PullRequest
2 голосов
/ 30 апреля 2020

Хийя,

В настоящее время я работаю над типом "виртуального магазина" в Прологе и пытаюсь поработать над функциональностью для обновления прохода. Однако, видя мое довольно ограниченное знание Пролога, я сталкиваюсь с некоторыми трудностями.

Предикаты и вызов:

/*  % First parameter: The shop (or "old list") that contains the unmodified data
    % Second parameter: Simply a index/counter keeping track of where we are in 
        the "recursive loop"
    % Third parameter: Index of where we want to get. We keep recursively looping 
        and either incrementing or decrementing until the second and third 
        parameters are the same.
    % Fourth parameter: Since the first parameter is a list of lists, this 
        parameter will contain the "inner list" which will replace another inner 
        list.
    % Fifth parameter: The shop (or "new list"), the result, whatever you'd like 
        to call it 
    */
update_aisle( [H|T], CurrentAisle, TargetAisle, NewObj, NewShop):-
    CurrentAisle < TargetAisle,
    Temp is CurrentAisle + 1,
    append( NewShop, H),
    update_aisle( T, Temp, TargetAisle, NewObj, NewShop).
update_aisle( [H|T], CurrentAisle, TargetAisle, NewObj, NewShop):-
    CurrentAisle > TargetAisle,
    Temp is CurrentAisle - 1,
    append( NewShop, H),
    update_aisle( T, Temp, TargetAisle, NewObj, NewShop).
update_aisle( [H|T], CurrentAisle, TargetAisle, NewObj, NewShop):-
    CurrentAisle is TargetAisle,
    nth0( 0, T, TempT),
    append( NewObj, TempT, NewShop).

?- Shop = [ [ "Bread", "Donuts", "Cookies" ], 
            [ "Beer", "Cider", "Juice" ],
            [ "Ham", "Raw Meat", "Sausage" ] ],
   write(Shop), nl,
   update_aisle(Shop, 0, 1, ["Beer", "Milk", "Juice"], NewShop),
   write(NewShop), nl.

Сейчас я получаю только директивы ( потерпел неудачу), так что не очень далеко (и я собираюсь предположить, что это потому, что append/2 не сотрудничает, как я бы этого хотел). Тем не менее, я бы хотел добиться следующего:

Shop = [ [ "Bread", "Donuts", "Cookies" ], 
         [ "Beer", "Cider", "Juice" ],
         [ "Ham", "Raw Meat", "Sausage" ] ].

NewShop = [ [ "Bread", "Donuts", "Cookies" ], 
            [ "Beer", "Milk", "Juice" ], 
            [ "Ham", "Raw Meat", "Sausage" ] ].

Другими словами, я пытаюсь провести l oop по списку и добавить «заголовок» списка для каждого рекурсивный l oop до тех пор, пока мы не там, где мы хотим быть в списке. Как только мы достигли этой точки, мы в основном пропустили после добавления NewObj в список (вместо головы, поскольку это заменяется) и работа сделана.

Я чувствую, что я ' Я упускаю что-то явно очевидное, но любая помощь будет полезна!

1 Ответ

1 голос
/ 04 мая 2020

Если я правильно интерпретирую ваш вопрос, вы хотите заменить элемент по заданному индексу в списке:

% replace_at( In, At, With, Replaced )
replace_at( [],  _I, _N, []).
replace_at( [_|T], I, N, [N|T]) :- I =:= 0.
replace_at( [H|T], I, N, [H|T2]) :- I > 0, I2 is I-1,
   replace_at( T, I2, N,    T2).

Тестирование:

?- Shop = [["Bread","Donuts","Cookies"],["Beer","Cider","Juice"],["Ham","Raw Meat","Sausage"]], 
   replace_at( Shop, 1,    ["Beer", "Milk", "Juice"],    NewShop), nl, 
   maplist( writeln, Shop), nl, maplist( writeln, NewShop), nl.

[Bread,Donuts,Cookies] 
[Beer,Cider,Juice]
[Ham,Raw Meat,Sausage]

[Bread,Donuts,Cookies]
[Beer,Milk,Juice]
[Ham,Raw Meat,Sausage]

Shop = [["Bread", "Donuts", "Cookies"], ["Beer", "Cider", "Juice"], ["Ham", "Raw Meat", "Sausage"]],
NewShop = [["Bread", "Donuts", "Cookies"], ["Beer", "Milk", "Juice"], ["Ham", "Raw Meat", "Sausage"]] ;
false.

Дает вывод что вы хотели.

То, что элементы списка сами по себе являются списками, здесь несущественно.

Если, с другой стороны, вы когда-нибудь захотите использовать два индекса в вызов, чтобы указать, что J -й элемент в I -ом списке (на основе 0) в списке списков должен быть заменен, вы можете просто использовать вышеупомянутый предикат, дважды, чтобы выполнить sh что:

% replace_at2d( In, AtLine, AtWord, With, Replaced )
replace_at2d(  LL,    I, J, W,     LL2 ) :-
  nth0(   I,   LL, L),                         % I-th line
  replace_at(      L,    J, W, L2 ),           % J-th word
  replace_at(  LL,    I,       L2, LL2 ).

Тестирование:

?- Shop = [["Bread","Donuts","Cookies"],["Beer","Cider","Juice"],["Ham","Raw Meat","Sausage"]], 
   replace_at2d( Shop, 1, 1,    "Milk",    NewShop), nl, 
   maplist( writeln, Shop), nl, maplist( writeln, NewShop), nl.

[Bread,Donuts,Cookies]
[Beer,Cider,Juice]
[Ham,Raw Meat,Sausage]

[Bread,Donuts,Cookies]
[Beer,Milk,Juice]
[Ham,Raw Meat,Sausage]

Shop = [["Bread", "Donuts", "Cookies"], ["Beer", "Cider", "Juice"], ["Ham", "Raw Meat", "Sausage"]],
NewShop = [["Bread", "Donuts", "Cookies"], ["Beer", "Milk", "Juice"], ["Ham", "Raw Meat", "Sausage"]] ;
false.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...