mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			281 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
			
		
		
	
	
			281 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
% This file has been included as an YAP library by Vitor Santos Costa, 1999
 | 
						|
 | 
						|
%   File   : QUEUES.PL
 | 
						|
%   Author : R.A.O'Keefe
 | 
						|
%   Updated: Friday November 18th, 1983, 8:09:31 pm
 | 
						|
%   Purpose: define queue operations
 | 
						|
%   Needs  : lib(lists) for append/3.
 | 
						|
 | 
						|
/** @defgroup Queues Queues
 | 
						|
@ingroup library
 | 
						|
@{
 | 
						|
 | 
						|
The following queue manipulation routines are available once
 | 
						|
included with the `use_module(library(queues))` command. Queues are
 | 
						|
implemented with difference lists.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
 @pred make_queue(+ _Queue_) 
 | 
						|
 | 
						|
 | 
						|
Creates a new empty queue. It should only be used to create a new queue.
 | 
						|
 | 
						|
 
 | 
						|
*/
 | 
						|
 | 
						|
 | 
						|
/** @pred empty_queue(+ _Queue_) 
 | 
						|
 | 
						|
 | 
						|
Tests whether the queue is empty.
 | 
						|
 | 
						|
 
 | 
						|
*/
 | 
						|
/** @pred head_queue(+ _Queue_, ? _Head_) 
 | 
						|
 | 
						|
 | 
						|
Unifies Head with the first element of the queue.
 | 
						|
 | 
						|
 
 | 
						|
*/
 | 
						|
/** @pred join_queue(+ _Element_, + _OldQueue_, - _NewQueue_) 
 | 
						|
 | 
						|
 | 
						|
Adds the new element at the end of the queue.
 | 
						|
 | 
						|
 
 | 
						|
*/
 | 
						|
/** @pred jump_queue(+ _Element_, + _OldQueue_, - _NewQueue_) 
 | 
						|
 | 
						|
 | 
						|
Adds the new element at the front of the list.
 | 
						|
 | 
						|
 
 | 
						|
*/
 | 
						|
/** @pred length_queue(+ _Queue_, - _Length_) 
 | 
						|
 | 
						|
 | 
						|
Counts the number of elements currently in the queue.
 | 
						|
 | 
						|
 
 | 
						|
*/
 | 
						|
/** @pred list_join_queue(+ _List_, + _OldQueue_, - _NewQueue_) 
 | 
						|
 | 
						|
 | 
						|
Ads the new elements at the end of the queue.
 | 
						|
 | 
						|
 
 | 
						|
*/
 | 
						|
/** @pred list_jump_queue(+ _List_, + _OldQueue_, + _NewQueue_) 
 | 
						|
 | 
						|
 | 
						|
Adds all the elements of  _List_ at the front of the queue.
 | 
						|
 | 
						|
 
 | 
						|
*/
 | 
						|
/** @pred list_to_queue(+ _List_, - _Queue_) 
 | 
						|
 | 
						|
 | 
						|
Creates a new queue with the same elements as  _List._
 | 
						|
 | 
						|
 
 | 
						|
*/
 | 
						|
/** @pred queue_to_list(+ _Queue_, - _List_) 
 | 
						|
 | 
						|
 | 
						|
Creates a new list with the same elements as  _Queue_.
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 */
 | 
						|
/** @pred serve_queue(+ _OldQueue_, + _Head_, - _NewQueue_) 
 | 
						|
 | 
						|
 | 
						|
Removes the first element of the queue for service.
 | 
						|
 | 
						|
 
 | 
						|
*/
 | 
						|
:- module(queues, [
 | 
						|
	make_queue/1,		%   create empty queue
 | 
						|
	join_queue/3,		%   add element to end of queue
 | 
						|
	list_join_queue/3,	%   add many elements to end of queue
 | 
						|
	jump_queue/3,		%   add element to front of queue
 | 
						|
	list_jump_queue/3,	%   add many elements to front of queue
 | 
						|
	head_queue/2,		%   look at first element of queue
 | 
						|
	serve_queue/3,		%   remove first element of queue
 | 
						|
	length_queue/2,		%   count elements of queue
 | 
						|
	empty_queue/1,		%   test whether queue is empty
 | 
						|
	list_to_queue/2,	%   convert list to queue
 | 
						|
	queue_to_list/2		%   convert queue to list
 | 
						|
    ]).
 | 
						|
 | 
						|
:- use_module(library(lists), [append/3]).
 | 
						|
 | 
						|
/*
 | 
						|
:- mode
 | 
						|
	make_queue(-),
 | 
						|
	join_queue(+, +, -),
 | 
						|
	list_join_queue(+, +, -),
 | 
						|
	jump_queue(+, +, -),
 | 
						|
	list_jump_queue(+, +, -),
 | 
						|
	head_queue(+, ?),
 | 
						|
	serve_queue(+, ?, -),
 | 
						|
	length_queue(+, ?),
 | 
						|
	length_queue(+, +, +, -),
 | 
						|
	empty_queue(+),
 | 
						|
	list_to_queue(+, -),
 | 
						|
	queue_to_list(+, -),
 | 
						|
	queue_to_list(+, +, -).
 | 
						|
*/
 | 
						|
 | 
						|
/*  In this package, a queue is represented as a term Front-Back,  where
 | 
						|
    Front  is  a list and Back is a tail of that list, and is normally a
 | 
						|
    variable.  join_queue will only work when the Back  is  a  variable,
 | 
						|
    the  other routines will accept any tail.  The elements of the queue
 | 
						|
    are the list difference, that is, all the elements starting at Front
 | 
						|
    and stopping at Back.  Examples:
 | 
						|
 | 
						|
	[a,b,c,d,e|Z]-Z	    has elements a,b,c,d,e
 | 
						|
	[a,b,c,d,e]-[d,e]   has elements a,b,c
 | 
						|
	Z-Z		    has no elements
 | 
						|
	[1,2,3]-[1,2,3]	    has no elements
 | 
						|
*/
 | 
						|
 | 
						|
%   make_queue(Queue)
 | 
						|
%   creates a new empty queue.  It will also match empty queues, but
 | 
						|
%   because Prolog doesn't do the occurs check, it will also match
 | 
						|
%   other queues, creating circular lists.  So this should ONLY be
 | 
						|
%   used to make new queues.
 | 
						|
 | 
						|
make_queue(X-X).
 | 
						|
 | 
						|
 | 
						|
 | 
						|
%   join_queue(Element, OldQueue, NewQueue)
 | 
						|
%   adds the new element at the end of the queue.  The old queue is
 | 
						|
%   side-effected, so you *can't* do
 | 
						|
%	join_queue(1, OldQ, NewQ1),
 | 
						|
%	join_queue(2, OldQ, NewQ2).
 | 
						|
%   There isn't any easy way of doing that, sensible though it might
 | 
						|
%   be.  You *can* do
 | 
						|
%	join_queue(1, OldQ, MidQ),
 | 
						|
%	join_queue(2, MidQ, NewQ).
 | 
						|
%   See list_join_queue.
 | 
						|
 | 
						|
join_queue(Element, Front-[Element|Back], Front-Back).
 | 
						|
 | 
						|
 | 
						|
 | 
						|
%   list_join_queue(List, OldQueue, NewQueue)
 | 
						|
%   adds the new elements at the end of the queue.  The elements are
 | 
						|
%   added in the same order that they appear in the list, e.g.
 | 
						|
%   list_join_queue([y,z], [a,b,c|M]-M, [a,b,c,y,z|N]-N).
 | 
						|
 | 
						|
list_join_queue(List, Front-OldBack, Front-NewBack) :-
 | 
						|
	append(List, OldBack, NewBack).
 | 
						|
 | 
						|
 | 
						|
 | 
						|
%   jump_queue(Element, OldQueue, NewQueue)
 | 
						|
%   adds the new element at the front of the list.  Unlike join_queue,
 | 
						|
%	jump_queue(1, OldQ, NewQ1),
 | 
						|
%	jump_queue(2, OldQ, NewQ2)
 | 
						|
%   *does* work, though if you add things at the end of NewQ1 they
 | 
						|
%   will also show up in NewQ2.  Note that
 | 
						|
%	jump_queue(1, OldQ, MidQ),
 | 
						|
%	jump_queue(2, MidQ, NewQ)
 | 
						|
%   makes NewQ start 2, 1, ...
 | 
						|
 | 
						|
jump_queue(Element, Front-Back, [Element|Front]-Back).
 | 
						|
 | 
						|
 | 
						|
 | 
						|
%   list_jump_queue(List, OldQueue, NewQueue)
 | 
						|
%   adds all the elements of List at the front of the queue.  There  are
 | 
						|
%   two  ways  we might do this.  We could add all the elements one at a
 | 
						|
%   time, so that they would appear at the beginning of the queue in the
 | 
						|
%   opposite order to the order they had in the list, or  we  could  add
 | 
						|
%   them in one lump, so that they have the same order in the  queue  as
 | 
						|
%   in  the  list.   As you can easily add the elements one at a time if
 | 
						|
%   that is what you want, I have chosen the latter.
 | 
						|
 | 
						|
list_jump_queue(List, OldFront-Back, NewFront-Back) :-
 | 
						|
	append(List, OldFront, NewFront).
 | 
						|
%	reverse(List, OldFront, NewFront).	% for the other definition
 | 
						|
 | 
						|
 | 
						|
 | 
						|
%   head_queue(Queue, Head)
 | 
						|
%   unifies Head with the first element of the queue.  The tricky part
 | 
						|
%   is that we might be at the end of a queue: Back-Back, with Back a
 | 
						|
%   variable, and in that case this predicate should not succeed, as we
 | 
						|
%   don't know what that element is or whether it exists yet.
 | 
						|
 | 
						|
head_queue(Front-Back, Head) :-
 | 
						|
	Front \== Back,		%  the queue is not empty
 | 
						|
	Front = [Head|_].
 | 
						|
 | 
						|
 | 
						|
 | 
						|
%   serve_queue(OldQueue, Head, NewQueue)
 | 
						|
%   removes the first element of the queue for service.
 | 
						|
 | 
						|
serve_queue(OldFront-Back, Head, NewFront-Back) :-
 | 
						|
	OldFront \== Back,
 | 
						|
	OldFront = [Head|NewFront].
 | 
						|
 | 
						|
 | 
						|
 | 
						|
%   empty_queue(Queue)
 | 
						|
%   tests whether the queue is empty.  If the back of a queue were
 | 
						|
%   guaranteed to be a variable, we could have
 | 
						|
%	empty_queue(Front-Back) :- var(Front).
 | 
						|
%   but I don't see why you shouldn't be able to treat difference
 | 
						|
%   lists as queues if you want to.
 | 
						|
 | 
						|
empty_queue(Front-Back) :-
 | 
						|
	Front == Back.
 | 
						|
 | 
						|
 | 
						|
 | 
						|
%   length_queue(Queue, Length)
 | 
						|
%   counts the number of elements currently in the queue.  Note that
 | 
						|
%   we have to be careful in checking for the end of the list, we
 | 
						|
%   can't test for [] the way length(List) does.
 | 
						|
 | 
						|
length_queue(Front-Back, Length) :-
 | 
						|
	length_queue(Front, Back, 0, N),
 | 
						|
	Length = N.
 | 
						|
 | 
						|
length_queue(Front, Back, N, N) :-
 | 
						|
	Front == Back, !.
 | 
						|
length_queue([_|Front], Back, K, N) :-
 | 
						|
	L is K+1,
 | 
						|
	length_queue(Front, Back, L, N).
 | 
						|
 | 
						|
 | 
						|
 | 
						|
%   list_to_queue(List, Queue)
 | 
						|
%   creates a new queue with the same elements as List.
 | 
						|
 | 
						|
list_to_queue(List, Front-Back) :-
 | 
						|
	append(List, Back, Front).
 | 
						|
 | 
						|
 | 
						|
 | 
						|
%   queue_to_list(Queue, List)
 | 
						|
%   creates a new list with the same elements as Queue.
 | 
						|
 | 
						|
queue_to_list(Front-Back, List) :-
 | 
						|
	queue_to_list(Front, Back, List).
 | 
						|
 | 
						|
queue_to_list(Front, Back, Ans) :-
 | 
						|
	Front == Back, !, Ans = [].
 | 
						|
queue_to_list([Head|Front], Back, [Head|Tail]) :-
 | 
						|
	queue_to_list(Front, Back, Tail).
 | 
						|
 |