Ответ в теме: Заменить часть списка в Prolog

      Комментарии к записи Ответ в теме: Заменить часть списка в Prolog отключены
#1786

«Одной рекурсией» — это так, что-ли?

swap_ab(Buffer, [], Buffer):-!.
swap_ab(Buffer, [97, 98|Tail], Swapped):-
  !, append(Buffer, [98, 97|Tail], SwappedList),
  swap_ab([], SwappedList, Swapped).
swap_ab(Buffer, [Head|Tail], Swapped):-
  append(Buffer, [Head], BufferWithHead),
  !, swap_ab(BufferWithHead, Tail, Swapped).

Тут используется метод накапливающего параметра — результат накапливается в первом аргументе функции до тех пор, пока входной список не окажется пустым. При пустом входном списке решением является накопленный в буфере результат. Изначально буфер пуст. Символы из основного списка постепенно попадают в буфер, т.е. конкатенация буфера и необработанной части списка на каждом шаге представляет собой промежуточный результат.
Функция пытается отделить от списка искомую комбинацию символов и, если это удается сделать:

  • при помощи стандартного предиката append из буфера и необработанной части формирует новый исходный список, в котором комбинация заменена;
  • выполняет рекурсивную обработку списка, при этом в качестве буфера передается пустой список, т.к. буфер уже включен в новый обрабатываемый список;

В противном случае первый символ необработанной части перемещается в конец буфера, остальные символы обрабатываются рекурсивно. Символ помещается именно в конец буфера (в отличии от предыдущего исходного кода), т.к. метод накапливающего параметра выполняет реверс результата. Первый обработанный элемент будет помещен в буфер первым, но если остальные элементы будут добавляться в начало — то окажется последним.