How should the check be made so that there are no line duplicates in the file
open ( FILE, ">newfile");
for( $a = 1; $a < 20; $a = $a 1 ) {
my $random_number = 1 int rand(10);;
# check to avoid inserting the line if the line is already present in the file
print FILE "Random number is $random_number \n";
}
close(FILE);
CodePudding user response:
Enter each line into a hash as well, what makes it easy and efficient to later check for it
use warnings;
use strict;
use feature 'say';
my $filename = shift or die "Usage: $0 filename\n";
open my $fh, '>', $filename or die "Can't open $filename: $!";
my %existing_lines;
for my $i (1..19)
{
my $random_number = 1 int rand(10);
# Check to avoid inserting the line if it is already in the file
if (not exists $existing_lines{$random_number}) {
say $fh "Random number is $random_number";
$existing_lines{$random_number} = 1;
}
}
close $fh;
This assumes that the intent in the question is to not repeat that number.
But if it is indeed the whole line (sentence) to be avoided then use that for the key
for my $i (1..19)
{
my $random_number = 1 int rand(10);
my $line = "Random number is $random_number";
# Check to avoid inserting the line if it is already in the file
if (not exists $existing_lines{$line}) {
say $fh $line;
$existing_lines{$line} = 1;
}
}
Notes and literature
Lexical filehandles (
my $fh
) are much better than globs (FILE
), and the three-argumentopen
is better. See the quide perlopentut and reference openAlways check the
open
call (or die...
above). It can and does fail -- quietlyThe C-style
for
loop is very rarely needed while the usualforeach
(with synonymfor
) is much nicer to use; see it in perlsyn. The..
is the range operatorAlways declare variables with my, and force that with strict pragma; always use warnings
If the filehandle refers to pipe-open (not the case here) always check its close
See perlintro for a general overview and for hashes; for more about Perl's data types see perldata. Keep in mind for later the notion of complex data structures, perldsc
CodePudding user response:
It seems like what you are asking is how to randomize the order of the numbers 1 to 20. I.e. no duplicates, random order. That can be easily done with a Schwartzian transform. For example:
perl -le'print for map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [$_, rand()] } 1..20'
6
7
16
14
5
20
3
13
19
17
4
8
15
10
9
11
18
1
2
12
In this case, reading from the end and backwards, we create a list of numbers 1 .. 20, we feed that into a map
statement which turns each number into an array-ref, containing the number, and a random number. Then we feed that list of array refs to a sort, where we sort numerically on the second argument in the array ref: the random number (hence creating a random order). Then we transform the array ref back into a simple number with another map
statement. Finally we print the list using a for
loop.
So in your case, the code would look something like:
print "Random number is: $_\n" for # print each number
map { $_>[0] } # restore to a number
sort { $a->[1] <=> $b->[1] } # sort the list on the random number
map { [ $_, rand() ] } # create array ref with random number as index
1 .. 20; # create list of numbers to randomize order of
Then you can use the program like below to redirect output to a file:
$ perl numbers.pl > newfile.txt
CodePudding user response:
return false
will do the trick.
Because you cannot generate 20 distinct numbers in the range [1, 10].