Кратчайший способ определения нескольких правил в прологе - PullRequest
4 голосов
/ 04 января 2011

Я пытаюсь выполнить упражнение, чтобы лучше познакомиться с прологом.

Задача следующая:

% 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 ]

7 голосов
/ 04 января 2011

Использование 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.
6 голосов
/ 04 января 2011

Некоторые версии 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 может быть более сложной, но для ваших целей этого должно быть достаточно.

3 голосов
/ 05 января 2011
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 .
...