Search code examples
listprologdigitsvisual-prolog

Prolog - Counting matches in two lists


I'm trying to understand the language of the prologue (using the program Visual Prolog 5.1/5.2)

There is a task - to realize the game "Bulls and Cows" (or an Outstanding mind).

The player makes a number (composed of numbers from 0 to 9, without repetition), for example, 1458, and enters it into the program. The computer tries to guess this number, putting forward assumptions. And then he asks the player how many “bulls” (exact matches), and how many “cows” (matched numbers that are not in their proper places). I wrote a program that does it. It works.

Now I want the computer to count the number of bulls and cows. How to do it right?

This is a work with two lists.

DOMAINS
list = integer*

list1 - Key (hidden number), list2 - assumption (computer)

I tried to write a predicate for bulls counting, but the program produces "No solution" (perhaps because of the reason below (converting))

comparison(_Key, Assemption, Bulls /*, Cows*/):-
    find_bulls(_Key, Assemption, Bulls),
    %find_cows(_Key, Assemption, Cows).

find_bulls(Key, Assemption, Bulls):- 
    find_bulls(Key, Assemption, Bulls, 0).

find_bulls([],[], Bulls, Amount):- Bulls=Amount,!.
find_bulls([A1|L1],[A2|L2], Bull, Amount):- 
    A1 = A2,
    Am = Amount + 1,
    find_bulls(L1, L2, Bull, Am). 

I also read the number through readint(_Key), but _Key not a list, is it? how do I convert the integer to the list to feed the predicate?

question(Assemption,_Key):-  
    assemption(Assemption), 
    not(contradictory(Assemption)), 
    %------------------------------------------------------------
    comparaison(_Key,Assemption, Bulls /*,Cows*/),
    %------------------------------------------------------------
        write("   My assemption: ", Assemption), nl,
        write("How much bulls? -----> ", Bulls), nl, %readint(Bulls),
        write("How much cows? -----> "), /*Cows)*/ readint(Cows), nl,
    Bulls + Cows <= size,
    assert(request(Assemption, Bulls, Cows)), 
    Bulls = size,
    !.

Thank You!

/-----------------------------------------------------------------------------/

new Addition (read list from keyboard, stoped while input char):

 domains
      list=integer*
   predicates
      readlist(list)
   clauses
      readlist([H|T]):-
         write("> "),
         readint(H),!,
         readlist(T).
      readlist([ ]).

Solution

  • [SOLVED]

    find_bull_and_cows(OldAssemption,Assemption,Bulls,Cows):-
            exact_match(OldAssemption,Assemption,Bulls),
            common_numbers(OldAssemption,Assemption,N2),
            Cows= N2 - Bulls.
    
    %bulls finding
        exact_match(X,Y,N):- exact_match(X,Y,0,N).
        exact_match([Digit|OldPin],[Digit|NewPin],K,N):- !, 
            K1=K+1,
            exact_match(OldPin,NewPin,K1,N).
        exact_match([_|OldPin],[_|NewPin],K,N):- exact_match(OldPin,NewPin,K,N).
        exact_match([],[],N,N).
    
    %cows finding
        common_numbers(X,Y,N):- common_numbers(X,Y,0,N).
        common_numbers([Digit|OldPin],NewPin,K,N):- 
            member(Digit,NewPin), !, 
            K1=K+1,
            common_numbers(OldPin,NewPin,K1,N).     
        common_numbers([_|OldPin],NewPin,K,N):- common_numbers(OldPin,NewPin,K,N).
        common_numbers([],_,N,N).    
    
    %member of list
        member(A,[A|_]):- !.
        member(A,[_|L]):- member(A,L).