Search code examples
prologclpfdconstraint-programming

Puzzle taken from Gardner


I'm trying to solve the following puzzle in Prolog:

Ten cells numbered 0,...,9 inscribe a 10-digit number such that each cell, say i, indicates the total number of occurrences of the digit i in this number. Find this number. The answer is 6210001000.

This is what I wrote in Prolog but I'm stuck, I think there is something wrong with my ten_digit predicate:

%count: used to count number of occurrence of an element in a list

count(_,[],0).
count(X,[X|T],N) :-
    count(X,T,N2),
    N is 1 + N2.
count(X,[Y|T],Count) :-
    X \= Y,
    count(X,T,Count).

%check: f.e. position = 1, count how many times 1 occurs in list and check if that equals the value at position 1
check(Pos,List) :-
    count(Pos,List,Count),
    valueOf(Pos,List,X),
    X == Count.

%valueOf: get the value from a list given the index
valueOf(0,[H|_],H).
valueOf(I,[_|T],Z) :-
    I2 is I-1,
    valueOf(I2,T,Z).

%ten_digit: generate the 10-digit number    
ten_digit(X):-
    ten_digit([0,1,2,3,4,5,6,7,8,9],X).

ten_digit([],[]).
ten_digit([Nul|Rest],Digits) :-
    check(Nul,Digits),
    ten_digit(Rest,Digits).

How do I solve this puzzle?


Solution

  • Check out the constraint global_cardinality/2.

    For example, using SICStus Prolog or SWI:

    :- use_module(library(clpfd)).
    
    ten_cells(Ls) :-
            numlist(0, 9, Nums),
            pairs_keys_values(Pairs, Nums, Ls),
            global_cardinality(Ls, Pairs).
    

    Sample query and its result:

    ?- time((ten_cells(Ls), labeling([ff], Ls))).
    1,359,367 inferences, 0.124 CPU in 0.124 seconds (100% CPU, 10981304 Lips)
    Ls = [6, 2, 1, 0, 0, 0, 1, 0, 0, 0] ;
    319,470 inferences, 0.028 CPU in 0.028 seconds (100% CPU, 11394678 Lips)
    false.
    

    This gives you one solution, and also shows that it is unique.