Skat计分器


11

您的任务是编写一个小程序,该程序计算Skat手的点数。Skat牌组有7到10张牌,分别是Jack,Queen,King和Ace(称为Unter,Ober,König和Daus)。我们使用的是德国西装,里面有橡子,树叶,心形和铃铛,而不是球杆,黑桃,心形和钻石。点数由卡上的数字确定:

  • 7、8和9是0分
  • 下限是2分
  • 奥伯是3分
  • 柯尼希(König)是4分
  • 10是10分
  • 道斯是11分。

输入输出

输入格式由两个符号组成,第一个代表值,第二个代表西装:

  • 7、8和9代表他们自我
  • 0(零)代表10
  • Unter,Ober,König和Daus以其首字母(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 KH20

规则

  • 高尔夫代码:最短的代码获胜
  • 通常的高尔夫规则适用
  • 该程序必须为所有人服务,而不仅仅是示例
  • GIGO:如果输入无效,则输出可以是任意的

附加输出到stderr(例如警告)可以吗?
Ventero 2011年

@Ventero:是的。可以采用任何错误的方法,但是对于用户而言,它必须清晰可见,即存在错误。
FUZxxl 2011年

杰克,皇后和王牌分别称为安特,奥伯,金和道斯?国王应该在那里吗?
Ry- 2011年

@minitech不,不是。
FUZxxl 2011年

2
我相信您的意思是“铃铛”,而不是“肚皮”。完全不同。
2012年

Answers:


2

杀伤人员地雷(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⍴⍨:定义一个具有该列表尺寸的矩阵(),其中包含A的值。然后将其行的元素连接在一起(),以给出一个列表列表,例如['UA','OB','DL','KH']
  • A←:将此列表存储在A中。
  • A≡∪A∪A是A中唯一元素的列表。如果等于A,则没有重复项,并且返回1,否则返回0。
  • ÷:用相等性测试的结果除以左边的内容(进行实际计算)。因此,如果没有重复项,则分数不变,如果有重复项,则DOMAIN ERROR由于除以零而得到a 。
  • ⊃¨A:给出A 的每个元素(¨)的第一个元素()的列表。因此,这将删除西服字母,留下得分字母。(UODK
  • 'D0.....KOU.'⍳:给出此字符串中每个乐谱字母的索引,对于不在字符串中的值返回12。(10 9 1 8
  • +/12-:从12中减去所有这些,然后将它们加在一起。(2 + 3 + 11 + 4 = 20


我完全想念您的答案是最短的。
FUZxxl 2015年

10

Ruby 1.9,52个字符

通过命令行参数输入。我假设拥有重复卡时的错误消息无关紧要,因此它只是抱怨评估/类型转换错误。

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

一方面,我认为重复卡的未定义变量错误有点la脚。另一方面,它不会违反规则,因此有点聪明。
Igby Largeman 2011年

1
@Charles:由于规范只要求一个错误,我想确切地说什么错误几乎是无关紧要的。我猜,如果有产生错误的简短方法,那应该没问题。
Joey

6

Scala,87个 82个字符

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

在重复的卡上引发异常。


4

哈斯克尔, 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
2011年

@FUZxxl:使用interact它不会打印换行符,因此我不确定是否可以接受。但是,通过使用不完整的模式而不是,我能够节省更多undefined
hammar 2011年

我在哪里说需要换行符?我不记得了
FUZxxl 2011年

2

高尔夫脚本54 53 52

编辑1:

我只是在代码中发现错误。如果重复项是输入中的前两个,则它不会检测到重复的卡(因为我使用的是*fold运算符,而不是/第一个循环的each运算符)。

现在,我修复了代码,并在此过程中设法去除了1个字符。这是新版本:

' '/{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:

meta网站上看到此帖子后,我决定发布代码说明。这也帮助我发现并修复了错误。因此,这里是:

# 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个字符

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中的list方法会引发错误,并且导入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无法确定我们是否已到达参数列表的末尾。

编辑:在问题陈述中允许的输入错误会导致错误。例如,etex filename.tex [OK]严重崩溃(因为K这不是有效的颜色)。


在我的机器上不起作用。
FUZxxl 2011年

@FUZxxl。输出是etex -v什么?错误消息大致是什么?代码应放在文件中(名称filename.tex或以结尾的任何其他文件.tex),并在命令行中使用该名称etex filename.tex [<argument>]。(对不起,我再次发表相同的评论,我忘记了“ @FUZxxl”)
Bruno Le Floch

请在此处查看:hpaste.org/48949
FUZxxl 2011年

@FUZxxl。感谢您的反馈意见。K不是有效的颜色,X在您的示例中将其替换为可以消除错误(K由于该字母具有另一种含义,即King,因此会崩溃)。我可以通过\string在每个##1字符之前添加来使错误不太可怕,但这会增加12个字符。
Bruno Le Floch

抱歉。我输错了例子。现在可以使用了。抱歉。
FUZxxl 2011年

1

Powershell,79 80

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

抛出“试图除以零。”,如果卡片出现两次。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.