Subject: Re: List

From: "Richard A. O'Keefe" <[email-masked]>
Date: Tue, 5 Sep 2000 15:53:04 +1200 (NZST)

I have the following setup.

	%   card(?Face, ?Rank)
	%   is true when Face is in [a,2..10,j,q,k] and Rank is
	%   the corresponding element of [1,2..10,11,12,13].

It is almost always a mistake to let the input/output formats of
a program dictate the internal data structures.  This predicate
would be useful for *converting* external form to internal form
and vice versa; for internal purposes, stick with the Ranks.

The predicate name is not good.  It should be something like

	card_face_rank(a, 1).
	...
	card_face_rank(k, 13).

	/* Card name,
	   stack */   
	    
	topcard(2, 1).
	topcard(8, 2).
	topcard(5, 3).
	topcard(9, 4).
	topcard(2, 5).
	topcard(10, 6).
	topcard(3, 7).
	topcard(j, 8).
	topcard(5, 9).
	topcard(3, 10).
	topcard(q, 11).
	topcard(4, 12).
	
I cannot make sense of this.  Theruntogetherpredicatename (why not
the more readable "top_card"?) seems to imply that it identifies
something as the top card.  But which is it?  Does "stack" in the
comment mean that the second argument (1..12) is a stack (or names
a stack in some fashion), or that the predicate is managed as a
stack?  If these things are stack numbers, why does no stack have
more than one card?

The first thing in good programming in *any* language is good
names (not names that *remind* someone who already knows what they
mean, but names that truthfully *inform* someone who *doesn't*
know what they mean yet) and good comments, again informing rather
than reminding.

	/* Test where two cards equals 14. */
	
Er, cards is cards and numbers is numbers.  How can a card
equal a number?

	is_fourteen(ICard1, ICard2):- 
	   card(ICard1,ICard1_Value), 
	   !,    
	   card(ICard2,ICard2_Value),
	   !,
	   14 =:= ICard1_Value + ICard2_Value.
	
What on earth are the cuts there for?

Presumably this predicate should be something like

	%   ranks_sum_to_fourteen(?Face1, ?Face2)
	%   is true when Face1 and Face2 are card faces
	%   (no suits involved) and their ranks sum to 14.

	ranks_sum_to_fourteen(Face1, Face2) :-
	    card_face_rank(Face1, Rank1),	
	    card_face_rank(Face2, Rank2),
	    Rank1 + Rank2 =:= 14.
	
	/* Returns a list of cards that equals 14. */
	 
	check_fourteen(Card1,Card2,StackCard1,StackCard2):-
	    topcard(Card1,StackCard1),
	    topcard(Card2,StackCard2),
	    is_fourteen(Card1,Card2).

The comment and the code couldn't contradict each other more
strongly.  The comment talks about a list, but there is no
list in the code.  The comment says "check", but the code will
"find".  The code even contradicts itself:  how can Card1 and
Card2 both be the top card?  The names in the code contradict
what the code does:  Card1 and Card2 are not (names of) cards
at all, but of card faces, and StackCard1 and StackCard2 are
not stacks, not cards, not stacks of cards, nor anything that
could be called a StackCard, but appear to be positions in a
sequence.  And again we have cards equalling numbers, which
makes as much sense as birds equalling typefaces.

Presumably this should be something like

	%   stacked_pair_summing_to_fourteen(Face1, Face2, Pos1, Pos2)
	%   is true when there is a card with face Face1 at position
	%   Pos1 in the stack, and a card with face Face2 at position
	%   Pos2 in the stack, and the ranks of those cards sum to
	%   fourteen.

	stacked_pair_summing_to_fourteen(Face1, Face2, Pos1, Pos2) :-
	    card_face_position(Face1, Pos1), % was topcard/2
	    card_face_position(Face2, Pos2),
	    ranks_sum_to_fourtenn(Face1, Face2).

	When I run this I get dups.

No you don't.

	A = 5
	B = 9
	C = 3
	D = 4 ;
	
	A = 9
	B = 5
	C = 4
	D = 3 
	
That's not a duplicate.  The two solutions I've quoted are DIFFERENT
solutions which are both really genuine right answers to the question
you asked.  Presumably what you really mean is

	%   stacked_pair_summing_to_fourteen(Face1, Face2, Pos1, Pos2)
	%   is true when there is a card with face Face1 at position
	%   Pos1 in the stack, and a card with face Face2 at position
	%   Pos2 in the stack, Pos1 is above Pos2, and the ranks of
        %   those cards sum to fourteen.

	stacked_pair_summing_to_fourteen(Face1, Face2, Pos1, Pos2) :-
	    card_face_position(Face1, Pos1),
	    card_face_position(Face2, Pos2),
	    Pos1 < Pos2,  % Pos1 is above Pos2
	    ranks_sum_to_fourtenn(Face1, Face2).