在原子列表上引入预测的优雅/惯用方式是什么?

问题描述 投票:0回答:2

假设我有对象

a1,a2,...,a{n}
,我想对这些对象有效地引入一个顺序,例如:

gt(a1,a2).
gt(a2,a3).
...
gt(a{n-1},a{n}).

现在

{n}
会是一个很大的数字,比如 200。而不是写成 199 个事实。在 Prolog 中是否有“更好”的方法来做到这一点?

我正在考虑定义一个列表,然后将

gt
应用于该列表的
zip
并对其进行移动。

如果这完全违背了 Prolog 的使用方式,并且必须竭尽全力才能找到这样的解决方案,那么我完全接受一个简短的解释来说明为什么这是答案。

prolog
2个回答
0
投票

如何将它们按从小到大的顺序放入列表中,以及描述它们在列表中的关系的语法:

cards([ace, two, three, four, five, six, seven,
       eight, nine, ten, jack, queen, king]).

% see https://www.metalevel.at/prolog/dcg "any sequence at all"
... --> [] | [_], ... .

gt_([Small, Big]) --> ..., [Small], ..., [Big].

gt(Big, Small) :-
    cards(Cards),
    phrase(gt_([Small, Big]), Cards, _).

由于这会消耗列表一次,因此它在算法上稍微干净一些,但可能比以下内容不太清晰并且开销更大:

cards([ace, two, three, four, five, six, seven,
       eight, nine, ten, jack, queen, king]).

gt(Smaller, Bigger) :-
    cards(Cards),
    nth1(Sindex, Cards, Smaller),
    nth1(Bindex, Cards, Bigger),
    Bindex > Sindex.

两者都留下选择点,并且都可以用来生成诸如“X 皇后比什么大?”之类的查询的答案。

以下版本将列表中的元素与索引列表配对,不会留下选择点,但无法生成答案:

cards([ace, two, three, four, five, six, seven,
       eight, nine, ten, jack, queen, king]).
    
gt(Smaller, Bigger) :-
    cards(Cards),
    length(Cards, Len),
    numlist(1, Len, Counts),
    pairs_keys_values(Pairs, Cards, Counts),
    memberchk(Smaller-Sindex, Pairs),
    memberchk(Bigger-Bindex, Pairs),
    Bindex > Sindex.

最后两个对数字进行简单的比较,因此对于像 Queen > ace 这样的东西,它避免了必须跟踪整个传递关系 queen > jack > 10 > 9 > ... 2 > ace,但它确实必须扫描多次列出。

您可以将它们放入 SWI Prolog 字典中以获得更快的查找速度,但语法不标准。或者循环遍历它们,将信息放入 Prolog 数据库中,这似乎不推荐,或者更容易编写一些代码一次为您写出 199 个事实,然后将其复制粘贴到您的代码中。 (也许是:

assertz

然后查询两次并比较值。


0
投票

% card(name, value) card(ace, 1). card(two, 2). ... card(king, 13).

这是完全相关的 - 导致 swi-prolog:

% Human-convenient order card_order(ace). card_order(ten). card_order(king). % Fill in the rest yourself populate_order_nums :- nb_setval(cards, 1), forall( card_order(Card), ( nb_getval(cards, I), % Create facts of e.g. card(ten, 2) assertz(card(Card, I)), I1 is I + 1, nb_setval(cards, I1) ) ). % Runs this when the program is loaded :- populate_order_nums. % Fast, indexed lookup card_lower_higher(CL, CH) :- card(CL, Low), card(CH, High), Low @< High.

© www.soinside.com 2019 - 2024. All rights reserved.