GNU Prolog - 搜索事实列表

时间:2010-12-15 03:57:41

标签: prolog rules

我必须有一个大脑放屁或其他东西,但我似乎无法找到解决方案。

如果您有列表事实,例如:

%country(country, population, capital)
country(sweden, 8823, stockholm).
country(usa, 221000, washington).
country(france, 56000, paris).
country(denmark, 3400, copenhagen).

%city(city, country, population)
city(lund, sweden, 88).
city(new_york, usa, 5000).
city(paris, usa, 1).
city(copenhagen, denmark, 1200).
city(aarhus, denmark, 330).
city(odense, denmark, 120).
city(stockholm, sweden, 350).
city(washington, usa, 3400).
city(paris, france, 2000).
city(marseilles, france, 1000).

我想找到第二大人口稠密的城市,在这种情况下将是华盛顿,拥有3400人。你怎么能这样做?

感谢。

2 个答案:

答案 0 :(得分:4)

尝试这个尺寸:

second_largest_city(City) :-
    findall(Size, city(_, _, Size), Sizes),
    sort(Sizes, SortedSizes),
    append(_, [Size2, _], SortedSizes),
    city(City, _Country, Size2).

说明findall/3查找所有city/3个事实的大小,这些事实按sort/2排序为升序顺序重复删除。对append/3模式的调用匹配将排序列表SortedSizes分成两部分;任意大小的列表(_)和长度为2的余数([Size2, _]) - 这会将变量Size2city/3个事实中的第二大城市大小绑定。最后,具有此大小的所有城市都位于city/3个事实之中,并且在输出上受到约束。

注意:如果sort/2 的内置功能不删除重复内容,则一般无法正常运行,因为这样可以解决问题city/3具有多个相等最大值的事实将仅返回最大值(最大值)。使用append/3来查找排序的大小列表的倒数第二个元素的此实现也假设sort/2排序的数字按升序排列。

另外,最后请注意,如果少于两个city/3事实,这将彻底失败 - 但这可能没问题,因为谓词寻找“第二大”城市,严格来说不会除非确实在DB中有至少两个城市的大小不同,否则不会成为一个城市。如果这是一个问题,您可以为second_largest_city/1编写更多条款来处理这种情况。

答案 1 :(得分:3)

@ sharky的优秀答案稍微缩短版本:

second_largest_city(Second) :-
    setof(Size/City, Country^city(City,Country,Size), Cities),
    append(_, [_/Second, _], Cities).

setof结合了findallsort。我们收集Size/City对,因此它们会自动按大小排序。构造X^Goal引入了一个存在量化变量X(如一阶逻辑中的∃ x )。