scramble Function

public function scramble(number_of_values) result(array)

NAME

scramble(3f) - [M_random] generate an integer array of specified size populated with a random permutation of 1 to size(array)
(LICENSE:MIT)

SYNOPSIS

function scramble( number_of_values )
integer,intent(in) :: number_of_values

DESCRIPTION

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.

OPTIONS

number_of_values  size of integer array to create

RETURNS

scramble    Integer array filled with integers 1 to NUMBER_OF_VALUES in random order

EXAMPLE

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

AUTHOR

John S. Urban

LICENSE

MIT License

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: number_of_values

Return Value integer, allocatable, (:)


Source Code

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