2016-03-09 14 views
2

假設我有一個英雄和幾個怪物的遊戲。如果你擊敗了他們,每個怪物都會給予一定數量的分數。如何對不同事實中的數字求和?

total_score(Hero, Score):- 
    defeated(Hero, Monster), 
    score(Monster, Points), 
    Score is Points. 

monster(bat). 
monster(skeleton). 
monster(boss). 

score(bat, 100). 
score(skeleton, 100). 
score(boss, 1000). 

defeated(bob, bat). 
defeated(bob, skeleton). 
defeated(bob, boss). 

如果我將來的請求:

?- total_score(bob, Y). 

我想答案是:

Y : 1200. 

,但我得到相反:

Y : 100, 
Y : 100, 
Y : 1000. 

什麼變化我應該用total_score來製作它工作?我明白爲什麼我會得到這個結果,但我真的不知道該如何做一個事實總結。

+3

的可能的複製[如何總結從多個結果謂詞在序言?](http://stackoverflow.com/questions/35867950/how-to-sum-multiple-results-from-a-predicate-in-prolog) – lurker

+2

@lurker它的確是這是一個近乎重複,但這個問題質量更好,答案也非常模糊(基本上只是指向文檔),所以我認爲已經成熟了一個適當的答覆:) –

回答

1

聚集由給定的目標是findall/3的所有答案的標準方法。我們可以通過修改total_score/2從而達到你想要的目的:

total_score(Hero, Score):- 
    findall(Points, 
      (defeated(Hero, Monster), 
       score(Monster, Points)), 
      Points), 
    sum_list(Points, Score). 

SWI-Prolog documentation for findall/3草圖停止使用謂詞這樣的:findall(+Template, :Goal, -Bag)。即,我們找到所有解決方案,例如Template給定Goal,這些值收集在Bag中。正如你從我提供的例子看到的那樣,目標可以是一個複合詞(即連詞或分詞)。

然而,SWI-Prolog的也提供了(默認值,即不需要明確的輸入)library(aggregate),有了它我們避免調用sum_list/2,即:

total_score(Hero, Score):- 
    aggregate_all(sum(Points), 
        (defeated(Hero, Monster), 
        score(Monster, Points)), 
        Score). 
3

嗯,我設法找到解決方案,事情是,我知道我可以使用findall和sum_list,但我不知道如何將不同的關係連接在一起。我終於設法找到了一些研究之後,解決方案...所以我做:

total_score(Hero, Score):- 
    findall(Points, (defeated(Hero, Monster), score(Monster, Points)), ListOfPoints), 
    sum_list(ListOfPoints, Score). 
相關問題