2011-01-04 2 views
4

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

Задача заключается в следующем:

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

Заранее спасибо.

ответ

5

Некоторые версии Prolog имеют между предикатами/3. Можно сказать, что

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

Если между недоступен, можно сказать, что

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

Если вы не хотите использовать элемент/2, использовать рекурсию.

Edit: Вы также можете осуществить между/3, как это:

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

Надежная и эффективная реализация между/3 может быть более сложной, но и для ваших целей, то это должно быть достаточно.

+1

Ваш второй вариант еще требует его прописать все 100 номеров, так что это еще требует 'O (N) 'печатать. Это также довольно неэффективно. – sepp2k

+1

Да, это так. С другой стороны, цифра (X): - 1 =

+0

Хорошо, мое плохое. Я недостаточно читал описание проблемы. – sepp2k

7

Использование SWI-Пролог:

:- 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
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 . 
Смежные вопросы