<<   >>

27. moo

The “moo” (AKA Cows and Bulls AKA Mastermind™) game is described in the Unix man pages:

NAME
     moo - guessing game
 
SYNOPSIS
/usr/games/moo
 
DESCRIPTION
moo is a guessing game imported from England. The computer picks a number consisting of four distinct decimal digits. The player guesses four distinct digits being scored on each guess. A cow is a correct digit in an incorrect position. A bull is a correct digit in a correct position. The game continues until the player guesses the number (a score of four bulls).
 
OWNER
   Ken

The following program plays the guesser in the game of moo. The algorithm was described to me in 1976 by Fred Appleyard of I.P. Sharp Associates, Calgary: A universe of remaining choices is kept. At each round, the computer selects a guess at random from the universe, then prunes the universe according to the guess and its score of bulls and cows.

moo←{
  univ  ← {(1=⌈/∘{≢⍵}⌸⍤1⊢t)⌿t←⍵⊤⍤1 0⍳×/⍵}

  guess ← {⍵⌷⍨?≢⍵}
  score ← {⍵{⍺ ⍵}⍞↓⍨≢⍞←'   ',⍨⍕⍵}
  solved← {g s←⍺ ⋄ s≡'b'⍴⍨≢g}
  bull  ← {g s←⍺ ⋄ ('b'+.=s)=⍵+.=g}
  bc    ← {g s←⍺ ⋄ (≢s)=+/⍵∊g}
  prune ← {⍺ solved ⍵:⍬ ⋄ ⍵⌿⍨⍺(bull∧bc)⍵}

  state←{
    ⍬≡⍵:⍵
    1=≢⍵:⍵⊣⎕←'one choice left; it must be ',⍕,⍵
    ⍵⊣⎕←(⍕≢⍵),' choices left'
  }

  moo1←{1≥≢⍵:⍵ ⋄ state(score guess ⍵)prune ⍵}
  moo1⍣≡ univ ⍵
}

The definitions are divided into groups:

univ generates the initial universe of choices given an integer list of the upper limits for each position. e.g. univ 4⍴10 or univ 10 11 12 . The phrase ⍵⊤⍤1 0×/⍳⍵ is recogized to be the odometer function from Chapter 28.

score displays an integer list on the screen, solicits a score from the keyboard, and returns a list of the score and the guess individually boxed. guess selects a guess at random from the universe. solved is 1 if the score is all b’s.  bull scores each choice in the universe regarding bulls; bc regarding bulls and cows. prune discards remaining choices from the universe inconsistent with the guess and its score.

state shows the size of the current universe.

moo plays the guesser in the game of moo. The argument is an integer list of the upper limits for each position. (e.g. moo 4⍴10 would be the game as described in the man page.) In each round, moo

  • checks that the universe contains more than one choice;
  • selects a guess at random and solicits its score;
  • prunes the universe; and
  • displays the state.

The following example shows the program in action.

   ⎕rl←7*5  ⍝ to get reproducible random numbers

   4?10     ⍝ sample target number
3 2 9 0

   moo 4⍴10
6 5 4 0   b
480 choices left
7 3 4 1   c
126 choices left
9 5 2 7   cc
23 choices left
6 9 1 2   cc
one choice left; it must be 3 2 9 0
3 2 9 0

   ⍝ play again with same target number
   moo 4⍴10
4 0 7 9   cc
1260 choices left
2 7 4 1   c
312 choices left
5 6 0 7   c
72 choices left
9 5 8 4   c
12 choices left
0 2 9 3   bbcc
3 choices left
0 9 2 3   cccc
one choice left; it must be 3 2 9 0
3 2 9 0


Appeared in J in [88].