2013-03-09 100 views
0

我只是無法理解我與prolog有關的這個問題。只是剛剛開始,但我似乎無法找到一種方法來查明對象是否是唯一的。繼承人我的代碼:我怎麼知道一個對象是否是唯一的

/* (Student Name, Student Number)*/ 
Student(stuart, 11234). 
Student(ross, 11235). 
Student(rose, 11236). 
Student(stuart, 11237). 

我怎麼能找出一個學生是否是獨一無二的。以Stuart爲例,有兩個學生叫Stuart,所以Stuart並不是唯一的。我怎麼能寫一個程序來判斷另一個學生是否叫斯圖爾特。

我試過在這上面花了這麼多小時,但我似乎無法控制原來的斯圖爾特而不是其他斯圖爾特,因爲我不能排除我正在尋找的那個如果其獨特的話。

感謝您的幫助。

回答

2

與數據庫例如,這可以做

​​

,因爲它產生

?- unique(S). 
S = ross ; 
S = rose ; 
false. 

一般來說,Prolog是朝着解決方案的存在針對性。然後關於基數的預測需要來自語言中「不純」部分的一些支持:nb_setarg它目前是我們最好的朋友,當我們需要有效地跟蹤基數。

使用這樣的metapredicate:

%% count_solutions(+Goal, ?C) 
% 
% adapted from call_nth/2 for http://stackoverflow.com/a/14280226/874024 
% 
count_solutions(Goal, C) :- 
    State = count(0, _), % note the extra argument which remains a variable 
    ( Goal, 
     arg(1, State, C1), 
     C2 is C1 + 1, 
     nb_setarg(1, State, C2), 
     fail 
    ; arg(1, State, C) 
    ). 

:- meta_predicate count_solutions(0, ?). 

你能解決這個問題,而不考慮第二個參數

unique(S) :- 
    student(S, _), count_solutions(student(S, _), 1). 

相同的謂詞可以使用aggregate_all(計數,學生(S,_) 1)來自庫(集合),但是這個庫目前在內部建立一個列表,那麼你可以考慮彼得的答案更容易實現。

+0

謝謝,我敢肯定,這是一種方法來做到這一點\ +,但我想你的解決方案處理它罰款:) – user1816481 2013-03-13 16:23:34

1

關於你的代碼的一些評論。這不是一個事實:

Student(Ross). 

這是兩個不同的事實(在SWI-Prolog的,至少):

student(ross). 
student('Ross'). 

換句話說,謂詞名稱必須以小寫字母開始,標識出發用大寫字母表示變量,而不是原子。您可以將任何字符串放在單引號中,使其成爲有效的原子。

現在,這是不利的,目前還不清楚你的目標是什麼。你將如何處理你的獨特的學生?你怎麼知道第一個是你正在尋找的那個,而不是第二個?爲什麼不使用學生號碼(至少在你的例子中兩個斯圖爾特似乎有不同的數字)?

+0

感謝您抽出一些時間來解決我的問題。是的,你說我的代碼無效。這只是一個如何做獨特的事情的例子。我想知道你是否可以用一種方式來表示學生是否獨一無二。是的,我可以使用學生號碼,但我真的很想知道一種方式,我可以告訴別人是否是獨一無二的。我將要對獨特的學生做什麼,告訴它是否唯一 – user1816481 2013-03-09 17:56:24

2

可能有相當多的解決這個問題的方法,但我會做這種方式:

% a student has a name and a number 
student(stuart, 11234). 
student(ross, 11235). 
student(rose, 11236). 
student(stuart, 11237). 

這段代碼說「找一個列表的長度相同的學生姓名的號碼」,然後「讓伯爵一樣的列表的長度」:

% a student name is unique (appears once and only once) is the 
% number_students count is 1 
unique_student(Name) :- 
    number_students(Name, 1). 
012:

% for every student name there is an associated count of how many times 
% that name appears 
number_students(Name, Count) :- 
    findall(_, student(Name, _), Students), 
    length(Students, Count). 

如果number_students是1此謂詞只會是真實的

測試:

12 ?- unique_student(ross). 
true. 

13 ?- unique_student(rose). 
true. 

14 ?- unique_student(bob). 
false. 

15 ?- unique_student(stuart). 
false. 

這是解決問題的一種簡單的方法,但因爲你不能說這樣的話是不是很大 Prolog的解決方案「給我一個獨特的學生姓名」,並得到一個列表所有獨特的名字。

+0

+1 @CapelliC答案。這比我的好多了! – 2013-03-10 12:16:13

+0

雖然仍然是一個很好的答案,感謝您的幫助:) – user1816481 2013-03-13 16:23:59

相關問題