Clicky

Fortran Wiki
scramble

RANDOM PERMUTATION OF A LIST

One 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 succintly using array syntax.

Here is a simple example that, given a list size

  1. creates an INTEGER array of the specified size N
  2. populates it with the values from 1 to N
  3. randomly switches values in the array to randomize it
  4. returns 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.

NAME

scramble(3f) - return an integer array prepopulated with the values 1 to size(array) in random order

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.

OPTIONS

number_of_values
size of integer array to create

RETURNS

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

EXAMPLE

Sample program and associated function shows a function returning an array, basic random number generation, and using the function results in an array syntax expression.

    program demo_scramble
    use M_scramble, only : scramble
    implicit none

    !@(#) print a list of character values in random order several times

    ! here is a list of character values to use for an example
    ! it could be a list of any type
    character(len=*),parameter :: list(*)=[character(len=5) :: &
     'one','two','three','four','five','six','seven','eight','nine','ten']
    integer  :: I

       do i = 1,8 ! use random values as indices to randomize array
          write(*,'(*(a,1x))') list(scramble(size(list)))
       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

module M_scramble
   implicit none
   private
   public scramble

contains

   function scramble( number_of_values ) result(array)

!@(#) 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)]

! 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

category: code