Lawliet,
Here is some proof of concept code I wrote for an algorithm I outlined here. It is rather naive and I didn't spend a lot of time making it efficient but I figured I would share anyway.
#!/usr/bin/perl use strict; use warnings; use Getopt::Std; my %opt; get_args(\%opt); my $dict = load_dictionary($opt{d}, $opt{w}); my %guessed; my $curr_guess = join '', map {'*'} 1 .. length($opt{w}); while (1) { last if $curr_guess eq $opt{w} || ! $opt{g}; print "Current value:\t$curr_guess\n"; my $best_letter = find_best_letter($dict, \%guessed); print "Best letter to choose: $best_letter\n"; my $result = index($opt{w}, $best_letter) == -1 ? 'wrong' : 'right +'; if (index($opt{w}, $best_letter) == -1) { print "You guessed wrong\n"; --$opt{g}; prune_dict_bad_guess($dict, $best_letter); } else { print "You guessed right\n"; $curr_guess = update_current($curr_guess, $opt{w}, $best_lette +r); prune_dict_correct_guess($dict, $curr_guess); } $guessed{$best_letter} = undef; } print "\n$curr_guess\n"; sub prune_dict_correct_guess { my ($dict, $curr) = @_; my %correct; for (0 .. length($curr) - 1) { my $chr = substr($curr, $_, 1); next if $chr eq '*'; $correct{$_} = $chr; } for my $word (keys %$dict) { for my $pos (keys %correct) { if (substr($word, $pos, 1) ne $correct{$pos}) { delete $dict->{$word}; last; } } } } sub update_current { my ($src, $tgt, $let) = @_; for (0 .. length($tgt) - 1) { substr($src, $_, 1, $let) if substr($tgt, $_, 1) eq $let; } return $src; } sub prune_dict_bad_guess { my ($dict, $letter) = @_; for my $word (keys %$dict) { delete $dict->{$word} if index($word, $letter) != -1; } } sub find_best_letter { my ($dict, $guessed) = @_; my %alpha; for my $word (keys %$dict) { my %uniq = map {$_ => undef} split //, $word; $alpha{$_}++ for keys %uniq; } delete @alpha{keys %$guessed}; # Would be better as water mark algorithm my @best = sort {$alpha{$b} <=> $alpha{$a}} keys %alpha; return $best[0]; } sub get_args { my ($opt) = @_; my $Usage = qq{Usage: $0 [options] -h : This help message -d : The (d)ictionary file Default: 'words.txt' in the current working directory -g : The number of (g)uesses Default: 7 -w : The (w)ord to be guessed } . "\n"; getopts('hd:g:w:', $opt) or die $Usage; die $Usage if $opt->{h}; die $Usage if ! $opt->{w} || $opt->{w} =~ /[^a-zA-Z] +/; $opt->{d} = 'words.txt' if ! defined $opt->{d}; $opt->{g} = 7 if ! defined $opt->{g}; $opt->{w} = lc($opt->{w}); } sub load_dictionary { my ($file, $word) = @_; my $desired_length = length($word); my %dict; open(my $fh, '<', $file) or die "Unable to open '$file' for readin +g: $!"; while (<$fh>) { tr/a-zA-Z//cd; next if length($_) != $desired_length; $dict{lc($_)} = undef; } return \%dict; }

Cheers - L~R


In reply to Re: Hangman Assistant by Limbic~Region
in thread Hangman Assistant by Lawliet

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.