Query runs one time then returns false

there is just a small mistake in your code but it runs perfectly THANKS, also I have another question,

gamesBelowX(Team,Points):-
	foreach(jogo(Z,Team,Other,CA,_,CB,_,CC,_,CD,_),
            ((CA+CB+CC+CD)<Points  ->  format('\nNo mês: '),write(Z),format(', a equipa '),write(Team),
                format(' contra '),write(Other),format(' marcou '),P is(CA+CB+CC+CD),write(P);write(''))),
	foreach(jogo(Z,Other,Team,_,FA,_,FB,_,FC,_,FD),
            ((FA+FB+FC+FD)<Points  ->  format('\nNo mês: '),write(Z),format(', a equipa '),write(Team),
                format(' contra '),write(Other),format(' marcou '),P is(FA+FB+FC+FD),write(P);write(''))).	

this code is meant to search for a game in which a Team score under the Points
it runs one time and then return false

@c0rdeiro

Since you started a new question and my answer to this will have more info that others may find of use, I am moving it to a new topic so that it can be more easily referenced.

Earlier question

Code on SWISH

1 Like

@c0rdeiro

At this point your code is getting complex enough that you need to refactor it to more easily manage it.

The first thing I would do is to separate the part of the code that generates results from the part of the code that displays the results. Also I would add unit test to ensure that the code runs as expected and that any changes you make to existing code that has a test continues to pass the test.

For example:

jogosPerdidos(Equipa):-  % games lost
    format('Perdeu com:\n'),
    format('Fora:'),     % Away
    foreach(jogo(_,X,Equipa,CA,FA,CB,FB,CC,FC,CD,FD),
            ((CA+CB+CC+CD)<(FA+FB+FC+FD) -> (format('\n'),write(X));write(''))),
    format('\nEm casa: '),  % Home
    foreach(jogo(_,Equipa,X,CA,FA,CB,FB,CC,FC,CD,FD),
            ((CA+CB+CC+CD) < (FA+FB+FC+FD) -> (format('\n'),write(X));write(''))).
  1. Break out this part so that it can be tested.
perdidos(Equipa,Oponente) :-    % Away lost
    jogo(_,Oponente,Equipa,CA,FA,CB,FB,CC,FC,CD,FD),
            ((CA+CB+CC+CD)<(FA+FB+FC+FD)).
:- begin_tests(stats).

test(001) :-
    perdidos(nets,Oponente),
    assertion( Oponente == cavaliers ).

:- end_tests(stats).
?- make.
% c:/users/eric/documents/projects/prolog/swi-discourse_001 compiled 0.03 sec, -6 clauses
% PL-Unit: stats 
Warning: c:/users/eric/documents/projects/prolog/swi-discourse_001.pl:1458:
        PL-Unit: Test 1: Test succeeded with choicepoint
 done
% test passed
true.

Notice that it runs but has a choice point

There are a few ways to fix this. If the code is suppose to have a choice point (nondetermniant) the test case can be modified a few ways.

  1. Add nondet to the test.
test(002,nondet) :-
    perdidos(nets,Oponente),
    assertion( Oponente == cavaliers ).

Note: Individual unit test can be run as follows

?- run_tests(stats:1).
% PL-Unit: stats:1 
Warning: c:/users/eric/documents/projects/prolog/swi-discourse_001.pl:1458:
        PL-Unit: Test 1: Test succeeded with choicepoint
 done
% test passed
true.

?- run_tests(stats:2).
% PL-Unit: stats:2 . done
% test passed
true.

So test 2 ran without a warning.

Another way resolve this is to have the unit test collect all of the answers and check them.

test(003, all(Oponente == [cavaliers,suns,nuggets,wizards,heat,knicks,philadelphia,bulls,grizzlies,bulls,rockets,magic,cavaliers,hornets,hawks,sacramento,lakers,bucks,pacers])) :-
    perdidos(nets,Oponente).
?- run_tests(stats:3).
% PL-Unit: stats:3 . done
% test passed
true.

Now that that the basic part of jogosPerdidos(Equipa) is being tested, the next part is to have the code and not the unit test collect the answers into a list using bagof/3

perdas(Equipa,Perdas) :-     % Away losses
    bagof(Oponente,perdidos(Equipa,Oponente),Perdas).

test(004) :-
    perdas(nets,Perdas),
    assertion( Perdas == [cavaliers,suns,nuggets,wizards,heat,knicks,philadelphia,bulls,grizzlies,bulls,rockets,magic,cavaliers,hornets,hawks,sacramento,lakers,bucks,pacers] ).
?- run_tests(stats:4).
% PL-Unit: stats:4 . done
% test passed
true.

Now to output the values. One way uses format/2 that prints the list on one line, the other uses print_term/2 that prints the list items on an individual line which is nicer for longer list.

perdas_exibicao_1(Equipa) :-
    perdas(Equipa,Perdas),
    format('Fora: ~w~n',[Perdas]).

perdas_exibicao_2(Equipa) :-
    perdas(Equipa,Perdas),
    print_term(Perdas,[]).
?- perdas_exibicao_1(nets).
Fora: [cavaliers,suns,nuggets,wizards,heat,knicks,philadelphia,bulls,grizzlies,bulls,rockets,magic,cavaliers,hornets,hawks,sacramento,lakers,bucks,pacers]
true.
?- perdas_exibicao_2(nets).
[ cavaliers,
  suns,
  nuggets,
  wizards,
  heat,
  knicks,
  philadelphia,
  bulls,
  grizzlies,
  bulls,
  rockets,
  magic,
  cavaliers,
  hornets,
  hawks,
  sacramento,
  lakers,
  bucks,
  pacers
]
true.

While this did not directly answer your question, it should put you on the path to being able to resolve the question you asked.

2 Likes