2016-04-21 16 views
5

Giả sử tôi muốn biểu diễn các số nguyên như sau: integer:Sign:[FirstDigit,SecondDigit,...]. Ví dụ: 42 sẽ được biểu thị là integer:positive:[4,2].Danh sách các số nguyên và vòng lặp vô hạn trong Prolog CLPFD

Tôi cần một vị từ tạo giá trị của số nguyên dựa trên biểu diễn này và ngược lại.

Dưới đây là những gì tôi đã đưa ra:

integer_value_('integer':Sign:[H],E) :- 
    H in 0..9, 
    (
     Sign = 'positive', 
     E #= H 
     ; 
     Sign = 'negative', 
     E #= -H 
    ). 
integer_value_('integer':Sign:[H,I|T],E) :- 
    H in 0..9, 
    length([I|T],L), 
    (
     Sign = 'positive', 
     E #= F + H * 10^L 
     ; 
     Sign = 'negative', 
     E #= F - H * 10^L 
    ), 
    integer_value_('integer':Sign:[I|T],F). 

này hoạt động như mong đợi. Tuy nhiên, nó có đặc tính không may khi chấp nhận những thứ như integer:positive:[0,1], tức là, dẫn đầu số 0 ở đầu danh sách. Điều này đặc biệt có vấn đề khi tôi liệt kê tất cả các số nguyên có thể sử dụng integer_value_(I,J), label([J]).: các số nguyên có số 0 đứng đầu cũng hiển thị.

sau đó tôi đã cố gắng để sửa chữa điều này bằng cách sử dụng integer_value_ chỉ cho tất cả nhưng chữ số đầu tiên, và sử dụng integer_value cho người đầu tiên (hãy nhớ rằng chúng ta cần phải chứa số 0 được trình bày với một danh sách chỉ chứa 0):

integer_value('integer':Sign:[H],E) :- 
    abs(E) #< 10, 
    abs(E) #> -1, 
    integer_value_('integer':Sign:[H],E). 
integer_value('integer':Sign:[H,I|T],E) :- 
    H in 1..9, 
    length([I|T],L), 
    (
     Sign = 'positive', 
     E #= F + H * 10^L 
     ; 
     Sign = 'negative', 
     E #= F - H * 10^L 
    ), 
    integer_value_('integer':Sign:[I|T],F). 

Tuy nhiên, hiện tại nó không hoạt động đúng cách. Ví dụ, integer_value(I,-19). trả về I = integer:negative:[1, 9], nhưng nếu chúng ta yêu cầu một câu trả lời khác, Prolog đi vào vòng lặp vô hạn vì những lý do tôi không hiểu (nó nên nói sai, hoặc đã biết không có câu trả lời nào khác).

Vấn đề này không xảy ra với truy vấn "đối diện" integer_value(integer:negative:[1,9],Z). trả về Z = 19 và sau đó giả mạo cũng không xảy ra khi cả hai đối số là Biến (nó liệt kê số đúng, không có số 0 đứng đầu).

Bất kỳ ý tưởng nào về vòng lặp vô hạn đó xảy ra và nếu có cách nào dễ dàng để sửa lỗi đó?

+0

+1 cho trường hợp sử dụng CLP (FD) rất thú vị và phù hợp! Tôi có một bình luận nhỏ liên quan đến dấu nháy đơn: Bạn có thể bỏ qua ''' cho tất cả các nguyên tử không cần những dấu ngoặc kép như 'positive',' negative', 'integer' vv. , chẳng hạn như 'Dấu = tích cực',' Dấu = tiêu cực' và 'số nguyên: Ký hiệu: [I | T]'. – mat

+0

@mat Tôi biết, nhưng kể từ khi tôi không phải là một lập trình viên Prolog tôi thấy nó khá xấu xí để có các nguyên tử như thế: p – Fatalize

Trả lời

5

Để xem vấn đề, bạn chỉ cần xem một phần nhỏ trong chương trình của mình. Trong thực tế, Sau đây là đủ:

 
integer_value('integer':Sign:[H],E) :- false, 
    abs(E) #< 10, 
    abs(E) #> -1, 
    integer_value_('integer':Sign:[H],E). 
integer_value('integer':Sign:[H,I|T],E) :- 
    H in 1..9, 
    length([I|T],L), false, 
    ( Sign = 'positive', 
     E #= F + H * 10^L 
     ; 
     Sign = 'negative', 
     E #= F - H * 10^L 
    ), 
    integer_value_('integer':Sign:[I|T],F). 

L xảy ra ở đây lần đầu tiên, vì vậy bất kỳ chiều dài là có thể. Bạn sẽ phải sửa đổi mục tiêu độ dài bằng cách nào đó.

+1

Nevermind tôi đã nhận nó. Bây giờ để giải quyết nó ... – Fatalize

+2

@Fatalize: Xem [this] (http://stackoverflow.com/a/28442760/772868) cho một vấn đề liên quan. – false

3

tôi quản lý để giải quyết vấn đề của tôi sử dụng this other answer chỉ ra bởi @false

Một trong những nắm bắt được để quyết định các dấu hiệu của số như là bước cuối cùng, do đó khi lặp lại thông qua các số nguyên có thể chúng tôi có được câu trả lời xen kẽ giữa số dương và âm: sau khi đạt 9 (1 chữ số), nó sẽ hợp nhất với -9, rồi -8, vv Sau -1, nó sẽ hợp nhất với 10, 11, v.v. Sau 99, nó sẽ hợp nhất với -99 , -98, v.v. Bạn nhận được điểm.

integer_value('integer':Sign:I,E) :- 
    integer_value('integer':Sign:I,0,E,E). 

integer_value('integer':Sign:[H],N0,N,M) :- 
    H in 0..9, 
    N1 #= H + N0 * 10, 
    abs(M) #>= abs(N1), 
    integer_value_('integer':Sign:[],N1,N,M). 
integer_value('integer':Sign:[H,I|T],N0,N,M) :- 
    H in 1..9, 
    N1 #= H + N0 * 10, 
    abs(M) #>= abs(N1), 
    integer_value_('integer':Sign:[I|T],N1,N,M). 

integer_value_('integer':Sign:[],N0,N,_) :- 
    (
     Sign = 'positive', 
     N #= N0 
     ; 
     Sign = 'negative', 
     N #\= 0, 
     N #= - N0 
    ). 
integer_value_('integer':Sign:[H],N0,N,M) :- 
    H in 0..9, 
    N1 #= H + N0 * 10, 
    abs(M) #>= abs(N1), 
    integer_value_('integer':Sign:[],N1,N,M). 
integer_value_('integer':Sign:[H,I|T],N0,N,M) :- 
    H in 0..9, 
    N1 #= H + N0 * 10, 
    abs(M) #>= abs(N1), 
    integer_value_('integer':Sign:[I|T],N1,N,M). 
Các vấn đề liên quan