PROLOG-REQUEST@SUSHI.STANFORD.EDU.UUCP (09/23/87)
PROLOG Digest Thursday, 24 Sep 1987 Volume 5 : Issue 64 Today's Topics: LP Library - stddef & stdio ---------------------------------------------------------------------- Date: Sun, 13 Sep 87 22:41:59 PDT From: Edouard Lagache <lagache@violet.Berkeley.EDU> Subject: stddef.pro /* FILE: STDDEF.PRO */ /******************************************************************************/ /* */ /* Standard PROLOG Predicate and data definition file */ /* */ /* This file contains predicates and data which effectively extend */ /* the PROLOG environment. These extensions are in the area of */ /* arithmetic predicates, and predicates to convert matching into other */ /* useful forms such as lists, sums, or counts of frequency. */ /* */ /* E. Lagache, Version - 1.40, July - 1987 */ /* Copyright(C) 1986,1987, ALL RIGHTS RESERVED */ /* */ /******************************************************************************/ /* Adapt A.D.A. PROLOG to run C&M standard programs */ call(X) :- X. /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'concat' concatenates to atom names into */ /* a new atom. */ /* */ /* E. Lagache, Vers. - 1.00, Jul - 87 */ /* */ /* Note: A more powerful variant of this */ /* predicate is built-in to A.D.A. PROLOG */ /* * * * * * * * * * * * * * * * * * * * * * * */ concat(Name1,Name2,Result) :- name(Name1,Stg1),name(Name2,Stg2), append(Stg1,Stg2,Stg3), name(Result,Stg3). /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'countmatch' returns the number of */ /* distinct matches of a variable X in a */ /* predicate 'Pred'. */ /* */ /* E. Lagache, Vers. - 1.10, Jul - 87 */ /* * * * * * * * * * * * * * * * * * * * * * * */ countmatch(Pred,_):- asserta(current_count(0)), call(Pred), /* Satisfy Pred */ update_countmatch, /* and increment counter */ fail. /* fail to try to resatisfy */ /* Catch failure of above clause, and return count */ countmatch(_,Count):- current_count(Count), retract(current_count(Count)),!. /* Increment counter */ update_countmatch:- current_count(I), J is I+1, retract(current_count(I)), asserta(current_count(J)), !. /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'evenp' is true for even numbers. */ /* */ /* E. Lagache, Vers. - 1.00, Dec - 86 */ /* * * * * * * * * * * * * * * * * * * * * * * */ evenp(I):- integer(I), J is I mod 2, J == 0. /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'findall' returns a list of all the */ /* matches to the variable 'X' in the */ /* predicate 'Pred'. */ /* */ /* From Clocksin and Mellish p 162 */ /* */ /* E. Lagache, Vers. - 1.01, Dec - 86 */ /* * * * * * * * * * * * * * * * * * * * * * * */ findall(X,Pred,_):- asserta(found('Do not use this symbol!')), call(Pred), /* Call predicate and store matches */ asserta(found(X)), fail. /* fail to force resatisfying */ /* This clause will be true when above has failed */ findall(_,_,Result):- collect_found([],Matchlist), !, /* Collect list */ Result = Matchlist. /* remove mark, and retract mark */ /* Collect matches in database and put on list */ collect_found(Partial,Matchlist) :- getnext(Item), !, collect_found([Item|Partial],Matchlist). collect_found(Matchlist,Matchlist). /* Retrieve matches placed in database */ getnext(Item):- retract(found(Item)), !, Item \== 'Do not use this symbol!'. /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'gensym' is used to generate new constant */ /* symbols. This predicate takes a seed name */ /* and appends a number to differentiate */ /* between successive calls. */ /* */ /* E. Lagache, Vers. - 1.00, Mar - 87 */ /* */ /* Clocksin and Mellish pp 159-162 */ /* * * * * * * * * * * * * * * * * * * * * * * */ gensym(Root,Atom) :- get_next_num(Root,Num), /* get next number */ name(Root,Name1), /* make root a string */ integer_name(Num,Name2), /* make number a string */ append(Name1,Name2,Name), /* Concat strings */ name(Atom, Name). /* create symbol */ /* >>> predicate 'get_next_num' retrieves next number in the sequence <<< */ /* >>> Called from 'gensym' <<< */ get_next_num(Root,New) :- retract(current_index_num(Root,Num)), !, New is Num + 1, asserta(current_index_num(Root,New)). get_next_num(Root,1) :- asserta(current_index_num(Root,1)). /* >>> predicate 'integer_name' converts numbers to ASCII strings <<< */ /* >>> Called from 'gensym' <<< */ integer_name(Int,List) :- integer_name(Int,[],List). integer_name(I,Sofar,[C|Sofar]) :- I < 10, !, C is I + 48. integer_name(I, Sofar, List) :- Tophalf is I/10, Bothalf is I mod 10, C is Bothalf + 48, integer_name(Tophalf,[C|Sofar],List). /* Solution using ADA specific predicates */ /* NOTE: 'get_next_num' is needed from above */ /* gensym(Root,Atom) :- get_next_num(Root,Num), /* get a new number */ /* atoi(Symbol,Num), /* make a symbol out of it */ /* concat(Atom,[Root,Symbol]). /* concat symbols */ /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'interval' generates all integers */ /* between 'Num1' and 'Num2'. */ /* */ /* E. Lagache, Vers. - 1.00, Nov - 86 */ /* * * * * * * * * * * * * * * * * * * * * * * */ interval(Num1,Num1,Num2). /* Select base of interval */ interval(Num0,Next,Num2):- Num0 < Num2, Num1 is Num0 + 1, /* Increment base */ interval(Num1,Next,Num2). /* of interval */ /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'max' returns the largest of two numbers */ /* */ /* E. Lagache, Vers. - 1.00, Apr - 87 */ /* * * * * * * * * * * * * * * * * * * * * * * */ max(Number1,Number2,Number1) :- Number1 >= Number2, !. max(Number1,Number2,Number2). /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'min' returns the smaller of two numbers */ /* */ /* E. Lagache, Vers. - 1.00, Apr - 87 */ /* * * * * * * * * * * * * * * * * * * * * * * */ min(Number1,Number2,Number1) :- Number1 =< Number2, !. min(Number1,Number2,Number2). /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'oddp' is true for odd numbers. */ /* */ /* E. Lagache, Vers. - 1.00, Nov - 86 */ /* * * * * * * * * * * * * * * * * * * * * * * */ oddp(I):- integer(I), J is I mod 2, J \== 0. /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'stringp' tests to see if the item is a */ /* string. Since all strings are lists of */ /* ASCII codes, the predicate just tests if */ /* item is a list. */ /* */ /* E. Lagache, Vers. - 1.10, Jul - 87 */ /* * * * * * * * * * * * * * * * * * * * * * * */ stringp([]). stringp([_|_]). /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'sum_match' returns the sum of an */ /* numerical field of predicate 'Pred'. */ /* The field name must be instantiated to */ /* 'X'. The result is returned in 'Sum'. */ /* */ /* E. Lagache, Vers. - 1.00, Nov - 86 */ /* * * * * * * * * * * * * * * * * * * * * * * */ /* Start by finding all values of 'X' and maintaining a running total in */ /* 'current_sum' */ sum_match(X,Pred,_):- assertz(current_sum(0)), /* Store 0 */ call(Pred), /* Try to satisfy */ update_sum_match(X), /* if possible store result */ fail. /* fail to try to resatisfy */ /* when first rule fails this rule will recover sum */ sum_match(_,_,Sum):- current_sum(Sum), retract(current_sum(Sum)), !. /* This rule computes and stores running total in database */ update_sum_match(X):- integer(X),current_sum(I), J is I+X, retract(current_sum(I)),assertz(current_sum(J)), !. /* end file: STDDEF.PRO */ ------------------------------ Date: Sun, 13 Sep 87 22:42:57 PDT From: Edouard Lagache <lagache@violet.Berkeley.EDU> Subject: stdio.pro /* FILE: STDIO.PRO */ /******************************************************************************/ /* */ /* Standard PROLOG input/output predicate definition file */ /* */ /* This file contains predicates and data which provide commonly */ /* needed input/output capabilities for interactive programming. */ /* */ /* E. Lagache, Version - 1.03, July - 1987 */ /* Copyright(C) 1987, ALL RIGHTS RESERVED */ /* */ /* Note: These predicates assume nothing more intelligent than a */ /* generic dumb terminal. For more intelligent terminal */ /* use the predicate library contained in the file 'ANSI-IO.PRO' */ /* */ /******************************************************************************/ /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'center_stg' prints out a string centered */ /* on an 80 column terminal screen. */ /* */ /* E. Lagache, Vers. - 1.00, Nov - 86 */ /* * * * * * * * * * * * * * * * * * * * * * * */ center_stg(String):- comp_tabs(String,Tabs), tab(Tabs),p_stg(String), nl. /*##> 'comp_tabs' computes the number of <##*/ /*##> spaced needed to center the string. <##*/ /*##> <##*/ /*##> Used by Predicate: 'center_stg' <##*/ comp_tabs(String,Tabs):- length(String,Length), X is 80-Length, evenp(X), Tabs is X/2, !. comp_tabs(String,Tabs):- length(String,Length), X is 79-Length, evenp(X), Tabs is X/2, !. /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'clear_screen' does a "poor mans" screen */ /* clearing by sending newlines. The */ /* directly send the required lines to */ /* increase speed. */ /* */ /* E. Lagache, Vers. - 1.00, Dec - 86 */ /* * * * * * * * * * * * * * * * * * * * * * * */ clear_screen:- nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl,nl, nl,nl,nl,nl,nl. /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'prtstr' provides efficient writing of */ /* strings by converting them to atom names */ /* and using 'write' */ /* */ /* Note: This predicate is builtin to ADA */ /* PROLOG. */ /* */ /* E. Lagache, Vers. - 1.01, Jul - 87 */ /* * * * * * * * * * * * * * * * * * * * * * * */ prtstr(String):- name(Atom,String), write(Atom). /* * * * * * * * * * * * * * * * * * * * * * * */ /* 'push_up' sends the requested number of */ /* newlines to output. */ /* */ /* E. Lagache, Vers. - 1.00, Dec - 86 */ /* * * * * * * * * * * * * * * * * * * * * * * */ push_up(0):- !. push_up(I):- J is I-1, nl,push_up(J). /* End file: STDIO.PRO */ ------------------------------ End of PROLOG Digest ********************