line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Games::Boggle; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Games::Boggle - find words on a boggle board |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use Games::Boggle; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
my $board = Games::Boggle->new("TRTO XIHP TEEB MQYP"); |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
foreach my $word (@wordlist) { |
14
|
|
|
|
|
|
|
print "OK $word\n" if $board->has_word($word); |
15
|
|
|
|
|
|
|
} |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 DESCRIPTION |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
This module lets you set up a Boggle board, and then query it for whether |
20
|
|
|
|
|
|
|
or not it is possible to find words on that board. |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 METHODS |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head2 new |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
my $board = Games::Boggle->new("TRTO XIHP TEEB MEQP"); |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
You initialize the board with a series of 16 letters representing the |
29
|
|
|
|
|
|
|
letters that are shown. Optional spaces may be inserted to make the |
30
|
|
|
|
|
|
|
board string more readable. |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
A 'Qu' should be entered solely as a 'Q'. |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head2 has_word |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
print "OK $word\n" if $board->has_word('tithe'); |
37
|
|
|
|
|
|
|
print "NOT OK $word\n" unless $board->has_word('queen'); |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
Given any word, we return whether or not that word can be found on the |
40
|
|
|
|
|
|
|
board following the normal rules of Boggle. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
In scalar context this returns the number of possible ways of finding |
43
|
|
|
|
|
|
|
this word. In list context it returns the starting squares from which this |
44
|
|
|
|
|
|
|
word can be found (but only once per square, no matter how many times it |
45
|
|
|
|
|
|
|
can be found there). |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
Words containing the letter Q should be entered in full ('Queen', rather |
48
|
|
|
|
|
|
|
than 'qeen'). Words containing a 'Q' not immediately followed by a 'U' |
49
|
|
|
|
|
|
|
are never playable. |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head1 AUTHOR |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
Tony Bowden |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head1 BUGS and QUERIES |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
Please direct all correspondence regarding this module to: |
58
|
|
|
|
|
|
|
bug-Games-Boggle@rt.cpan.org |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
Copyright (C) 2002-2005 Tony Bowden. |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under |
65
|
|
|
|
|
|
|
the terms of the GNU General Public License; either version 2 of the License, |
66
|
|
|
|
|
|
|
or (at your option) any later version. |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT |
69
|
|
|
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
70
|
|
|
|
|
|
|
FOR A PARTICULAR PURPOSE. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head1 SEE ALSO |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
Advanced Perl Programming, 2nd Edition, by Simon Cozens |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=cut |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
$VERSION = '1.01'; |
79
|
|
|
|
|
|
|
|
80
|
1
|
|
|
1
|
|
28804
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
32
|
|
81
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
500
|
|
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub _unique { |
84
|
5
|
|
|
5
|
|
11
|
my %list = map { $_ => 1 } @_; |
|
17
|
|
|
|
|
46
|
|
85
|
5
|
|
|
|
|
42
|
return sort { $a <=> $b } keys %list; |
|
2
|
|
|
|
|
22
|
|
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
my $play = [ |
89
|
|
|
|
|
|
|
[1 .. 16], |
90
|
|
|
|
|
|
|
[2,5,6],[1,3,5..7],[2,4,6..8],[3,7,8], |
91
|
|
|
|
|
|
|
[1,2,6,9,10],[1..3,5,7,9..11],[2..4,6,8,10..12],[3,4,7,11,12], |
92
|
|
|
|
|
|
|
[5,6,10,13,14],[5..7,9,11,13..15],[6..8,10,12,14..16],[7,8,11,15,16], |
93
|
|
|
|
|
|
|
[9,10,14],[9..11,13,15],[10..12,14,16],[11,12,15] |
94
|
|
|
|
|
|
|
]; |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub new { |
97
|
1
|
|
|
1
|
1
|
74
|
my ($class, $string) = @_; |
98
|
1
|
|
|
|
|
25
|
my @board = grep /\S/, split //, uc $string; |
99
|
16
|
|
|
|
|
53
|
bless { |
100
|
|
|
|
|
|
|
_board => ["-", @board], |
101
|
1
|
|
|
|
|
8
|
_has => { map { $_ => 1 } @board }, |
102
|
|
|
|
|
|
|
}, $class; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub has_word { |
106
|
16
|
|
|
16
|
1
|
9097
|
my $self = shift; |
107
|
16
|
|
|
|
|
173
|
my $word = uc shift; |
108
|
16
|
100
|
|
|
|
63
|
return if $word =~ /Q(?!U)/; # Can't have lone Q in boggle. |
109
|
15
|
|
|
|
|
31
|
$word =~ s/QU/Q/; |
110
|
15
|
100
|
|
|
|
33
|
return unless $self->_have_letters($word); |
111
|
13
|
|
|
|
|
40
|
my @starts = _can_play($self->{_board}, $word, 0); |
112
|
13
|
100
|
|
|
|
151
|
return wantarray ? _unique @starts : scalar @starts; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
# Quick sanity check to stop us looking for words with letters we don't |
116
|
|
|
|
|
|
|
# have. We don't check to ensure that we have ENOUGH copies of each |
117
|
|
|
|
|
|
|
# letter in the word, as that is considerably slower. |
118
|
|
|
|
|
|
|
sub _have_letters { |
119
|
15
|
|
|
15
|
|
26
|
my ($self, $word) = @_; |
120
|
15
|
100
|
|
|
|
47
|
while (my $let = chop $word) { return unless $self->{_has}->{$let}; } |
|
57
|
|
|
|
|
254
|
|
121
|
13
|
|
|
|
|
36
|
return 1; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub _can_play { |
125
|
204
|
|
|
204
|
|
513
|
my ($board, $word, $posn) = @_; |
126
|
204
|
100
|
|
|
|
477
|
if (length $word > 1) { |
127
|
83
|
|
|
|
|
191
|
my $last = chop $word; |
128
|
108
|
|
|
|
|
157
|
return map { |
129
|
83
|
|
|
|
|
230
|
local $board->[$_] = "-"; |
130
|
108
|
|
|
|
|
175
|
_can_play($board, $word, $_); |
131
|
|
|
|
|
|
|
} _can_play($board, $last, $posn); |
132
|
|
|
|
|
|
|
} |
133
|
121
|
|
|
|
|
132
|
return grep $board->[$_] eq $word, @{ $play->[$posn] }; |
|
121
|
|
|
|
|
774
|
|
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
return q/ |
137
|
|
|
|
|
|
|
AGGReGaTeD HeRBS ALLoW EXoTiC FLaVoR; OVeRZeaLouS PeoPLe ReaLiZe We USe |
138
|
|
|
|
|
|
|
PReMiXeD CaViaR & DRiNK UP HuMBLeD GRoG IN MeGaDoSeS |
139
|
|
|
|
|
|
|
/; |