Проверьте, содержит ли номер цифры A и B. Пролог - PullRequest
0 голосов
/ 13 января 2020
contains_digits(0,_,_,_,_):-
  !.
contains_digits(N,A,B,A1,B1):-

  % if the last digit of the number is equals to a digit A,
  % then flag A1 is set to 1, and if a digit B was founded then exit recursion.
  N2 is N mod 10, N2 =:= A, A1 is 1, B1 =:= 0;

  % here is the same like above, but for a digit B.
  N2 is N mod 10, N2 =:= B, B1 is 1, A1 =:= 0;

  % take the number N without the last digit. 12345 -> 1234 -> 123 -> ... -> 1
  N1 is N div 10,
  contains_digits(N1,A,B,A1,B1),

  % if both digits has been found, then return true, else return false.
  A1 is 1, B1 is 1.

Я называю это так:

?- contains_digits(123456,3,9,0,0).

Но этот код не работает, потому что я не знаю, как правильно объявить флаги A1 и B1. В этом коде он возвращает false, когда я пытаюсь A1 is 1 или B1 is 1, из-за A1 = 0 и B1 = 0, и я не знаю, как изменить их на 1.

Я сделал это следующим образом, и он работает правильно.

read_digits(A,B):-
  write("Number A: "),
  read(A), nl,
  write("Number B: "),
  read(B), nl.

contains(0,_):-
  !.

contains(N,X):-
  N2 is N mod 10,
  X \= N2,
  N1 is N div 10,
  contains(N1,X).

foo(N):-
  read_digits(A,B),
  not(contains(N,A)),
  not(contains(N,B)).

Ответы [ 2 ]

0 голосов
/ 14 января 2020

Вот решение, основанное на damianodamiano ответ с использованием встроенных предикатов:

contains_digits(Number,Digit1,Digit2) :-                                        
    between(0,inf,Number),                                                      
    between(0,9,Digit1),                                                        
    between(0,9,Digit2),                                                        
    atom_number(Char1,Digit1),                                                  
    atom_number(Char2,Digit2),                                                  
    number_chars(Number,Chars),                                                 
    member(Char1,Chars),                                                        
    member(Char2,Chars).    

Вы можете использовать memberchk/2 вместо member/2. Важным моментом является то, что contains_digits/3 имеет следующую спецификацию :

contains_digits(?Number,?Digit1,?Digit2) is nondet.

Например:

?- contains_digits(N,D1,D2).
% succeeds with all solutions for N, D1 and D2.

?- findall((N,M),contains_digits(123,N,M),Sols).
Sols = [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)].

?- findall(N,contains_digits(123,N,2),Sols).
Sols = [1, 2, 3].

?- findall(N,contains_digits(123,1,N),Sols).
Sols = [1, 2, 3].

?- contains_digits(123,1,2).
true ;
false.

?- contains_digits(123,1,5).
false.

?- contains_digits(123,5,1).
false.

?- contains_digits(123,5,8).
false.

Это решение жертвует полудетерминизмом для возможности создания решений для произвольно созданных номеров и цифр. Более сложные подходы будут использовать библиотеку CLP (FD) или DCG для эффективной генерации возможных решений. Это выходит за рамки этого ответа.

0 голосов
/ 14 января 2020

Простое решение на основе этого :

contains(Number,A,B):-
    number_codes(Number,N), 
    maplist(plus(48),X,N),    
    member(A,X),
    member(B,X).

?- contains(123456,1,3).
true ;
false

Вы также можете использовать memberchk/2, если не хотите также ложное решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...