Я пытаюсь написать предикат в Prolog, который будет использовать мой предикат 'PAR', который проверяет, соответствует ли 4-значное число определенным условиям, но возвращает список всех чисел, которые являются PAR, то есть всех чисел, которые возвращают истину при передаче в par. .

pars(A, C)
    :-  A =< 9999,
        par(A) -> append(C, A, C),
        A1 is A+1,
        pars(A1, C).

Это мой текущий код, в котором A изначально передается как 1000 (наименьшее 4-значное число), но он вернет только false при попытке первого числа или тайм-аут, если первое число является PAR.

Я также хочу, чтобы предикат принимал только один аргумент, например pars (X), где X - это список PAR.

par(A)
    :-  number_chars(A, [W,X,Y,Z]),
        unique([W,X,Y,Z]),
        atom_number(W, W1),
        atom_number(X, X1),
        atom_number(Y, Y1),
        atom_number(Z, Z1),
        B1 is W1 * 10 + X1,
        B2 is Y1 * 10 + Z1,
        0 is mod(B1,B2).

Вот мой предикат par для справки, я знаю, что это тоже, вероятно, очень неэффективно.

Любая помощь будет оценена, заранее спасибо.

1
user14462428 27 Ноя 2020 в 21:31

1 ответ

Лучший ответ

Самый простой способ - использовать метапредикат "сбора решений", например { {X0}}, bagof/3 или setof/3:

findall(P,(between(1000,9999,P),par(P)),Bag).

В этом случае подцелью является between(1000,9999,P),par(P):

  • Создайте число P от 1000 до 9999
  • Тест на равенство
  • Если вышеперечисленное выполнено успешно, оно будет в списке Bag при успешном выполнении findall/3.
  • Если вышеперечисленное не удается, процессор Prolog возвращается к началу подцели и пытается снова, генерируя и проверяя следующее число.

Это также можно написать более подробно (т.е. не «встроить»):

subgoal(P) :- between(1000,9999,P),par(P).

findthem(Bag) :- findall(P,subgoal(P),Bag).

(Проверка не удалась, потому что у меня нет определения unique/1, которое используется в par/1.)

2
David Tonhofer 27 Ноя 2020 в 18:47