Melhor pontuação Yahtzee

26

Yahtzee é um jogo jogado com cinco dados de seis lados e uma folha de pontuação com treze caixas diferentes para preencher uma pontuação. Cada caixa tem suas próprias regras de pontuação:

  • 1s, 2s, 3s, 4s, 5s, 6s marcam todos os pontos iguais à soma dos dados respectivos (ou seja, uma jogada de [3, 2, 3, 1, 5] pontuada como 3s recebe 6 pontos: 3 para cada 3).
  • 3 do tipo e 4 do tipo (como soam, três ou quatro dados rolam o mesmo) marcam pontos iguais à soma dos cinco dados.
  • Full house (dois dados mostram um valor, os outros três mostram outro) obtém 25 pontos
  • Pequena sequência (quatro valores consecutivos) marca 30 pontos
  • Reta grande (todos os valores consecutivos) marca 40 pontos
  • Yahtzee (todos os dados mostram o mesmo valor) obtém 50 pontos

A décima terceira (chance) faz sentido no jogo, mas não tanto para esse desafio; Além disso, o jogo tem bônus para Yahtzees extras que não fazem sentido aqui. Porque o desafio é ...

Dado cinco dados como entrada (cinco inteiros de 1 a 6, porém, a entrada é conveniente, você pode assumir que a entrada é sempre válida), produza a pontuação mais alta possível para essa 'mão'. Para os propósitos deste desafio, apenas os métodos de pontuação na lista acima são válidos (especificamente, a chance não é uma caixa de pontuação válida para esse desafio). A pontuação deve ser exibida como seu valor numérico decimal, seja um número inteiro ou uma representação de sequência, seja qual for. Deve ser imediatamente reconhecido como um número. O espaço em branco à esquerda / à direita é bom, trata-se de obter a pontuação e não a apresentação.

Código golf, para que a resposta com o menor número de bytes em um determinado idioma ganhe. Falhas padrão proibidas.

Casos de teste

(Observe que todos são independentes, o desafio é marcar uma 'mão' de dados):

in: 1 5 4 3 2
out: 40
in: 1 1 4 3 1
out: 10
in: 2 2 6 5 3
out: 6
in: 2 4 2 4 6
out: 8
in: 1 1 1 1 1
out: 50
in: 5 2 5 3 6
out: 10
in: 1 6 3 4 2
out: 30
in: 1 3 1 1 3
out: 25
in: 6 5 5 6 6
out: 28
in: 1 2 3 5 6
out: 6
brhfl
fonte
3
devemos fechar a pergunta mais antiga? IMO esta é uma pergunta melhor do que um ...
Giuseppe
5
Na IMO, isso não é uma duplicata na pontuação de um jogo de yahtzee. Isso indica explicitamente que é a pontuação mais alta para uma mão, onde a outra pergunta está pedindo uma pontuação inteira de uma lista de rolagens de dados. Por fim, e mais importante, não vejo nenhuma resposta do possível dupe que possa ser usado aqui em um cenário de "copiar e colar". Por favor, considere reabrir.
DevelopingDeveloper
2
FWIW, eu estava ciente da pergunta mais antiga quando montei essa. Meus pensamentos ecoaram o que o @DevelopingDeveloper disse. Tendo feito isso como exercício antes, encontrei algumas oportunidades interessantes para otimizar esse processo. Eu também acho que esse é um desafio mais arrumado.
Brhfl 12/12
"A décima terceira (chance) faz sentido no jogo, mas não tanto para esse desafio" Então é contado?
Unihedron

Respostas:

6

R , 146 141 bytes

function(d)max(unique(d<-sort(d))*(g=table(d)),any(g>2)*sum(d),all(2:3%in%g)*25,(s=sum((R=diff(d))==1))<4&all(R<2)*30,(s>3)*40,(0==sd(d))*50)

Experimente online!

Superado por plannapus

Pega a entrada como uma lista e retorna a pontuação.

um pouco destruído:

function(d){
 d <- sort(d)
 u <- unique(d)                  # unique dice
 g <- table(d)                   # table of counts
 Ns <- u*g                       # scores as 1s, 2s, ... etc.
 NKind <- any(g>2)*sum(d)        # 3 or 4 of a kind if any counts are at least 3
 FHouse <- all(2:3%in%g)*25      # full house is 25 if 2 & 3 are in counts
 R <- diff(d)                    # consecutive differences
 s <- sum(R==1)                  # sum of differences equal to 1
 sStraight <- s<4 &              # if the number of 1s is 3 and
               all(R<2)*30       # no consecutive numbers are 2 apart
 bStraight <- (s>3)*40           # all 1s means big straight
 Yahtzee <- sd(d)==0             # sd = 0 means all are equal
 max(Ns,NKind,FHouse,sStraight,bStraight,Yahtzee)
}

Giuseppe
fonte
f(c(1,2,3,5,6))falha - deve render 6 e, ao invés, render 30. Parece que é porque você está contando quantos pares (pós-classificação) diferem por um, o que é de fato quatro para a sequência acima, mesmo que não seja uma sequência de quatro. Eu acho que eu corri para este quando eu fiz isso como um exercício um tempo atrás, e eu provavelmente deveria acrescentar que, como um caso de teste ...
brhfl
@ brhfl isso foi corrigido agora.
11557 Giuseppe
5

Python 2 , 187 184 167 165 bytes

-17 bytes graças a @mypetlion
-2 bytes graças a @chrstphrchvz

def f(d):r=range(1,7);c=d.count;m=map(c,r);s=`m`[1::3];return max([i*c(i)for i in r]+[sum(d)*(max(m)>2),25*(set(m)>{2,3}),30*(4*'1'in s),40*(5*'1'in s),50*(5 in m)])

Experimente online!

ovs
fonte
4

R, 136 134 bytes

function(n,y=table(factor(n,1:6)),z=sum(!diff(diff(sort(n)))))max(1:6*y,c(25,sum(n),10*3:5)[c(all(y<4&y-1),any(y>2),z>1,z>2,any(y>4))])

Joguei 2 bytes graças a @ Giuseppe !

Recuado,

function(n, #vector of die scores
         y=table(factor(n,1:6)), #Contingency table
         z=sum(!diff(diff(sort(n))))) #Diff of diff of ordered scores
    max(1:6*y,
        c(25,sum(n),10*3:5)*c(all(y<4&y-1), #Full house
                            any(y>2), #3 and 4 of a kind
                            z>1, #Small straight
                            z>2, #Long straight
                            any(y>4))] #Yahtzee

Alguns casos de teste:

> f=function(n,y=table(factor(n,1:6)),z=sum(!diff(diff(sort(n)))))max(1:6*y,c(25,sum(n),10*3:5)*c(all(y<4&y-1),any(y>2),z>1,z>2,any(y>4)))
> f(c(2,4,2,4,6))
[1] 8
> f(c(1,2,3,5,6))
[1] 6
> f(c(6,5,5,6,6))
[1] 28
> f(c(6,5,3,1,4))
[1] 30
> f(c(6,5,3,2,4))
[1] 40
plannapus
fonte
1
Pensei factorpor um segundo quente antes de me distrair. Mas eu acho que se eu usar a sua abordagem com z( sna minha resposta), eu posso mina de golfe até 134 ...
Giuseppe
Além disso, você pode salvar três bytes usando all(y<4&y-1)e usando em *vez de [e definindo yinline em vez de como argumento de função, e ele ainda passa em todos os casos de teste: Experimente online!
21817 Giuseppe #:
Além disso, reestruturei o arquivo maxe acho que salvou o byte da configuração yinline.
Giuseppe
3

Lote, 359 bytes

@echo off
set/at=s=m=r1=r2=r3=r4=r5=r6=0
for %%r in (%*)do set/a"m+=!(m-r%%r),r%%r+=1,t+=%%r,p=s-r%%r*%%r,p&=p>>9,s-=p
goto %m%
:1
if %r1% neq %r6% set s=40&goto g
:2
set/at=r3*r4*(r2*(r1+r5)+r5*r6)
if %t% gtr 0 set s=30
goto g
:3
set/a"s=r1^r2^r3^r4^r5^r6"
if %s%==1 if %t% lss 25 set s=25&goto g
:4
set/as=t
goto g
:5
set s=50
:g
echo %s%

Explicação:

@echo off
set/at=s=m=r1=r2=r3=r4=r5=r6=0
for %%r in (%*)do set/a"m+=!(m-r%%r),r%%r+=1,t+=%%r,p=s-r%%r*%%r,p&=p>>9,s-=p
goto %m%

Calcule o número de dados para cada número, mais o máximo, mais o total de todos os dados, mais o total mais alto de dados do mesmo número.

:1
if %r1% neq %r6% set s=40&goto g

Se todos os dados forem diferentes, pode ser uma longa sequência, mas é preciso que exista ou não 1ou não 6.

:2
set/at=r3*r4*(r2*(r1+r5)+r5*r6)
if %t% gtr 0 set s=30
goto g

Caso contrário, ou se, no máximo, dois dados forem iguais, ainda pode ser uma sequência curta. Deve haver, pelo menos, um 3e um 4e também uma combinação dos outros quatro números.

:3
set/a"s=r1^r2^r3^r4^r5^r6"
if %s%==1 set s=25&goto g

Se houver três dados iguais, verifique se há um full house desde então 3^2==1. No entanto, algumas casas completas, como 6s e 5s, têm pontuação mais alta como 3-de-um-tipo.

:4
set/as=t
goto g

Caso contrário, ou se houver quatro iguais, marque o total.

:5
set s=50

E se houver cinco iguais, então Yahtzee!

:g
echo %s%

Saída a melhor pontuação.

Neil
fonte
1
Obrigado por me lembrar da possível armadilha [5,5,6,6,6] registrada como casa cheia - eu adicionei isso como um caso de teste. Eu sabia que havia alguns casos estranhos que eu estava esquecendo.
Brhfl 13/12
3

Geléia , 58 bytes

ċЀ`Ṁ>2ȧS
ṢI=1Ạµ-ƤẸ,E;ṢI$E$;⁸Lƙ`Ṣ⁼2,3¤a3,5,4,2.Ṁ×⁵»Ç»Sƙ`Ṁ$

Experimente online!

Erik, o Outgolfer
fonte
É perfeitamente válido, mas estou curioso e não conheço Jelly bem o suficiente para resolver por conta própria ... por que a casa cheia volta 25.0enquanto nenhum outro caso tem o rastro .0?
Brhfl 13/12
@brhfl Bem, porque é inferido como 2.5 × 10 = 25.0(aritmética de flutuação), enquanto os outros 30são inferidos como 3 × 10 = 30(aritmética de número inteiro).
Erik the Outgolfer
2
Obrigado! Eu realmente não exprimi bem minha pergunta; Fiquei mais curioso sobre o método que você está usando para detectar uma casa cheia que resulta em fazer as contas de maneira diferente - mas agora que penso nisso, acho que é apenas um jogador de golfe fazer 2,5, 3, 4, 5 * 10 x 25, 30, 40, 50. Acho que respondi minha própria pergunta.
Brhfl 13/12
@brhfl Exatamente, uma vez que × 10são 2 bytes, 2.5são 2 bytes iguais 25e 3,5,4economizam 3 bytes 30,50,40, então 3 + 0 - 2 = 1 byte salvo.
Erik the Outgolfer
2

Perl 6 , 159 bytes

->\b{max map {$_(b)},|(1..6).map({*{$_}*$_}),{.kxxv.sum*?.values.grep(*>2)},{25*(6==[*]
.values)},30*?*{3&4&(1&2|2&5|5&6)},40*?*{2&3&4&5&(1|6)},50*(*.keys==1)}

Experimente online!

Como a entrada pode ser aceita "por mais conveniente que seja", minha função a toma como uma instância do Bag classe, que é um contêiner com multiplicidade. A Bagtambém é um contêiner associativo; $bag{$key}retorna quantas vezes $keyocorre na bolsa.

A maior parte da função é apenas uma lista de funções que avaliam cada mão Yahtzee possível, retornando a pontuação dessa mão ou zero se as condições da mão não forem atendidas.

  • |(1..6).map({ *{$_} * $_ })é uma lista de seis funções que avaliam ponteiros com base em repetidas execuções dos números 1-6. A liderança| nivelam essa lista na lista ao redor.
  • {.kxxv.sum * ?.values.grep(* > 2) }avalia as mãos 3 e 4 do mesmo tipo. .kxxvem a Bagretorna as chaves repetidas com a multiplicidade de cada uma, recuperando a lista original de rolagens e.sum claro, somando os dados. Essa soma é multiplicada por um valor booleano ( ?) que é verdadeiro se as bolsas .values(ou seja, as multiplicidades) contiverem um valor maior que 2.
  • { 25 * (6 == [*] .values) }avalia a mão da casa cheia. 25 é multiplicado por um valor booleano que é verdadeiro se o produto das multiplicidades for 6, o que para cinco dados só pode acontecer se um for 3 e o outro for 2.
  • 30 * ?*{ 3 & 4 & (1 & 2 | 2 & 5 | 5 & 6) }avalia a mão pequena e reta. É uma WhateverCodefunção; a segunda estrela *é a Bag. A expressão entre chaves é a junção dos valores 3 e 4, e 1 e 2, ou 2 e 5, ou 5 e 6. Procurar essa junção nos Bagresultados em uma junção das multiplicidades correspondentes. Se as múltiplas multiplicidades de 3 e 4 e pelo menos uma de 1 e 2, ou 2 e 5, ou 5 e 6 forem diferentes de zero, a junção será verdadeira quando forçada a um valor booleano (com? ), e esse booleano é multiplicado por 30 para obter a pontuação.
  • 40 * ?*{ 2 & 3 & 4 & 5 & (1 | 6) }avalia da mesma forma a mão grande e reta. É mais simples, porque os dados devem incluir cada um dos números 2-5 e 1 ou 6.
  • 50 * (*.keys == 1)avalia a mão Yahtzee. É simplesmente 50 vezes um valor booleano que é verdadeiro se o número de dados distintos for um.
Sean
fonte
2

Pip , 65 63 bytes

n:_NgM\,6MXn*\,6AL[2<MXn23=JSNn3<Y#MX Jn^0MXn=5]*[$+g25--y*t50]

Toma os dados como cinco argumentos de linha de comando. Experimente online!

Ungolfed + explicação

(Esta é a versão original.)

                    g is list of cmdline args; t is 10 (implicit)

Y                   Yank into y:
  _Ng                function that counts occurrences of its argument in g
 M                   mapped to
  \,6                inclusive range from 1 to 6
                    This gives us how many dice are showing each number 1-6

s:                  Assign to s:
  # MX               length of max of
      Jy ^ 0         join y into string and split on zeros
                    This gives us the length of the longest straight

MX                  Max of
   y * \,6           each die frequency in y, times its value
 AL                  to which list append
   [                 this list:
                      3- and 4-of-a-kind:
    MXy > 2 & $+g      If max frequency is 3 or more, sum of g (else 0)
                      Full house:
    23 = J SNy & 25    Sort y and join into string; if it's 000023, 25 (else 0)
                      Straights:
    s > 3 & --s*t      If s is 4 or more, (s-1)*10 (else 0)
                      Yahtzee:
    MXy = 5 & 50       If max frequency is 5, 50 (else 0)
   ]
                    The result of the last expression is autoprinted
DLosc
fonte
1

Ruby , 184 bytes

Programa completo. Para facilitar o teste de entrada, adicione $/=' 'no topo a leitura no formato "dígito separado por espaços". (191 caracteres)

a=$<.map &:to_i
b=a.|c=[]
d=(1..6).map{|x|e=a.count x
c<<x*e
e}
e=a.sum
p !b[1]?50:b[4]&&!(a&[1,6])[1]?40:(1..3).any?{|x|(a&[*x..x+3])[3]}?30:(d-[0,2,3])[0]?d.max>2?e:c.max: [25,e].max

Estabeleci a quebra da barreira de 200 bytes e consegui destruí-la com uma dúzia de bytes restantes, com facilidade!

Experimente online!

Explicação

Não é muito bom embora. Espero que você tenha algum conhecimento sobre Ruby ~

a=$<.map &:to_i # a: input as [number]*5
b=a.|c=[]       # c: [], b: a.uniq
d=(1..6).map{|x|
    e=a.count x # e: occurrence count in a 
    c<<x*e      # add (number * occurrence count) to c
    e           # return value in d
}
e=a.sum         # e: sum of input
p !b[1] ? 50 :  #   condition to print 50 <= if a.uniq has length 0 (el 1 is nil)
  b[4] &&       #   condition to print 40 <= if a.uniq has length 5 (el 4 exists)
  !(a&[1,6])[1] ? 40 : # <- arr & [mask]  # and a does not have both 1 and 6
  (1..3).any?{|x| # condition to print 30 <= if any of 1..4, 2..5, 3..6
  (a&[*x..x+3])[3]} ? 30 : # [3] to assert entire mask is found in a
  (d-[0,2,3])[0] ? # if, after removing 0 (not found) 2 (a pair) 3 (a triple)
                   # and something is found, this is not full house
  d.max > 2 ?   # is triple / quadruple ?
     e :        # weakly dominating alternatives
     c.max      # choose best by-suit
  : [25,e].max  # choose best by-score
Unihedron
fonte