Penghitung skor untuk Skat

11

Tugas Anda adalah menulis sebuah program kecil, yang menghitung poin-poin dari tangan Skat. Deck Skat memiliki kartu 7 hingga 10, Jack, Queen, King dan Ace (disebut Unter, Ober, König dan Daus). Kami menggunakan jas Jerman, yang memiliki Acorns, Leaves, Hearts and Bells, bukan Club, Spades, Hearts dan Diamonds. Poin ditentukan oleh nomor pada kartu:

  • 7, 8 dan 9 adalah 0 poin
  • Unter adalah 2 poin
  • Ober adalah 3 poin
  • König adalah 4 poin
  • 10 adalah 10 poin
  • Daus adalah 11 poin.

Input output

Format input terdiri dari dua simbol, yang pertama mewakili nilai, sedangkan yang kedua adalah singkatan dari suit:

  • 7, 8 dan 9 mewakili mereka sendiri
  • 0 (nol) adalah 10
  • Unter, Ober, König dan Daus diberi nama sesuai dengan huruf pertama mereka (U, O dan D)
  • Hal yang sama untuk Acorns, Leaves, Hearts and Bellys (A, L, H dan B)

Input adalah satu baris kartu, dipisahkan oleh spasi tunggal. Anda dapat mengambil input dari mana saja, argumen baris perintah juga oke. Outputnya adalah nilai tangan, baik dicetak atau dikembalikan sebagai kode keluar. Output dari program Anda harus menunjukkan kesalahan, jika ada kartu yang muncul dua kali di tangan. (Jadi 7A 0L 7Aharus mengembalikan kesalahan, bukan 10). Tidak apa-apa untuk berhenti dengan kode keluar 255 bukannya menunjukkan kesalahan, jika ini adalah cara default program Anda untuk menampilkan hasilnya.

Contohnya

  • 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 DBmemberi 120
  • 7A 8L 0K DB 8L memberikan kesalahan
  • UA OB DL KHmemberi 20

Aturan

  • Golf kode: Kode terpendek menang
  • Aturan golf kode biasa berlaku
  • Program harus bekerja untuk semua tangan, bukan hanya contoh
  • GIGO: Jika input tidak valid, output mungkin arbitrer
FUZxxl
sumber
Apakah output tambahan untuk stderr (mis. Peringatan) ok?
Ventero
@Ventero: Ya, benar. Cara apa pun untuk berbuat kesalahan tidak apa-apa, tetapi harus jelas terlihat oleh pengguna, bahwa ada kesalahan.
FUZxxl
Jack, Queen, dan Ace disebut Unter, Ober, King dan Daus? Apakah raja seharusnya ada di sana?
Ry-
@minitech Tidak, tidak.
FUZxxl
2
Saya percaya maksud Anda "lonceng", bukan "perut". Sangat berbeda.
Stanby

Jawaban:

2

APL ( 54 48)

Ada memiliki untuk menjadi cara yang lebih pendek memilih nilai kartu, tapi saya tidak melihatnya.

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

Anda mendapatkan DOMAIN ERRORjika ada kartu duplikat.

Penjelasan:

  • A←⍞~' ': store ( ) ke Adalam baris input pengguna ( ) tanpa ( ~) spasi.
  • 2,⍨2÷⍨⍴A: daftar dua elemen, yang berisi panjang ( ) Adibagi dengan ( ÷⍨) 2, diikuti oleh ( ,⍨) angka 2. (Jadi, jika input adalah UA OB DL KHdaftar adalah (4, 2)).
  • ↓A⍴⍨: define a matrix ( ), dengan dimensi daftar itu, berisi nilai-nilai A. Kemudian gabungkan elemen-elemen dari barisnya bersama-sama ( ), memberikan daftar daftar, misalnya ['UA','OB','DL','KH'].
  • A←: Simpan daftar ini di A.
  • A≡∪A: ∪Aadalah daftar elemen unik dalam A. Jika ini sama dengan A, tidak ada duplikat dan ini mengembalikan 1, jika tidak 0.
  • ÷: bagi apa yang ada di sebelah kiri (yang melakukan perhitungan aktual) dengan hasil tes kesetaraan. Jadi jika tidak ada duplikat, skornya tidak berubah, dan jika ada duplikat Anda mendapatkan DOMAIN ERRORkarena pembagian dengan nol.
  • ⊃¨A: Daftar yang memberikan elemen pertama ( ) dari setiap elemen ( ¨) A. Jadi ini menjatuhkan surat gugatan, meninggalkan surat skor. ( UODK)
  • 'D0.....KOU.'⍳: memberikan indeks dari masing-masing huruf skor dalam string ini, mengembalikan 12 untuk nilai-nilai yang tidak ada dalam string. ( 10 9 1 8)
  • +/12-: kurangi semua ini dari 12, dan kemudian tambahkan bersama-sama. ( 2 + 3 + 11 + 4 = 20)

marinus
sumber
Saya benar-benar merindukan bahwa jawaban Anda adalah yang terpendek.
FUZxxl
10

Ruby 1.9, 52 karakter

Masukan melalui argumen baris perintah. Saya berasumsi pesan kesalahan ketika memiliki kartu duplikat tidak masalah, jadi itu hanya mengeluh tentang kesalahan konversi jenis / eval.

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

Contoh penggunaan:

$ 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
sumber
Di satu sisi saya pikir kesalahan variabel yang tidak terdefinisi untuk kartu duplikat agak timpang. Di sisi lain, itu tidak melanggar aturan, jadi itu agak pintar.
Igby Largeman
1
@ Charles: Sejak spec hanya panggilan untuk sebuah kesalahan, saya kira apa kesalahan sebenarnya cukup banyak tidak relevan. Dan jika ada metode pendek untuk menghasilkan kesalahan, itu seharusnya baik-baik saja, saya kira.
Joey
6

Scala, 87 82 karakter

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

Melempar pengecualian pada kartu yang diulang.

Rex Kerr
sumber
4

Haskell, 122 108 107 karakter

import List
main=interact$f.words
f x|nub x==x=show$sum$map(maybe 0 id.(`elemIndex`"  UOK     0D").head)x
hammar
sumber
error""lebih pendek dari undefined. Simpan satu char menggunakan interact.
FUZxxl
@ FuZxxl: Menggunakannya interacttidak akan mencetak baris baru, jadi saya tidak yakin apakah itu dapat diterima. Namun, saya bisa menghemat lebih banyak dengan menggunakan pola yang tidak lengkap undefined.
hammar
Di mana saya katakan, bahwa baris baru diperlukan? Saya tidak ingat.
FUZxxl
2

GolfScript 54 53 52

Edit 1:

Saya baru saja menemukan kesalahan dalam kode. Itu tidak mendeteksi kartu duplikat jika duplikat adalah dua yang pertama dalam input (karena saya menggunakan *operator lipat dan bukan /masing - masing operator untuk loop pertama).

Sekarang saya memperbaiki kode dan juga berhasil menghapus 1 char dalam proses. Ini versi baru:

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

Masukan harus berada di tumpukan sebagai string, dalam format yang ditentukan (contoh '7A UA DA':).

Jika inputnya valid, program akan mencetak nilai total kartu.

Jika setidaknya ada satu kartu duplikat, program melempar pengecualian berikut:

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

Edit 2:

Setelah melihat posting ini di situs meta , saya memutuskan untuk mengirim deskripsi kode. Ini juga membantu saya menemukan dan memperbaiki kesalahan. Jadi begini:

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

Python, 114 karakter

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

Sayangnya, indexmetode daftar di Python memunculkan kesalahan jika elemen tidak ditemukan daripada mengembalikan nilai negatif, dan mengimpor defaultdictakan membutuhkan lebih banyak karakter daripada yang akan disimpan.

TUSUKAN
sumber
1

eTeX, 201 karakter (tidak termasuk dua linebreak yang tidak relevan)

\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

Digunakan sebagai etex filename.tex [UA OB DL KH]. Menempatkan argumen dalam tanda kurung diperlukan: jika tidak, eTeX tidak memiliki cara untuk menentukan bahwa kita mencapai akhir dari daftar argumen.

EDIT: sebagaimana diizinkan dalam pernyataan pertanyaan, input yang salah dapat menyebabkan (an) kesalahan. Misalnya, etex filename.tex [OK]crash parah (karena Kbukan warna yang valid).

Bruno Le Floch
sumber
Tidak berfungsi di mesin saya.
FUZxxl
@FUZxxl. Apa output dari etex -v? Apa pesan kesalahan (kurang-lebih)? Kode harus dimasukkan ke dalam file (dengan nama filename.tex, atau apa pun yang berakhir dengan .tex), dan gunakan nama itu di baris perintah etex filename.tex [<argument>]. (maaf untuk mengirim ulang komentar yang sama, saya lupa " @FUZxxl")
Bruno Le Floch
Silakan lihat di sini: hpaste.org/48949
FUZxxl
@FUZxxl. Terima kasih atas tanggapan Anda. Kbukan warna yang valid, dan menggantinya dengan Xdalam contoh Anda menghilangkan kesalahan (rusak Kkarena surat itu memiliki arti lain, Raja). Saya bisa membuat kesalahan lebih buruk dengan menambahkan \stringsebelum masing-masing ##1, tetapi itu akan membutuhkan 12 karakter lebih banyak.
Bruno Le Floch
Maaf. Saya salah menuliskan contoh. Ini berfungsi sekarang. Maaf.
FUZxxl
1

PowerShell, 79 80

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

Lempar »Berusaha membagi dengan nol.« Jika kartu muncul dua kali.

Joey
sumber