scramble(3f) - [M_random] generate an integer array of specified size populated with a random permutation of 1 to size(array)
(LICENSE:MIT)
function scramble( number_of_values )
integer,intent(in) :: number_of_values
Return an integer array of the size specified populated with the
numbers 1 to "number_of_values" in random order.
A simple way to randomly scramble a list of any type is to create
a random permutation of all the index values of the array and then
access the original list elements using that list of indices. The
list itself can be re-ordered very succinctly using array syntax.
Given a list size ..
1. create an INTEGER array of the specified size N
2. populate it with the values from 1 to N
3. randomly switch values in the array to randomize it
4. return the newly created array for use as indices
The resulting random permutation of the indices can then be used to
access essentially any type of list in random order.
number_of_values size of integer array to create
scramble Integer array filled with integers 1 to NUMBER_OF_VALUES in random order
Sample program
program demo_scramble
use M_random, only : scramble, init_random_seed_by_system_clock
implicit none
character(len=*),parameter :: list(*)=[character(len=5) :: &
& 'one','two','three','four','five',&
& 'six','seven','eight','nine','ten']
integer :: i
integer :: n=size(list)
character(len=len(list)) :: newlist(size(list))
call init_random_seed_by_system_clock()
do i = 1,8
! use random values as indices to randomize array
newlist=list(scramble(n))
write(*,'(*(a,1x))') newlist
enddo
end program demo_scramble
Example output
ten six eight one four nine two five three seven
three five ten nine one four six seven two eight
four eight ten two seven nine six three one five
three one nine seven ten five two six eight four
two seven nine one four three eight ten five six
three one nine six ten five eight two four seven
four five six eight one ten three nine seven two
three nine four two one seven ten five six eight
John S. Urban
MIT License
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(in) | :: | number_of_values |
function scramble( number_of_values ) result(array) ! ident_3="@(#) M_random scramble(3f) return integer array of random values 1 to N." integer,intent(in) :: number_of_values integer,allocatable :: array(:) integer :: i, j, k, m, n integer :: temp real :: u array=[(i,i=1,number_of_values)] ! make the array and populate it with 1 thru number_of_values ! The intrinsic RANDOM_NUMBER(3f) returns a real number (or an array ! of such) from the uniform distribution over the interval [0,1). (ie. ! it includes 0 but not 1.). ! ! To have a discrete uniform distribution on ! the integers {n, n+1, ..., m-1, m} carve the continuous distribution ! up into m+1-n equal sized chunks, mapping each chunk to an integer. ! ! One way is: ! call random_number(u) ! j = n + FLOOR((m+1-n)*u) ! choose one from m-n+1 integers n=1 m=number_of_values do k=1,2 do i=1,m call random_number(u) j = n + FLOOR((m+1-n)*u) ! switch values temp=array(j) array(j)=array(i) array(i)=temp enddo enddo end function scramble