home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / lang / prolog / 1569 < prev    next >
Encoding:
Internet Message Format  |  1992-08-20  |  3.9 KB

  1. Path: sparky!uunet!mcsun!uknet!edcastle!aiai!ken
  2. From: ken@aiai.ed.ac.uk (Ken Johnson)
  3. Newsgroups: comp.lang.prolog
  4. Subject: A little block stacking program
  5. Message-ID: <7254@skye.ed.ac.uk>
  6. Date: 20 Aug 92 17:50:09 GMT
  7. Followup-To: comp.lang.prolog
  8. Organization: Bugs-R-Us
  9. Lines: 129
  10.  
  11.  
  12.  
  13. % A little block stacking program.
  14. % Ken Johnson 20 August 1992
  15. % You may use and distribute this code freely but if you sell copies of it
  16. % at a profit, I want a share. 
  17. % The state of the game is represented in a canonical form; it is
  18. % important that your start and goal states are stated in canonical form. 
  19. % There is no check that the problem is correctly stated and feasible, so
  20. % don't say I didn't warn you.
  21. %
  22. % The canonical form is a term state/1 whose argument is list of lists of
  23. % atoms.  Each sublist is a pile, each atom is a brick name, leftmost on
  24. % top.  The empty pile does not exist.  Lists are ordered by their first
  25. % atom using sort/2.  So both
  26. %   A                    A
  27. %   B   C       and  C   B
  28. %   -----            -----
  29. % are represented as state([[a,b],[c]]) because a precedes c
  30. % The method uses iterative deepening and depth first search; this
  31. % combination is guaranteed to find first the path with the fewest moves. 
  32. % The part is a list of states.
  33.  
  34. % Run example_1/0 and example_2/0 to get the idea
  35.  
  36. % Example 1 starts from
  37. %                              C
  38. %   A                          B
  39. %   B  C      and moves to     A
  40.  
  41. example_1 :-
  42.     Start = state([[a,b],[c]]),
  43.     Goal  = state([[c,b,a]]),
  44.     search(Start,Goal,Path),
  45.     write('Start '), write(Start), nl,
  46.     write('Goal '), write(Goal), nl,
  47.     write('Path '), write(Path), nl.
  48.  
  49. % Example 2
  50. %                           B
  51. %   A                       C
  52. %   B   D                   D
  53. %   C   E               E   A
  54.  
  55. example_2 :-
  56.     Start = state([[a,b,c],[d,e]]),
  57.     Goal  = state([[b,c,d,a],[e]]),        % Canonical order!
  58.     search(Start,Goal,Path),
  59.     write('Start '), write(Start), nl,
  60.     write('Goal '), write(Goal), nl,
  61.     write('Path '), write(Path), nl.
  62.  
  63. % To search for a state
  64.  
  65. search(A,B,P) :-
  66.     search_w_lim(0,A,B,R),            % Iterative limit init 0
  67.     reverse(R,P).                % Reverse path as it is
  68.                                                 % saved in reverse order
  69. search_w_lim(N,A,B,R) :-
  70.     search(N,A,B,R).
  71.  
  72. search_w_lim(N,A,B,R) :-
  73.     N1 is N + 1,
  74.     search_w_lim(N1,A,B,R).
  75.  
  76. search(N,A,B,R) :-                % Real work starts here
  77.     search_1(N,[A],B,R).
  78.  
  79. search_1(_,[G|As],G,[G|As]).            % Found goal, succeed
  80.  
  81. search_1(N,[A|As],G,R) :-            % Not there yet
  82.     N > 0,                    % Can make more moves?
  83.     move(A,B),                % Find applicable move
  84.     \+ member(B,[A|As]),            % Check new state not used
  85.     N1 is N - 1,                % Decr move limit
  86.     search_1(N1,[B,A|As],G,R).        % Keep going
  87.  
  88. % What the moves are:
  89. % (a) Pick up a block of a pile of two or more blocks and put it
  90. %     on the table
  91.  
  92. move(state(Piles),state(Canonical)) :-
  93.     member([Block,Block_1|Pile],Piles,Piles_1),
  94.     sort([[Block],[Block_1|Pile]|Piles_1],Canonical).
  95.  
  96. % (b) Pick a block up off the table and put it onto a pile of one
  97. %     or more
  98.  
  99. move(state(Piles),state(Canonical)) :-
  100.     member([Block],Piles,Piles_1),
  101.     member(Pile,Piles_1,Piles_left),
  102.     sort([[Block|Pile]|Piles_left],Canonical).
  103.  
  104. % (c) Pick a block up off one pile of two or more and put it onto
  105. %     another pile of one or more.
  106.  
  107. move(state(Piles),state(Canonical)) :-
  108.     member([Block,B1|Bm],Piles,Piles_1),
  109.     member([A1|Am],Piles_1,Piles_2),
  110.     sort([[B1|Bm],[Block,A1|Am]|Piles_2],Canonical).
  111.  
  112. % Utilities
  113.  
  114. member(X,[X|_]).
  115. member(X,[_|T]) :-
  116.     member(X,T).
  117.  
  118. member(X,[X|R],R).
  119. member(X,[H|T],[H|R]) :-
  120.     member(X,T,R).
  121.     
  122.  
  123. reverse(A,B) :-
  124.     reverse(A,[],B).
  125.  
  126. reverse([],X,X).
  127.  
  128. reverse([H|T],Acc,Rev) :-
  129.     reverse(T,[H|Acc],Rev).
  130.  
  131. -- 
  132. ////  Advice to dieters:          ////  Ken Johnson, A I Applications Institute
  133. ////    Never eat more than       ////       80 South Bridge, EDINBURGH EH1 1HN
  134. ////    you can carry.            ////                 E-mail ken@aiai.ed.ac.uk
  135. ////               -- Miss Piggy  ////     phone 031-650 2756  fax 031-650 6513
  136.