15
\$\begingroup\$

From a challenge in a programming book long ago, PNZ is a game where the user must guess three unique digits in the correct order.

Rules:

  1. A random 3 digit number with no repeating digits is generated. (This is what the user is trying to guess)
  2. The user inputs a guess of 3 digits, which is to be evaluated by the program.
  3. Output a "P" for every correct digit in a correct place.
  4. Output a "N" for every correct digit in an incorrect place.
  5. Output a "Z" only if no digits are correct.
  6. Continue accepting inputs until all digits are correct and in the correct place, then output "PPP" followed by the number of guesses it took on a new line.

Note:

  • A "Correct digit" means that one of the digits in the guess is also one of the digits in the random 3 digit number.

  • A "Correct place" means it is a "Correct digit" AND is in the same place as the 3 digit random number.

  • The order of outputting should be all "P"'s first, then "N"'s, or only "Z" if nothing is correct.

  • If an input contains repeating digits, "P" takes priority over "N" (Example: Number: 123 Input: 111 Output: P)

  • (OPTIONAL) Inputs that are not exactly 3 digits in length should not be evaluated, nor count towards the running total of guesses

Example if the generated digits were 123

> 147
P
> 152
PN
> 126
PP
> 123
PPP
4

Example if the generated digits were 047

> 123
Z
> 456
N
> 478
NN
> 947
PP
> 047
PPP
5

This is CodeGolf, so the shortest program wins!

\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! This is a great first challenge, but I'm afraid we've done this before. The game is otherwise known as Mastermind. Here is the existing challenge but I can't make up my mind whether to close the old one or the new. I'm slightly leaning towards closing this, but I'll let the community decide. \$\endgroup\$ – Martin Ender Jan 20 '16 at 16:49
  • \$\begingroup\$ @MartinBüttner Ah, that's my bad. It does seem like a pretty similar problem. I'll agree with you and let the community decide. \$\endgroup\$ – Mr Public Jan 20 '16 at 16:52
  • \$\begingroup\$ @MartinBüttner What's the criterion here? To what extend should the old one have precedence? \$\endgroup\$ – Luis Mendo Jan 20 '16 at 17:26
  • 2
    \$\begingroup\$ @MartinBüttner I think between requiring the digits to be unique and the interactive nature, this challenge is distinct enough to be worthwhile. \$\endgroup\$ – AdmBorkBork Jan 20 '16 at 17:44
  • \$\begingroup\$ @LuisMendo There is no official criterion I think, because closing old challenges is a fairly recent thing. My personal criterion is "which challenge is better and/or more barebones". \$\endgroup\$ – Martin Ender Jan 20 '16 at 17:52
5
\$\begingroup\$

JavaScript (ES6) 184 187 195

Edit Saved 8 bytes thx @Neil Edit Saved 3 bytes thx @user81655

(newlines counted as 1 byte)

d=[...'0123456789']
x=[10,9,8].map(l=>d.splice(Math.random()*l,1))
for(c=p=a='';!p[2];++c)g=prompt(a),n=p='',x.map((d,i)=>d-g[i]?~g.search(d)?n+='N':0:p+='P'),a=p+n||'Z'
alert(a+' '+c)

Test

d=[...'0123456789']
x=[10,9,8].map(l=>d.splice(Math.random()*l,1))
for(c=p=a='';!p[2];++c)
  g=prompt(a),
  n=p='',
  x.map((d,i)=>
        d-g[i]?~g.search(d)?n+='N':0:p+='P'
       ),
  a=p+n||'Z'
alert(a+' '+c)

\$\endgroup\$
  • \$\begingroup\$ I think d.splice(v=Math.random()*-~l,1) saves you 5 or maybe even 8 bytes (at the cost of some performance). \$\endgroup\$ – Neil Jan 20 '16 at 21:05
  • \$\begingroup\$ @Neil I rejected splice when I started to find a solution, it seemed lengthy. Now I'll try again \$\endgroup\$ – edc65 Jan 20 '16 at 21:38
  • 1
    \$\begingroup\$ @user81655 right, thanks. Really a weird cast \$\endgroup\$ – edc65 Jan 21 '16 at 8:14
3
\$\begingroup\$

PowerShell v2+, 177 231 168 bytes

$g=-join(0..9|Random -c 3);for($c=0;$o-ne"PPP";$c++){$n=$p='';$i=read-host;$o=-join(0..2|%{((("","N")[$i.IndexOf($g[$_])-ge0]),"P")[$g[$_]-eq$i[$_]]}|sort -des);($o,"Z")[!$o]}$c

Oddly, I was able to golf the fixed version to be a shorter length than the unfixed version ... o.O

Many thanks to @edc65 for his assistance and inspiration!

Explanation:

$g=-join(0..9|Random -c 3)   # Create an array @(0,1,2,...9) and choose 3 distinct elements
for($c=0;$o-ne"PPP";$c++){   # Loop until output = "PPP", incrementing $count each time
  $i=read-host               # Read input from the user

  $o=-join(0..2|%{((("","N")[$i.IndexOf($g[$_])-ge0]),"P")[$g[$_]-eq$i[$_]]}|sort -des)
       # OK, this is the convoluted part. We're constructing an array of "N", "P", or "",
       # sorting them by descending order (so the P's are first), and then joining them
       # together into a string. The array is constructed by essentially an if/elseif/else
       # statement that is evaluated three times thanks to the 0..2|%{} loop.
       # Starting from the innermost, we choose between "" and "N" based on whether the
       # input number has the current-digit of the secret number somewhere within it. We
       # then choose between that or "P" based on whether it's the _current_ digit of the
       # user input number.

  ($o,"Z")[!$o]
       # Here we output either $o from above or "Z" based on whether $o is empty
}
$c                           # The loop finished (meaning the user guessed), output $count

Example run:

PS C:\Tools\Scripts\golfing> .\pnz.ps1
123
N
111
Z
222
P
452
PN
562
NN
275
PN
258
PPP
7
\$\endgroup\$
  • \$\begingroup\$ How do you check that digits are not repeated? \$\endgroup\$ – edc65 Jan 20 '16 at 18:21
  • \$\begingroup\$ @edc65 Corrected output. That was expensive. Still working to golf further, but I'm not hopeful ... \$\endgroup\$ – AdmBorkBork Jan 21 '16 at 14:32
  • \$\begingroup\$ I'm sure you can do better. Leverage the fact that the guess can have repetitions, but the number to guess have not. For instance, in my answer I start from each digit to be guessed and check the input, the contrary would not work \$\endgroup\$ – edc65 Jan 21 '16 at 14:36
  • \$\begingroup\$ @edc65 Thanks for the inspiration and assistance - golfed the fixed version to be shorter than the non-fixed version! :D \$\endgroup\$ – AdmBorkBork Jan 21 '16 at 21:01
  • \$\begingroup\$ Now I am bound to upvote \$\endgroup\$ – edc65 Jan 21 '16 at 23:05
0
\$\begingroup\$

R,178 166 bytes

y=!(s<-sample(48:57,3))
while(any(y!=s)){F=F+1
y<-utf8ToInt(readline())
cat(rep("P",p<-sum(y==s)),rep("N",n<-sum(y%in%s)-p
),if(!(n+p))"Z","
",if(all(y==s))F,sep="")}

Try it online!

TIO link is just for byte count - try this in your R console! (or let me know if there is an alternate option).

See history for less-golfed, more readable version.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.