列表中相同数字的 Prolog Max 2

Prolog Max 2 of the same numbers in a list

让我们进入正题。 我正在尝试自己制作一个数独构造求解器(与学校无关)。我一直在寻找一些方法来让它发挥作用,但我遇到了一个问题,也许更多人遇到过。

因为在一行或一列中可能有相同数字的倍数,例如,如果数独是 10 x 10,而您必须填写 1 到 5 之间的数字,则固解将为 1,2 ,1,3,2,3,4,5,4,5。由于所有数字都已使用并且最小值和最大值为 2。现在问题仍然存在,我如何编写一个接受列表的谓词和 returns 基于列表中的数字的真或假。

因为不可能使用内置谓词 all_distinct 但可能看起来像它,因为如果有 2 个相同的数字,现在而不是所有不同的都是不同的,如果你跟着我.

我试图做一些丑陋的固定谓词,但它并没有引导我到任何地方。 例如。

distinct_but_2(A,B,C,D) :-
(   A = B
->  A \= C,
    A \= D),
(   A = C
->  A \= B,
    A \= D),
(   A = D
->  A \= B,
    A \= C),
(   B = A
->  B \= C,
    B \= D),
(   B = C
->  B \= A,
    B \= D),
(   B = D
->  B \= A,
    B \= C),
(   C = A
->  C \= B,
    C \= D),
(   C = B
->  C \= A,
    C \= D),
(   C = D
->  C \= A,
    C \= B),
(   D = A
->  D \= B,
    D \= C),
(   D = B
->  D \= A,
    D \= C),
(   D = C
->  D \= A,
    D \= B).

其中我只是想说如果 A = B 那么它不等于所有其他元素,但我仍然缺乏它需要让所有元素都具有相同的另一个元素.

这是我试过的另一个例子

    distinct_but_2(A,B,C,D) :-
(isEqual(A,B), isEqual(C,D), notIsEqual(A,C), notIsEqual(A,D));
(isEqual(A,C), isEqual(B,D), notIsEqual(A,B), notIsEqual(A,D));
(isEqual(A,D), isEqual(B,C), notIsEqual(A,B), notIsEqual(A,C)).

isEqual(A,B) :- A = B.

notIsEqual(A,B) :- A \= B.

查询结果distinct_but_2(1,1,2,2)。 会是真的,但它说它还有其他解决方案。那是假的。我完全不明白为什么。

所以最后一个问题是,如果所有元素的最小值和最大值都相同,是否可以创建一个谓词来检查列表。

*请注意,由于我试图使其适用于 4 个元素,因此我没有制作接受列表的谓词,但我应该接受一个列表。

你没有说你使用的是哪个 Prolog 系统,但你似乎在寻找类似 global_cardinality/{2,3} 的东西,因为 SWI 有它:http://www.swi-prolog.org/pldoc/man?predicate=global_cardinality/3

这是一个如何使用它的例子:

:- use_module(library(clpfd)).

two_each(Numbers, Vars) :-
    length(Numbers, Len),
    Len2 #= 2*Len,
    length(Vars, Len2),
    bagof(X-2, member(X, Numbers), Pairs),
    global_cardinality(Vars, Pairs).

查询:

?- two_each([1,2,3], Vars), label(Vars).
Vars = [1, 1, 2, 2, 3, 3] ;
Vars = [1, 1, 2, 3, 2, 3] ;
Vars = [1, 1, 2, 3, 3, 2] 

带数独提示的查询:

?- two_each([1,2,3], Vars), Vars=[_,3,_,1,1,_], label(Vars).
Vars = [2, 3, 2, 1, 1, 3] ;
Vars = [2, 3, 3, 1, 1, 2] ;
Vars = [3, 3, 2, 1, 1, 2].