Search code examples
prologzebra-puzzle

prolog printing out same answer for different parameters


I am writing a Prolog program that solves a logic puzzle. When trying to print out the answers its gives me the same answers for all of them. The answers to the logic puzzle are:

  • genevieve bought a size 4 manzarita
  • lucia bought a size 7 Graffetz
  • shawna bought a size 5 williford
  • vanessa bought a size 6 Abbot Hill

my code is the following:

customer(genevieve).
customer(lucia).
customer(shawna).
customer(vanessa).

shoesize(4).
shoesize(5).
shoesize(6).
shoesize(7).

manufactorer(abbothill).
manufactorer(manzarita).
manufactorer(graffetz).
manufactorer(williford).

solve :-
   shoesize(GenevieveShoesize),
   shoesize(LuciaShoesize),
   shoesize(ShawnaShoesize),
   shoesize(VanessaShoesize),
   all_different([GenevieveShoesize, LuciaShoesize, ShawnaShoesize,     VanessaShoesize]),
   manufactorer(AbbotHillManufactorer),
   manufactorer(ManzaritaManufactorer),
   manufactorer(GraffetzManufactorer),
   manufactorer(WillifordManufactorer),

   all_different([AbbotHillManufactorer, ManzaritaManufactorer, 
    GraffetzManufactorer, WillifordManufactorer]),
   List = [ [genevieve,GenevieveShoesize,AbbotHillManufactorer],
      [lucia,LuciaShoesize,ManzaritaManufactorer],
      [shawna,ShawnaShoesize,GraffetzManufactorer],
      [vanessa,VanessaShoesize,WillifordManufactorer]],

   \+(member([_,5,manzarita],List)),
   \+(member([_,6,manzarita],List)),
   \+(member([lucia,5,_],List)),
   \+(member([lucia,6,_],List)),
   \+(member([genevieve,_,abbothill],List)),
   \+(member([shawna,_,graffetz],List)),
   (member([vanessa,_,abbothill],List)),

   tell(genevieve,GenevieveShoesize,GeneieveManufactorer),
   tell(lucia,LuciaShoesize,LuciaManufactorer),
   tell(shawna,ShawnaShoesize,ShawnaManufactorer),
   tell(vanessa,VanessaShoesize,VanessaManufactorer).

all_different([H | T]) :- member(H,T), !, fail.
all_different([_ | T]) :- all_different(T).
all_different([]).


tell(X,Y,Z) :-
   customer(X),
   shoesize(Y),
   manufactorer(Z),
   write(X), write(' got their shoes from'),
   write(Y), write(' and is a size '), write(Z), nl.

When I go to SWI and ask it to:

-tell(X,Y,Z) it outputs: X equals genevieve, Y equals 4, Z equals abbot hill.

and if I specify one of the variables for example tell(vanessa,Y,Z) it will print out : vanessa bought a size 4 abbot hill ; leaving the values of Y and Z the same.


Solution

  • The answers to the logic puzzle are: -genevieve bought a size 4 manzarita -lucia bought a size 7 Graffetz -shawna bought a size 5 williford -vanessa bought a size 6 Abbot Hill"

    If those are the only answers to the puzzle then your logic is wrong, your code generates alot more answers than that.

    Here are some of the solutions according to your program:

    X = genevieve,
    Y = 4,
    Z = abbothill ;
    genevieve got their shoes from4 and is a size manzarita
    X = genevieve,
    Y = 4,
    Z = manzarita ;
    genevieve got their shoes from4 and is a size graffetz
    X = genevieve,
    Y = 4,
    Z = graffetz ;
    genevieve got their shoes from4 and is a size williford
    X = genevieve,
    Y = 4,
    Z = williford ;
    genevieve got their shoes from5 and is a size abbothill
    X = genevieve,
    Y = 5,
    Z = abbothill ;
    genevieve got their shoes from5 and is a size manzarita
    X = genevieve,
    Y = 5,
    Z = manzarita ;
    genevieve got their shoes from5 and is a size graffetz
    X = genevieve,
    Y = 5,
    Z = graffetz ;
    genevieve got their shoes from5 and is a size williford
    X = genevieve,
    Y = 5,
    Z = williford ;
    

    If you want to find all unique solutions you can run: setof((X,Y,Z), tell(X,Y,Z), Y).

    Which generates 64 different solutions that are valid according to your program.

    if I specify one of the variables for example tell(vanessa,Y,Z) it will print out : vanessa bought a size 4 abbot hill ; leaving the values of Y and Z the same.

    It does'nt leave the values Y and Z the same, it simply means that Y = 4, Z = abbothill is the first solution to X = vanessa, you can generate the next solution with ; and you'll see that Y and Z are not always the same, e.g:

    ?- tell(vanessa,Y,Z).
    vanessa got their shoes from4 and is a size abbothill
    Y = 4,
    Z = abbothill ;
    vanessa got their shoes from4 and is a size manzarita
    Y = 4,
    Z = manzarita ;
    vanessa got their shoes from4 and is a size graffetz
    Y = 4,
    Z = graffetz ;
    vanessa got their shoes from4 and is a size williford
    Y = 4,
    Z = williford ;
    vanessa got their shoes from5 and is a size abbothill
    Y = 5,
    Z = abbothill ;
    

    Edit: If it is this logic puzzle you are aiming to solve:

    There are 4 customers: Genevieve, Lucia, Shawna, Vanessa

    There are 4 shoe sizes: 4, 5, 6, 7

    There are 4 shoe manufacturers: Abbott Hill, Manzarita, Graffetz, Williford

    1. Of the Manzarita footwear and Lucia's pair, one was a size 7 and the other was a size 4.

    2. Genevieve's pair was 2 sizes smaller than the Abbott Hill footwear.

    3. Vanessa's pair was 2 sizes larger than Genevieve's pair.

    4. The Graffetz footwear was somewhat larger than Shawna's pair.

    For each customer, show their name, their shoe size and their shoe's manufacturer in a format similar to this:

    Joe bought a size 13 Nike.

    Tom bought a size 12 Reebok.

    You can use something like this:

    customer(genevieve).
    customer(lucia).
    customer(shawna).
    customer(vanessa).
    
    shoesize(4).
    shoesize(5).
    shoesize(6).
    shoesize(7).
    
    manufactorer(abbothill).
    manufactorer(manzarita).
    manufactorer(graffetz).
    manufactorer(williford).
    
    four_or_seven(L):-
        member((lucia, 7, _), L),
        member((_, 4, manzarita), L).
    four_or_seven(L):-
        member((lucia, 4, _), L),
        member((_, 7, manzarita), L).
    
    less_than_abbott_hill(L):-
        member((genevieve, S0, _), L),
        member((_, S1, abbothill), L),
        S0 is S1-2.
    
    vanessa_larger_than_genevieve(L):-
        member((vanessa, S0, _), L),
        member((genevieve, S1, _), L),
        S0 is S1+2.
    
    graffetz_larger_than_shawna(L):-
        member((shawna, S0, _), L),
        member((_, S1, graffetz), L),
        S1 > S0.
    
    solve:-
        shoesize(S0), manufactorer(M0),
        shoesize(S1), manufactorer(M1),
        shoesize(S2), manufactorer(M2),
        shoesize(S3), manufactorer(M3),
        all_different([M0,M1,M2,M3]),
        L = [(genevieve, S0, M0), (lucia, S1, M1), (shawna, S2, M2), (vanessa, S3, M3)],
        four_or_seven(L),
        less_than_abbott_hill(L),
        vanessa_larger_than_genevieve(L),
        graffetz_larger_than_shawna(L),
        print(L).
    
    all_different([H | T]) :- member(H,T), !, fail.
    all_different([_ | T]) :- all_different(T).
    all_different([]).
    
    print([(C, S, M)|T]):-
        format("~p bhought a size ~p ~p~n", [C,S,M]),
        print(T).
    
    print([]).
    

    Note that there are multiple solutions to this puzzle, example run:

    ?- [puzzle].
    true.
    
    ?- solve.
    genevieve bhought a size 4 manzarita
    lucia bhought a size 7 graffetz
    shawna bhought a size 4 williford
    vanessa bhought a size 6 abbothill
    true ;
    genevieve bhought a size 4 manzarita
    lucia bhought a size 7 graffetz
    shawna bhought a size 5 williford
    vanessa bhought a size 6 abbothill
    true