Problem:
Make as many words as possible with the letters a,a,c,c,e,i,n,t,v; each
word must contain the letter c.
My solution:
Using the English language word list at www.wordlist.sourceforge.net/ ,
I've come up with the following:
while(<>) {
if (/^[aceintv]*$/ && /c/) {
my %hash;
foreach (split //) {$hash{$_}++};
print "$_" if $hash{v}<=1 && $hash{c}<=2 &&
$hash{c}>=1 && $hash{i}<=1 && $hash{n}<=1 && $hash{t}<=1 && $hash{e}<=1;
}
}
Does somebody have a more elegant solution?
gtoomey
Try : "Get a Life !"
> Try : "Get a Life !"
Try my killfile.
Tassilo
--
$_=q!",}])(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus;})(rekcah{lrePbus;})(lreP{rehtonabus;})(rehtona{tsuJbus!;
$_=reverse;s/sub/(reverse"bus").chr(32)/xge;tr~\n~~d;eval;
Why? The OP is just trying to learn. What's wrong with that?
Anyhow, I have a nice, cozy place for you in my killfile.
Cheers,
Bernard
--
echo 42|perl -pe '$#="Just another Perl hacker,"'
Not sure which part you are trying to solve in your code snippet:
- creating all the permutation of the characters
- comparing them with the list of English words.
If it's about the permutations then you may want to check out "perldoc -q
permute" for some ideas.
jue
> Problem:
> Make as many words as possible with the letters a,a,c,c,e,i,n,t,v; each
> word must contain the letter c.
> while(<>) {
> if (/^[aceintv]*$/ && /c/) {
> my %hash;
> foreach (split //) {$hash{$_}++};
> print "$_" if $hash{v}<=1 && $hash{c}<=2 &&
^ ^
^ ^
Those quotes don't do anything (useful), so they should not be there.
> $hash{c}>=1 && $hash{i}<=1 && $hash{n}<=1 && $hash{t}<=1 && $hash{e}<=1;
> }
> }
Your code does not check for "a" characters...
> Does somebody have a more elegant solution?
This one seems to me to be easier to read and understand:
----------------------------------
while(<>) {
next unless /^[aceintv]*c[aceintv]*$/; # has disallowed character
my $word = $_;
chomp;
foreach my $ch (qw/a a c c e i n t v/) { # remove allowed characters
s/$ch//;
}
print $word unless length; # matched if no chars are left
}
----------------------------------
--
Tad McClellan SGML consulting
ta...@augustmail.com Perl programming
Fort Worth, Texas
Gregory Toomey wrote:
>
> My solution:
> Using the English language word list at www.wordlist.sourceforge.net/ ,
Is this the right URL? My computer cannot find it, and it looks like a good
site to test some things I'm doing.
Oh, to your question. If it works, it's elegant. TIMTOWTDI, and, to a first
approximation (okay, within an order of magnitude), they're all equally elegant.
Thanks,
Cameron
--
Cameron Dorey
Associate Professor of Chemistry
University of Central Arkansas
Phone: 501-450-5938
came...@mail.uca.edu
> Subject: Perfecting my Perl
The subject line should have contained the phase "perl golf".
> Problem:
> Make as many words as possible with the letters a,a,c,c,e,i,n,t,v; each
> word must contain the letter c.
> I've come up with the following:
>
> while(<>) {
> if (/^[aceintv]*$/ && /c/) {
> my %hash;
> foreach (split //) {$hash{$_}++};
> print "$_" if $hash{v}<=1 && $hash{c}<=2 &&
> $hash{c}>=1 && $hash{i}<=1 && $hash{n}<=1 && $hash{t}<=1 && $hash{e}<=1;
> }
> }
>
> Does somebody have a more elegant solution?
That would, of course, depend on your elegance metric.
while (<>) {
print if /c/ && !/[^aceintv]/ && !/([eintv]).*\1/ && !/([ac]).*\1.*\1/;
}
(The outer loop can be replaced by invoking perl with the -n switch).
> "Gregory Toomey" <nob...@noplace.com> wrote in message news:<01c2864c$6cb47f00$88498a90@gmtoomey>...
>
>> Subject: Perfecting my Perl
>
> The subject line should have contained the phase "perl golf".
Not necessarily. I am not inclined to see every elegant Perl solution as a
piece of Perl golf. Sometimes more verbose code can have its own air of
elegance. See CPAN, hardly a golf parcours.
Tassilo v. Parseval <tassilo....@post.rwth-aachen.de> wrote in article
<aqe2n4$7eu$1...@nets3.rz.RWTH-Aachen.DE>...
> The following posted on request sent in a personal mail from Cameron
> Dorey (her newsservice appears to be down):
>
> Gregory Toomey wrote:
>
> >
> > My solution:
> > Using the English language word list at www.wordlist.sourceforge.net/
,
>
>
> Is this the right URL? My computer cannot find it, and it looks like a
good
> site to test some things I'm doing.
Sorry its http://wordlist.sourceforge.net/
I use
"SCOWL (Spell Checker Oriented Word Lists) is a collection of word lists
split up in various sizes, and other categories, intended to be suitable
for use in spell checkers. However, I am sure it will have numerous other
uses as well. "
There are some 670,000 words if you add all the sublists together.
gtoomey
There are cash prizes. I used Perlt to solve a more complex transposition
cipher problem in the same magazine.
gtoomey
Try this:
http://wordlist.sourceforge.net/
--Rick
I would replace each '.*' in the regexen with '.*?', for slightly
improved efficiency.
Also, perhaps a check for length() <= 9.
--
my $n = 2; print +(split //, 'e,4c3H r ktulrnsJ2tPaeh'
."\n1oa! er")[map $n = ($n * 24 + 30) % 31, (42) x 26]
: I'm helping a relative with some word puzzles but the solution I've come up
Depends entirely on how you want to measure elegance.
Here's one I've had for a while. It started life as a golfish
one-liner, so clarity takes a shot on the chin. The basic idea is the
same as yours except the letters aren't hardcoded, and there isn't a
nicely abstract way to glue in the "must contain 'c'" requirement.
#!perl -p
sub f{my%w;$w{$_}++for/./g;%w}
%j=f;for$k(keys%j){$_ x=$j{$k}<=$i{$k}}
BEGIN{
die("Usage: $0 [letters] [dictionary file]")unless@ARGV==2;
$_=shift;%i=f
}
If you anticipate scrabbling many lettersets in one run, there is
obvious benefit in keeping the word list around in some kind of data
structure; a hash-of-arrays of words that are anagrams of each other
seems a decent choice. From there it's just hash lookups on letterset
permutations. Add a simple filtering callback mechanism, whatever
other bells and whistles you want, et voila.
#!perl
use warnings;
use strict;
print "$_\n"
for scrabble(
letters => 'aacceintv',
filter => sub{$_[0] =~ /c/}
);
sub scrabble {
my %args = @_;
$args{filter} ||= sub{1};
my $anagrams = wordlist();
my @ret;
for( permute_letters( $args{letters} ) ) {
next unless $args{filter}->($_);
push @ret, @{$anagrams->{$_}}
if defined $anagrams->{$_};
}
return @ret;
}
sub uniq {
my %seen;
@seen{@_} = ();
return keys %seen;
}
sub permute_letters {
my @elems = sort $_[0] =~ /./g;
my @perms;
for my $mask ( 1 .. (1<<@elems) - 1 ) {
push @perms, join '',
map $mask & 1<<$_
? $elems[$_]
: '',
0..$#elems;
}
return uniq(@perms);
}
{
my $words; # crude memoization of the sub's only return
sub wordlist {
unless( defined $words ) {
print "Reading word list...";
open WORDS, '<', 'wordlist.txt' or die $!;
while(<WORDS>) {
chomp;
my $key = join '', sort /./g;
push @{$words->{$key}}, $_;
}
close WORDS;
print "Done.\n";
}
return $words;
}
}
gtoomey