Contador de puntajes para Skat


11

Su tarea es escribir un pequeño programa que cuente los puntos de una mano Skat. Una baraja Skat tiene cartas 7 a 10, Jack, Reina, Rey y As (llamadas Unter, Ober, König y Daus). Utilizamos los trajes alemanes, que tienen bellotas, hojas, corazones y campanas en lugar de palos, espadas, corazones y diamantes. Los puntos están determinados por el número en la tarjeta:

  • 7, 8 y 9 son 0 puntos
  • Unter es 2 puntos
  • Ober es de 3 puntos
  • König es de 4 puntos
  • 10 es 10 puntos
  • Daus tiene 11 puntos.

De entrada y salida

El formato de entrada consta de dos símbolos, el primero representa el valor, mientras que el segundo representa el palo:

  • 7, 8 y 9 representan ellos mismos
  • 0 (cero) representa 10
  • Unter, Ober, König y Daus llevan el nombre de sus primeras letras (U, O y D)
  • Lo mismo para Bellotas, Hojas, Corazones y Vientre (A, L, H y B)

La entrada es una sola línea de tarjetas, separadas por un solo espacio en blanco. Puede tomar la entrada desde cualquier lugar, los argumentos de la línea de comandos también están bien. El resultado es el valor de la mano, ya sea impreso o devuelto como un código de salida. La salida de su programa debe mostrar un error, si alguna tarjeta aparece dos veces en la mano. (Por 7A 0L 7Alo tanto, debe devolver un error en lugar de 10). También está bien salir con un código de salida de 255 en lugar de mostrar un error, si esta es la forma predeterminada de su programa para generar el resultado.

Ejemplos

  • 7A 8A 9A UA OA KA 0A DA 7L 8L 9L UL OL KL 0L DL 7H 8H 9H UH OH KH 0H DH 7B 8B 9B UB OB KB 0B DBda 120
  • 7A 8L 0K DB 8L da un error
  • UA OB DL KHda 20

Reglas

  • Código de golf: el código más corto gana
  • Se aplican las reglas habituales de golf de código
  • El programa tiene que funcionar para todas las manos, no solo para los ejemplos.
  • GIGO: si la entrada no es válida, la salida puede ser arbitraria

¿Está bien la salida adicional a stderr (por ejemplo, advertencias)?
Ventero

@Ventero: Sí, lo es. Cualquier forma de errar está bien, pero debe ser claramente visible para el usuario, que hay un error.
FUZxxl

¿Jack, Queen y Ace se llaman Unter, Ober, King y Daus? ¿Se supone que un rey debe estar allí?
Ry-

@minitech No, no lo es.
FUZxxl

2
Creo que te refieres a "campanas", no a "barrigas". Muy diferente, eso.
stand

Respuestas:


2

APL ( 54 48)

No tiene que haber una manera más corta de seleccionar el valor de la tarjeta, pero no lo ven.

(+/12-'D0.....KOU.'⍳⊃¨A)÷A≡∪A←↓A⍴⍨2,⍨2÷⍨⍴A←⍞~' '

Obtienes un DOMAIN ERRORsi hay una tarjeta duplicada.

Explicación:

  • A←⍞~' ': almacenar ( ) en Auna línea de entrada del usuario ( ) sin ( ~) los espacios.
  • 2,⍨2÷⍨⍴A: una lista de dos elementos, que contiene la longitud de ( ) Adividida por ( ÷⍨) 2, seguida de ( ,⍨) el número 2. (Entonces, si la entrada es UA OB DL KHla lista es (4, 2)).
  • ↓A⍴⍨: define una matriz ( ), con las dimensiones de esa lista, que contiene los valores de A. Luego une los elementos de sus filas ( ), dando una lista de listas, por ejemplo ['UA','OB','DL','KH'].
  • A←: Almacene esta lista en A.
  • A≡∪A: ∪Aes la lista de elementos únicos en A. Si es igual a A, no hay duplicados y esto devuelve 1, de lo contrario 0.
  • ÷: divide lo que está a la izquierda (que hace el cálculo real) por el resultado de la prueba de igualdad. Entonces, si no hay duplicados, el puntaje no cambia y si hay duplicados, obtienes un resultado DOMAIN ERRORdebido a la división por cero.
  • ⊃¨A: Una lista que da el primer elemento ( ) de cada elemento ( ¨) de A. Así que esto deja caer la letra del palo, dejando la letra del puntaje. ( UODK)
  • 'D0.....KOU.'⍳: da el índice de cada una de las letras de puntuación en esta cadena, devuelve 12 para los valores que no están en la cadena. ( 10 9 1 8)
  • +/12-: restar todo esto de 12, y luego sumarlos. ( 2 + 3 + 11 + 4 = 20)


Extrañé totalmente que tu respuesta sea la más corta.
FUZxxl

10

Ruby 1.9, 52 caracteres

Entrada a través de argumentos de línea de comando. Supongo que el mensaje de error cuando tener tarjetas duplicadas no importa, por lo que solo se queja de un error de conversión eval / type.

p eval$*.uniq!||$*.map{|i|"..UOK#$<.0D"=~/#{i}?/}*?+

Ejemplo de uso:

$ ruby1.9 skatscore.rb 7A 8A 9A UA OA KA 0A DA 7L 8L 9L UL OL KL 0L DL 7H 8H 9H UH OH KH 0H DH 7B 8B 9B UB OB KB 0B DB
120

$ ruby1.9 skatscore.rb 7A 7A
skatscore.rb:1:in `eval': can't convert Array into String (TypeError)
    from skatscore.rb:1:in `<main>'

Por un lado, creo que el error variable indefinido para tarjetas duplicadas es un poco lamentable. Por otro lado, no rompe las reglas, por lo que es un poco inteligente.
Igby Largeman

1
@Charles: Dado que la especificación solo requiere un error, supongo que el error es prácticamente irrelevante. Y supongo que si hay métodos cortos para producir algún error, debería estar bien.
Joey

6

Scala, 87 82 caracteres

args.distinct(args.size-1);println(args.map(a=>1+" UOK     0D".indexOf(a(0))).sum)

Lanza una excepción en tarjetas repetidas.


4

Haskell 122 108 107 caracteres

import List
main=interact$f.words
f x|nub x==x=show$sum$map(maybe 0 id.(`elemIndex`"  UOK     0D").head)x

error""es más corto que undefined. Ahorra un personaje usando interact.
FUZxxl

@FUZxxl: su uso interactno imprimirá una nueva línea, por lo que no estoy seguro de si eso es aceptable. Sin embargo, pude ahorrar mucho más usando un patrón incompleto en lugar de undefined.
hammar

¿Dónde dije que se necesita una nueva línea? No me acuerdo
FUZxxl

2

GolfScript 54 53 52

Editar 1:

Acabo de descubrir un error en el código. No detectó tarjetas duplicadas si los duplicados eran los dos primeros en la entrada (porque estaba usando el *operador de plegado y no el /operador de cada uno para el primer bucle).

Ahora arreglé el código y también logré quitar 1 carácter en el proceso. Aquí está la nueva versión:

' '/{1$1$?){]?}{\+}if}/2%{"UOK0D"\?).0>+.4>5*+}%{+}*

La entrada debe estar en la pila como una cadena, en el formato especificado (ejemplo:) '7A UA DA'.

En caso de que la entrada sea válida, el programa imprime el valor total de las tarjetas.

En caso de que haya al menos una tarjeta duplicada, el programa genera la siguiente excepción:

(eval):1:in `block in initialize': undefined method `class_id' for nil:NilClass (NoMethodError)

Edición 2:

Después de ver esta publicación en el meta sitio , decidí publicar una descripción del código. Esto también me ayudó a encontrar y corregir un error. Entonces, aquí va:

# Initially, we epect the input string to be on the stack
# Example: "7A UA DA"

' '/            # split the input string by spaces
                # now we have on the stack an array of strings
                # (in our example: ["7A" "UA" "DA"])

# {1$1$?)!{\+}{]?}if}/  -> this piece of code checks for duplicate cards
#
# The trailing symbol (/) is the 'each' operator, meaning that the 
# preceding code block (enclosed in curly brackets) will be executed 
# for every cards in the previous array.
#
# Before each execution of the code block, the current card value
# is pushed on the stack.
#
# Basically what this code does is concatenate cards into a string
# and checks whether the current card is contained in the accumulated
# value.
#
# So, for each card, this is what we execute:

1$              # copies the concatenated string on top of the stack
                # (initially this is an empty string)

1$              # copies the current card on top of the stack

?               # returns (places on the stack) the 0-based index where 
                # the current card is found in the concatenated string
                # or -1 if not found

)               # increments the topmost stack value
                # Now we have 0 if the card is not a duplicate
                # or a value greater than 0 otherwise

{]?}{\+}if      # if the current stack value is non-0 (duplicate)
                # then execute the first code {]?} (generates an error)
                # Otherwise, if the card is valid, execute the {\+} block.
                # What this code does is essentially concatenate the current 
                # card value:
                #    \ -> swaps the two topmost stack values; now we have
                #         the concatenated string and the current card value
                #    + -> this is the concatenation operator

# After the previous code block finishes execution (in case the input is)
# valid, we end up having the concatenated card values on the stack
# In our example, this value is "DAUAUB7A".

# The next code fragment is the one that computes the card values
# This is the code: 2%{"UOK0D"\?).0>+.4>5*+}%{+}*

# And this is how it can be broken down:

2%              # takes only the even indexed chars from the existing string 
                # in our case, "DAUA7A" -> "DU7"
                # Only these characters are important for determining the 
                # card values.

# The following piece of code is:
# {"UOK0D"\?).0>+.4>5*+}%

# This code performs a map; it takes the individual chars,
# computes the corresponding numeric value for each of them and outputs an
# array containing those values

# This is achieved using the map operator (%) which evaluates the preceding 
# code block, delimited by curly braces, so, essentially this is the code that 
# computes the value for a card:
# "UOK0D"\?).0>+.4>5*+
# It can be broken down like this:

"UOK0D"         # pushes the "UOK0D" string on the stack
\               # swaps the two topmost stack values
                # Now, these values are: "UOK0D" and "l" 
                # (where "l" represents the current letter
                # that gives the card its value: U,O,K,0,D,7,8...)

?               # Find the index of the card's letter in the
                # "UOK0D" string.
                # Remember, this is 0-based index, or -1 if not found.

)               # increment the index value
                # Now we have the following value:
                #     1 if the card is U
                #     2 if the card is O
                #     3 if the card is K
                #     4 if the card is 0
                #     5 if the card is D
                #     0 if it is anything else

.0>+            # if the current value is greater than 0,
                # add 1 to it.

.4>5*+          # if the current value is greater than 4,
                # add 5 to it.

# Passing through these steps, we now have the following value:
#     2  if the card is U
#     3  if the card is O
#     4  if the card is K
#     10 if the card is 0
#     11 if the card is D
#     0  if it is anything else
# This is the exact value we were looking for.

# Now we have an array containing the value of each card.
# in our example, [0, 2, 11]
# The next piece of code is easy:

{+}*            # uses the * (fold) operator to add up all the
                # values in the array.

# This leaves the total value of the cards on the stack,
# which is exactly what we were looking for (0+2+11=13).

# Golfscript is awesome! :-)

1

Python, 114 caracteres

i=input().split();print(sum(int(dict(zip('7890UOKD','000A234B'))[x[0]],16)for x in i)if len(i)<=len(set(i))else'')

Desafortunadamente, el indexmétodo de listas en Python genera un error si no se encuentra un elemento en lugar de devolver un valor negativo, y la importación defaultdictrequeriría más caracteres de los que ahorraría.


1

eTeX, 201 caracteres (sin contar los dos saltos de línea irrelevantes)

\def~#1#2{\catcode`#113\lccode`~`#1\lowercase{\def~}##1 {\ifcsname
#1##1 ~\D\fi\if\csname#1##1 ~\fi+"#2}}~70~80~90~0A~U2~O3~K4~DB\def
\a[#1]{\let~\endcsname\write6{^^J \the\numexpr#1 }\end}\expandafter\a

Usado como etex filename.tex [UA OB DL KH]. Es necesario poner el argumento entre paréntesis: de lo contrario, eTeX no tiene forma de determinar que llegamos al final de la lista de argumentos.

EDITAR: según lo permitido en la declaración de la pregunta, una entrada incorrecta puede causar (un) error. Por ejemplo, se etex filename.tex [OK]bloquea horriblemente (porque Kno es un color válido).


No funciona en mi máquina.
FUZxxl

@FUZxxl. ¿Cuál es la salida de etex -v? ¿Cuál es el mensaje de error (aproximadamente)? El código debe colocarse en un archivo (con el nombre filename.texo cualquier otra cosa que termine en .tex) y usar ese nombre en la línea de comando etex filename.tex [<argument>]. (perdón por volver a publicar el mismo comentario, lo olvidé " @FUZxxl")
Bruno Le Floch

Mire aquí: hpaste.org/48949
FUZxxl

@FUZxxl. Gracias por tus comentarios. Kno es un color válido, y al reemplazarlo Xen sus ejemplos elimina los errores (se bloquea Kporque esa letra tiene otro significado, King). Podría hacer que el error sea menos horrible agregando \stringantes de cada uno ##1, pero eso costaría 12 caracteres más.
Bruno Le Floch

Lo siento. Escribí mal el ejemplo. Ahora funciona. Lo siento.
FUZxxl

1

PowerShell, 79 80

($a=$args|sort)|%{$s+=(10,11+4..0)['0DKOU'.IndexOf($_[0])]}
$s/("$a"-eq($a|gu))

Lanza »Intentó dividir por cero.« Si las cartas aparecen dos veces.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.