Punktezähler für Skat

11

Ihre Aufgabe ist es, ein kleines Programm zu schreiben, das die Punkte einer Skat-Hand zählt. Ein Skat-Deck hat Karten 7 bis 10, Jack, Queen, King und Ace (genannt Unter, Ober, König und Daus). Wir verwenden die deutschen Anzüge, die Eicheln, Blätter, Herzen und Glocken anstelle von Keulen, Pik, Herzen und Diamanten haben. Die Punkte werden durch die Nummer auf der Karte bestimmt:

  • 7, 8 und 9 sind 0 Punkte
  • Unter ist 2 Punkte
  • Ober ist 3 Punkte
  • König ist 4 Punkte
  • 10 ist 10 Punkte
  • Daus ist 11 Punkte.

Input-Output

Das Eingabeformat besteht aus zwei Symbolen, wobei das erste den Wert darstellt, während das zweite für die Farbe steht:

  • 7, 8 und 9 stehen für sich selbst
  • 0 (Null) steht für 10
  • Unter, Ober, König und Daus sind nach ihren Anfangsbuchstaben (U, O und D) benannt.
  • Gleiches gilt für Eicheln, Blätter, Herzen und Bauch (A, L, H und B)

Die Eingabe ist eine einzelne Kartenzeile, die durch ein einzelnes Leerzeichen getrennt ist. Sie können die Eingabe von überall übernehmen. Befehlszeilenargumente sind ebenfalls in Ordnung. Die Ausgabe ist der Wert der Hand, der entweder ausgedruckt oder als Exit-Code zurückgegeben wird. Die Ausgabe Ihres Programms muss einen Fehler anzeigen, wenn eine Karte zweimal in der Hand erscheint. ( 7A 0L 7AMuss also einen Fehler zurückgeben statt 10). Es ist auch in Ordnung, mit einem Exit-Code von 255 zu beenden, anstatt einen Fehler anzuzeigen, wenn dies die Standardmethode Ihres Programms ist, um das Ergebnis auszugeben.

Beispiele

  • 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 DBgibt 120
  • 7A 8L 0K DB 8L gibt einen Fehler
  • UA OB DL KHgibt 20

Regeln

  • Code Golf: Der kürzeste Code gewinnt
  • Es gelten die üblichen Code-Golfregeln
  • Das Programm muss für alle Hände funktionieren, nicht nur für die Beispiele
  • GIGO: Wenn die Eingabe ungültig ist, kann die Ausgabe beliebig sein
FUZxxl
quelle
Ist eine zusätzliche Ausgabe an stderr (z. B. Warnungen) in Ordnung?
Ventero
@ Ventero: Ja, das ist es. Jeder Fehler ist in Ordnung, aber für den Benutzer muss klar erkennbar sein, dass ein Fehler vorliegt.
FUZxxl
Jack, Queen und Ace heißen Unter, Ober, King und Daus? Soll ein König dort drin sein?
Ry
@minitech Nein, das ist es nicht.
FUZxxl
2
Ich glaube du meinst "Glocken", nicht "Bauch". Ganz anders.
Standby

Antworten:

2

APL ( 54 48)

Es muss eine kürzere Möglichkeit geben, den Kartenwert auszuwählen, aber ich sehe ihn nicht.

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

Sie erhalten eine, DOMAIN ERRORwenn es eine doppelte Karte gibt.

Erläuterung:

  • A←⍞~' ': store ( ) in Aeiner Zeile mit Benutzereingaben ( ) ohne ( ~) Leerzeichen.
  • 2,⍨2÷⍨⍴A: Eine Liste mit zwei Elementen, die die Länge von ( ) Ageteilt durch ( ÷⍨) 2, gefolgt von ( ,⍨) der Zahl 2 enthält. (Wenn die Eingabe also UA OB DL KHdie Liste ist, ist (4, 2)).
  • ↓A⍴⍨: Definieren Sie eine Matrix ( ) mit den Abmessungen dieser Liste, die die Werte von A enthält. Fügen Sie dann die Elemente ihrer Zeilen zusammen ( ) und geben Sie beispielsweise eine Liste mit Listen an ['UA','OB','DL','KH'].
  • A←: Speichern Sie diese Liste in A.
  • A≡∪A: ∪Aist die Liste der eindeutigen Elemente in A. Wenn dies gleich A ist, gibt es keine Duplikate und dies gibt 1 zurück, andernfalls 0.
  • ÷: Teilen Sie, was links ist (was die eigentliche Berechnung durchführt), durch das Ergebnis des Gleichheitstests. Wenn also keine Duplikate vorhanden sind, bleibt die Punktzahl unverändert, und wenn Duplikate vorhanden sind, erhalten Sie DOMAIN ERRORaufgrund der Division durch Null eine.
  • ⊃¨A: Eine Liste mit dem ersten Element ( ) jedes Elements ( ¨) von A. Dadurch wird der Anzugbuchstabe gelöscht und der Punktebuchstabe belassen. ( UODK)
  • 'D0.....KOU.'⍳: Gibt den Index aller Punktebuchstaben in dieser Zeichenfolge an und gibt 12 für Werte zurück, die nicht in der Zeichenfolge enthalten sind. ( 10 9 1 8)
  • +/12-: subtrahieren Sie alle diese von 12 und addieren Sie sie dann. ( 2 + 3 + 11 + 4 = 20)

Marinus
quelle
Ich habe total vermisst, dass deine Antwort die kürzeste ist.
FUZxxl
10

Ruby 1.9, 52 Zeichen

Eingabe über Befehlszeilenargumente. Ich gehe davon aus, dass die Fehlermeldung bei doppelten Karten keine Rolle spielt, und beschwert sich daher nur über einen Fehler bei der Auswertung / Typkonvertierung.

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

Anwendungsbeispiel:

$ 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
quelle
Einerseits denke ich, dass der undefinierte Variablenfehler für doppelte Karten etwas lahm ist. Auf der anderen Seite verstößt es nicht gegen die Regeln, also ist es ein bisschen klug.
Igby Largeman
1
@ Charles: Da die Spezifikation nur einen Fehler fordert , denke ich, welcher Fehler genau ziemlich irrelevant ist. Und wenn es kurze Methoden gibt, um Fehler zu erzeugen, sollte das in Ordnung sein, denke ich.
Joey
6

Scala, 87 82 Zeichen

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

Wirft eine Ausnahme auf wiederholte Karten.

Rex Kerr
quelle
4

Haskell, 122 108 107 Zeichen

import List
main=interact$f.words
f x|nub x==x=show$sum$map(maybe 0 id.(`elemIndex`"  UOK     0D").head)x
Hammar
quelle
error""ist kürzer als undefined. Speichern Sie ein Zeichen mit interact.
FUZxxl
@FUZxxl: Wenn Sie interactes verwenden, wird keine neue Zeile gedruckt, daher bin ich mir nicht sicher, ob dies akzeptabel ist. Ich konnte jedoch viel mehr sparen, indem ich stattdessen ein unvollständiges Muster verwendete undefined.
Hammar
Wo habe ich gesagt, dass eine neue Zeile benötigt wird? Ich kann mich nicht erinnern.
FUZxxl
2

GolfScript 54 53 52

Bearbeiten 1:

Ich habe gerade einen Fehler im Code entdeckt. Es wurden keine doppelten Karten erkannt, wenn die doppelten Karten die ersten beiden in der Eingabe waren (weil ich den *Falzoperator und nicht /jeden Operator für die erste Schleife verwendet habe).

Jetzt habe ich den Code korrigiert und dabei auch 1 Zeichen entfernt. Hier ist die neue Version:

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

Die Eingabe muss sich als Zeichenfolge im angegebenen Format auf dem Stapel befinden (Beispiel :) '7A UA DA'.

Wenn die Eingabe gültig ist, druckt das Programm den Gesamtwert der Karten.

Falls mindestens eine doppelte Karte vorhanden ist, löst das Programm die folgende Ausnahme aus:

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

Bearbeiten 2:

Nachdem ich diesen Beitrag auf der Meta-Site gesehen hatte , beschloss ich, eine Beschreibung des Codes zu veröffentlichen. Dies hat mir auch geholfen, einen Fehler zu finden und zu beheben. Also, hier geht's:

# 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
quelle
1

Python, 114 Zeichen

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

Leider indexlöst die Listenmethode in Python einen Fehler aus, wenn ein Element nicht gefunden wird, anstatt einen negativen Wert zurückzugeben, und für den Import defaultdictwären mehr Zeichen erforderlich als gespeichert.

JAB
quelle
1

eTeX, 201 Zeichen (ohne die beiden irrelevanten Zeilenumbrüche)

\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

Verwendet als etex filename.tex [UA OB DL KH]. Das Argument in Klammern zu setzen ist notwendig: Andernfalls kann eTeX nicht feststellen, dass wir das Ende der Argumentliste erreicht haben.

BEARBEITEN: Wie in der Erklärung der Frage zulässig, kann eine falsche Eingabe (einen) Fehler verursachen. Zum Beispiel etex filename.tex [OK]stürzt schrecklich ab (weil Kkeine gültige Farbe ist).

Bruno Le Floch
quelle
Funktioniert nicht auf meinem Computer.
FUZxxl
@FUZxxl. Was ist die Ausgabe von etex -v? Was ist die Fehlermeldung (ungefähr)? Der Code sollte in eine Datei eingefügt werden (mit Namen filename.texoder irgendetwas anderem, das auf endet .tex), und diesen Namen in der Befehlszeile verwenden etex filename.tex [<argument>]. (Entschuldigung, den gleichen Kommentar erneut zu veröffentlichen, ich habe " @FUZxxl" vergessen )
Bruno Le Floch
Bitte schauen Sie hier: hpaste.org/48949
FUZxxl
@FUZxxl. Vielen Dank für dein Feedback. Kist keine gültige Farbe, und wenn XSie sie in Ihren Beispielen durch ersetzen, werden die Fehler behoben (es stürzt ab, Kweil dieser Buchstabe eine andere Bedeutung hat, König). Ich könnte den Fehler weniger schrecklich machen, indem ich ihn \stringvor jedem hinzufüge ##1, aber das würde 12 weitere Zeichen kosten.
Bruno Le Floch
Es tut uns leid. Ich habe das Beispiel falsch eingegeben. Es funktioniert jetzt. Es tut uns leid.
FUZxxl
1

PowerShell, 79 80

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

Wirft »Versuch, durch Null zu teilen.«, Wenn die Karten zweimal erscheinen.

Joey
quelle