PNZ (adivinhe três dígitos únicos em ordem)

15

A partir de um desafio de um livro de programação há muito tempo, o PNZ é um jogo em que o usuário deve adivinhar três dígitos únicos na ordem correta.

Regras :

  1. Um número aleatório de 3 dígitos sem dígitos repetidos é gerado. (É isso que o usuário está tentando adivinhar)
  2. O usuário digita um palpite de 3 dígitos, que deve ser avaliado pelo programa.
  3. Emita um "P" para cada dígito correto no local correto.
  4. Emita um "N" para cada dígito correto em um local incorreto.
  5. Emita um "Z" apenas se nenhum dígito estiver correto.
  6. Continue aceitando as entradas até que todos os dígitos estejam corretos e no lugar correto e, em seguida, imprima "PPP" seguido do número de palpites necessários em uma nova linha.

Nota :

  • Um "dígito correto" significa que um dos dígitos no palpite também é um dos dígitos do número aleatório de 3 dígitos.

  • Um "local correto" significa que é um "dígito correto" E está no mesmo local que o número aleatório de 3 dígitos.

  • A ordem de saída deve ser todos os "P" primeiro, depois os "N" ou apenas "Z" se nada estiver correto.

  • Se uma entrada contém dígitos repetidos, "P" tem prioridade sobre a "N" (Exemplo: Number: 123 Input: 111 Output: P)

  • (OPCIONAL) Entradas que não tenham exatamente 3 dígitos de comprimento não devem ser avaliadas nem contar para o total de tentativas em execução

Exemplo se os dígitos gerados foram 123

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

Exemplo se os dígitos gerados foram 047

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

Este é o CodeGolf, então o programa mais curto vence!

Mr Public
fonte
Bem-vindo ao PPCG! Este é um ótimo primeiro desafio, mas acho que já fizemos isso antes. O jogo também é conhecido como Mastermind. Aqui está o desafio existente, mas não consigo decidir se devo fechar o antigo ou o novo. Estou um pouco inclinado a fechar isso, mas deixarei a comunidade decidir.
Martin Ender
@ MartinBüttner Ah, isso é ruim. Parece um problema bem parecido. Concordo com você e deixarei a comunidade decidir.
Sr. Pública
@ MartinBüttner Qual é o critério aqui? Até que ponto o antigo deve ter precedência?
Luis Mendo
2
@ MartinBüttner Acho que entre exigir que os dígitos sejam únicos e a natureza interativa, esse desafio é distinto o suficiente para valer a pena.
AdmBorkBork
@LuisMendo Acho que não existe um critério oficial, porque fechar desafios antigos é algo bastante recente. Meu critério pessoal é "qual desafio é melhor e / ou mais barebones".
Martin Ender

Respostas:

5

JavaScript (ES6) 184 187 195

Editar 8 bytes salvos thx @Neil Editar 3 bytes salvos thx @ user81655

(novas linhas contadas como 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)

Teste

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)

edc65
fonte
Eu acho que d.splice(v=Math.random()*-~l,1)economiza 5 ou talvez 8 bytes (ao custo de algum desempenho).
Neil
@ Neil Rejeitei a emenda quando comecei a encontrar uma solução, parecia demorada. Agora eu vou tentar de novo
edc65
1
@ user81655 certo, obrigado. Realmente um elenco estranho
edc65
3

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

Estranhamente, consegui jogar golfe na versão fixa com um comprimento menor do que na versão não fixa ... oO

Muito obrigado a @ edc65 por sua assistência e inspiração!

Explicação:

$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

Exemplo de execução:

PS C:\Tools\Scripts\golfing> .\pnz.ps1
123
N
111
Z
222
P
452
PN
562
NN
275
PN
258
PPP
7
AdmBorkBork
fonte
Como você verifica se os dígitos não são repetidos?
edc65
@ edc65 Saída corrigida. Isso foi caro. Ainda estou trabalhando para o golfe ainda mais, mas não tenho esperança ...
AdmBorkBork 21/01
Tenho certeza que você pode fazer melhor. Aproveite o fato de que o palpite pode ter repetições, mas o número a adivinhar não. Por exemplo, na minha resposta eu começar a partir de cada dígito a ser adivinhada e verificar a entrada, o contrário não iria funcionar
edc65
@ edc65 Obrigado pela inspiração e assistência - jogou a versão fixa para ser mais curta que a versão não fixa! : D
AdmBorkBork
Agora sou obrigado a upvote
edc65
0

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="")}

Experimente online!

O link TIO é apenas para contagem de bytes - tente isso no seu console R! (ou deixe-me saber se existe uma opção alternativa).

Veja o histórico para uma versão menos legível e com menos golfe.

JayCe
fonte