Ответ в теме: Помогите решить задачу Железнодорожная стрелка

#1873

Может быть стоит отделять не первый и последний элементы, а делить список в любом месте (ведь поезд можно разорвать в любом месте) – посмотрите правило sublist.
Я думаю, что локомотив может оказаться в середине поезда теоретически :).

В зависимости от того, какие варианты генерации новых состояний вы допустите, будет зависеть и формат хранения состояния.

check(([], [T], L)):- %1
  T = лок, ([лок|_] = L; last(L, лок)), !.
generate((L, [V], R), (LL, [], RR)):- %2
  append(L, [V], LL), RR = R; LL = L, append([V], R, RR).
generate((L, [], R), (LL, [V], RR)):- %3
  LL = L, R = [V|RR]; append(LL, [V], L), RR = R.
% ...

Я привел лишь вариант, не самый лучший, наверное. Явно в конец надо дописать правил генерации состояний.

Первое приведенное правило срабатывает когда на левой ветке пусто, в тупике стоит локомотив, а список, стоящий в правой части, содержит локомотив первым или последним элементом. Аналогично должно быть описано правило, когда пусто в правой ветке. Это правило проверки правильности размещения вагонов, если оно завершилось удачно — то решение найдено.

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

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

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

Отделять, наверное есть смысл только тот вагон, который является ближним к тупику.
Если это правый поезд — то просто отделяйте первый элемент.
Если же это левый поезд — то отделять надо последний элемент. Для этого можно использовать встроенный предикат last(?List, ?Last). Завершается успешно когда Last является последним элементом списка List.