【问题标题】:Shortest way to define multiple rules in prolog在 prolog 中定义多个规则的最短方法
【发布时间】:2011-01-04 15:36:12
【问题描述】:

我正在尝试解决一个练习,以便更加熟悉 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]

提前致谢。

【问题讨论】:

    标签: prolog logic-programming clpfd


    【解决方案1】:

    使用 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.
    

    【讨论】:

      【解决方案2】:

      某些版本的 Prolog 有 between/3 谓词。你可以说

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

      如果 between 不可用,你可以说

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

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

      编辑:你也可以像这样实现 between/3:

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

      between/3 的健壮且高效的实现可能更复杂,但就您的目的而言,这应该足够了。

      【讨论】:

      • 您的第二个选项仍然要求他拼出所有 100 个数字,因此仍然需要输入O(n)。效率也很低。
      • 是的,没错。另一方面, digit(X) :- 1 =
      • 好吧,我的错。我没有仔细阅读问题描述。
      • 怎么样:?- maplist(between(0,100), [L,R,T]), L+R+T =:= 100, L*50 + R*10 + T*1 =:= 500。当然,约束版本比这个简单的生成和测试要快得多。
      【解决方案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 .
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多