2013-06-13 2 views
1

숫자가 포함 된 복합 용어의 가능한 모든 평가를 생성하는 술어를 만들려고합니다. assign_distinct_values([A-B], E).은 99 개의 결과를 산출해야합니다.용어의 변수에 다른 숫자 할당

  • 1-0
  • 0-1
  • : 같은 중복과 대칭 결과를 생성

    assign_distinct_values(E, A) :- 
         term_variables(E, V), 
         assign_distinct_values(E, V, [0,1,2,3,4,5,6,7,8,9], A). 
    
    assign_distinct_values(E, [], [], E). 
    assign_distinct_values(E, [], _, E). 
    assign_distinct_values(E, V, N, A) :- 
         select(Num, N, N2), 
         select(Var, V, V2), 
         Var is Num, 
         assign_distinct_values(E, V2, N2, A). 
    

    :

    그러나, 나는 내 현재의 노력의 비결정론을 찾을 수 없습니다

  • 0-1
  • 1-0
프롤로그 술어를 사용

답변

2

먼저 더 의미있는 이름 지정 규칙을 사용하는 것이 좋습니다 : 나는 목록을 나타내는 변수의 이름에 "S"를 추가하고 (0부터 시작)보다 체계적를 번호,보다 선언적를 사용하는 것이 좋습니다를 의미있는 술어 이름 :

with_distinct_integers(E0, E) :- 
     term_variables(E0, Vs), 
     with_distinct_integers(E0, Vs, [0,1,2,3,4,5,6,7,8,9], E). 

with_distinct_integers(E, [], [], E). 
with_distinct_integers(E, [], _, E). 
with_distinct_integers(E0, Vs0, Ns0, E) :- 
     select(Num, Ns0, Ns), 
     select(Var, Vs0, Vs), 
     Var is Num, 
     with_distinct_integers(E0, Vs, Ns, E). 

이제 with_distinct_integers/4에 초점을 맞추십시오. 첫 번째 절이 두 번째 절에 포함되어 있으므로 솔루션을 잃지 않고 첫 번째 절을 생략 할 수 있습니다. 변수 VarNum 그것을 통합하는 데 사용됩니다, 그래서 당신은 바로 하나의 변수 사용할 수 있습니다 : 당신은 여전히이 단순화 된 버전으로 의도하지 않은 중복 솔루션을 찾을 수

with_distinct_integers(E, [], _, E). 
with_distinct_integers(E0, Vs0, Ns0, E) :- 
     select(Num, Ns0, Ns), 
     select(Num, Vs0, Vs), 
     with_distinct_integers(E0, Vs, Ns, E). 

을, 내가 찾을 수있는 쉬운 운동으로 떠나

?- with_distinct_integers(X-Y, [X,Y], [0,1], A). 
..., A = 0-1 ; 
..., A = 1-0 ; 
..., A = 1-0 ; 
..., A = 0-1 ; 
false. 

힌트 : 선언적으로 단순화 된 정의를 통해 그냥 이유 무슨 일이 원인이 부족합니다. 단순화로 계속하기 : 필요한 변수, 즉 변수가 모두 필요한 경우 원래 용어를 그대로 사용해야하는 이유는 무엇입니까? 고려 :

with_distinct_integers(E) :- 
     term_variables(E, Vs), 
     numlist(0, 9, Ns), 
     with_distinct_integers(Vs, Ns). 

with_distinct_integers([], _). 
with_distinct_integers([V|Vs], Ns0) :- 
     select(V, Ns0, Ns), 
     with_distinct_integers(Vs, Ns). 

예 쿼리를 모든 솔루션을 계산 :

?- findall(., with_distinct_integers([X-Y]), Ls), length(Ls, L). 
Ls = ['.', '.', '.', '.', '.', '.', '.', '.', '.'|...], 
L = 90. 

서프라이즈를 측면에 : 만 90 솔루션,하지 (99)이있다.

또한 당신이 쉽게 작업을 공식화하자 정수 이상의 관계입니다 유한 도메인 제약 조건, 사용을 고려 :

:- use_module(library(clpfd)). 

with_distinct_integers(E) :- 
     term_variables(E, Vs), 
     Vs ins 0..9, 
     all_different(Vs), 
     label(Vs). 

예 쿼리를 다음 그 아주 특별한 경우를

?- with_distinct_integers(X-Y). 
X = 0, 
Y = 1 ; 
X = 0, 
Y = 2 ; 
X = 0, 
Y = 3 . 
+0

위대한 anwser, cplfd를 사용하지 않는 설명 주셔서 감사합니다. – vvondra

2

L 값 E리스트되고, 상기 출력 변수

assign_distinct_values(E, A, L) :- 
    member(E,L), 
    delete(L,E,L1), 
    member(A,L1). 

상당히 빠르다. member(X,L)은 X가 L에 있는지 검사하고, 그렇다면 delete(L,X,L1)과 함께 X가 포함되지 않은 새 목록 L1을 만들고 동일한 방법으로 두 번째 구성원을 다시 확인합니다.

또 다른 버전 :

assign_distinct_values(E, A) :- 
    L = [0,1,2,3,4,5,6,7,8,9], 
    member(E,L), 
    delete(L,E,L1), 
    member(A,L1). 

가 작동합니까? 내 컴퓨터에 프롤로그가 설치되어 있지 않습니다.

감사

+0

이 유일한 작품 주어진 용어는 * 하나의 변수입니다. 그러나 OP의 유스 케이스에서,이 용어는 실제로 여러 변수를 포함 할 수 있습니다. 예를 들어'? - assign_distinct_values ​​(X-Y, E, [0,1]) .' 쿼리에 해당합니다. – mat