Search code examples
prologswi-prolog

receives_twice(C, A): the client received exactly two transfers, each of which an amount not less than A;


Relations are defined in the Prolog program

account(B, C, N)

  • B is the name of the bank
  • C is client
  • N is the account number

transactions(N1, N2, A, D)

  • N1 is the number of the sender's account
  • N2 is the recipient's account number
  • A is the transfer amount
  • D is the date transfer

Write rule for the following relations:

a) receives_twice(C, A)
the client received exactly two transfers, each of which an amount not less than A;

account(reiffeisen, max, "0").
account(privat24, john, "1").
account(reiffeisen, olivia, "2").
account(privat24, jack, "3").
account(monobank, linda, "4").
account(monobank, omen, "5").
account(privat24, johnny, "6").
account(reiffeisen, historia, "7").
account(reiffeisen, clark, "8").
account(monobank, victor, "9").
transactions("0", "1", 100, "05").
transactions("1", "4", 200, "10").
transactions("1", "8", 500, "12").
transactions("9", "7", 100, "06").
transactions("5", "3", 5000, "08").
transactions("6", "9", 10, "01").
transactions("8", "7", 50, "02").
transactions("9", "0", 1200, "04").
transactions("5", "1", 800, "03").
transactions("3", "0", 1000, "07").
transactions("1", "6", 1400, "04").
transactions("6", "1", 2000, "05").
transactions("3", "1", 2500, "05").
transactions("1", "1", 2800, "05").

receives_twice(C, A) :-
    account(_, C, Q),
    transactions(_, Q, M, _),
    M >= A.

I don`t know how verify that the customer received exactly two transfers.


Solution

  • Can use a helper predicate:

    call_goal_t(Goal, Goal, Bool) :-
        call(Goal), !,
        Bool = true.
    call_goal_t(Goal, Goal, false).
    

    The 2nd arg is then a convenient transactions term. And the 3rd arg is whether successful.

    The rest of the code is:

    receives_min(Client, MinAmount, Trans, Bool) :-
        % Allowing a client to have more than 1 account
        account(_B, Client, AccNum),
        receives_min_(AccNum, MinAmount, Trans, Bool).
    
    receives_min_(AccNum, MinAmount, Trans, Bool) :-
        call_goal_t(transactions(_N1, AccNum, Amount, _D), Trans, Bool),
        (Bool == true -> Amount >= MinAmount ; true).
    
    receives_twice(Client, MinAmount) :-
        receives_min(Client, MinAmount, Trans1, true),
        dif(Trans1, Trans2),
        receives_min(Client, MinAmount, Trans2, true),
        dif(Trans1, Trans3),
        dif(Trans2, Trans3),
        receives_min(Client, MinAmount, Trans3, false).
    

    Result in swi-prolog:

    ?- receives_twice(C, 1000).
    C = max ;
    false.