Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Re^2: Next from inner loop only works "most of the time"

by Marshall (Canon)
on May 20, 2021 at 06:59 UTC ( [id://11132757]=note: print w/replies, xml ) Need Help??


in reply to Re: Next from inner loop only works "most of the time"
in thread Next from inner loop only works "most of the time"

Hi Ken!

Ok, I didn't post the entire code. I did archive a version with the labeled next which I will post below, sans the dictionary file which is 150+K lines. Right now I don't remember where I got this word list from - sorry. I don't claim that this is a masterpiece of Perl code. I didn't write this with the intention of posting it here and as such it contains some things that I wouldn't want new Perler's to emulate. There are some unnecessary lc operations, I would use explicit my variables for the loops, etc.

Here is how this code came about... I was playing "Word Nut" on my cellphone. I got up to a high level with the addition of turning the difficulty level up to the max. I was confronted with a grid of boxes like a crossword puzzle, except that there are no sentences for clues! The puzzle that "triggered" me had just 5,6,7 letter boxes, no "easy" 3 or 4 letter words. I typed in something more than 20 completely valid 5 letter words (formed according to the 7 letters given). None of these words appeared in the puzzle, but the program counts them and I got bonus points for finding valid words that don't appear.

You can get a hint from the program, but that means that you are required to watch a bunch of ads. For some reason that offended me and I decided to retaliate with some Perl code!

In order to "get started", it is important to find a word, any word that appears in the crossword grid. Once that is done, there will be an intersecting word and you will know that for example, for that word, the 2nd letter is an "r" or whatever.

For the "triggering" puzzle, I typed in 32 valid 5 letter words with the help of my "cheater" program before I got the first "hit" in the crossword grid! Before completely solving the puzzle, there were 42 valid words that did not appear in the grid!

These puzzles use uncommon words like "resaw". I am a native born, reasonably read English speaker and although I understand that word, I've never used it myself in a sentence, read a sentence with it or heard anybody else say that word!

Here is the code... I don't see any obvious way that this can "fail" other than the code that I did post. Please also note that this code works "most of the time".

use strict; use warnings; use Data::Dumper; # Word Master quick hack on 5/18/2021 # en-US.dic is a flat file of sorted words (about 150K words) open (my $fh, '<', 'en-US.dic') or die "can't find dictionary file: en +-US.dic"; my @dic = map{chomp; $_}grep {!/'/ and !/[A-Z]/}<$fh>; #no apostrophes + allowed #no proper nouns Rome (capit +al letters) $0 =~ m!(\\|/)([\w.]+)\s*$!; print "Word Master ($2)\n"; #like wm.pl this allows renaming the pro +gram print "# Enter list of letters by using semicolon followed by the lett +ers\n"; print "# example>:omdee\n"; print "# in pattern, use simple dash for single unknown letters\n"; print "# m-de would match \"mode\"\n"; print "# quit|exit|q to exit program\n"; print "\n"; my $line; my %master_letter_freq; my $master_letter_list =""; #could be repeated letters like ee,tt,etc while ( (print "list of letters or pattern: "),$line=<>, $line !~ /\s* +quit|exit|q\s*$/i) { next unless $line =~ /\S/; #skip blank lines chomp $line; my $cur_pattern; if ($line =~ /^\s*:([a-zA-Z]+)\s*$/) # new list of letters { $master_letter_list = lc $1; ## Force all letter lists to LOWE +R CASE only for (split //,$master_letter_list) { $master_letter_freq{$_}++; } print "master_letter_freq:\n"; print Dumper \%master_letter_freq; ##################### } elsif ($line =~ /^\s*([a-zA-Z-]+)\s*$/) #no leading ":", this is a p +attern { $cur_pattern = lc $1; # Force all patters to LOWER CASE only if ($master_letter_list eq "") { print "No master letter list exists -> can't run this patt +ern! Error!\n"; next; } my $regex = ''; for (split //, $cur_pattern) # gen regex { if ($_ ne '-' and !exists $master_letter_freq{$_}) { print "Pattern has a letter that's not in master list! + Error!\n"; next; } if ($_ eq '-') {$regex .= "[$master_letter_list]";} else {$regex .= "$_";} } my @result = grep{/^$regex$/i}@dic; # filter out any result if the number of times a # letter is repeated is more than the number of times it is # repeated in the master letter list # RESULT: foreach (@result) { my %seen; $seen{$_}++ for (split //,lc $_); # print "Testing Result $_, seen histogram is:\n"; # print Dumper \%seen; foreach (keys %seen) { next RESULT if ($seen{$_} > $master_letter_freq{$_}); } print "$_\n"; } } else { print "Illegal input line!\n"; } } __END__ Copied from Command Line - shows difference on different runs list of letters or pattern: :otrwreh list of letters or pattern: --r-w threw throw list of letters or pattern: ---w thew trow whew list of letters or pattern: list of letters or pattern: :otrwreh list of letters or pattern: --r-w threw throw list of letters or pattern: ---w thew trow whew list of letters or pattern: q list of letters or pattern: :otrwreh master_letter_freq: $VAR1 = { 'w' => 1, 'h' => 1, 't' => 1, 'o' => 1, 'r' => 2, 'e' => 1 }; list of letters or pattern: ---w thew trow list of letters or pattern

Added: sorry if I offended anybody by describing the origins of the code. That is relevant here. I wanted to post some code that I have seen fail. If I change the code, that might affect its ability to "fail". I am not asking for help to make the code "better". I just don't understand why this can fail "some, but not all of the time". I do acknowledge that there are style failings in this code. I was just explaining that I did this quickly and hence some style failings.

Replies are listed 'Best First'.
Re^3: Next from inner loop only works "most of the time"
by tybalt89 (Monsignor) on May 20, 2021 at 09:34 UTC

    First guess:

    $master_letter_list = lc $1; ## Force all letter lists to LOWE +R CASE only %master_letter_freq = (); # <--- ** MISSING LINE ** for (split //,$master_letter_list)

    Every time $master_letter_list is changed, the frequency hash must be cleared before being added to.

    The occasional "failure" is due to the differing sequences of user interaction.

      I appreciate your suggestion!

      This very well could be the "solution to the problem".
      And also explain why previous commands made a difference in the result.
      A state dependent failure where what happened before affects what happens now.

      My previous thinking of reproducing an entire session would have caused a "hard failure".
      The issue is "previous state" dependent.

      Thank you, Marshall

      if ($line =~ /^\s*:([a-zA-Z]+)\s*$/) # new list of letters { $master_letter_list = lc $1; ## Force all letter lists to LOWE +R CASE only %master_letter_freq=(); ########### ADDED ########## for (split //,$master_letter_list) { $master_letter_freq{$_}++; } print "master_letter_freq:\n"; print Dumper \%master_letter_freq; ##################### }
      Here is a new version of wm.pl:

      Update:
      I am using the improved code and so far no program issues have been found.
      The words in these puzzles are just crazy!
      list of letters or pattern: :lfseka
      list of letters or pattern: --e
      ale

      The correct word was FAE!

      "The most commonly accepted meaning of the word “fae” on the internet is that the word is a shortened abbreviation for the word “fairy.” “Fairy” in this sense meaning the mythical and playful, often mischievous, human-like woodland creatures from stories and legends."
      Perl cannot help with wacko stuff like that!

      Update:
      I just started a new puzzle with :buepol
      My very first guess was "bole" and it worked.
      GEEZ!
      my second guess was "plebe" - that didn't even count as a valid word! What ?!

Re^3: Next from inner loop only works "most of the time"
by GrandFather (Saint) on May 20, 2021 at 11:51 UTC

    I crunched your code down a little to turn it into a test script. You may like to try running it to see if it reproduces the issue. If it doesn't you could try adding back elements of your script until you get back to a UFO. At that point you will have identified a critical component (whatever you added last) and that may help us figure out where the issue is.

    use strict; use warnings; print "Starting\n"; for (1 .. 100000) { my @results = draw(); print "@results\n" if 2 != @results; } print "Done\n"; sub draw { my @dic = ('thew', 'trow', 'whew'); my %master_letter_freq; my $master_letter_list = 'otrwreh'; my $regex = ''; ++$master_letter_freq{$_} for split //, $master_letter_list; for (split //, '---w') { $regex .= $_ eq '-' ? "[$master_letter_list]" : $_; } my @result = grep {/^$regex$/i} @dic; my @results; RESULT: foreach (@result) { my %seen; $seen{$_}++ for (split //, lc $_); foreach (keys %seen) { next RESULT if ($seen{$_} > $master_letter_freq{$_}); } push @results, $_; } return @results; }

    On my machine running Perl 3.30.1 prints:

    Starting Done
    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
Re^3: Next from inner loop only works "most of the time"
by kcott (Archbishop) on May 22, 2021 at 08:10 UTC

    Firstly, apologies for the slow response: I've been ill and haven't logged in for some days.

    I received a couple of private messages from you, possibly (and I'm completely guessing here) due to frustration if you thought I was ignoring you: not the case. And regarding the downvote: can't help; wasn't me; I've only just seen your post.

    I do tend to avoid mutliple uses of $_ in the same construct. Even when it's not a problem with actual logic, it does reduce readability and maintainability. I generally concur with what others have already written about that, so I'll leave it there.

    I was genuinely interested in where your problem might lie. My posted code, using your exact code, was an attempt to identify the issue: as shown, I couldn't reproduce it.

    I see there's been a lot more discussion since I was last here. I don't believe I can add anything to that.

    — Ken

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-04-19 21:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found