在prolog中定义多个规则的最短方法

时间:2011-01-04 15:36:12

标签: prolog logic-programming clpfd

我正在尝试解决练习,以便更熟悉prolog。

任务如下:

% Sten wants to send Lisa 100 flowers. He can choose from lilies, roses and tulips.
% One lily costs $50, rose $10 and tulip $1. Find how many flowers of each type he 
% must buy, so that he spends exactly $500.

我已经解决了这个练习,但我觉得有点笨重。我的代码是:

% numbers 1..100
digit(1). digit(2). digit(3). digit(4). digit(5). digit(6). digit(7). digit(8).
digit(9). digit(10). digit(11). digit(12). digit(13). digit(14). digit(15). digit(16). 
digit(17). digit(18). digit(19). digit(20). digit(21). digit(22). digit(23). digit(24). 
digit(25). digit(26). digit(27). digit(28). digit(29). digit(30). digit(31). digit(32). 
digit(33). digit(34). digit(35). digit(36). digit(37). digit(38). digit(39). digit(40).
digit(41). digit(42). digit(43). digit(44). digit(45). digit(46). digit(47). digit(48). 
digit(49). digit(50). digit(51). digit(52). digit(53). digit(54). digit(55). digit(56). 
digit(57). digit(58). digit(59). digit(60). digit(61). digit(62). digit(63). digit(64). 
digit(65). digit(66). digit(67). digit(68). digit(69). digit(70). digit(71). digit(72). 
digit(73). digit(74). digit(75). digit(76). digit(77). digit(78). digit(79). digit(80).
digit(81). digit(82). digit(83). digit(84). digit(85). digit(86). digit(87). digit(88). 
digit(89). digit(90). digit(91). digit(92). digit(93). digit(94). digit(95). digit(96). 
digit(97). digit(98). digit(99). digit(100).

quantity(A1,A2,A3):-
    var(A1), var(A2), var(A3),
    digit(A1), digit(A2), digit(A3),
    X is A1+A2+A3, X is 100,
    Y is (A1*50)+(A2*10)+(A3*1), Y is 500.

有人可以建议一种更好的方法来初始化这些规则吗?例如在Haskell中,我可以这样做:

let numbers = [1..100]

提前致谢。

3 个答案:

答案 0 :(得分:7)

使用SWI-Prolog:

:- use_module(library(clpfd)).

flowers(L, R, T) :-
        [L,R,T] ins 0..sup,
        L+R+T #= 100,
        L*50 + R*10 + T*1 #= 500.

示例查询:

?- flowers(Lilies, Roses, Tulips), label([Lilies,Roses,Tulips]).
Lilies = 1,
Roses = 39,
Tulips = 60 ;
false.

答案 1 :(得分:6)

Prolog的某些版本具有介于/ 3之间的谓词。你可以说

digit(X):-between(1,100,X).

如果没有,你可以说

digit(X):-member(X,[1,2,3,4,5 and so on]).

如果您不想使用member / 2,请使用递归。

编辑:你也可以像这样在/ 3之间实现:

my_between(X,Y,Z):-X<Y,(Z=X;X2 is X+1,my_between(X2,Y,Z)).

/ 3之间强大而有效的实现可能会更复杂,但就您的目的而言,这应该足够了。

答案 2 :(得分:3)

quantity(lilies(L),roses(R),tulips(T)) :- 
    between(0,100,L),
    between(0,100,R),
    between(0,100,T),
    L + R + T =:= 100,
    L*50 + R*10 + T =:= 500 .