Licznik punktów dla Skata

11

Twoim zadaniem jest napisanie małego programu, który liczy punkty ręki Skata. Talia Skata zawiera karty od 7 do 10, walet, królową, króla i asa (zwane Unter, Ober, König i Daus). Używamy niemieckich kolorów, które mają żołędzie, liście, serca i dzwony zamiast trefl, pik, kier i diamentów. Punkty zależą od liczby na karcie:

  • 7, 8 i 9 oznaczają 0 punktów
  • Unter to 2 punkty
  • Ober ma 3 punkty
  • König to 4 punkty
  • 10 to 10 punktów
  • Daus ma 11 punktów.

Wejście wyjście

Format wejściowy składa się z dwóch symboli, pierwszy reprezentuje wartość, a drugi oznacza kolor:

  • 7, 8 i 9 oznaczają ich samych
  • 0 (zero) oznacza 10
  • Unter, Ober, König i Daus są nazwane po pierwszych literach (U, O i D)
  • To samo dotyczy żołędzi, liści, serc i brzucha (A, L, H i B)

Dane wejściowe to pojedyncza linia kart oddzielona pojedynczym białym znakiem. Możesz pobrać dane wejściowe z dowolnego miejsca, argumenty wiersza poleceń też są w porządku. Wynik jest wartością ręki, wydrukowaną lub zwróconą jako kod wyjścia. Wyjście twojego programu musi pokazywać błąd, jeśli jakakolwiek karta pojawi się dwukrotnie w ręce. (Więc 7A 0L 7Amusi zwrócić błąd zamiast 10). Można także wyjść z kodem wyjścia 255 zamiast wyświetlać błąd, jeśli jest to domyślny sposób wyświetlania wyniku przez program.

Przykłady

  • 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 DBdaje 120
  • 7A 8L 0K DB 8L daje błąd
  • UA OB DL KHdaje 20

Zasady

  • Code golf: wygrywa najkrótszy kod
  • Obowiązują zwykłe zasady gry w golfa
  • Program musi działać na wszystkie ręce, a nie tylko na przykłady
  • GIGO: Jeśli dane wejściowe są nieprawidłowe, dane wyjściowe mogą być dowolne
FUZxxl
źródło
Czy dodatkowe wyjście do stderr (np. Ostrzeżenia) jest w porządku?
Ventero,
@Ventero: Tak, to prawda. Każdy sposób na usunięcie błędu jest w porządku, ale musi być wyraźnie widoczny dla użytkownika, że ​​wystąpił błąd.
FUZxxl,
Jack, Queen i Ace nazywają się Unter, Ober, King i Daus? Czy król powinien tam być?
Ry-
@minitech Nie, nie jest.
FUZxxl
2
Wierzę, że masz na myśli „dzwonki”, a nie „brzuch”. Zupełnie inaczej.
stoisko do

Odpowiedzi:

2

APL ( 54 48)

Tam ma być krótsza droga wybierając wartość karty, ale ja tego nie widzę.

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

Dostajesz, DOMAIN ERRORjeśli istnieje duplikat karty.

Wyjaśnienie:

  • A←⍞~' ': store ( ) w Awierszu danych wejściowych użytkownika ( ) bez ( ~) spacji.
  • 2,⍨2÷⍨⍴A: lista dwuelementowa, zawierająca długość ( ) Apodzieloną przez ( ÷⍨) 2, a następnie ( ,⍨) liczbę 2. (Tak więc, jeśli dane wejściowe to UA OB DL KHlista to (4, 2)).
  • ↓A⍴⍨: zdefiniuj macierz ( ) o wymiarach tej listy zawierającej wartości A. Następnie połącz elementy jej wierszy razem ( ), podając na przykład listę list ['UA','OB','DL','KH'].
  • A←: Zapisz tę listę w A.
  • A≡∪A: ∪Ajest listą unikalnych elementów w A. Jeśli jest ona równa A, nie ma duplikatów i zwraca 1, w przeciwnym razie 0.
  • ÷: podziel to, co jest po lewej stronie (co faktycznie oblicza) przez wynik testu równości. Więc jeśli nie ma duplikatów, wynik pozostaje niezmieniony, a jeśli są duplikaty, otrzymujesz wynik z DOMAIN ERRORpowodu podziału przez zero.
  • ⊃¨A: Lista podająca pierwszy element ( ) każdego elementu ( ¨) z A. Tak więc to upuszcza literę koloru, pozostawiając literę wyniku. ( UODK)
  • 'D0.....KOU.'⍳: podaje indeks każdej z liter wyniku w tym ciągu, zwraca 12 dla wartości spoza łańcucha. ( 10 9 1 8)
  • +/12-: odejmij je wszystkie od 12, a następnie dodaj je razem. ( 2 + 3 + 11 + 4 = 20)

marinus
źródło
Tęskniłem za tym, że twoja odpowiedź jest najkrótsza.
FUZxxl
10

Ruby 1.9, 52 znaki

Wprowadzanie za pomocą argumentów wiersza poleceń. Zakładam, że komunikat o błędzie przy zduplikowanych kartach nie ma znaczenia, więc po prostu narzeka na błąd konwersji eval / type.

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

Przykładowe użycie:

$ 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
źródło
Z jednej strony myślę, że niezdefiniowany błąd zmiennej dla zduplikowanych kart jest trochę kiepski. Z drugiej strony nie łamie zasad, więc jest trochę sprytny.
Igby Largeman
1
@Charles: Od spec wywołuje tylko dla z błędu, myślę co błąd dokładnie jest prawie bez znaczenia. A jeśli istnieją krótkie metody popełniania błędów, to chyba powinno być w porządku.
Joey,
6

Scala, 87 82 znaków

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

Zgłasza wyjątek na powtarzających się kartach.

Rex Kerr
źródło
4

Haskell, 122 108 107 znaków

import List
main=interact$f.words
f x|nub x==x=show$sum$map(maybe 0 id.(`elemIndex`"  UOK     0D").head)x
hammar
źródło
error""jest krótszy niż undefined. Zaoszczędź jeden znak za pomocą interact.
FUZxxl,
@FUZxxl: Korzystanie z interactniego nie spowoduje wydrukowania nowego wiersza, więc nie jestem pewien, czy jest to dopuszczalne. Byłem jednak w stanie zaoszczędzić znacznie więcej, używając zamiast tego niekompletnego wzorca undefined.
hammar
Gdzie powiedziałem, że potrzebna jest nowa linia? Nie pamiętam
FUZxxl,
2

GolfScript 54 53 52

Edycja 1:

Właśnie odkryłem błąd w kodzie. Nie wykrył duplikatów kart, jeśli duplikaty były pierwszymi dwoma na wejściu (ponieważ użyłem *operatora składania, a nie /każdego operatora dla pierwszej pętli).

Teraz poprawiłem kod, a także udało mi się usunąć 1 znak w tym procesie. Oto nowa wersja:

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

Dane wejściowe muszą znajdować się na stosie jako ciąg znaków, w określonym formacie (przykład '7A UA DA':).

Jeśli dane wejściowe są prawidłowe, program drukuje całkowitą wartość kart.

W przypadku, gdy istnieje co najmniej jedna zduplikowana karta, program zgłasza następujący wyjątek:

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

Edycja 2:

Po obejrzeniu tego postu na stronie meta postanowiłem opublikować opis kodu. Pomogło mi to również znaleźć i naprawić błąd. Oto więc:

# 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
źródło
1

Python, 114 znaków

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

Niestety indexmetoda list w Pythonie wywołuje błąd, jeśli element nie zostanie znaleziony, zamiast zwracać wartość ujemną, a importowanie defaultdictwymagałoby więcej znaków niż zaoszczędziłoby.

UKŁUCIE
źródło
1

eTeX, 201 znaków (nie licząc dwóch nieistotnych podziałów linii)

\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

Używany jako etex filename.tex [UA OB DL KH]. Umieszczenie argumentu w nawiasach jest konieczne: w przeciwnym razie eTeX nie ma możliwości ustalenia, że ​​osiągnęliśmy koniec listy argumentów.

EDYCJA: jak dozwolone w pytaniu pytania, nieprawidłowe dane wejściowe mogą powodować (an) błąd. Na przykład etex filename.tex [OK]powoduje awarię okropnie (ponieważ Knie jest prawidłowym kolorem).

Bruno Le Floch
źródło
Nie działa na moim komputerze.
FUZxxl,
@FUZxxl. Jaka jest wydajność etex -v? Jaki jest komunikat o błędzie (z grubsza)? Kod powinien zostać umieszczony w pliku (z nazwą filename.texlub inną czcionką kończącą się na .tex) i użyj tej nazwy w wierszu poleceń etex filename.tex [<argument>]. (przepraszam, że ponownie opublikowałem ten sam komentarz, zapomniałem „ @FUZxxl”)
Bruno Le Floch,
Zajrzyj tutaj: hpaste.org/48949
FUZxxl,
@FUZxxl. Dziękujemy za twoją opinię. Knie jest poprawnym kolorem, a zastąpienie go Xw twoich przykładach usuwa błędy (ulega awarii, Kponieważ litera ma inne znaczenie, King). Mógłbym sprawić, by błąd był mniej okropny, dodając \stringprzed każdym ##1, ale to kosztowałoby 12 dodatkowych znaków.
Bruno Le Floch,
Przepraszam. Źle wpisałem ten przykład. To teraz działa. Przepraszam.
FUZxxl,
1

PowerShell, 79 80

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

Rzuca »Próba podzielenia przez zero«, jeśli karty pojawią się dwukrotnie.

Joey
źródło