Bulls and cows/Player: Difference between revisions
Content added Content deleted
Thundergnat (talk | contribs) (Rename Perl 6 -> Raku, alphabetize, minor clean-up) |
|||
Line 2,138: | Line 2,138: | ||
How many cows? 0 |
How many cows? 0 |
||
That's bull! You messed up your scoring.</pre> |
That's bull! You messed up your scoring.</pre> |
||
=={{header|Nim}}== |
|||
If there is an impossibility, the program ask the user for the number to guess and indicates where are the errors in scoring. |
|||
<lang Nim>import parseutils |
|||
import random |
|||
import sequtils |
|||
import strformat |
|||
import strutils |
|||
const |
|||
Digits = "123456789" |
|||
DigitSet = {Digits[0]..Digits[^1]} |
|||
Size = 4 |
|||
InvalidScore = -1 |
|||
type |
|||
Digit = range['1'..'9'] |
|||
Score = tuple[bulls, cows: int] |
|||
HistItem = tuple[guess: string, bulls, cows: int] |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc buildChoices(digits: set[Digit]; size: Natural): seq[string] = |
|||
## Build the list of choices when starting the game. |
|||
if size == 0: |
|||
return @[""] |
|||
for d in digits: |
|||
for s in buildChoices(digits - {d}, size - 1): |
|||
result.add(d & s) |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc getValues(): Score = |
|||
## Read the number of bulls and cows provided by the user. |
|||
let input = stdin.readLine().strip() |
|||
let fields = input.splitWhitespace() |
|||
if fields.len != 2 or |
|||
fields[0].parseInt(result.bulls, 0) == 0 or result.bulls notin 0..Size or |
|||
fields[1].parseInt(result.cows, 0) == 0 or result.cows notin 0..Size: |
|||
echo &"Wrong input; expected two number between 0 and {Size}" |
|||
return (InvalidScore, InvalidScore) |
|||
if result.bulls + result.cows > Size: |
|||
echo &"Total number of bulls and cows exceeds {Size}" |
|||
return (InvalidScore, InvalidScore) |
|||
#--------------------------------------------------------------------------------------------------- |
|||
func score(value, guess: string): Score = |
|||
## Return the score of "guess" against "value". |
|||
for idx, digit in guess: |
|||
if digit == value[idx]: |
|||
inc result.bulls |
|||
elif digit in value: |
|||
inc result.cows |
|||
#--------------------------------------------------------------------------------------------------- |
|||
proc findError(history: seq[HistItem]) = |
|||
## Find the scoring error. |
|||
var value: string |
|||
## Get the number to find. |
|||
while true: |
|||
stdout.write("What was the number to find? ") |
|||
value = stdin.readLine().strip() |
|||
if value.len == Size and allCharsInSet(value, DigitSet) and value.deduplicate.len == Size: |
|||
break |
|||
# Find inconsistencies. |
|||
for (guess, userbulls, usercows) in history: |
|||
let (bulls, cows) = score(guess, value) |
|||
if userbulls != bulls or usercows != cows: |
|||
echo &"For guess {guess}, score was wrong:" |
|||
echo &" Expected {bulls} / {cows}, got {userBulls} / {userCows}." |
|||
#--------------------------------------------------------------------------------------------------- |
|||
func suffix(n: Positive): string = |
|||
## Return the suffix for an ordinal. |
|||
case n |
|||
of 1: "st" |
|||
of 2: "nd" |
|||
of 3: "rd" |
|||
else: "th" |
|||
#--------------------------------------------------------------------------------------------------- |
|||
var history: seq[HistItem] |
|||
randomize() |
|||
var choices = buildChoices(DigitSet, Size) |
|||
choices.shuffle() |
|||
echo "Choose a number with four unique digits between 1 and 9." |
|||
echo "Give the number of bulls and cows separated by one or more spaces." |
|||
var guesses = 0 |
|||
var remaining: seq[string] |
|||
while true: |
|||
inc guesses |
|||
var userbulls, usercows: int |
|||
let guess = choices.pop() |
|||
echo &"My {guesses}{suffix(guesses)} guess is {guess}" |
|||
# Get scoring. |
|||
while true: |
|||
stdout.write("How many bulls and cows? ") |
|||
(userbulls, usercows) = getValues() |
|||
if userbulls != InvalidScore and usercows != InvalidScore: |
|||
break |
|||
if userbulls == Size: |
|||
echo &"Victory! I found the number in {guesses} attempts." |
|||
break |
|||
history.add((guess, userbulls, usercows)) |
|||
# Eliminate incompatible choices. |
|||
remaining.setLen(0) |
|||
for choice in choices: |
|||
let (bulls, cows) = score(guess, choice) |
|||
if bulls == userbulls and cows == usercows: |
|||
remaining.add(choice) |
|||
if remaining.len == 0: |
|||
echo &"There is an impossibility. For some guess you made an error in scoring." |
|||
history.findError() |
|||
break |
|||
choices.shallowCopy(remaining)</lang> |
|||
{{out}} |
|||
<pre>Choose a number with four unique digits between 1 and 9. |
|||
Give the number of bulls and cows separated by one or more spaces. |
|||
My 1st guess is 3748 |
|||
How many bulls and cows? 0 2 |
|||
My 2nd guess is 4139 |
|||
How many bulls and cows? 1 2 |
|||
My 3rd guess is 4971 |
|||
How many bulls and cows? 0 2 |
|||
My 4th guess is 8193 |
|||
How many bulls and cows? 0 2 |
|||
My 5th guess is 9436 |
|||
How many bulls and cows? 1 1 |
|||
My 6th guess is 1234 |
|||
How many bulls and cows? 4 0 |
|||
Victory! I found the number in 6 attempts. |
|||
---- |
|||
Choose a number with four unique digits between 1 and 9. |
|||
Give the number of bulls and cows separated by one or more spaces. |
|||
My 1st guess is 6251 |
|||
How many bulls and cows? 0 2 |
|||
My 2nd guess is 1597 |
|||
How many bulls and cows? 1 0 |
|||
My 3rd guess is 3692 |
|||
How many bulls and cows? 1 1 |
|||
My 4th guess is 2687 |
|||
How many bulls and cows? 1 0 |
|||
My 5th guess is 1634 |
|||
How many bulls and cows? 3 0 |
|||
There is an impossibility. For some guess you made an error in scoring. |
|||
What was the number to find? 1234 |
|||
For guess 6251, score was wrong: |
|||
Expected 1 / 1, got 0 / 2. |
|||
For guess 3692, score was wrong: |
|||
Expected 0 / 2, got 1 / 1. |
|||
For guess 2687, score was wrong: |
|||
Expected 0 / 1, got 1 / 0.</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |