Compteur de score pour Skat

11

Votre tâche consiste à écrire un petit programme, qui compte les points d'une main Skat. Un deck Skat a les cartes 7 à 10, Jack, Queen, King et Ace (appelées Unter, Ober, König et Daus). Nous utilisons les costumes allemands, qui ont des glands, des feuilles, des coeurs et des cloches au lieu de clubs, piques, coeurs et diamants. Les points sont déterminés par le numéro sur la carte:

  • 7, 8 et 9 sont 0 points
  • Unter est 2 points
  • Ober est de 3 points
  • König est de 4 points
  • 10 est 10 points
  • Daus est de 11 points.

Entrée sortie

Le format d'entrée se compose de deux symboles, le premier représente la valeur, tandis que le second représente la combinaison:

  • 7, 8 et 9 représentent eux-mêmes
  • 0 (zéro) représente 10
  • Unter, Ober, König et Daus sont nommés d'après leurs premières lettres (U, O et D)
  • La même chose pour les glands, les feuilles, les coeurs et les ventres (A, L, H et B)

L'entrée est une seule ligne de cartes, séparée par un seul espace blanc. Vous pouvez prendre l'entrée de n'importe où, les arguments de la ligne de commande sont également corrects. La sortie est la valeur de l'aiguille, imprimée ou retournée sous forme de code de sortie. La sortie de votre programme doit afficher une erreur, si une carte apparaît deux fois dans la main. (Il 7A 0L 7Afaut donc retourner une erreur au lieu de 10). Il est également correct de quitter avec un code de sortie de 255 au lieu d'afficher une erreur, si c'est la manière par défaut de votre programme de sortir le résultat.

Exemples

  • 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 DBdonne 120
  • 7A 8L 0K DB 8L donne une erreur
  • UA OB DL KHdonne 20

Règles

  • Code golf: le code le plus court gagne
  • Les règles de golf du code habituel s'appliquent
  • Le programme doit fonctionner pour toutes les mains, pas seulement les exemples
  • GIGO: Si l'entrée n'est pas valide, la sortie peut être arbitraire
FUZxxl
la source
La sortie supplémentaire vers stderr (par exemple les avertissements) est-elle correcte?
Ventero
@Ventero: Oui, ça l'est. Tout moyen de se tromper est correct, mais il doit être clairement visible pour l'utilisateur, qu'il y a une erreur.
FUZxxl
Jack, Queen et Ace s'appellent Unter, Ober, King et Daus? Un roi est-il censé être là-dedans?
Ry-
@minitech Non, ce n'est pas le cas.
FUZxxl
2
Je pense que vous voulez dire "cloches", pas "cloches". Très différent, ça.
stand

Réponses:

2

APL ( 54 48)

Il doit y avoir un moyen plus court de sélectionner la valeur de la carte, mais je ne la vois pas.

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

Vous obtenez un DOMAIN ERRORs'il y a une carte en double.

Explication:

  • A←⍞~' ': store ( ) dans Aune ligne d'entrée utilisateur ( ) sans ( ~) les espaces.
  • 2,⍨2÷⍨⍴A: une liste à deux éléments, contenant la longueur de ( ) Adivisé par ( ÷⍨) 2, suivi de ( ,⍨) le nombre 2. (Donc, si l'entrée est UA OB DL KHla liste est (4, 2)).
  • ↓A⍴⍨: définir une matrice ( ), avec les dimensions de cette liste, contenant les valeurs de A. Puis joindre les éléments de ses lignes ensemble ( ), donnant une liste de listes, par exemple ['UA','OB','DL','KH'].
  • A←: Stocker cette liste dans A.
  • A≡∪A: ∪Aest la liste des éléments uniques dans A. Si cela est égal à A, il n'y a pas de doublons et cela renvoie 1, sinon 0.
  • ÷: divisez ce qui est à gauche (qui fait le calcul réel) par le résultat du test d'égalité. Donc, s'il n'y a pas de doublons, le score est inchangé et s'il y a des doublons, vous obtenez un en DOMAIN ERRORraison de la division par zéro.
  • ⊃¨A: Une liste donnant le premier élément ( ) de chaque élément ( ¨) de A. Cela laisse tomber la lettre de costume, laissant la lettre de score. ( UODK)
  • 'D0.....KOU.'⍳: donne l'index de chacune des lettres de score de cette chaîne, renvoie 12 pour les valeurs ne figurant pas dans la chaîne. ( 10 9 1 8)
  • +/12-: soustrayez tous ces éléments de 12, puis ajoutez-les ensemble. ( 2 + 3 + 11 + 4 = 20)

marinus
la source
J'ai totalement manqué que votre réponse soit la plus courte.
FUZxxl
10

Ruby 1.9, 52 caractères

Entrée via des arguments de ligne de commande. Je suppose que le message d'erreur lorsque des cartes en double n'a pas d'importance, il se plaint simplement d'une erreur de conversion eval / type.

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

Exemple d'utilisation:

$ 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>'
Ventero
la source
D'une part, je pense que l'erreur de variable non définie pour les cartes en double est un peu boiteuse. D'un autre côté, cela ne viole pas les règles, donc c'est plutôt intelligent.
Igby Largeman
1
@Charles: Étant donné que la spécification appelle uniquement une erreur, je suppose que quelle erreur exactement est à peu près non pertinente. Et s'il existe des méthodes courtes pour produire une erreur, cela devrait être correct, je suppose.
Joey
6

Scala, 87 82 caractères

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

Lève une exception sur les cartes répétées.

Rex Kerr
la source
4

Haskell, 122 108 107 caractères

import List
main=interact$f.words
f x|nub x==x=show$sum$map(maybe 0 id.(`elemIndex`"  UOK     0D").head)x
hammar
la source
error""est plus court que undefined. Enregistrez un caractère en utilisant interact.
FUZxxl
@FUZxxl: Son utilisation interactn'imprimera pas de nouvelle ligne, donc je ne sais pas si c'est acceptable. Cependant, j'ai pu économiser beaucoup plus en utilisant un modèle incomplet au lieu de undefined.
hammar
Où ai-je dit qu'une nouvelle ligne est nécessaire? Je ne m'en souviens pas.
FUZxxl
2

GolfScript 54 53 52

Modifier 1:

Je viens de découvrir une erreur dans le code. Il n'a pas détecté de cartes en double si les doublons étaient les deux premiers dans l'entrée (parce que j'utilisais l' *opérateur de pliage et non /chaque opérateur pour la première boucle).

Maintenant, j'ai corrigé le code et j'ai également réussi à supprimer 1 caractère dans le processus. Voici la nouvelle version:

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

L'entrée doit être sur la pile sous forme de chaîne, au format spécifié (exemple:) '7A UA DA'.

Si l'entrée est valide, le programme imprime la valeur totale des cartes.

Dans le cas où il y a au moins une carte en double, le programme lève l'exception suivante:

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

Modifier 2:

Après avoir vu ce post sur le méta site , j'ai décidé de poster une description du code. Cela m'a également aidé à trouver et à corriger une erreur. Alors, voici:

# 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! :-)
Cristian Lupascu
la source
1

Python, 114 caractères

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

Malheureusement, la indexméthode des listes en Python génère une erreur si un élément n'est pas trouvé plutôt que de renvoyer une valeur négative, et l'importation defaultdictnécessiterait plus de caractères qu'elle n'en enregistrerait.

COUP
la source
1

eTeX, 201 caractères (sans compter les deux sauts de ligne non pertinents)

\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

Utilisé comme etex filename.tex [UA OB DL KH]. Mettre l'argument entre crochets est nécessaire: sinon, eTeX n'a ​​aucun moyen de déterminer que nous avons atteint la fin de la liste des arguments.

EDIT: comme autorisé dans l'énoncé de la question, une entrée incorrecte peut provoquer (une) erreur. Par exemple, se etex filename.tex [OK]bloque horriblement (car ce Kn'est pas une couleur valide).

Bruno Le Floch
la source
Ne fonctionne pas sur ma machine.
FUZxxl
@FUZxxl. Quelle est la sortie de etex -v? Quel est le message d'erreur (en gros)? Le code doit être placé dans un fichier (avec un nom filename.texou toute autre chose se terminant par .tex) et utiliser ce nom dans la ligne de commande etex filename.tex [<argument>]. (désolé de republier le même commentaire, j'ai oublié " @FUZxxl")
Bruno Le Floch
Veuillez regarder ici: hpaste.org/48949
FUZxxl
@FUZxxl. Merci pour votre avis. Kn'est pas une couleur valide, et le remplacer par Xdans vos exemples supprime les erreurs (il se bloque avec Kparce que cette lettre a une autre signification, King). Je pourrais rendre l'erreur moins horrible en ajoutant \stringavant chacun ##1, mais cela coûterait 12 caractères de plus.
Bruno Le Floch
Pardon. J'ai mal saisi l'exemple. Ça fonctionne maintenant. Pardon.
FUZxxl
1

PowerShell, 79 80

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

Lance »Tentative de division par zéro.« Si les cartes apparaissent deux fois.

Joey
la source