Mejor puntaje de Yahtzee

26

Yahtzee es un juego que se juega con cinco dados de seis lados y una hoja de puntaje con trece cuadros diferentes para completar un puntaje. Cada cuadro tiene sus propias reglas de puntaje:

  • 1s, 2s, 3s, 4s, 5s, 6s, todos los puntos de puntuación equivalen a la suma de los dados respectivos (es decir, una tirada de [3, 2, 3, 1, 5] obtenida como 3 se otorgará 6 puntos: 3 por cada 3).
  • 3-of-a-kind y 4-of-a-kind (como suenan, tres o cuatro dados arrojaron el mismo) obtienen puntos equivalentes a la suma de los cinco dados.
  • La casa llena (dos dados muestran un valor, los otros tres muestran otro) obtiene 25 puntos
  • Las rectas pequeñas (cuatro valores consecutivos) obtienen 30 puntos
  • La recta grande (todos los valores consecutivos) obtiene 40 puntos
  • Yahtzee (todos los dados muestran el mismo valor) obtiene 50 puntos

La decimotercera (oportunidad) tiene sentido en el juego, pero no tanto para este desafío; Además, el juego tiene bonos para Yahtzees adicionales que no tienen sentido aquí. Porque el desafío es ...

Dado cinco dados como entrada (cinco enteros 1-6, la entrada, sin embargo, es conveniente, puede suponer que la entrada siempre es válida), genera la puntuación más alta posible para esa 'mano'. Para los propósitos de este desafío, solo los métodos de puntaje en la lista anterior son válidos (específicamente, el azar no es un cuadro de puntaje válido para este desafío). El puntaje debe salir como su valor numérico decimal, ya sea un entero o una representación de cadena del mismo, lo que sea. Debe ser inmediatamente reconocible como un número. El espacio en blanco inicial / final está bien, se trata de obtener la puntuación y no la presentación.

Codifique golf, de modo que gane la respuesta con la menor cantidad de bytes en un idioma determinado. Lagunas estándar prohibidas.

Casos de prueba

(Tenga en cuenta que todos estos son independientes, el desafío es anotar una 'mano' 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
fuente
3
¿deberíamos cerrar la pregunta anterior en su lugar? OMI, esta es una pregunta mejor que esa ...
Giuseppe
55
OMI, esto no es en absoluto un duplicado de la puntuación de un juego de yahtzee. Esto establece explícitamente que es la puntuación más alta para una mano, donde la otra pregunta es pedir una puntuación completa de una lista de tiradas de dado. Por último, y lo más importante, no veo ninguna respuesta del posible engaño que pueda usarse aquí en un escenario de "copiar y pegar". Por favor considere reabrir.
DevelopingDeveloper
2
FWIW, estaba al tanto de la pregunta anterior cuando formulé esta. Mis pensamientos hicieron eco de lo que dijo @DevelopingDeveloper. Habiendo hecho esto como ejercicio una vez antes, encontré algunas oportunidades interesantes para optimizar este proceso. También creo que este es un desafío más ordenado.
brhfl
"La decimotercera (oportunidad) tiene sentido en el juego, pero no tanto para este desafío" ¿Entonces se cuenta?
Unihedron

Respuestas:

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)

Pruébalo en línea!

Superado por plannapus

Toma la entrada como una lista y devuelve la puntuación.

ungolfed un poco:

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
fuente
f(c(1,2,3,5,6))falla: debería producir 6 y en su lugar, 30. Parece que esto se debe a que está contando cuántos pares (clasificación posterior) difieren en uno, que en realidad es cuatro para la secuencia anterior, aunque no es una recta de cuatro. Creo que me encontré con esto cuando hice esto como un ejercicio hace un tiempo, y probablemente debería añadir que como un caso de prueba ...
brhfl
@brhfl esto se solucionó ahora.
Giuseppe
5

Python 2 , 187 184 167 165 bytes

-17 bytes gracias a @mypetlion
-2 bytes gracias 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)])

Pruébalo en línea!

ovs
fuente
4

R, 136134 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))])

Golfed 2 bytes gracias a @Giuseppe !

Sangrado,

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

Algunos casos de prueba:

> 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
fuente
1
Huh, lo consideré factorpor un segundo caliente antes de distraerme. Pero creo que si utilizo su enfoque con z( sen mi respuesta), puedo jugar golf hasta 134 ...
Giuseppe
Además, puede guardar tres bytes utilizando all(y<4&y-1)y utilizando en *lugar de [, y configurando en ylínea en lugar de como un argumento de función, y todavía pasa todos los casos de prueba: ¡ Pruébelo en línea!
Giuseppe
Además, reestructuré el maxy creo que salvó el byte de la configuración en ylínea.
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%

Explicación:

@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 el número de dados para cada número, más el máximo, más el total de todos los dados, más el total más alto de dados del mismo número.

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

Si todos los dados son diferentes, esto podría ser una larga recta, pero eso debe ser no 1o no 6.

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

De lo contrario, o si a lo sumo dos dados son iguales, entonces esto podría ser una recta corta. Debe haber al menos a 3y a 4y también una combinación de los otros cuatro números.

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

Si hay tres dados iguales, busque una casa llena, desde entonces 3^2==1. Sin embargo, algunas casas completas, como 6s y 5s, obtienen una puntuación más alta como 3 de su tipo.

:4
set/as=t
goto g

De lo contrario, o si hay cuatro iguales, califique el total.

:5
set s=50

Y si hay cinco iguales, ¡entonces Yahtzee!

:g
echo %s%

Salida de la mejor puntuación.

Neil
fuente
1
Gracias por recordarme el potencial peligro [5,5,6,6,6] -scored-as-full-house - He agregado esto como un caso de prueba. Sabía que había un par de extraños casos marginales que estaba olvidando.
brhfl
3

Jalea , 58 bytes

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

Pruébalo en línea!

Erik el Outgolfer
fuente
Es perfectamente válido, pero tengo curiosidad y no conozco a Jelly lo suficientemente bien como para descubrirlo por mi cuenta ... ¿por qué regresa la casa completa 25.0mientras que ningún otro caso tiene el final .0?
brhfl
@brhfl Bueno, porque se infiere como 2.5 × 10 = 25.0(aritmética flotante), mientras que las demás 30se infieren como 3 × 10 = 30(aritmética de enteros).
Erik the Outgolfer
2
¡Gracias! Realmente no dije bien mi pregunta; Tenía más curiosidad sobre el método que está utilizando para detectar una casa completa que resulta en hacer las matemáticas de manera diferente, pero ahora que lo pienso, supongo que es más golfista hacer 2.5, 3, 4, 5 * 10 vs 25, 30, 40, 50. Creo que respondí mi propia pregunta.
brhfl
@brhfl Exactamente, dado que × 10es de 2 bytes, 2.5es igual a 2 bytes 25y 3,5,4ahorra 3 bytes 30,50,40, por lo que 3 + 0 - 2 = 1 byte guardado.
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)}

Pruébalo en línea!

Como la entrada puede ser aceptada "como sea conveniente", mi función la toma como una instancia de la Bagclase, que es un contenedor con multiplicidad. A Bages también un contenedor asociativo; $bag{$key}devuelve cuántas veces $keyocurre en la bolsa.

La mayor parte de la función es solo una lista de funciones que evalúan cada posible mano de Yahtzee, devolviendo el puntaje para esa mano o cero si no se cumplen las condiciones para la mano.

  • |(1..6).map({ *{$_} * $_ })es una lista de seis funciones que evalúan las manos en base a corridas repetidas de los números 1-6. El líder |aplana esta lista en la lista circundante.
  • {.kxxv.sum * ?.values.grep(* > 2) }evalúa las manos 3 y 4 de su tipo. .kxxven un Bagdevuelve las teclas repetidas con la multiplicidad de cada uno, recuperando la lista original de tiradas .sumde dados y, por supuesto, suma los dados. Esa suma se multiplica por un valor booleano ( ?) que es verdadero si las bolsas .values(es decir, las multiplicidades) contienen un valor mayor que 2.
  • { 25 * (6 == [*] .values) }evalúa la mano de la casa llena. 25 se multiplica por un valor booleano que es verdadero si el producto de las multiplicidades es 6, que para cinco dados solo puede suceder si uno es 3 y el otro es 2.
  • 30 * ?*{ 3 & 4 & (1 & 2 | 2 & 5 | 5 & 6) }evalúa la pequeña mano recta. Es una WhateverCodefunción; La segunda estrella *es la Bag. La expresión entre las llaves es la unión de los valores 3 y 4, y 1 y 2, o 2 y 5, o 5 y 6. Buscar esta unión en los Bagresultados en una unión de las multiplicidades correspondientes. Si las mulitplicities de 3 y 4, y al menos una de 1 y 2, o 2 y 5, o 5 y 6, son distintas de cero, la unión es verdadera cuando se convierte en un booleano (con ?), y este booleano se multiplica por 30 para obtener el puntaje
  • 40 * ?*{ 2 & 3 & 4 & 5 & (1 | 6) }evalúa de manera similar la mano recta grande. Es más simple porque los dados deben incluir cada uno de los números 2-5 y 1 o 6.
  • 50 * (*.keys == 1)evalúa la mano de Yahtzee. Es simplemente 50 veces un valor booleano que es cierto si el número de dados distintos es uno.
Sean
fuente
2

Pip , 65 63 bytes

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

Toma los dados como cinco argumentos de la línea de comandos. Pruébalo en línea!

Ungolfed + explicación

(Esta es la versión 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
fuente
1

Rubí , 184 bytes

Programa completo Para facilitar la prueba de entrada, agregue $/=' 'en la parte superior para leer en el formato "dígito separado por espacios". (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

Me propuse romper la barrera de 200 bytes y logré destruirla con una docena de bytes restantes, ¡con facilidad!

Pruébalo en línea!

Explicación

Sin embargo, no es muy bueno. Espero que tengas algún conocimiento de 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
fuente