http://www.perlmonks.org?node_id=255437

Was the phrase used in The Perl Journal which kept me from submiting this. However, I think it's pretty nice, and I have made it as short as I know how.
```sub q{\$;=1;for(0..3){\$;[\$_]=int(rand(9))}}sub _{print@_}&q;for(;;){\$:=
+\$~=0
;_"\$/\$; ";\$_=<>;if(/^\d{4}\$/){@q=split//;--\$#q;\$@=-1;for(@q){\$a=\$_;(\$a
+==\$;
[++\$@])&&++\$:||(grep/\$a/,@;)&&++\$~}_"\$~W\$:B ";++\$;;\$:==4|\$;>10&&_(@;)&
+&&q}}

Replies are listed 'Best First'.
Re: "Another thrice-damned version of Mastermind"
by jgallagher (Pilgrim) on May 04, 2003 at 07:00 UTC
Very cool. My only question is why, in the for(@q){...}, do you have to set \$a = \$_? I tried to do it with just \$_, and sure enough, it didn't work, but I have no idea why that is.

Spoilers below!
```#!/usr/bin/perl -w

sub q {
\$; = 1;                        # \$; stores how many tries you've h
for (0..3) {
\$;[\$_] = int(rand(9))      # @; stores the correct four number
+s; set it up here
}
}

sub _ {
print @_
}

&q;

for (;;) {
\$: = \$~ = 0;        # set \$: (right number in the right spot) and
+\$~ (right number) to 0
_ "\$/\$; ";          # prints a newline then the number of tries yo
\$_ = <>;            # read a line into \$_

if (/^\d{4}\$/) {    # if the line is exactly 4 digits...
@q = split //;  # @q holds the 4 digits

--\$#q;          # set \$#q = 3, ignoring the newline at \$q[4]
\$@ = -1;        # set \$@ to -1

# This loops through the input digits and checks for correctne
+ss

for (@q) {                         # set \$_ to each of the 4 i
+nput digits
\$a = \$_;                       # set \$a to the current dig
+it (why not leave it \$_?)
(\$a == \$;[++\$@]) && ++\$:       # increment \$: if you have
+a right number in the right spot
|| (grep /\$a/, @;) && ++\$~ # else increment \$~ if you
+have a right number in the wrong spot
}

_ "\$~W\$:B ";  # print out the total of right/wrong (\$~W) and r
+ight/right (\$:B)
++\$;;         # increment number of tries

\$: == 4       # if we have four right numbers all in the right
+ spots
| \$; > 10 # or we have already had 10 tries
&& _ (@;) # print out the correct answer
&& &q     # and start the game over
}
}
Taking a quick cursory look, I'd assume due to grep /\$a/, @;

Makeshifts last the longest.

Nice work. I was reviewing it and I honestly don't remember why I did that (it's been a while since I originally wrote it). The only thing I can think is that I might have been concerned about overwriting the digit. I did have a quit (q) command in there when it was longer, though that is just a shot in the dark. With your suggestion implemented, it does seem to work fine:
```sub q{\$;=1;for(0..3){\$;[\$_]=int(rand(9))}}sub _{print@_}&q;for(;;){\$:=
+\$~=0
;_"\$/\$; ";\$_=<>;if(/^\d{4}\$/){@q=split//;--\$#q;\$@=-1;for(@q){(\$_==\$;[+
++\$@]
)&&++\$:||(grep/\$_/,@;)&&++\$~}_"\$~W\$:B ";++\$;;\$:==4|\$;>10&&_(@;)&&&q}}
Actually, it doesn't. As per Aristotle's suggestion above, the (grep/\$_/,@;) would return true every time, thus always telling you you had four correct numbers.
Doh.
by tinypig (Beadle) on May 04, 2003 at 17:25 UTC
Re: "Another thrice-damned version of Mastermind"
by Your Mother (Archbishop) on May 05, 2003 at 06:12 UTC
I think it's buggy though with Ws. Using the version jgallagher posted (the original wouldn't run for me? Complained of unbalanced braces.)

Given hidden pattern: 8565

7566 -->> 1W2B (should be 0W2B, right?)
6566 -->> 2W2B (should also be 0W2B)
Or am I missing something. I'm sad b/c I was enjoying playing it.
Eek, you're right. I just checked the Mastermind rules and it should not work like that. That is how I coded it to work, however. Here's a quick hack that seems to correct the problem... now to fix the obfuscated version...
```#!/usr/bin/perl -w

sub q {
\$; = 1;                        # \$; stores how many tries you've h
for (0..3) {
\$;[\$_] = int(rand(9))      # @; stores the correct four number
+s; set it up here
}
}

sub _ {
print @_
}

&q;

for (;;) {
\$: = \$~ = 0;        # set \$: (right number in the right spot) and
+\$~ (right number) to 0
_ "\$/\$; ";          # prints a newline then the number of tries yo
\$_ = <>;            # read a line into \$_

if (/^\d{4}\$/) {    # if the line is exactly 4 digits...
@q = split //;  # @q holds the 4 digits

--\$#q;          # set \$#q = 3, ignoring the newline at \$q[4]
\$@ = -1;        # set \$@ to -1

# This loops through the input digits and checks for correctne
+ss

my @j = @;;
for (@q) {                   # set \$_ to each of the 4 input d
+igits
(\$_ eq \$j[++\$@]) && ++\$: && (\$j[\$@]='X') && (\$q[\$@]='Y')
}
for (@q) {                   # set \$_ to each of the 4 input d
+igits
\$a = \$_;                 # set \$a to the current digit (wh
+y not leave it \$_?)
(grep /\$a/, @j) && ++\$~  # else increment \$~ if you have a
+ right number in the wrong spot
}

_ "\$~W\$:B ";  # print out the total of right/wrong (\$~W) and r
+ight/right (\$:B)
++\$;;         # increment number of tries

\$: == 4       # if we have four right numbers all in the right
+ spots
| \$; > 10 # or we have already had 10 tries
&& _ (@;) # print out the correct answer
&& &q     # and start the game over
}
}