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

Hey, sorry to post so much code, but I have no idea where the problem could be. Basically, this program is being designed to generate a number of grammatically correct sentences using random word data (btw, count is not a counter, it's a noun type). I'm new to subroutines and I'm not entirely sure I understand the passing process and return process. The issue however is not so much with those things which I do not understand about passing/returning, but currently why the program is hanging where it is. It's hanging before it even gets to "You entered such and such number", which I put it there to debug. I thought the program execution was linear from top to bottom - so why does it hang there? When it's hung, you can still enter data, but nothing happens until ctrl+C, and then it just goes on the command line. I omitted data from the word lists to save space. Oh, and when it was working before (not hanging I mean), it mentioned problems with uninitiated strings and/or concatenations so I passed data to the subroutines and now it just hangs... These were found in the createNP and createVP subroutines. I'm currently running WinXP (will be switching to a Linux environment soon). Sorry about the messy and incomplete code... (can anyone please give me a clue?)

#!/usr/bin/perl use strict; use warnings; my @det; #determiner my @pro; #pronoun my @properNoun; #proper noun my @conj; #conjunction my @prep; #preposition my @intrans; #intransitive verb my @ditrans; #ditransitive verb my @trans; #transitive verb my @adv; #adverb my @adj; #adjective my @mass; #mass noun my @count; #count noun my @aux; #auxilliary my @noun; #regular noun my @pluralNoun; #plural noun @det = ( 'the', 'a', 'ninety' ); @pro = ( 'it', 'I', 'ya', 'theirs' ); @properNoun = ( 'Alpesh', 'Ann', 'China', 'Beijing' ); @conj = ( 'and', 'that', 'provided that' ); @prep = ( 'of', 'in', 'underneath', 'relative to' ); @intrans = ( 'die', 'sleep', 'paint', 'travel' ); @trans = ( 'edit', 'hold', 'make', 'like' ); @ditrans = ( 'advise', 'ask', 'tell', 'urge' ); @adv = ( 'accidentally', 'afterwards', 'yearly', 'yesterday' ); @adj = ( 'average', 'big', 'voiceless', 'whispering' ); @noun = ( 'assistance', 'attempt', 'breadwinner', 'breakfast' ); @pluralNoun = ( 'afternoons', 'airmail', 'breadwinners', 'breakfasts' ); @mass = ( 'wood', 'cloth', 'homework', 'advice' ); @count = ( 'pen', 'table', 'taboo', 'rest' ); @aux = ( 'will', 'would', 'could', 'must' ); print "How many sentences would you like to generate? "; chomp(my $num_to_gen = <STDIN>); print "\nYou entered: $num_to_gen"; my $randnum; my @np; my @vp; my @pp; my $adjp; my $sentence; sub createADJP{ $randnum = int(rand(2)+1); if ($randnum == 1) { $adjp = $adv[int(rand($#adv + 1))] . ' ' . $adj[int(rand($ +#adj + 1))]; return $adjp; } else { $adjp = $adj[int(rand($#adj + 1))]; return $adjp; } } sub createNP{ my(@adjp); while ((my$counter = 0) < 100) { $randnum = int(rand(5)+1); if ($randnum == 1) { $randnum = int(rand(2)+1); if ($randnum == 1) { $np[$counter] = $det[int(rand($#det + 1))] . ' ' . + $adjp . ' ' . $noun[int(rand($#noun + 1))]; } else { $np[$counter] = $det[int(rand($#det + 1))] . ' ' . + $noun[int(rand($#noun + 1))]; } } elsif ($randnum == 2) { $np[$counter] = $pro[int(rand($#pro + 1))]; } elsif ($randnum == 3) { $np[$counter] = $properNoun[int(rand($#properNoun + 1))]; } elsif ($randnum == 4) { $randnum = int(rand(4)+1); if ($randnum == 1) { $np[$counter] = $det[int(rand($#det + 1))] . ' ' . + $adjp . ' ' . $pluralNoun[int(rand($#pluralNoun + 1))]; } elsif ($randnum == 2) { $np[$counter] = $det[int(rand($#det + 1))] . ' ' . + $pluralNoun[int(rand($#pluralNoun + 1))]; } elsif ($randnum == 3) { $np[$counter] = $adjp . ' ' . $pluralNoun[int(rand +($#pluralNoun + 1))]; } else { $np[$counter] = $pluralNoun[int(rand($#pluralNoun ++ 1))]; } } else { $randnum = int(rand(4)+1); if ($randnum == 1) { $np[$counter] = $det[int(rand($#det + 1))] . ' ' . + $adjp . ' ' . $mass[int(rand($#mass + 1))]; } elsif ($randnum == 2) { $np[$counter] = $det[int(rand($#det + 1))] . ' ' . + $mass[int(rand($#mass + 1))]; } elsif ($randnum == 3) { $np[$counter] = $adjp . ' ' . $mass[int(rand($#mas +s + 1))]; } else { $np[$counter] = $mass[int(rand($#mass + 1))]; } } $counter += 1; } return @np; } sub createVP{ my(@np); while ((my$counter = 0) < 100) { $randnum = int(rand(3)+1); if ($randnum == 1) { $vp[$counter] = $intrans[int(rand($#intrans + 1))]; } elsif ($randnum == 2) { $vp[$counter] = $trans[int(rand($#trans + 1))] . ' ' . $np +[int(rand($#np + 1))]; } else { $vp[$counter] = $ditrans[int(rand($#ditrans + 1))] . ' ' . + $np[int(rand($#np + 1))] . ' ' . $np[int(rand($#np + 1))]; } $counter+= 1; } return @vp; } sub createPP{ my(@np); while ((my $counter = 0) < 100) { $pp[$counter] = $prep[int(rand($#prep + 1))] . ' ' . $np[i +nt(rand($#np + 1))]; $counter += 1; } return @pp; } sub createSentence{ $randnum = int(rand(2)+1); my(@np,@vp); if ($randnum == 1) { $sentence = ($np[int(rand($#np + 1))] . ' ' . $vp[int(rand +($#vp + 1))]); return $sentence; } else { $sentence = ($np[int(rand($#np + 1))] . ' ' . $vp[int(rand +($#vp + 1))] . ' ' . $conj[int(rand($#conj + 1))] . ' ' . $np[int(ran +d($#np + 1))] . ' ' . $vp[int(rand($#vp + 1))]); return $sentence; } } &createADJP; &createNP($adjp); &createVP(@np); &createPP(@np); &createSentence(@np, @vp); my$counter; while (($counter = 0) < 100) # adds PPs to NP array, every 7th +one { $np[$counter] = $np[$counter] . ' ' . createPP($pp[int(rand($#pp + + 1))]); ; # $counter +=7; } while (($counter = 1) < 100) # adds CONJs to NP array, every 7t +h one { $np[$counter] = $np[$counter] . ' ' . $conj[int(rand($#conj + 1))] + . ' ' . $np[int(rand($#np + 1))]; $counter +=7; } while (($counter = 0) < 100) # adds AUXs to VP array, every 5th + one { $vp[$counter] = $aux[int(rand($#aux + 1))] . ' ' . $vp[$counter]; $counter +=5; } while (($counter = 1) < 100) # adds PPs to VP array, every 5th +one { $vp[$counter] = $vp[$counter] . ' ' . createPP($pp[int(rand($#pp + + 1))]); $counter +=5; } if (int(rand(1))) { print &createSentence; } else { print "\n" . $sentence . ' ' . $conj[int(rand($#conj + 1))] . ' ' +. $sentence; } <STDIN>

2005-01-19 Janitored by Arunbear - added readmore tags, as per Monastery guidelines

  • Comment on hanging at odd place, can still input but see nothing on screen (newbie)
  • Download Code

Replies are listed 'Best First'.
Re: hanging at odd place, can still input but see nothing on screen (newbie)
by g0n (Priest) on Jan 19, 2005 at 11:03 UTC
    try running this:

    while ((my $counter=0) <100){print $counter++};

    $counter is always 0, the syntax of the while is wrong

    try declaring $counter before the while, or use

    for (my $counter=0;$counter<100;$counter++)

    and ditch the $counter+=1.

    Its keeling over in createNP by the way. I found that out by putting in "print "foo\n";" in various places until it didn't get printed. Simple but effective!

      thank you Kumar and g0n, this is helping very much! \(^o^)/
Re: hanging at odd place, can still input but see nothing on screen (newbie)
by osunderdog (Deacon) on Jan 19, 2005 at 15:04 UTC

    Whew! I started to refactor this but ran into some things I couldn't translate. So I thought I would point out what I found and let you do the work. (Who knows, it might be homework.)

    First off, you use the following block over and over. It screams for a subroutine:

    $trans[int(rand($#trans + 1))]
    At first I wrote this as a sub called pick:
    sub pick { my $aref = shift; return $aref->[int(rand(scalar(@$aref)))]; }

    Second, rather than having an array for each language element type, I would put this in a hash of arrays (HOA):

    my %parts = ( det => [qw{the a ninety}], #determiner pro => [qw{it I ya theirs}], # pronoun properNoun => [qw{Alpesh Ann China Beijing}], # proper noun ...

    That way you could access individual items with:

    $parts{adj}->[1]

    And combine this with the pick function I mentioned up above. To pick one word out of any part:

    pick($parts{adj});

    Next a couple of observations. In createNP I ran across a problem. You're using a global variable $randnum to hold a random number:

    sub createNP{ my(@adjp); while ((my$counter = 0) < 100) { $randnum = int(rand(5)+1); if ($randnum == 1) { $randnum = int(rand(2)+1); if ($randnum == 1)

    After looking at it, it looks right, but it would be better if you used a local variable to hold the random value that is used within a local scope. Also the problem with the while loop that was mentioned earlier.

    sub createNP{ my(@adjp); my $counter = 0; while ($counter < 100) { my $outerRN = int(rand(5)+1); if ($outerRN == 1) { my $innerRN = int(rand(2)+1); if ($innerRN == 1)

    Finally, I noticed that you are using an array to accumulate results:

    $np[$counter] = $pluralNoun[int(rand($#pluralNoun + 1))];

    This can be done without an index by using the push function.

    push(@np , $pluralNoun[int(rand($#pluralNoun + 1))])

    All I've got time for now. HIH.


    "Look, Shiny Things!" is not a better business strategy than compatibility and reuse.

Re: hanging at odd place, can still input but see nothing on screen (newbie)
by sasikumar (Monk) on Jan 19, 2005 at 10:52 UTC
    Hi

    What does this sentence mean. Chk out what do u want here?? i suspect

    sub createNP{ my(@adjp); while ((my $counter = 0) < 100)

    Update: Change all such while loops

    sub createNP{ my(@adjp); my $counter=0; # sometimes $counter=1 as u do so inside the while +loop while (($counter) < 100)

    Thanks
    SasiKumar