Bulls and cows/Player
You are encouraged to solve this task according to the task description, using any language you may know.
The task is to write a player of the Bulls and Cows game, rather than a scorer. The player should give intermediate answers that respect the scores to previous attempts.
Haskell
<lang haskell>import Data.List import Control.Monad import System.Random (randomRIO) import Data.Char(digitToInt)
combinationsOf 0 _ = [[]] combinationsOf _ [] = [] combinationsOf k (x:xs) = map (x:) (combinationsOf (k-1) xs) ++ combinationsOf k xs
player = do
let ps = concatMap permutations $ combinationsOf 4 ['1'..'9'] play ps where play ps = if null ps then
putStrLn "Unable to find a solution"
else do i <- randomRIO(0,length ps - 1) let p = ps!!i :: String
putStrLn ("My guess is " ++ p) >> putStrLn "How many bulls and cows?" input <- takeInput let bc = input ::[Int] ps' = filter((==sum bc).length. filter id. map (flip elem p)) $ filter((==head bc).length. filter id. zipWith (==) p) ps if length ps' == 1 then putStrLn $ "The answer is " ++ head ps' else play ps'
takeInput = do inp <- getLine let ui = map digitToInt $ take 2 $ filter(`elem` ['0'..'4']) inp if sum ui > 4 || length ui /= 2 then do putStrLn "Wrong input. Try again"
takeInput else return ui</lang> Example: <lang haskell>*Main> player My guess is 4923 How many bulls and cows? 2 2 My guess is 3924 How many bulls and cows? 1 3 My guess is 4329 How many bulls and cows? 1 3 My guess is 4932 How many bulls and cows? 4 0 The answer is 4932</lang>
J
<lang j>require'misc'
poss=:1+~.4{."1 (i.!9)A.i.9 fmt=: ' ' -.~ ":
play=:3 :0
while.1<#poss=.poss do. smoutput'guessing ',fmt guess=.({~ ?@#)poss bc=.+/\_".prompt 'how many bull and cows? ' poss=.poss #~({.bc)=guess+/@:="1 poss poss=.poss #~({:bc)=guess+/@e."1 poss end. if.#poss do. 'the answer is ',fmt,poss else. 'no valid possibilities' end.
)</lang>
For example: <lang j> play guessing 7461 how many bull and cows? 0 1 guessing 3215 how many bull and cows? 0 3 guessing 2357 how many bull and cows? 2 0 guessing 1359 how many bull and cows? 3 0 the answer is 1358</lang>
PicoLisp
<lang PicoLisp>(load "@lib/simul.l")
(de bullsAndCows ()
(let Choices (shuffle (mapcan permute (subsets 4 (range 1 9)))) (use (Guess Bulls Cows) (loop (prinl "Guessing " (setq Guess (pop 'Choices))) (prin "How many bulls and cows? ") (setq Bulls (read) Cows (read)) (setq Choices (filter '((C) (let B (cnt = Guess C) (and (= Bulls B) (= Cows (- (length (sect Guess C)) B)) ) ) ) Choices ) ) (NIL Choices "No matching solution") (NIL (cdr Choices) (pack "The answer is " (car Choices))) ) ) ) )</lang>
Output:
: (bullsAndCows) Guessing 4217 How many bulls and cows? 0 2 Guessing 5762 How many bulls and cows? 1 1 Guessing 9372 How many bulls and cows? 0 1 Guessing 7864 How many bulls and cows? 1 2 Guessing 8754 How many bulls and cows? 0 2 -> "The answer is 2468"
Python
<lang python>from itertools import permutations from random import shuffle
try:
raw_input
except:
raw_input = input
try:
from itertools import izip
except:
izip = zip
digits = '123456789' size = 4
def parse_score(score):
score = score.strip().split(',') return tuple(int(s.strip()) for s in score)
def scorecalc(guess, chosen):
bulls = cows = 0 for g,c in izip(guess, chosen): if g == c: bulls += 1 elif g in chosen: cows += 1 return bulls, cows
choices = list(permutations(digits, size)) shuffle(choices) answers = [] scores = []
print ("Playing Bulls & Cows with %i unique digits\n" % size)
while True:
ans = choices[0] answers.append(ans) #print ("(Narrowed to %i possibilities)" % len(choices)) score = raw_input("Guess %2i is %*s. Answer (Bulls, cows)? " % (len(answers), size, .join(ans))) score = parse_score(score) scores.append(score) #print("Bulls: %i, Cows: %i" % score) found = score == (size, 0) if found: print ("Ye-haw!") break choices = [c for c in choices if scorecalc(c, ans) == score] if not choices: print ("Bad scoring? nothing fits those scores you gave:") print (' ' + '\n '.join("%s -> %s" % (.join(an),sc) for an,sc in izip(answers, scores))) break</lang>
Sample output
Playing Bulls & Cows with 4 unique digits Guess 1 is 1935. Answer (Bulls, cows)? 0,2 Guess 2 is 4169. Answer (Bulls, cows)? 0,3 Guess 3 is 6413. Answer (Bulls, cows)? 1,1 Guess 4 is 9612. Answer (Bulls, cows)? 1,1 Guess 5 is 9481. Answer (Bulls, cows)? 3,0 Guess 6 is 9471. Answer (Bulls, cows)? 4,0 Ye-haw!
Sample bad output
If the scores are inconsistent you get output like:
Playing Bulls & Cows with 4 unique digits Guess 1 is 1549. Answer (Bulls, cows)? 0,0 Guess 2 is 3627. Answer (Bulls, cows)? 1,0 Bad scoring? nothing fits those scores you gave: 1549 -> (0, 0) 3627 -> (1, 0)
Tcl
<lang tcl>package require struct::list package require struct::set
proc scorecalc {guess chosen} {
set bulls 0 set cows 0 foreach g $guess c $chosen {
if {$g eq $c} { incr bulls } elseif {$g in $chosen} { incr cows }
} return [list $bulls $cows]
}
- Allow override on command line
set size [expr {$argc ? int($argv) : 4}]
set choices {} struct::list foreachperm p [split 123456789 ""] {
struct::set include choices [lrange $p 1 $size]
} set answers {} set scores {}
puts "Playing Bulls & Cows with $size unique digits\n" fconfigure stdout -buffering none while 1 {
set ans [lindex $choices [expr {int(rand()*[llength $choices])}]] lappend answers $ans puts -nonewline \
"Guess [llength $answers] is [join $ans {}]. Answer (Bulls, cows)? "
set score [scan [gets stdin] %d,%d] lappend scores $score if {$score eq {$size 0}} {
puts "Ye-haw!" break
} foreach c $choices[set choices {}] {
if {[scorecalc $c $ans] eq $score} { lappend choices $c }
} if {![llength $choices]} {
puts "Bad scoring? nothing fits those scores you gave:" foreach a $answers s $scores { puts " [join $a {}] -> ([lindex $s 0], [lindex $s 1])" } break
}
}</lang> Sample Output
Playing Bulls & Cows with 4 unique digits Guess 1 is 8527. Answer (Bulls, cows)? 0,1 Guess 2 is 5143. Answer (Bulls, cows)? 0,2 Guess 3 is 9456. Answer (Bulls, cows)? 2,0 Guess 4 is 9412. Answer (Bulls, cows)? 2,1 Guess 5 is 9481. Answer (Bulls, cows)? 3,0 Guess 6 is 9471. Answer (Bulls, cows)? 4,0 Ye-haw!
Sample Bad Output
Playing Bulls & Cows with 4 unique digits Guess 1 is 6578. Answer (Bulls, cows)? 0,0 Guess 2 is 3241. Answer (Bulls, cows)? 1,0 Bad scoring? nothing fits those scores you gave: 6578 -> (0, 0) 3241 -> (1, 0)