Как убедиться, что только 3 из 5 чисел совпадают? - PullRequest
1 голос
/ 01 июня 2019

Я использую clpfd и у меня 5 переменных, как я могу убедиться, что максимум 3 из этих 5 переменных будут одинаковыми?Например:
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 голосов
/ 02 июня 2019

Вот, пожалуйста!

Код:

:-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: ..

NUMBERS: количество имеющихся у вас чисел - в вашем случае это 5

DOMAIN: домен, в котором ваши номера принимают значение (например, 1..10, 3..7 и т. Д.)

РЕЗУЛЬТАТ: возвращаемый список / вывод.

...