2015-12-08 18 views
5

Tôi đang cố gắng viết biến vị ngữ rowN/3 trả về phần tử n thứ (trong trường hợp này) của ma trận. Ví dụ:Prolog - Trả về hàng thứ n của ma trận

?- rowN([[1,2],[3,4],[5,6]], 2, R). 
R = [3,4]; 
No 

Tôi đang gặp khó khăn với bộ đếm. Tôi đã thử không thành công để tìm một số ví dụ khá giống nhau. Cho đến nay tôi đã quản lý để viết những dòng này:

Code:

rowN(L,[],[]). 
rowN([],X,[]). 
rowN([],[],[]. 
rowN([H|T],X,R) :- 
    A==X, 
    A is A + 1, 
    rowI(T,A,H). 

Trả lời

4

dòng này không có ý nghĩa nhiều:

rowN(L,[],[]). 

vì đối số thứ hai là một số nguyên (nếu tôi hiểu đúng) và bạn sử dụng danh sách. Đây là trường hợp với gần như tất cả các đối số của bạn. Hơn nữa, bạn sử dụng RowI trong cuộc gọi đệ quy của mình?

Giải pháp

Một giải pháp là lần đầu tiên xác định rằng hàng đầu tiên (I = 1), tương đương với người đứng đầu của ma trận:

rowN([H|_],1,H). 

tiếp theo bạn cần phải tìm một cách lặp đi lặp lại để liệt kê thông qua ma trận của bạn. Vì vậy, các tiêu đề chắc chắn là một cái gì đó có dạng:

rowN([H|T],I,X) :- 
# ... 

Bây giờ chúng ta sẽ cho rằng I không bằng 1 (chúng tôi sẽ thảo luận về chủ đề này sau). Trong trường hợp đó, chúng ta cần phải đi qua ma trận xa hơn, vì vậy chúng tôi sẽ có đuôi và đặt bộ đếm I một mặt sau. Điều này có thể được thực hiện bằng:

rowN([_|T],I,X) :- 
    I1 is I-1, 
    rowN(T,I1,X). 

Vì vậy, vị ngữ của chúng ta đọc:

rowN([H|_],1,H). 
rowN([_|T],I,X) :- 
    I1 is I-1, 
    rowN(T,I1,X). 

Bây giờ nếu bạn sử dụng ngữ này, nó sẽ cho kết quả chính xác:

?- rowN([[1,2],[3,4],[5,6]], 2, R). 
R = [3, 4] ; 
false. 

Câu hỏi đặt ra là tại sao không biến vị ngữ không tạo ra kết quả khác: sau khi hiển thị kết quả đầu tiên, cho rowN([[1,2],[3,4],[5,6]], 2, R) :- rowN([[3,4],[5,6]],1,[3,4])., nó có thể tìm cách thay thế. Nó làm như vậy bằng cách sử dụng mệnh đề thứ hai, nhưng sau đó nó cuối cùng sẽ chạy ra khỏi các hàng và gọi cho vị từ rowN([],_,_), vì không phù hợp với các mệnh đề, nó sẽ thất bại.

Giải pháp này không hoàn hảo: nó không hoạt động đúng mọi hướng, mà nói chung là khó trong Prolog. Đó là lý do tại sao các lập trình viên Prolog giỏi có thư viện viết.

Sử dụng 's BUILTIN nth1/3

Thay vì reinventing the wheel, bạn có thể tận dụng các nth1/3 vị trong SWI-Prolog. Mặc dù các đối số được hoán đổi - bạn cần gọi nó là nth1(2,[[1,2],[3,4],[5,6]],R). - nó có lợi thế là nó hoạt động theo nhiều hướng hơn mà hầu hết mọi người có thể đưa ra trong một giải pháp nhanh, nó gần như là một bugfree (vì nó đã được kiểm tra hàng tỷ lần bởi tất cả các chương trình Prolog sử dụng biến vị ngữ) và một số các nội trang này được triển khai trong C++ làm cho chúng đôi khi nhanh hơn.Ví dụ:

?- nth1(2, [[1,2],[3,4],[5,6]], R). 
R = [3, 4]. 

?- nth1(I, [[1,2],[3,4],[5,6]], [5,6]). 
I = 3. 

?- nth1(I, [[1,2],[3,4],[5,6]], R). 
I = 1, 
R = [1, 2] ; 
I = 2, 
R = [3, 4] ; 
I = 3, 
R = [5, 6]. 

?- nth1(I,M,[2,3]). 
I = 1, 
M = [[2, 3]|_G23] ; 
I = 2, 
M = [_G22, [2, 3]|_G26] ; 
I = 3, 
M = [_G22, _G25, [2, 3]|_G29] ; 
I = 4, 
M = [_G22, _G25, _G28, [2, 3]|_G32] . 

Bạn do đó có thể yêu cầu những gì hàng thứ hai là, hỏi nơi hàng [5,6] có vị trí, làm cho truy vấn chung chung hơn bằng cách trả lời với các bộ của chỉ số I và hàng R và tạo ra một ma trận với một hàng [2,3] ở đâu đó.

+2

Câu trả lời này rất sâu sắc! Thankyou @CommuSoft –

Các vấn đề liên quan