如何确保5个数字中只有3个相同?

时间:2019-06-01 16:24:47

标签: prolog swi-prolog clpfd

我正在使用clpfd,并且我有5个变量,如何确保这5个变量中的最多3个相同? 例如:
1,1,1,2,2->允许
1,1,1,2,3->允许
1,1,1,1,4->不允许
...

我认为它会像这样工作:

number(N1),
number(N2),
number(N3),
number(N4),
number(N5),
((N1 #= N2 #/\ N1 #= N3) #==> (N1 #\= N4 #/\ N1 #\= N5)) #\/ ((N1 #= N2 #/\ N1 #= N4) #==> (N1 #\= N3 #/\ N1 #\= N5)) #\/ ...

但是这个解决方案似乎太长了,我想知道是否可以用更少的代码来解决它。

1 个答案:

答案 0 :(得分:0)

你去了!

代码:

:-use_module(library(clpfd)).

check([H1,H2,H3,H4]):- #\(H1#=H2#/\H2#=H3#/\H3#=H4),!.
check([H1,H2,H3,H4|T]):- #\(H1#=H2#/\H2#=H3#/\H3#=H4),check([H2,H3,H4|T]).

count_frequencies([],_,LIST,LIST).
count_frequencies([HEAD|TAIL],PREVIOUS,INIT,LIST):-
HEAD\=PREVIOUS,
count_frequencies(TAIL,HEAD,[HEAD-1|INIT],LIST).
count_frequencies([HEAD|TAIL],HEAD,[HEAD-F|T],LIST):-
    F2 is F+1,
    count_frequencies(TAIL,HEAD,[HEAD-F2|T],LIST).

max_frequency_is_3(NUMBERS,DOMAIN,RESULT):-
    length(LIST,NUMBERS),
    LIST ins DOMAIN,
    chain(LIST,#=<),
    check(LIST),
    label(LIST),
    count_frequencies(LIST,false,[],LIST2),
    length(RESULT,NUMBERS),
    global_cardinality(RESULT,LIST2),
    label(RESULT).

示例查询:

?- max_frequency_is_3(5,1..5,LIST).

结果:

L = [1, 1, 1, 2, 2] ;
L = [1, 1, 2, 1, 2] ;
L = [1, 1, 2, 2, 1] ;
L = [1, 2, 1, 1, 2] ;
L = [1, 2, 1, 2, 1] ;
...

max_frequency_is_3 / 3的参数是..

数字:您拥有的数字数量-在您的情况下为5

DOMAIN:您的数字所取值的域(例如1..10、3..7等)

结果:返回列表/输出。