Path: utzoo!utgpu!water!watmath!clyde!att!pacbell!ames!amdcad!sun!pitstop!sundc!seismo!uunet!mcvax!ukc!etive!aiva!ken
From: ken@aiva.ed.ac.uk (Ken Johnson)
Newsgroups: comp.lang.misc
Subject: Re: Random permutation algorithm
Summary: Prolog solution
Message-ID: <532@aiva.ed.ac.uk>
Date: 19 Aug 88 10:22:19 GMT
References: <5200012@m.cs.uiuc.edu> <32265@cca.CCA.COM>
Reply-To: ken@uk.ac.ed.aiva (Ken Johnson,E32 SB x212E)
Followup-To: comp.lang.misc
Organization: Dept. of AI, Univ. of Edinburgh, UK
Lines: 60

Story so far: Looking for a way of randomly permuting N elements
in a declarative language.
The imperative algorithm is

>	for i from [1...n] sequentially chosen
>	  select j from [i...n] randomly
>	  exchange a(i),a(j)
>	  end loop

Here it is in Prolog. Untested etc. I am reasonably certain you could
speed this up, but the question was to show that it could be done at all,
and I've only got ten minutes...

% randperm(List_in,List_out)
% Random permutation of List_in. Mode: randperm(+,-).
% Not debugged, warranted or anything.  If you copy this source in a
% program and make money out of it, please send me some. 
% Good Luck!

randperm(List_in,List_out) :-
	length(List_in,N),		% Length of list (system func)
	randperm(1,N,List_in,List_out).

randperm(I,N,List_in,List_in) :-	% Done
	I > N.

randperm(I,N,List_in,List_out) :-
	I =< N,
	random(N,R),			% Library function (?) R is random int
					% between 1 and N inclusive
	exchange_elements(I,R,List_in,List_1), % Swap elements
	J is I + 1,
	randperm(J,N,List_1,List_out).


exchange_elements(I,J,List_in,List_out) :-	% Get Ith and Jth elements
	get_elem(I,List_in,Ei),			% and swap. This is more
	get_elem(J,List_in,Ej),			% time consuming than
	put_elem(J,List_in,Ei,List_1),		% necessary but it will work
	put_elem(I,List_in,Ej,List_out).

get_elem(1,[X|_],X).				% Find I'th element of list

get_elem(I,[_|T],X) :-
	I > 1,
	I1 is I - 1,
	get_elem(I1,T,X).

put_elem(1,[_|T],X,[X|T]).			% Replace I'th element of
						% list by X giving new list
put_elem(I,[H|T],X,[H|U]) :-
	I > 1,
	I1 is I - 1,
	put_elem(I1,T,X,U).
-- 
------------------------------------------------------------------------------
From:    Ken Johnson (Half Man Half Bicycle)
Address: AI Applications Institute, The University, EDINBURGH
Phone:   031-225 4464 ext 212
Email:   k.johnson@ed.ac.uk