Лічильник балів для Skat


11

Ваше завдання - написати невелику програму, яка підраховує бали руки Скат. Колода Skat має картки від 7 до 10, Джек, Королева, Король та Туз (звані Унтер, Обер, Кеніг та Даус). Ми використовуємо німецькі костюми, які замість клубів, лопат, сердець і діамантів мають жолуді, листя, сердечки та дзвіночки. Бали визначаються номером на картці:

  • 7, 8 і 9 - 0 балів
  • Унтер - 2 бали
  • Обер - 3 бали
  • Кеніг - 4 бали
  • 10 - це 10 балів
  • Даус - 11 балів.

Введення-виведення

Формат введення складається з двох символів, перший представляє значення, а другий означає масть:

  • 7, 8 і 9 стоять за них самостійно
  • 0 (нуль) означає 10
  • Унтер, Обер, Кеніг і Даус названі на честь своїх перших літер (U, O і D)
  • Те саме для жолудів, листя, серця і черевця (A, L, H і B)

Вхід - це один рядок карт, розділений одним пробілом. Ви можете брати дані з будь-якого місця, і аргументи командного рядка теж нормальні. Вихід - це значення руки, роздрукованої або поверненої як вихідний код. У результатах вашої програми повинно з’явитися помилка, якщо якась картка з’являється двічі в руці. (Тому 7A 0L 7Aпотрібно повернути помилку замість 10). Також добре вийти з кодом виходу 255 замість того, щоб показувати помилку, якщо це спосіб за замовчуванням вашої програми для виведення результату.

Приклади

  • 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
  • 7A 8L 0K DB 8L дає помилку
  • UA OB DL KHдає 20

Правила

  • Код гольфу: виграє найкоротший код
  • Діють звичайні правила гольфу
  • Програма повинна працювати на всі руки, а не лише на прикладах
  • GIGO: Якщо вхід недійсний, вихід може бути довільним

Окремий додатковий вихід на stderr (наприклад, попередження)?
Вентеро

@ Вентеро: Так, так і є. Будь-який спосіб помилитися добре, але він повинен бути чітко видно користувачеві, що є помилка.
FUZxxl

Джека, Королеву та туза називають Унтером, Обер, Королем та Даусом? Чи там повинен бути король?
Ри-

@minitech Ні, це не так.
FUZxxl

2
Я вважаю, ви маєте на увазі "дзвіночки", а не "живіт". Дуже різне, що.
кабіна

Відповіді:


2

APL ( 54 48)

Там повинно бути коротким шляхом вибору значення карти, але я не бачу його.

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

Ви отримуєте, DOMAIN ERRORякщо є дублікат картки.

Пояснення:

  • A←⍞~' ': зберігання ( ) у Aрядок введення користувача ( ) без ~пробілів.
  • 2,⍨2÷⍨⍴A: двоелементний список, що містить довжину ( ), Aрозділену на ( ÷⍨) 2, а потім ( ,⍨) число 2. (Отже, якщо вхідний UA OB DL KHсписок є (4, 2)).
  • ↓A⍴⍨: визначте матрицю ( ) з розмірами цього списку, що містить значення А. Потім з'єднайте елементи її рядків разом ( ), даючи, наприклад, список списків ['UA','OB','DL','KH'].
  • A←: Збережіть цей список в A.
  • A≡∪A: ∪Aце список унікальних елементів у A. Якщо це дорівнює A, немає дублікатів, і це поверне 1, інакше 0.
  • ÷: розділіть ліворуч (що робить фактичний розрахунок) за результатом тесту на рівність. Отже, якщо немає дублікатів, оцінка не змінюється, а якщо є дублікати, ви отримуєте результат DOMAIN ERRORчерез ділення на нуль.
  • ⊃¨A: Список, який містить перший елемент ( ) кожного елемента ( ¨) А. Отже, це відміняє лист костюма, залишаючи літеру. ( UODK)
  • 'D0.....KOU.'⍳: дає індекс кожної літери балів у цьому рядку, повертає 12 для значень, які не є в рядку. ( 10 9 1 8)
  • +/12-: відняти все це від 12, а потім додати їх разом. ( 2 + 3 + 11 + 4 = 20)


Я зовсім пропустив, що ваша відповідь найкоротша.
FUZxxl

10

Рубін 1,9, 52 символи

Введіть аргументи командного рядка. Я припускаю, що повідомлення про помилку, коли дублікати карт не має значення, тому воно просто скаржиться на помилку конверсії eval / type.

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

Приклад використання:

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

З одного боку, я вважаю, що невизначена помилка змінної для дублікатів карт є своєрідною кульгавою. З іншого боку, це не порушує правила, тому це щось розумно.
Ігбі Ларгеман

1
@Charles: Оскільки специфікація викликає тільки з помилкою, я думаю , що помилка саме в значній мірі не має значення. І якщо існують короткі методи помилок, то, мабуть, це буде добре.
Joey

6

Скала, 87 82 символи

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

Кидає виняток на повторних картках.


4

Haskell, 122 108 107 символів

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

error""коротше, ніж undefined. Збережіть одну таблицю за допомогою interact.
FUZxxl

@FUZxxl: Використання interactцього файлу не надрукує новий рядок, тому я не впевнений, чи прийнятно це. Однак мені вдалося зекономити набагато більше, використовуючи незавершений зразок замість undefined.
хаммар

Де я сказав, що потрібен новий рядок? Я не можу згадати.
FUZxxl

2

GolfScript 54 53 52

Редагувати 1:

Я щойно виявив помилку в коді. Він не виявив дублікатів карт, якщо дублікати були першими двома на вході (тому що я використовував *оператор fold, а не /кожен оператор для першого циклу).

Тепер я виправив код і також встиг зняти з нього 1 char. Ось нова версія:

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

Вхід повинен бути у стеці у вигляді рядка у визначеному форматі (приклад '7A UA DA':).

У випадку, якщо введення дійсне, програма виводить загальну вартість карт.

Якщо є хоча б одна дублікат картки, програма видає такий виняток:

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

Редагувати 2:

Побачивши цю публікацію на мета-сайті , я вирішив опублікувати опис коду. Це також допомогло мені знайти та виправити помилку. Отже, ось що:

# 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

Пітон, 114 символів

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

На жаль, indexметод списків у Python викликає помилку, якщо елемент не знайдеться, а не поверне негативне значення, а для імпорту defaultdictзнадобиться більше символів, ніж збережеться.


1

eTeX, 201 символ (не рахуючи двох неактуальних розривів рядків)

\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

Використовується як etex filename.tex [UA OB DL KH]. Поставити аргумент у дужки потрібно: інакше eTeX не може визначити, що ми дійшли до кінця списку аргументів.

EDIT: як це дозволено в постановці питання, неправильний ввід може спричинити (а) помилку. Наприклад, etex filename.tex [OK]жахливо виходить з ладу (тому що Kце невірний колір).


Не працює на моїй машині.
FUZxxl

@FUZxxl. Який вихід etex -v? Що таке повідомлення про помилку (приблизно)? Код слід ввести у файл (з ім'ям filename.texабо чим-небудь іншим, що закінчується .tex), і використовувати це ім'я в командному рядку etex filename.tex [<argument>]. (вибачте, що перепублікували той самий коментар, я забув " @FUZxxl")
Бруно Ле Флоч

Будь ласка, подивіться тут: hpaste.org/48949
FUZxxl

@FUZxxl. Спасибі за ваш відгук. Kне є дійсним кольором, і замінивши його Xу своїх прикладах, вилучає помилки (він виходить з ладу, Kоскільки ця літера має інше значення, король). Я можу зробити помилку менш жахливою, додаючи \stringперед кожною ##1, але це коштуватиме ще 12 символів.
Бруно Ле Флох

Вибачте. Я неправильно ввів приклад. Це працює зараз. Вибачте.
FUZxxl

1

PowerShell, 79 80

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

Кидки »Спроба розділити на нуль.« Якщо картки з’являються двічі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.