Пролог: деление числа
Я хотел сделать предикат, который возвращает список делителей числа. Пример: 72 = 2*2*2*3*3.
prdel(A,[],_):-
A is 1.
prdel(P,[D|L],D):-
0 is mod(P,D),
P1 is P/D,
prdel(P1,L,D).
prdel(P,L,D):-
D1 is D+1,
prdel(P,L,D1).
Это работает и возвращает правильный список. Проблема в том, что он не останавливается после этого, а возвращает один и тот же список снова и снова, если я нажимаю пробел (извините, я не знаю термин на английском языке, когда вы используете один и тот же предикат для получения другого ответа). Я хочу, чтобы это прекратилось после первого раза.
Я пытался отредактировать последний как этот,
prdel(P,L,D):-
D1 is D+1,
D1<P,
prdel(P,L,D1).
но теперь он возвращает только ложь, а не список.
РЕДАКТИРОВАТЬ:
Я ищу ответ без разреза.
1 ответ
Одна проблема в вашем коде состоит в том, что он пытается разделить число P
от D
даже когда ясно, что разделение не будет успешным, потому что D
слишком высоко Это позволяет D
"убежать" без ограничений.
Добавление чека для D1
быть ниже или равно P
исправляет эту проблему:
prdel(1,[],_).
prdel(P,[D|L],D):-
0 is mod(P,D),
P1 is P/D,
prdel(P1,L,D).
prdel(P,L,D):-
D1 is D+1,
D1 =< P,
prdel(P,L,D1).
Это создает все комбинации делителей, включая не простые ( демо).
[[2, 2, 2, 3, 3], [2, 2, 2, 9], [2, 2, 3, 6],
[2, 2, 18], [2, 3, 3, 4], [2, 3, 12], [2, 4, 9],
[2, 6, 6], [2, 36], [3, 3, 8], [3, 4, 6], [3, 24],
[4, 18], [6, 12], [8, 9], [72]]
Если вы этого не хотите, добавьте условие mod(P,D) > 0
в последнем пункте:
prdel(1,[],_).
prdel(P,[D|L],D):-
0 is mod(P,D),
P1 is P/D,
prdel(P1,L,D).
prdel(P,L,D):-
mod(P,D) > 0,
D1 is D+1,
D1 =< P,
prdel(P,L,D1).
Это производит только [2, 2, 2, 3, 3]
( демо).