Thanks for quick lesson and pro-tips. I'll be sure to implement some of these.

In case you were wondering, I am indeed using strict and warnings. diagnostics, too.

Thanks again.

On 1/18/15 9:05 PM, Brandon McCaig wrote:
Mike:

On Sun, Jan 18, 2015 at 07:00:05PM -0500, Mike wrote:
So I've got a text file in a multi column format (three
columns), each column is separated by a single space. Here is a
snippet for reference:

artless base-court apple-john
bawdy bat-fowling baggage
beslubbering beef-witted barnacle

I want to be able to randomly select a word from the first
column, then from the second column, then from the third
column, and concatenate them to together into a single string.
Here's the code I currently have, but I'm stuck:
First a little code review.

Be sure to always use strict and warnings to help identify bugs.
Add this to the top of your programs.

use strict;
use warnings;

Perhaps you're already using it. At the very least, your snippet
is strict and warnings approved. :) That said, it is best to
include a full example of what you'e trying, including pragmas.
It saves us the trouble of emphasizing best practices that you're
already following and omitting them might also alter the behavior
of code and confuse us and you. So hopefully you're already using
strict and warnings, but next time include them in your post too!
:)

sub gen_ins {
     open(FH, '<', 'insults2.txt') or die "[-] ERROR: Can't find
insult list.";
It is better to use lexical file handles.

open(my $fh, '<', 'insults2.txt') or
         die "[-] ERROR: Can't find insult list.";

Good job using 3-arg open and handling failure. Often you should
include the output of $! in your error message because it will
contain information about what exactly went wrong. For example,
perhaps insults2.txt exists, but the user doesn't have the
necessary permissions to read it. Take that into account also
when you're writing your error messages to avoid confusing the
user (which may be yourself).

open(my $fh, '<', 'insults2.txt') or
         die "[-] ERROR opening insults list: $!";

     my @cols = split (" ", <FH>);
     print "$cols[0]";
     close FH;
}

gen_ins();

When currently run, gen_ins() will print out the first word of
the given column: $cols[0], $cols[1], or $cols[2]. How can I
access the rest of the words below the first?
Others have demonstrated good solutions to this problem already.
Here's an alternative take emphasizing modularity and reuse.

use strict;
use warnings;

use Readonly;

exit(main(@ARGV));

sub main {
     Readonly::Scalar my $Filename => 'insults2.txt';

     my ($max) = (@_, 1);

     my $insults = load_insults($Filename);

     for (1..$max) {
         my @chain = random_insult_chain($insults);

         local $, = ' ';

         print @chain, "\n";
     }

     return 0;
}

sub get_random_index($) {
     my ($length) = @_;

     # Note: rand() is not meant to be particular good at picking
     # randomly. Look to CPAN for alternative options if you need
     # something *good*.

     return int rand $length;
}

sub load_insults {
     my ($filename) = @_;

     open my $fh, '<', $filename or die "open $filename: $!";

     my @insults;

     # Load the insults into an array of arrays.
     while (<$fh>) {
         my ($first, $second, $third) = split;

         push @{$insults[0]}, $first;
         push @{$insults[1]}, $second;
         push @{$insults[2]}, $third;
     }

     close $fh or warn "close $filename: $!";

     return \@insults;
}

sub random_insult_chain {
     my ($insults) = @_;

     my @words = map random_insult_word($_), @$insults;

     return @words;
}

sub random_insult_word {
     my ($insult_column) = @_;

     my $i = get_random_index @$insult_column;

     my $word = $insult_column->[$i];

     return $word;
}

__END__

Regards,




--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to