Creating 1 file w/ the contents of 7 other files mixed randomly.

G

game4itguy

Arguments aside (it's awfully dull reading the same rants over and
over), this script will do what you want if you place it in the
directory of the original text files. It should be noted that on my
Windows machine file8.txt was not overwritten with each run of the
script.

#!/usr/bin/perl -w
use strict;
my $rand;
my @indir;
my @files;
opendir(DH,".") || die $!;
@indir = readdir(DH);
close(DH);
foreach(@indir) {
if ($_ =~ m/.txt/) {
open(FH,$_);
push(@files, <FH>);
close(FH);
}
}
open(SAVETO,">file8.txt") || die $!;
while($#files > 0)
{
$rand = int(rand(@files));
print SAVETO $files[$rand];
delete $files[$rand];
}
close SAVETO;
exit;

As a novice I'd be interested in receiving a critique of this script
and how I could make it better/things I've done wrong, if anyone's
interested in providing one? Although whilst I'm aware it will
undoubtedly get torn to shreds by the pros, I must say I'm rather
pleased that it works at all!
 
R

robic0

Arguments aside (it's awfully dull reading the same rants over and
over), this script will do what you want if you place it in the
directory of the original text files. It should be noted that on my
Windows machine file8.txt was not overwritten with each run of the
script.

#!/usr/bin/perl -w
use strict;
my $rand;
my @indir;
my @files;
opendir(DH,".") || die $!;
@indir = readdir(DH);
close(DH);
foreach(@indir) {
if ($_ =~ m/.txt/) {
open(FH,$_);
push(@files, <FH>);
close(FH);
}
}
open(SAVETO,">file8.txt") || die $!;
while($#files > 0)
{
$rand = int(rand(@files));
print SAVETO $files[$rand];
delete $files[$rand];
}
close SAVETO;
exit;

As a novice I'd be interested in receiving a critique of this script
and how I could make it better/things I've done wrong, if anyone's
interested in providing one? Although whilst I'm aware it will
undoubtedly get torn to shreds by the pros, I must say I'm rather
pleased that it works at all!

I haven't even read it, but I like your attitude! You take that step
knowing there may be no floor to land on.

You have the power Luke, practice your saber..
The force is with you young one
 
T

Tad McClellan

Zachary said:
I want the line
order to be randomly mixed.


perldoc -q random

Might someone
help me accomplish this?


That would be much easier for us to do if you told us what part
it is that you are stuck on.

What part are you stuck on?

Got any code?
 
Z

Zachary

I am so very sorry if I've wasted anyones time. I obviously should
have read more posts in an attempt to better understand the conventions
use to post to this newsgroup. I'm a newbie and while that doesn't
excuse my actions I hope you all will understand so that in the future
you don't just simply pass up my posts when you see my name. I truly
didn't intend to seem slack (get it? Slack Zack). I was simply trying
to state my problem as briefly as possible without going into detail
about how the entire program works. The problem is just a portion of
the program. I would never try to get any of you to work for free and
I certainly didn't intend to waste any of your valuable time. I
promise that I value your time as much as anyone else does. For those
of you that replied with helpful info, I thank you very much and I will
surely make every attempt not to waste your time in the future.

As for Paul Lalli, if you spend that much time correcting every post
you see unfit then you need a woman. You need to go dancing, have a
beer or anything that'll allow you some release. Put the newsgroups
down for awhile dog.

I'll come back when I learn a little more about "netiquette."
Jeeez! I got a lot of new words to learn too.

Thanks,
Zachary
 
U

Uri Guttman

g> Arguments aside (it's awfully dull reading the same rants over and
g> over), this script will do what you want if you place it in the
g> directory of the original text files. It should be noted that on my
g> Windows machine file8.txt was not overwritten with each run of the
g> script.

and rants aside your program is amazingly buggy and poorly written.

g> #!/usr/bin/perl -w
g> use strict;
g> my $rand;
g> my @indir;
g> my @files;

don't declare those until they are used.

g> opendir(DH,".") || die $!;

use lexical handles as they are safer.

g> @indir = readdir(DH);
g> close(DH);
g> foreach(@indir) {
g> if ($_ =~ m/.txt/) {

no need for $_.

g> open(FH,$_);

no check for open failure.

g> push(@files, <FH>);

oooh! slurping. maybe you should look into file::slurp?

and that array contains all the lines in the files, not the files
themselves. a better name is needed for it.
g> close(FH);
g> }
g> }

ever heard of indenting?

g> open(SAVETO,">file8.txt") || die $!;
g> while($#files > 0)
g> {
g> $rand = int(rand(@files));
g> print SAVETO $files[$rand];
g> delete $files[$rand];

here is your big bug. that doesn't do what you think it does. have you
run this code? my turing machine says it will never stop.

g> }
g> close SAVETO;
g> exit;

g> As a novice I'd be interested in receiving a critique of this script
g> and how I could make it better/things I've done wrong, if anyone's
g> interested in providing one? Although whilst I'm aware it will
g> undoubtedly get torn to shreds by the pros, I must say I'm rather
g> pleased that it works at all!

are you sure it works? delete doens't remove an element from an array,
just the value. $#files will not change.

perl -le '@a = (1 .. 3); print $#a ; delete $a[1]; print $#a'
2
2

try this on for size (untested):

use File::Slurp ;
use List::Util qw( shuffle ) ;

write_file( 'file8.txt', shuffle
map read_file( "file$_.txt" ), 1 .. 7
) ;

kinda cute, ain't it? clear, fast, no variables (other than $_).

uri
 
J

John Bokma

Uri Guttman said:
oooh! slurping. maybe you should look into file::slurp?

File::Slurp you mean ;-) (file::slurp works on Windows, but fails on
CaSEsEnsitIVe filesystems.
 
A

Anno Siegel

John Bokma said:
File::Slurp you mean ;-) (file::slurp works on Windows,

....for small values of "works". It will load the module but not
import anything from it.

Anno
 
P

Paul Lalli

Zachary said:
I am so very sorry if I've wasted anyones time. I obviously should
have read more posts in an attempt to better understand the conventions
use to post to this newsgroup.

And you *still* haven't read the Posting Guidelines for this group, as
evidenced by your very rude lack of quoting any context in your
replies.
I'm a newbie and while that doesn't
excuse my actions I hope you all will understand so that in the future
you don't just simply pass up my posts when you see my name.

After I read this paragraph, I thought "Okay, he apologized, I'm
willing to help him again."
As for Paul Lalli, if you spend that much time correcting every post
you see unfit then you need a woman. You need to go dancing, have a
beer or anything that'll allow you some release. Put the newsgroups
down for awhile dog.

..... and then I read this. This is how you show how mature you are,
and how you ask the newsgroup to continue to help you despite the poor
first impressions? By insulting the people trying to help you? Good
luck getting any help out of this newsgroup. It will be an uphill
battle, I'm sure, as you've most likely just landed in the killfiles of
many of the most helpful people in this newsgroup.
I'll come back when I learn a little more about "netiquette."
Jeeez! I got a lot of new words to learn too.

Not to mention manners.

Paul Lalli
 
T

Tad McClellan

Zachary said:
I am so very sorry if I've wasted anyones time.


I do not believe you, given what you wrote below.

I obviously should
have read more posts in an attempt to better understand the conventions
use to post to this newsgroup. I'm a newbie and while that doesn't
excuse my actions I hope you all will understand so that in the future
you don't just simply pass up my posts when you see my name.


Too late...

As for Paul Lalli, if you spend that much time correcting every post
you see unfit then you need a woman. You need to go dancing, have a
beer or anything that'll allow you some release. Put the newsgroups
down for awhile dog.


.... because you felt the need to include that.

Each component of Paul's followup would have helped you to
accomplish your goal.

I'll come back when I learn a little more about "netiquette."


And you will be invisible when you do. So long!

*plonk*
 
D

Dr.Ruud

Zachary schreef:
if you spend that much time correcting every post
you see unfit then you need a woman.

You're leaving. Please don't forget to close the door behind you, we
don't need no creeps here.
 
G

game4itguy

g> #!/usr/bin/perl -w
don't declare those until they are used.

Why? Constructive criticism involves explanations, not dictats.
use lexical handles as they are safer.

Can you expand please?
and that array contains all the lines in the files, not the files
themselves. a better name is needed for it.

What difference would that have to the operation of the program? Surely
this is personal preference?
ever heard of indenting?

What difference would that have to the operation of the program? Sure
this too is personal preference?
g> open(SAVETO,">file8.txt") || die $!;
g> while($#files > 0)
g> {
g> $rand = int(rand(@files));
g> print SAVETO $files[$rand];
g> delete $files[$rand];
here is your big bug. that doesn't do what you think it does. have you
run this code? my turing machine says it will never stop.

Ran fine on my machine, would you care to explain further?
are you sure it works? delete doens't remove an element from an array,
just the value. $#files will not change.

Has worked everytime I've tried it, although if $#files does not change
then it obviously works for a reason other than the one I had imagined.
 
A

Anno Siegel

Why? Constructive criticism involves explanations, not dictats.

Not on Usenet, it doesn't. There are accepted best practices. Declaring
variables in the smallest possible scope is one of them. It's enough
to point them out, no need to explain them all over each time.

No-one can dictate you. It's up to you to understand and decide if
you want to follow.
Can you expand please?

Again, accepted best practice. It's a corollary of the "smallest scope"
rule.
What difference would that have to the operation of the program? Surely
this is personal preference?

No. A well-written program is, above all, readable. Poorly chosen variable
names detract from readability.
What difference would that have to the operation of the program? Sure
this too is personal preference?

If you ever want to write a program that qualifies as "well written" you
better start indenting your code.

[snip discussion of run-time behavior]

Anno
 
G

game4itguy

Why? Constructive criticism involves explanations, not dictats.
Not on Usenet, it doesn't. There are accepted best practices. Declaring
variables in the smallest possible scope is one of them. It's enough
to point them out, no need to explain them all over each time.

No-one can dictate you. It's up to you to understand and decide if
you want to follow.

At present I don't feel inclined to follow this practice, purely
because I still don't fully understand the difference it would make
(experience may change my mind of course as there is invariably a
reason things are done the way they are). Thank you for the reply
though, your point about readability is well taken.
 
D

David Squire

At present I don't feel inclined to follow this practice, purely
because I still don't fully understand the difference it would make
(experience may change my mind of course as there is invariably a
reason things are done the way they are).

Hmmm. Surely it would be more rational to adopt the accepted way of
doing things until your understanding and experience are sufficient for
you to make an informed choice to do so or not.

DS
 
G

game4itguy

At present I don't feel inclined to follow this practice, purely
Hmmm. Surely it would be more rational to adopt the accepted way of
doing things until your understanding and experience are sufficient for
you to make an informed choice to do so or not.

I disagree. I would rather continue doing things the way I am
comfortable with until my methods fail in a way that demonstrates why I
should do things differently. If I adopted the accepted standard
without understanding why I was doing so I might not discover the flaw
in my original methods to justify why I was doing things by the
accepted method. I understand your point, but I prefer to figure out
why 2x2 doesn't equal 5, rather than just accepting it equals 4.
Undoubtedly irrational, but unfortunately me.
 
P

Paul Lalli


So you can't accidentally use a variable on line 53403 that you
declared on line 2, when you meant to use the similarly-named variable
that you declared on line 53400.

Also so that you don't have to trace through 53401 lines of code
looking for every instance of the variable to see what might have
happened to it. Just look at the top of the inner-most block and
you'll see where it was declared and everything that could have
happened to it before the relevant line.

Will it change the behavior of a "working" program? Nope. This tip is
intended to make it easier to find bugs when you introduce them.
Can you expand please?

1) Global barewords are just that - global. If you use DH on line 30,
and while you're reading from it, use a function that's defined on line
400, and that function also opens a directory with the DH handle, you
will have blown away any possibility of reading this original
directory.

2) Global barewords are not subject to strict. If you name your handle
"MY_DIR0", and at one point typo it as "MY_DIRO", strict will not
complain to you. Instead, you'll get a very confusing "read on closed
directory handle" warning, or similar, and spend valuable time wasted
trying to figure out when you closed your directory handle.

3) Global bareword handles cannot be used in recursive subroutines,
because they are non-rentrant. The second, third, etc times a function
is entered, the function will attempt to open a directory with the
existing directory handle, again clobbering your original read.
What difference would that have to the operation of the program?

None - until your maintenence programmer has to read your code and
figure out what the hell you're doing.
Surely this is personal preference?

Yes, and I have yet to meet any person anywhere who prefers confusing
and unreadable code to clear and readable. You're basically just lying
to anyone who reads your code, including yourself. You have a variable
named @files, but you don't put files into it? Why? What is gained by
this misdirection?
What difference would that have to the operation of the program? Sure
this too is personal preference?

Yup. See above.

See also:
perldoc perlstyle

This is another problem that wasn't pointed out to you. You're
ignoring one line from the file. $#files contains the last index of
the array @files. When @files contains only one element, $#files will
be equal to 0. That should say
while ($#files > -1)
g> {
g> $rand = int(rand(@files));
g> print SAVETO $files[$rand];
g> delete $files[$rand];
here is your big bug. that doesn't do what you think it does. have you
run this code? my turing machine says it will never stop.

mine says it should "most likely" stop, since *eventually* the last
element will probably be chosen and deleted, and then *eventually* the
new last element will probably be chosen and deleted, etc.
Ran fine on my machine, would you care to explain further?

According to the docs, delete will only undefine an element of an
array, not remove it. EXCEPT when dealing with the end of the array.
If you delete the last element, the array will indeed shrink. So yes,
this will (most likely) eventually go through all the files. However,
after "deleting" $files[3], for example, your program can then again
choose 3 and attempt to print the now undefined element. Very
inefficient.

Actually, seeing this problem brought to light two realizations I
hadn't had before:
1) The array will shrink down to the last element for which exists()
still returns true
2) A delete'd element returns a false value for exists() (which is
documented in `perldoc -f delete` but seems very contradictory to
`perldoc -f exists`, IMO).

End result - yes, this program will (most likely) "work", but it is
very inefficient and likely to produce warnings as you are allowing the
possibility of choosing and printing an undefined value.

Not quite true. It does remove an element if its the *last* element.

Hope this helps clarify why you were suggested to do some of these
'best practices'

Paul Lalli
 
P

Paul Lalli

Paul said:
g> while($#files > 0)
g> {
g> $rand = int(rand(@files));
g> print SAVETO $files[$rand];
g> delete $files[$rand];
End result - yes, this program will (most likely) "work", but it is
very inefficient and likely to produce warnings as you are allowing the
possibility of choosing and printing an undefined value.

I stand partially corrected. This will not print the warnings I had
envisioned. Although *why* it doesn't print them, I couldn't begin to
guess:
perl -we'
my @foo = (1..10);
while ($#foo > -1) {
my $i = rand(@foo);
print "$foo[$i] ";
delete $foo[$i];
}
'
This gives output of:
7 6 3 5 10 4 9 1 2 8
with no warnings.

It is interesting, however, that interpolating the array in a double
quoted string *does* produce one warning for each undefined element:
perl -we'
my @foo = (1..3);
while ($#foo > -1) {
my $i = rand(@foo);
print "@foo\n";
delete $foo[$i];
}
'
1 2 3
Use of uninitialized value in join or string at -e line 5.
1 3
Use of uninitialized value in join or string at -e line 5.
Use of uninitialized value in join or string at -e line 5.
3
Use of uninitialized value in join or string at -e line 5.
Use of uninitialized value in join or string at -e line 5.
3

I have no idea why one produces warnings while the other doesn't. I'm
almost tempted to call this a bug in the warnings system. Anyone else
have any thoughts?

Paul Lalli
 
K

Keith Keller

I disagree. I would rather continue doing things the way I am
comfortable with until my methods fail in a way that demonstrates why I
should do things differently. If I adopted the accepted standard
without understanding why I was doing so I might not discover the flaw
in my original methods to justify why I was doing things by the
accepted method.

That's fine for code that you don't share, but for code that you publish
here, you're more likely to receive constructive help if you do follow
the accepted coding standards. That's not a MUST, but it is a SHOULD
(in RFC parlance).

--keith
 
G

game4itguy

Paul said:
So you can't accidentally use a variable on line 53403 that you
declared on line 2, when you meant to use the similarly-named variable
that you declared on line 53400.

This hasn't been a problem for me so far as I have never coded anything
of that length, but I see your point. I shall revise my usage.
None - until your maintenence programmer has to read your code and
figure out what the hell you're doing.

My perl scripts have in the past only ever been intended for my own
learning purposes, but posting them for others to read does present the
need to make them more legible I agree (and for my own benefit in
reading my old scripts, in fact). This will be something I'll need to
work on.
According to the docs, delete will only undefine an element of an
array, not remove it. EXCEPT when dealing with the end of the array.
If you delete the last element, the array will indeed shrink. So yes,
this will (most likely) eventually go through all the files. However,
after "deleting" $files[3], for example, your program can then again
choose 3 and attempt to print the now undefined element. Very
inefficient.

Interesting. I had assumed, given the name "delete", that the element
would have been removed rather than remain in the array undefined.
Useful lesson, thank you.
Hope this helps clarify why you were suggested to do some of these
'best practices'

Very much so, thank you.
 
P

Paul Lalli

Interesting. I had assumed, given the name "delete", that the element
would have been removed rather than remain in the array undefined.

This is a common misperception. Adding to the confusion is the fact
that this expectation *is* exactly how delete works on hashes.

I recommend:
1) making sure you read `perldoc -f delete`
2) never using delete() on arrays. Instead, use splice() (and read
`perldoc -f splice`)

Paul Lalli
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top