Contatore dei punteggi per Skat


11

Il tuo compito è quello di scrivere un piccolo programma, che conti i punti di una mano Skat. Un mazzo Skat ha carte da 7 a 10, Jack, Queen, King e Ace (chiamati Unter, Ober, König e Daus). Usiamo i semi tedeschi, che hanno ghiande, foglie, cuori e campane invece di fiori, picche, cuori e diamanti. I punti sono determinati dal numero sulla carta:

  • 7, 8 e 9 sono 0 punti
  • Unter è di 2 punti
  • Ober è di 3 punti
  • König ha 4 punti
  • 10 è 10 punti
  • Daus ha 11 punti.

Input Output

Il formato di input è composto da due simboli, il primo rappresenta il valore, mentre il secondo rappresenta il seme:

  • 7, 8 e 9 rappresentano se stessi
  • 0 (zero) sta per 10
  • Unter, Ober, König e Daus prendono il nome dalle loro prime lettere (U, O e D)
  • Lo stesso per ghiande, foglie, cuori e ventre (A, L, H e B)

L'input è una singola linea di carte, separate da un singolo spazio bianco. Puoi prendere l'input da qualsiasi luogo, anche gli argomenti della riga di comando vanno bene. L'output è il valore della mano, stampato o restituito come codice di uscita. L'output del tuo programma deve mostrare un errore, se una carta appare due volte nella mano. (Quindi 7A 0L 7Adeve restituire un errore anziché 10). Va anche bene uscire con un codice di uscita di 255 invece di mostrare un errore, se questo è il modo predefinito del tuo programma di produrre il risultato.

Esempi

  • 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 DB120
  • 7A 8L 0K DB 8L dà un errore
  • UA OB DL KH20

Regole

  • Codice golf: vince il codice più breve
  • Si applicano le normali regole del golf
  • Il programma deve funzionare per tutte le mani, non solo per gli esempi
  • GIGO: se l'input non è valido, l'output potrebbe essere arbitrario

L'output aggiuntivo su stderr (ad es. Avvisi) è ok?
Ventero,

@Ventero: Sì, lo è. Qualsiasi modo di sbagliare va bene, ma deve essere chiaramente visibile all'utente, che c'è un errore.
FUZxxl

Jack, Queen e Ace si chiamano Unter, Ober, King e Daus? Un re dovrebbe essere lì?
Ry,

@minitech No, non lo è.
FUZxxl,

2
Credo che intendi "campane", non "ventre". Molto diverso, quello.
stand

Risposte:


2

APL ( 54 48)

Ci deve essere un modo più breve di selezionare il valore della carta, ma io non lo vedo.

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

Ottieni una DOMAIN ERRORse c'è una carta duplicata.

Spiegazione:

  • A←⍞~' ': store ( ) in Auna riga di input dell'utente ( ) senza ( ~) gli spazi.
  • 2,⍨2÷⍨⍴A: un elenco di due elementi, contenente la lunghezza di ( ) Adiviso per ( ÷⍨) 2, seguito da ( ,⍨) il numero 2. (Quindi, se l'ingresso è UA OB DL KHl'elenco è (4, 2)).
  • ↓A⍴⍨: definisce una matrice ( ), con le dimensioni di quell'elenco, contenente i valori di A. Quindi unisci insieme gli elementi delle sue righe ( ), fornendo ad esempio un elenco di elenchi ['UA','OB','DL','KH'].
  • A←: Memorizza questo elenco in A.
  • A≡∪A: ∪Aè l'elenco di elementi univoci in A. Se questo è uguale ad A, non ci sono duplicati e questo restituisce 1, altrimenti 0.
  • ÷: dividi ciò che è a sinistra (che esegue il calcolo effettivo) per il risultato del test di uguaglianza. Quindi, se non ci sono duplicati, il punteggio è invariato e se ci sono duplicati ottieni un a DOMAIN ERRORcausa della divisione per zero.
  • ⊃¨A: Un elenco che fornisce il primo elemento ( ) di ciascun elemento ( ¨) di A. Quindi questo lascia cadere la lettera del seme, lasciando la lettera del punteggio. ( UODK)
  • 'D0.....KOU.'⍳: fornisce l'indice di ciascuna delle lettere del punteggio in questa stringa, restituisce 12 per i valori non nella stringa. ( 10 9 1 8)
  • +/12-: sottrarre tutti questi da 12 e quindi sommarli. ( 2 + 3 + 11 + 4 = 20)


Mi mancava totalmente che la tua risposta fosse la più breve.
FUZxxl

10

Ruby 1.9, 52 caratteri

Input tramite argomenti della riga di comando. Suppongo che il messaggio di errore quando si hanno carte duplicate non ha importanza, quindi si lamenta solo di un errore di conversione di tipo / valutazione.

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

Esempio di utilizzo:

$ 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>'

Da un lato, penso che l'errore variabile indefinito per le carte duplicate sia un po 'zoppo. D'altra parte, non infrange le regole, quindi è abbastanza intelligente.
Igby Largeman,

1
@Charles: poiché la specifica richiede solo un errore, immagino quale errore sia praticamente irrilevante. E se ci sono metodi brevi per produrre errori, dovrebbe andare bene, immagino.
Joey,

6

Scala, 87 82 caratteri

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

Genera un'eccezione su carte ripetute.


4

Haskell, 122 108 107 caratteri

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

error""è più corto di undefined. Salva un carattere usando interact.
FUZxxl

@FUZxxl: Usarlo interactnon stamperà una nuova riga, quindi non sono sicuro che sia accettabile. Tuttavia, sono stato in grado di risparmiare molto di più utilizzando un modello incompleto invece di undefined.
Hammar

Dove ho detto che è necessaria una nuova riga? Non ricordo.
FUZxxl,

2

GolfScript 54 53 52

Modifica 1:

Ho appena scoperto un errore nel codice. Non ha rilevato carte duplicate se i duplicati erano i primi due nell'input (perché stavo usando l' *operatore di piega e non /ciascun operatore per il primo ciclo).

Ora ho risolto il codice e sono riuscito anche a rimuovere 1 carattere nel processo. Ecco la nuova versione:

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

L'input deve essere nello stack come stringa, nel formato specificato (esempio:) '7A UA DA'.

Nel caso in cui l'input sia valido, il programma stampa il valore totale delle carte.

Nel caso in cui ci sia almeno una carta duplicata, il programma genera la seguente eccezione:

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

Modifica 2:

Dopo aver visto questo post sul meta sito , ho deciso di pubblicare una descrizione del codice. Questo mi ha anche aiutato a trovare e correggere un errore. Quindi, ecco qui:

# 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 caratteri

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

Sfortunatamente, il indexmetodo degli elenchi in Python genera un errore se un elemento non viene trovato anziché restituire un valore negativo e l'importazione defaultdictrichiederebbe più caratteri di quanti ne salverebbe.


1

eTeX, 201 caratteri (senza contare le due interruzioni di riga irrilevanti)

\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

Usato come etex filename.tex [UA OB DL KH]. Mettere l'argomento tra parentesi è necessario: in caso contrario, eTeX non ha modo di determinare che siamo arrivati ​​alla fine dell'elenco degli argomenti.

EDIT: come consentito nell'affermazione della domanda, un input errato può causare (un) errore. Ad esempio, si etex filename.tex [OK]blocca in modo orribile (perché Knon è un colore valido).


Non funziona sulla mia macchina.
FUZxxl,

@FUZxxl. Qual è l'output di etex -v? Qual è il messaggio di errore (approssimativamente)? Il codice deve essere inserito in un file (con nome filename.texo qualsiasi altra cosa che termina in .tex) e utilizzare quel nome nella riga di comando etex filename.tex [<argument>]. (mi dispiace ripubblicare lo stesso commento, ho dimenticato " @FUZxxl")
Bruno Le Floch,

Si prega di guardare qui: hpaste.org/48949
FUZxxl

@FUZxxl. Grazie per il tuo feedback. Knon è un colore valido e sostituendolo con Xnei tuoi esempi rimuove gli errori (si blocca Kperché quella lettera ha un altro significato, King). Potrei rendere l'errore meno orribile aggiungendo \stringprima di ognuno ##1, ma costerebbe 12 caratteri in più.
Bruno Le Floch,

Scusate. Ho sbagliato a scrivere l'esempio. Ora funziona. Scusate.
FUZxxl,

1

PowerShell, 79 80

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

Lancia »Tentativo di dividere per zero.« Se le carte appaiono due volte.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.