Article View: comp.lang.prolog
Article #1021Re: Having a problem understanding the cut (arrgh!)
From: Richard O'Keefe
Date: Fri, 27 Jul 1990 09:39
Date: Fri, 27 Jul 1990 09:39
113 lines
4780 bytes
4780 bytes
In article <90207.090559F0O@psuvm.psu.edu>, F0O@psuvm.psu.edu writes:
> Players in a squash club are divided into three leagues, and players
> may only challenge members in their own league or the league below,
> if there is one.
> Write a Prolog program that will display all possible matches between
> club players in the form:
> tom versus bill
> Use the cut to ensure for example, that
> Tom versus bill
> and
> bill versus tom
> are not both displayed.
> Where have I gone astray?
(a) Why use Turbo Prolog when you could use ALS Prolog?
(b) Why use a cut?
> member(ann, 3).
> member(joyce, 3).
> member(ramona, 2).
> member(cynthia, 2).
> member(susan, 1).
> member(lisa, 1).
1. It is just plain confusing to use member/2 here.
member(X, L) is almost always used for "L is a list and X is a
member of L". It's also a good idea to use two-pair names so
that you can keep track of which argument is which. I'd use
player_league(Player, League)
player_league(ann, 3).
player_league(joyce, 3).
player_league(ramona, 2).
player_league(cynthia, 2).
player_league(susan, 1).
player_league(lisa, 1).
> match :-
> member(Player1, League1),
> member(Player2, League2),
> Player1 <> Player2,
> League1 >= League2,
> write(Player1, " versus ",Player2), nl, fail.
2. We want
may_challenge(Challenger, Challengee)
to be true when Challenger and Challengee are names of players
and Challenger may challenge Challengee. The original specification
says quite clearly that C1 may challenge C2 only if C1 and C2 are in
the same league, or if C2 is in THE league below C1, which I take to
mean that C1 may challenge players C2 who are *ONE* rung lower but not
two rungs lower. So a player in league 3 may challenge a player in
league 2, but not a player in league 1. The specification thus needs
to be clarified. As there are only three leagues, let's write
permissible_leagues(3, 3). % same league
permissible_leagues(3, 2). % or one league lower.
permissible_leagues(2, 2). % same league
permissible_leagues(2, 1). % or one league lower.
permissible_leagues(1, 1). % same league (there is none lower).
may_challenge(Challenger, Challengee) :-
player(Challenger, HigherLeague),
player(Challengee, LowerLeague),
Challenger \== Challengee,
permissible_leagues(HigherLeague, LowerLeague).
To write out all permitted challenges:
write_all_permissible_challenges :-
forall( may_challenge(X, Y),
format('~w challenges ~w.~n', [X,Y])
).
3. Now, the definition above *will* produce both solutions
?- may_challenge(ann, joyce).
?- may_challenge(joyce, ann).
but that's RIGHT because these two solutions say DIFFERENT things.
The first says that "ann may challenge joyce" and the second says
that "joyce may challenge ann" and these are different statements.
(For example, the challenger might serve first or something like
that, so we might be talking about different possible games.)
If you want to consider the game (X against Y) as being the same as
the game (Y against X), then the simplest way to eliminate one of
them is to change the specification. Instead of talking about
permitted challenges, let's talk about possible games, and now we
are going to use a "canonical description" of a game: the canonical
description of a game between X and Y is either X,Y or Y,X depending
on whether X alphabetically precedes or follows Y.
possible_game(Player1, Player2) :-
player_league(Player1, League1),
player_league(Player2, League2),
Player1 @< Player2, % generate only canonical descriptions
League1-League2 =< 1, % difference not too great one way
League2-League1 =< 1. % difference not too great other way.
write_all_games :-
forall( possible_game(Player1, Player2)
, format('~w versus ~w.~n', [Player1,Player2])
).
This is a good example of a problem where a cut should NOT be used.
What we did was to eliminate duplicate solutions from the SPECIFICATION
so that a logical implementation of the specification didn't _need_ a cut.
I've spent about half an hour thinking about this, and I haven't thought
of any natural or good way of coding it that involves a cut.
Technical Details
Message-ID:
<4921@munnari.oz.au>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!usc!elroy.jpl.nasa.gov!ames!uhccux!virtue!comp.vuw.ac.nz!munnari.oz.au!mudla!okReferences:
<90207.090559F0O@psuvm.psu.edu>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!usc!elroy.jpl.nasa.gov!ames!uhccux!virtue!comp.vuw.ac.nz!munnari.oz.au!mudla!ok From: ok@mudla.cs.mu.OZ.AU (Richard O'Keefe) Newsgroups: comp.lang.prolog Subject: Re: Having a problem understanding the cut (arrgh!) Message-ID: <4921@munnari.oz.au> Date: 27 Jul 90 09:39:05 GMT References: <90207.090559F0O@psuvm.psu.edu> Sender: news@cs.mu.oz.au Lines: 113