Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

variables from STDIN

by stigmatt (Initiate)
on Feb 22, 2012 at 10:30 UTC ( [id://955491]=perlquestion: print w/replies, xml ) Need Help??

stigmatt has asked for the wisdom of the Perl Monks concerning the following question:

I am really sorry for the misunderstanding my question created. I am writing a syllable structure checker with a search pattern given as an input, for example CVC for BOB or CCVVCV for Sheila, where C stands for a consonant and V for a vowel. Consonants and vowels for different languages are stored in separate arrays.

Since there are thousands of possible combinations, I though about assigning a separate numbered variable for each letter read from the input and use them afterwards in foreach structures, for example:

foreach $c1 (@consonants) { foreach $v1 (@vowels) { foreach $c2 (@consonants) { foreach $v2 (@vowels) { print FH "$c1$v1$c2$v2\n"; } } } }

Thank you for your replies!

Replies are listed 'Best First'.
Re: variables from STDIN
by moritz (Cardinal) on Feb 22, 2012 at 10:47 UTC

    Your question isn't very clear. Maybe it would be helpful if you told us what you want to achieve in the end.

    If you want to dynamically create variables based on user input, this is usually a very bad idea. Instead of variables $a1, $a2, $a3 you should use an array @a, where you can then access the individual elements easily by an index: $a[0] or $a[$some_number].

    Likewise if the name (and not the number) is dynamic, you should consider using a hash instead.

    perldata and perlintro will tell you more.

Re: variables from STDIN
by derby (Abbot) on Feb 22, 2012 at 13:35 UTC

    Interesting ... if I'm reading the OP correctly, you want to create a looping structure that is influenced in two ways by a command line argument: first, the number of loops is controlled by the length of the command line argument; and two, what you're looping is controlled by the command line argument.

    So if the command line argument is CV, you loop as such:

    foreach my $con ( @consonants ) { foreach my $vow ( @vowels ) { .. } }
    and if the command line argument is CVCCVC, you loop as such:
    foreach my $con_1 ( @consonants ) { foreach my $vow_1 ( @vowels ) { foreach my $con_2 ( @consonants ) { foreach my $con_3 ( @consonants ) { foreach my $vow_2 ( @vowels ) { foreach my $con_4 ( @consonants ) { ... } } } } } }
    is that correct?

    My first reaction is find another way. But if you wish to persist, I think recursion is your frenemy here:

    #!/usr/bin/perl my $template = shift || die "usage: $0 <template>\n"; my @pattern = split( //, $template ); my $levels = scalar( @pattern ); my $vowels = [ qw( a e i o u y ) ]; my $consonants = [ qw( b c d f g h j k l m n p q r s t v w x z ) ]; output_cv( 0, \@pattern, $consonants, $vowels, "" ); sub output_cv { my( $level, $pattern, $consonants, $vowels, $string ) = @_; # if we have no more levels in the pattern, output the buffered stri +ng if( $level == scalar( @$pattern ) ) { print "$string\n"; } else { # figure out which array at this pattern level my $array = $pattern->[$level] eq 'C' ? $consonants : $vowels; foreach my $ele ( @$array ) { # start new buffer string my $new_string = $string . $ele; # recurse to next level my $new_level = $level + 1; output_cv( $new_level, $pattern, $consonants, $vowels, $new_stri +ng ); } } }

    I say frenemy because the above is a fairly naive implementation and eventually some combination of template size and/or arrays is going to blow the stack.

    -derby

      See Algorithm::Loops::NestedLoops(). It knows how to be an iterator and so need never "blow the stack" even if you give it so much work that it could never be done before the sun burns out.

      - tye        

      Thank you very much for the advice and for the code. You are right, the recursion can sometimes be fastidious with a bigger data input. Actually, there are lots of syllable checkers and hyphenators over there, but as far as I know none of them can help to define all possible syllable structures in a not predefined language.

      And thanks to everybody intersted in the question. All your ideas are very helpful.

Re: variables from STDIN
by JavaFan (Canon) on Feb 22, 2012 at 10:43 UTC
    I don't know what you mean by a "first a", or a "second a". How do you distinguish between them?
    my $a1 = "a"; # Does it matter "which" 'a' this is? my $a2 = "a"; my $a4 = "a"; my $b1 = "b";
    Perhaps you mean something else. Could you reformulate your question?
Re: variables from STDIN
by roboticus (Chancellor) on Feb 22, 2012 at 10:59 UTC

    stigmatt:

    After three readings, I can't decipher your question. You may want to update it with a bit more detail and an example or two to clarify it.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: variables from STDIN
by Marshall (Canon) on Feb 22, 2012 at 13:59 UTC
    I was just trying to "hard code" this C->consonant and V->vowel for "just" English (probably one of the most difficult languages) and I wound up in trouble. For example in English sometimes Y is a vowel and sometimes a consonant (or so I think...grammar was never my strong suit).
    oxforddictionaries.com/words/is-the-letter-y-a-vowel-or-a-consonant

    I think that the "rules" are more complex than you have specified.
    This code is simple, but I think it illustrates this "y" difficulty.

    #!/usr/bin/perl -w use strict; my @array = ("BOB", "Sheila", "Very", "by", "berry", "beyond"); foreach my $word (@array) { my $original = $word; $word = uc $word; $word =~ s/V/C/g; $word =~ s/[AEIOUY]/V/g; $word =~ s/[^V]/C/g; printf "%-10s %s\n", $original, $word; } __END__ BOB CVC Sheila CCVVCV Very CVCV by CV berry CVCCV beyond CVVVCC #No!!!
    I guess at the end of the day, I don't understand the complete problem.
    But if am to match some input words against some CVC pattern, I need to be able to translate the words into that pattern and I don't know how to do that according to the grammar rules that have been specified.
      A vowel is a voice sound (from the Latin vox - a voice) characterized by the absence of friction-causing obstruction in the vocal tract, allowing the breath stream free passage. In written text it is a character that represents that sound. So you are right about the "y". Consonant too refers to a sound (from the Latin sonãre - to sound).
Re: variables from STDIN
by nemesdani (Friar) on Feb 22, 2012 at 14:38 UTC
    I think you should consider to use language-hashes instead of arrays.
    %english = {"a" => "V", "b" => "C"} etc.
    You can look up each character's class easily, no need to multi-iterate over several arrays.
Re: variables from STDIN
by rovf (Priest) on Feb 22, 2012 at 11:36 UTC
    What is a sign of the standard input? Do we now have signed and unsigned standard input????

    Your question leaves me slightly confused.

    -- 
    Ronald Fischer <ynnor@mm.st>
Re: variables from STDIN
by bimleshsharma (Beadle) on Feb 22, 2012 at 10:41 UTC
    Could you elaborate little bit more?
    It ia not look like local-whisky, it's hard though.
Re: variables from STDIN
by nemesdani (Friar) on Feb 22, 2012 at 11:50 UTC
    Maybe you want to know the _position_ of the first a, second a, etc? Otherwise it makes no sense.
Re: variables from STDIN
by aaron_baugher (Curate) on Feb 22, 2012 at 18:38 UTC

    If I understand you correctly, you're talking about using nested loops to create all the possible combinations of letters matching your pattern, and then using those to search....something.

    This is going to result in extremely large arrays of strings -- way more than "thousands." A six-letter pattern containing 3 Cs and 3 Vs will result in over a million words, while a pattern like CVCCVCVCV (matching 'configure') would create over 12 billion, requiring over 100GB of space just to hold them. And in each case, only a tiny percentage of them would be actual words. (The 'configure' pattern matches 1415 words in my /usr/share/dict/words, or .000011% of the possible letter combos.)

    If you're looking for actual words, and not just random assortments of letters, it's very likely that you would be better off going the other direction -- start with a dictionary of valid words, which probably won't have more than a million entries, and search it for words that match your pattern.

    Aaron B.
    My Woefully Neglected Blog, where I occasionally mention Perl.

      If you want to find matching real words many times, I'd suggest building a hash of your dictionary first.

      Foreach word in the dictionary, check the letters in sequence, and browse your way down a three-way hash. Add that word to an array at the end of the path.

      EG: When you get to "apple", follow:

      my $pos = $dictionary; #this would be a loop of course. $pos = $pos->{vowel}; # The A $pos = $pos->{cons}; # First P $pos = $pos->{cons}; # Second P $pos = $pos->{cons}; # The L $pos = $pos->{vowel}; # The E #end loop push @{$pos->{words}}, "apple";

      This way you can find all words with a specific pattern of Vowel/Consonant extremely fast.

      $dictionary->{vowel}{cons}{cons}{cons}{vowel}{words} will include apple, uncle, intro, extra, ochre and many more. $dictionary->{vowel}{words} would contain "I" and "a"

      Alternatively, if you are planning to do only one search, you could build a regex string full of [aeiou]s and [^aeiou]s, then grep your dictionary.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://955491]
Approved by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2024-04-19 04:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found