Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Selecting Random values

118 views
Skip to first unread message

Davk

unread,
Oct 30, 2012, 11:50:59 AM10/30/12
to
Hi there,

I am involving a program in which i have to select a value through a range of values, but i do not know precisely how to use random function in FORTRAN.

For example, I show you a small part of my data below. So, I need to divide each line into 4 part and pick just one "1" of each part.

211110122122
121011111110
121112111211
211121111111
100122221121
121101211211
121121111112
111200112111
112111110111
111211111112

In each part that i have three "1", I have to be able to select one of those randomly.

Help me please to solve this problem, coz i have been spending many days to solve that but i couldn't.

Thanks in advance
Davood

ken.fa...@gmail.com

unread,
Oct 30, 2012, 12:33:38 PM10/30/12
to
On Tuesday, October 30, 2012 8:50:59 AM UTC-7, Davk wrote:
> Hi there,
>
> I am involving a program in which i have to select a value through
> a range of values, but i do not know precisely how to use random
> function in FORTRAN.
>
> For example, I show you a small part of my data below. So, I need
> to divide each line into 4 part and pick just one "1" of each part.
>
211110122122
...
[snip]

Understanding that english is likely not your first language, I have
a great deal of difficulty understanding the problem you're trying to
solve. So here are a series of questions that may help:

1) Your data, are the (a) characters in a text file, as "211110122122"
on the 1st line you show, or (b) are they treated as integer values?

2) What do you mean by "divide each line into 4 part[s]"?

In the context of Fortran, we generally use "divide" in the numerical/
mathematical sense, so if your answer to 1) was (b), that each line
is a value; do you mean (a) divide the value by four, x=211110122122/4;
do you mean (b) find four multiplicative factors of the value, such
that E*F*G*H = 211110122122; do you mean (c) find four additive factors
of the value?

If your answer to 1) was (a), with "211110122122" treated as characters,
then do you want to "split" that string of characters into four pieces?

If so, in Fortran we would usually refer to those as "substrings". Do
you want to split (d) each line into equal-length substrings; or do you
(e) want to randomly choose the substring lengths?

> In each part that i have three "1", I have to be able to select one
> of those randomly.

3) Assuming you answered question 2) with answer (d), so that you now
have four equal-length substrings, what exactly are you trying to
select?

It's still unclear what you mean when you say, "in each part that I have
three '1'...". Do you mean, IF a substring contrains three "1" characters,
THEN do something? What if the substring has two "1"s, or only a single "1"?
What then?

By "select one of those randomly", do you mean, select the location within
the substring of one of the "1"s?

If you can answer these questions, it will greatly help us formulate the
problem you're trying to solve and offer you some help.

-Ken

e p chandler

unread,
Oct 30, 2012, 3:54:28 PM10/30/12
to
On Tuesday, October 30, 2012 11:50:59 AM UTC-4, Davk wrote:
> I am involving a program in which i have to select a value through a range of > values, but i do not know precisely how to use random function in FORTRAN.

1. If you are using a function in Fortran (this is the modern spelling of the language), then you probably are not getting a "good" source of random numbers.
The current language standard contains a _subroutine_ which returns a single value or an array of values of uniformly distributed random numbers. See RANDOM_NUMBER in your compiler's or in your language documentation.

If your random generator returns an integer, then the risk is high that using this number may give you unwanted results.

2. For example, you want to generate a random number in a particular range, say 1 to 6 with each draw being equally likely. This would simulate the roll of one half of a pair of dice. Taking an integer value MOD 6 and adding 1 might get you into trouble as some integer random values cycle through a range of values in their low order (binary) digits in a predictable fashion. It would be better to have a routine that returns a REAL (or some KIND of REAL), and scale it by multiplication,

integer K
real U
...
call random_number(u)
...
K=INT(1+6*U)

> For example, I show you a small part of my data below. So, I need to divide each line into 4 part and pick just one "1" of each part.
> 211110122122
> 121011111110
> 121112111211
> 211121111111
> 100122221121
> 121101211211
> 121121111112
> 111200112111
> 112111110111
> 111211111112

> In each part that i have three "1", I have to be able to select one of those randomly.

It is very unclear what you actually want to do from this description.
Posting a small program that you already have written might help us understand the problem.

Gib Bogle

unread,
Oct 30, 2012, 3:57:38 PM10/30/12
to
On 31/10/2012 4:50 a.m., Davk wrote:
> Hi there,
>
> I am involving a program in which i have to select a value through a
> range of values, but i do not know precisely how to use random
> function in FORTRAN.

Is this homework?

Davk

unread,
Oct 31, 2012, 8:56:13 AM10/31/12
to
No, is not homework. If you don't like or can not answer, you are not allowed to joke someone.
But thank you for reading that

Davk

unread,
Oct 31, 2012, 9:15:35 AM10/31/12
to
Dear e p chandler
Thank you for all comments. As you can see below, I put my written program below.

For example, in first row of data (211110122122), I need to write a program to read this row like this: 211 and write down in new file just one "1" randomely, then 110 and write down in new file one "1", then, 122 and etc. for all rows.

*************************************
PROGRAM SPLIT
IMPLICIT NONE

INTEGER:: OPENSTATUS, i, j, M, N
INTEGER::PACKED(10,12)
INTEGER::LINE(12)
INTEGER::a(10,3)
INTEGER::b(10,1)

TYPE LINEE
INTEGER::PACKED(10,12)
INTEGER::LINE(12)
END TYPE LINEE
TYPE(LINEE)::X(10)



OPEN(UNIT=18, FILE="FIRST-PACK.txt", STATUS="OLD", IOSTAT=OPENSTATUS)
IF (OPENSTATUS>0) STOP "***CANNOT OPEN FILE***"

OPEN(UNIT=12, FILE="x.txt", STATUS="REPLACE", ACTION="WRITE")

READ(18,30) ((PACKED(N,M),M=1,12),N=1,10)
30 FORMAT(12I1)

DO I=1,10
X(I)%line(:)=PACKED(I,:)
END DO

DO i=1,10
DO j=1,4
a(i,((j-1)*3+1):j*3)=X(I)%line(((j-1)*3+1):j*3)
if(a(i,(j-1)*3+1:j*3) .eq. 1) then
b=a(i,((j-1)*3+1:j*3))
end where
END DO
WRITE(12,'(12i1)') b(i,:)
END DO

END PROGRAM SPLIT
********************************

Ok, when it is done, how can we know where was the position of written down element of array.

I hope my description and incomplete program be logical to understand what i meant.

thanks in advance

e p chandler

unread,
Oct 31, 2012, 10:44:57 PM10/31/12
to
"Davk" wrote in message
news:31ab0564-18c9-445b...@googlegroups.com...
On Tuesday, October 30, 2012 8:54:28 PM UTC+1, e p chandler wrote:
> On Tuesday, October 30, 2012 11:50:59 AM UTC-4, Davk wrote:
> > I am involving a program in which i have to select a value through a
> > range of > values, but i do not know precisely how to use random
> > function in FORTRAN.
> > For example, I show you a small part of my data below. So, I need to
> > divide each line into 4 part and pick just one "1" of each part.
> > 211110122122
> > 121011111110
> > 121112111211
> > 211121111111
> > 100122221121
> > 121101211211
> > 121121111112
> > 111200112111
> > 112111110111
> > 111211111112
> > In each part that i have three "1", I have to be able to select one of
> > those randomly.

> It is very unclear what you actually want to do from this description.
> Posting a small program that you already have written might help us
> understand the problem.

Dear e p chandler
Thank you for all comments. As you can see below, I put my written program
below.

For example, in first row of data (211110122122), I need to write a program
to read this row like this: 211 and write down in new file just one "1"
randomely, then 110 and write down in new file one "1", then, 122 and etc.
for all rows.

[program code snipped]

TYPE LINEE
INTEGER::PACKED(10,12)
INTEGER::LINE(12)
END TYPE LINEE
TYPE(LINEE)::X(10)
....
READ(18,30) ((PACKED(N,M),M=1,12),N=1,10)
30 FORMAT(12I1)
....
DO I=1,10
X(I)%line(:)=PACKED(I,:)
END DO
DO i=1,10
DO j=1,4
a(i,((j-1)*3+1):j*3)=X(I)%line(((j-1)*3+1):j*3)
if(a(i,(j-1)*3+1:j*3) .eq. 1) then
b=a(i,((j-1)*3+1:j*3))
end where <-- ??????
END DO
WRITE(12,'(12i1)') b(i,:)
END DO

END PROGRAM SPLIT
********************************
Ok, when it is done, how can we know where was the position of written down
element of array.
I hope my description and incomplete program be logical to understand what i
meant.

----> I don't see the utility of the derived type. Why not use character
variables? Modern Fortran has some facilities for working with them.
It looks like you are doing pattern matching, followed by some string
manipulation. There are a number of "scripting" languages very well suited
for this type of task. I think that Perl or AWK lets you pick up the
position where a match is found. If you must write in Fortran, these others
might let you prototype your problem.

How about just posting a few lines of sample input followed by a few lines
of sample output?

Otherwise, I'm still mystified.
--- e


glen herrmannsfeldt

unread,
Nov 1, 2012, 12:46:33 AM11/1/12
to
e p chandler <ep...@juno.com> wrote:

(snip)

> For example, in first row of data (211110122122), I need to write a program
> to read this row like this: 211 and write down in new file just one "1"
> randomely, then 110 and write down in new file one "1", then, 122 and etc.
> for all rows.

If you are always writing out a "1" then it is easier to
just write the "1" than to randomly select one from
a bunch of "1"s.

Now, what if there aren't any "1"s in the group?

-- glen

Davk

unread,
Nov 1, 2012, 8:01:28 AM11/1/12
to
On Thursday, November 1, 2012 5:46:35 AM UTC+1, glen herrmannsfeldt wrote:
> e p chandler <ep...@juno.com> wrote:
>
>
>
> (snip)
>
>
>
> > For example, in first row of data (211110122122), I need to write a program
>
> > to read this row like this: 211 and write down in new file just one "1"
>
> > randomly, then 110 and write down in new file one "1", then, 122 and etc.
>
> > for all rows.
>
>
>
> If you are always writing out a "1" then it is easier to
>
> just write the "1" than to randomly select one from
>
> a bunch of "1"s.
>
>
>
> Now, what if there aren't any "1"s in the group?
>
>
>
> -- glen

Ok, If there are not any "1" in each part, Fortran should be able to ignore that part and go to the next.

Thanks

e p chandler

unread,
Nov 1, 2012, 6:00:57 PM11/1/12
to
"Davk" wrote
> > > For example, in first row of data (211110122122), I need to write a
> > > program
> > > to read this row like this: 211 and write down in new file just one
> > > "1"
> > > randomly, then 110 and write down in new file one "1", then, 122 and
> > > etc.
> > > for all rows.

"Glen" replied
> > Now, what if there aren't any "1"s in the group?

"Davk" replied
> Ok, If there are not any "1" in each part, Fortran should be able to
> ignore that part and go to the next.

Here is a small program that may do what you want. It also prints some
intermediate results along the way.
Note that I have used character variables instead of integers, in particular
an array of 4 "strings", each 3 characters long.

---- start ----
C:\Users\epc\temp>type x.f90
program split
implicit none
character(len=3) a(4) !4 fields of 3 characters each
integer b(4),m !list of fields that match, number of matches
integer ierr,i !i/o status, loop index
integer k !random position in the match list, if any
real u !random(0,1)

open(10,file='in.txt')
do
!read and echo input character data
read(10,'(4a3)',iostat=ierr) a
if (ierr /= 0) exit
write(*,'(4(1x,a3))') a

!find matching fields
m=0 !no matches yet
b=0 !fill whole array for display purposes
do i=1,4
if (a(i) == '111') then
m=m+1
b(m)=i !add index of field to list
end if
end do
write(*,'(4(1x,i1))') b !list of matches

!if any matches, generate a random integer 1..m
if (m == 0) then !list empty
write(*,'(a)') 'no matches'
else
call random_number(u)
k=int(1+m*u) ! 1..m !random position in the list
write(*,'(a,i1,a)') 'list item ',k,' is drawn'
write(*,'(a,a3)') 'and the winner is ',a(b(k))
end if
end do
end program split

C:\Users\epc\temp>g95 x.f90

C:\Users\epc\temp>a
211 110 122 122
0 0 0 0
no matches
121 011 111 110
3 0 0 0
list item 1 is drawn
and the winner is 111
121 112 111 211
3 0 0 0
list item 1 is drawn
and the winner is 111
211 121 111 111
3 4 0 0
list item 1 is drawn
and the winner is 111
100 122 221 121
0 0 0 0
no matches
121 101 211 211
0 0 0 0
no matches
121 121 111 112
3 0 0 0
list item 1 is drawn
and the winner is 111
111 200 112 111
1 4 0 0
list item 2 is drawn
and the winner is 111
112 111 110 111
2 4 0 0
list item 2 is drawn
and the winner is 111
111 211 111 112
1 3 0 0
list item 1 is drawn
and the winner is 111

C:\Users\epc\temp>
---- end ----

Note that m is the number of matches. Note that the B array contains the
numbers from 1..4 of any fields that match.
Now there may be some constructs in modern Fortran that make this easier,
but this "old school" aproach works.
Of course , all the "winners" are "111". How boring [smile]. Also this
illustrates some Fortran idioms for you.

--- e




Davk

unread,
Nov 1, 2012, 7:18:07 PM11/1/12
to
Hey Glen

Thank you for all you have done, But based on below part, you said that whenever (a(i) == '111') then ... .
you know, i need to any "1" in each segment. Fortran have to write out in new file wherever at least one "1" exists. for example, in 121, I need just one "1", also in 111 I need just one "1", in 202 (or 002,222,000,220,...) which there is not any "1" it's never mind. Fortran shold be able to jump over that and should be able to keep going on reading inputs to the end.

!find matching fields
m=0 !no matches yet
b=0 !fill whole array for display purposes
do i=1,4
if (a(i) == '111') then
m=m+1
b(m)=i !add index of field to list
end if
end do

I do apologize for any inconvenience

marcio.pmz

unread,
Nov 1, 2012, 10:12:29 PM11/1/12
to
Davk,

Trying to understand you demand, I developed the following, hope it helps!

program davk
character(12)::davkst
open(1,file='davk.data',status='old')
do while(not(eof(1)))
read(1,*,err=100,iostat=istat)davkst
call random_number(u)
ind=INT(1+4*U) !this value migth be 1, 2, 3 or 4
write(*,'(a,x,i3,x,a)')davkst,ind,davkst((ind-1)*3+1:ind*3)
enddo

100 if (istat/=0) write(*,*)'error'
end


davk.data (input file)
211110122122
121011111110
121112111211
211121111111
100122221121
121101211211
121121111112
111200112111
112111110111
111211111112

Output

211110122122 1 211
121011111110 1 121
121112111211 2 112
211121111111 3 111
100122221121 4 121
121101211211 4 211
121121111112 2 121
111200112111 4 111
112111110111 4 111
111211111112 4 112

e p chandler

unread,
Nov 1, 2012, 11:45:15 PM11/1/12
to
[program and text snipped]

> Hey Glen
Glen made the comment, I posted the program listing [smile].

>Thank you for all you have done, But based on below part, you said that
>whenever (a(i) == '111') then ... .
>you know, i need to any "1" in each segment. Fortran have to write out in
>new file wherever at least one "1" exists. for example, in 121, I need just
>one "1", also in 111 I need just one "1", in 202 > (or 002,222,000,220,...)
>which there is not any "1" it's never mind. Fortran shold be able to jump
>over that and should be able to keep going on reading inputs to the end.

Modern Fortran has a very nice construct that takes care of what you need.
Look up the SCAN function.

replace
if (a(i) == '111') then
with
if (SCAN(a(i),'1') > 0) then

This function finds the first location of any member of the set (which here
consists of just a single character) in the source. If not found, it returns
zero.
So if there are any '1's in the field, then do whatever, otherwise do
something else.

Maybe the random selection is not needed for your problem, but by this point
you should be able to figure out the rest.

---- e




Davk

unread,
Nov 2, 2012, 4:51:08 AM11/2/12
to
Please note to the my desired output of data set,

211,110,122,122 => output:1 1 1 1
122,011,111,200 => output:1 1 1
121,112,111,211 => output:1 1 1 1
211,121,111,111 => output:1 1 1 1
200,122,221,121 => output: 1 1 1
121,101,211,211 => output:1 1 1 1
121,121,222,112 => output:1 1 1
111,200,112,111 => output:1 1 1
112,111,110,111 => output:1 1 1 1
111,211,111,112 => output:1 1 1 1

I, intentionally, put comma between each part in order to be clear. In fact, each "1" represents one SNP in each gene and I want to keep at least one SNP in each region. Then, using an pack function, i will eliminate any vacancies.

Thanks guys










e p chandler

unread,
Nov 2, 2012, 9:15:09 PM11/2/12
to

"Davk" wrote in message
> Please note to the my desired output of data set,

> 211,110,122,122 => output:1 1 1 1
> 122,011,111,200 => output:1 1 1
> 121,112,111,211 => output:1 1 1 1
> 211,121,111,111 => output:1 1 1 1
> 200,122,221,121 => output: 1 1 1
> 121,101,211,211 => output:1 1 1 1
> 121,121,222,112 => output:1 1 1
> 111,200,112,111 => output:1 1 1
> 112,111,110,111 => output:1 1 1 1
> 111,211,111,112 => output:1 1 1 1

> I, intentionally, put comma between each part in order to be clear. In
> fact, each "1" represents one SNP in each gene and I want to keep at least
> one SNP in each region.
> Then, using an pack function, i will eliminate any vacancies.

Just for fun, here is a very small and simple program:

C:\Users\epc\temp>type x.f90
program split
implicit none
character(len=3) a(4)
character b(4)
integer ierr

open(10,file='in.txt')
do
read(10,'(4a3)',iostat=ierr) a
if (ierr /= 0) exit
where (scan(a,'1') > 0)
b='1'
elsewhere
b=' '
end where
write(*,*) a,'=>',b
end do
end program split

C:\Users\epc\temp>g95 -Wall x.f90

C:\Users\epc\temp>a
211110122122=>1111
122011111200=>111
121112111211=>1111
211121111111=>1111
200122221121=> 111
121101211211=>1111
121121222112=>11 1
111200112111=>1 11
112111110111=>1111
111211111112=>1111

C:\Users\epc\temp>

0 new messages