Недавно я столкнулся с математической головоломкой, которая выглядит следующим образом:
Представьте себе 13 конвертов, каждый из которых пронумерован от 1 до 13. Возьмите 13 учетных карточек, пронумерованных от 528 до 540. Найдите возможное расположениекарты в конвертах, так что число на каждой карте можно разделить на содержащий конверт без остатка.
Я решил это вручную и нашел более одного решения. Ручная техника, которую я использовал, состояла в том, чтобы перечислить делители каждой индексной карточки и найти те, которые имеют только один делитель. Затем я вычеркиваю этот делитель из других чисел и продолжаю процесс, ища числа только с одним делителем. (Иногда были некоторые с двумя, и это или приводило к тупикам, или приводило к множественным решениям)
Я не знаю, как сделать это разумно в прологе. Мне удалось только сделать грубую силу, то есть проверить каждый возможный порядок
valid([], []).
valid([EHEAD|ETAIL], [CHEAD|CTAIL]) :- 0 is mod(EHEAD, CHEAD), valid(ETAIL, CTAIL).
numlist(1,13,Envelopes),
permutation(Contents, C), numlist(528, 540, C),
valid(Contents, Envelopes).
Это решение не работает в разумное время, поэтому я не могу его проверить (но оно выглядит о праве). Как я могу заставить его вернуться назад, например, я инстинктивно знаю, что бесполезно искать решения, которые пытаются связать нечетное число с любым четным числом (и это обобщает все номера конвертов), но не знают, как это реализовать.