Scopaハンドのスコアは何ですか?


14

私はカードゲームチャレンジが好きなので、イタリアのカードゲームScopa向けにこれを作りました。私の家族は太古からこのゲームをプレイしています。それはゴルフにとって楽しいはずの非常に興味深い得点システムを持っています。楽しみを始めるためにRに回答を投稿し、人々が改善することを確信しています。

課題:ラウンド中にプレイヤーが入力としてキャプチャしたカードを考慮して、Scopaのラウンドで獲得したポイント数を計算します。

Scopaデッキには40枚のカードがあります。国際デッキを使用している場合は、8、9、10を削除し、各スーツにA、2、3、4、5、6、7、Q、J、Kを残します。1 2人のプレーヤーまたはパートナーシップがあり、各ラウンドの後、すべてのカードは2人のプレーヤーのいずれかによってキャプチャされます。スコアは次のようにカウントされます(詳細はこちら):

  • 最も多くのカードを持つプレイヤーが1ポイントを獲得します。
  • 最も多くのダイアモンド(またはイタリアのデッキを使用している場合はコイン)を持つプレイヤーは1ポイントを獲得します。
  • セッテベロまたは美しいセブンとして知られる7のダイヤモンド(またはコイン)持つプレーヤーは、1ポイントを獲得します。
  • 最高のプリミエラを持つプレイヤーは1ポイントを獲得します。プレイヤーのプリミエラスコアは、各スーツでプレイヤーが獲得した最高価値のカードのスコアの合計です(下の表を参照)。すべてのスーツに少なくとも1枚のカードがない場合、対戦相手のスコアを超えてもスコアはデフォルトで負けます。どちらのプレイヤーもすべてのスーツに少なくとも1枚のカードを持っているという非常にまれなケースでは、より高いプリミエラの合計を持つプレイヤーがポイントを獲得します。2

初生スコアの表

| Rank  | Value |
| ----- | ----- |
| 7     | 21    |
| 6     | 18    |
| A     | 16    |
| 5     | 15    |
| 4     | 14    |
| 3     | 13    |
| 2     | 12    |
| Q,J,K | 10    |

したがって、プレーヤーはラウンドで最大4ポイントを獲得できます。3カード、ダイアモンド、またはプリミエラで可能な同点がある場合、誰もポイントを獲得しません。

各カードは2人のプレイヤーのうちの1人がキャプチャする必要があるため、1人のプレイヤーがどのカードを使用したかだけを知っていても、他のプレイヤーがどのカードを使用したかを推測できることに注意してください。primieraを正しくスコアリングするには、これを行う必要があります。

チャレンジルール

入力

コードは、Scopaのラウンド中に1人のプレイヤーがキャプチャしたカードを入力として使用する必要があります。

入力は文字列形式である必要があります。1文字は各カードのランクを表し、1文字はそのスーツを表します。これにより、原始スコアを直接入力として渡す潜在的な抜け穴がなくなります。カードランクの初級スコアへの変換は、プログラムで実行する必要があります。ただし、スペースまたはコンマで区切られた単一の文字列、文字列の配列、またはその他の形式を使用することもできます。たとえば、あなたは、エンコードとしてランクに選択した場合76A5432QJKとし、スーツDCHS、次のような入力を使用することができます['7D', '6H', 'QD', 'JS']または'7D,6H,QD,JS'

出力

プレーヤーのスコアを表す0〜4の整数。

勝ち

バイト単位の最短回答が勝ちます!

テストケース

["7D", "6D", "AD", "5D", "4D", "3D", "2D", "QD", "7C", "6C", "4C", "3C", "2C", "7H", "4H", "2H", "5S", "3S", "QS", "JS", "KS"]

スコア4:> 20枚のカードの1点、> 5足のダイヤモンド、ダイヤモンドの7 1点、そしてにおけるスコアリング78のための1点1点primiera(相手が7,6,5を有する7,7,7,5、 64のK)

["3D", "7C", "6C", "AC", "5C", "4C", "3C", "2C", "QC", "4H", "7S"]

スコア0:<= 20枚のカード、<= 5個のダイヤモンド、ダイヤモンドのない7、及び唯一のスコア69 primiera(相手が7,7,6、70のためにKを有する7,7,4,3)

[7D", "6D", "AD", "5D", "4D", "3D", "2D", "7C", "6C", "AC", "5C", "4C", "3C", "2C", "7H", "6H", "AH", "5H", "4H", "3H", "2H"]

スコア 3:20枚以上のカードで1ポイント、5枚以上のダイヤモンドで1ポイント、7枚のダイヤモンドで1ポイント。primieraは 63(7,7,7)であろうと相手は、51(7、Q、Q、Q)を得点することができるが、この手は、それがデフォルトでポイントを失うないスペードを持っていないからです。

["7D", "6D", "AD", "5D", "4D", "3D", "2D", "QD", "JD", "KD", "QC", "QH", "QS"]

スコア 3:20枚以下のカード、5個以上のダイヤモンドでは1ポイント、7個のダイヤモンドでは1ポイント。primieraのみスコア51(7、Q、Q、Q)と対戦相手は、63(7,7,7)を得点することができますが、相手の手は何のダイヤモンドを持っていないので、この手は勝利primieraのデフォルトでポイントを。

["7D", "6D", "AD", "5D", "4D", "3D", "2D", "QD", "JD", "KD", "7C", "7H"]

スコア 3:20枚以下のカード、5個以上のダイヤモンドでは1ポイント、7個のダイヤモンドでは1ポイント。この手は何のスペードを持っていないにもかかわらず、それはまだ勝ちprimieraを相手の手が何のダイヤモンドを持っていないので、(7,6,6対7,7,7)57から63のスコアで。

["7D", "6D", "AD", "5D", "4D", "3D", "2D", "QD", "JD", "KD", "QC", "QH"]

スコア2:20枚以下のカード、5個以上のダイヤモンドでは1ポイント、7個のダイヤモンドでは1ポイント。この手にはスペードがなく、相手の手にはダイヤモンドがありません。対戦相手は勝利primieraを 41から63のスコア(対7,7,7 7、Q、Q)。

[] (空の配列)

スコア0


1:少なくとも私たちの家族では、ジャックはスコパでクイーンを上回っていますが、これはスコアリングの目的には無関係です。

2:私は子供の頃からこのゲームをプレイしてきましたが、それが起こるのを見たことはありませんが、あなたのコードはそのケースを処理できる方が良いでしょう!

3:ラウンド中に得られた「スイープ」にはボーナスポイントがありますが、このチャレンジの目的のために無視しています。


1
各ランクは個別のキャラクターで表現する必要がありますか?
ドアノブ

@Doorknob必ずしもそうとは限りませんが、少なくとも私が取り組んでいるソリューションでは、すべてのテストケースを正しく行うために、各ランクに一意のキャラクターが必要であることがわかりました。
qdread

@Grimy良いキャッチ。おかげで
-qdread

回答:


6

ルビー、156 153バイト

->a{b='';([a[40],a.scan(/.d/)[5],a=~/;d/,'dchs'.gsub(/./){l=a.scan /.(?=#$&)/;l.size<10&&b+=(';865432'.tr(l*'','')+?0)[0];l.max}.sum>b.sum||p]-[p]).size}

オンラインでお試しください!

->a{
b='';                # stores primiera of other player
([                   # this array stores all checks
a[40],               # check if >20 cards (>40 characters)
a.scan(/.d/)[5],     # check if >5 diamonds
a=~/;d/,             # check if 7 of diamonds
'dchs'.gsub(/./){    # for each suit, build a string with...
l=a.scan /.(?=#$&)/; # find all cards with this suit
l.size<10&&          # if there are less than 10, the other person has some, so
b+=                  # append to their score string the following:
(';865432'           #   start with all the cards
.tr(l*'','')         #   remove the ones we have
+?0)                 #   add back the JQK at the end
[0];                 #   take the highest
l.max}               # return the highest card that we have
.sum                 # take the sum of the codepoints
>b.sum               # check if it's greater than the other player's sum
||p                  # if not, evaluate to nil
]-[p])               # remove all nils
.size}               # count how many are left

これは;865432000表すために使用します76A5432QJKそれぞれ、スーツは小文字です。(文字の選択は、それぞれから38を引くことでそれらのプリミエラ値が得られるためですが、相対的な差のみが重要であるため、実際にはそうしません。)

すべてのカードは38に実際の価値を加えたものとしてカウントされるため、誰かがスーツを紛失した場合、獲得できる最高スコアは(21 + 38)*です。 3 = 177、これは(10 + 38)* 3 + 21 + 38 = 203未満で、他のプレイヤーが獲得できる最低スコアです。プレイヤーは0、1、または2スーツしか失うことができないため、2人のプレイヤーが等しくないゼロ以外の数のスーツを失うことはできません。


4

R、320 298 265 238 229 224 211 209 179バイト

これは、主に関数の形式の@digEmAllによるソリューションです。

オンラインでお試しください!

function(h,S=sum,A=apply,l=99+c(11,8,5:2,6,!1:3)%o%!!1:4)S(S(p<-outer(c(7:2,'A','K','J','Q'),c('D','C','H','S'),paste0)%in%h)>20,S(p[1:10])>5,p[1],S(A(l*p,2,max)-A(l*!p,2,max))>0)

以下は、209バイトの私の昔からの最高の試みです。

編集:いくつかの関数をエイリアスし、スーツをチェックする代わりに定数をスコアに追加するというDoorknobのアイデアを取り入れることで、ゴルフを始めました。

次の編集:冗長性を取り除き、Giuseppeからのいくつかの改善を取り入れました

次の編集:digEmAllのおかげで-2バイト

私はこれがひどいので、誰かが時間をかけたいと思うなら、これを改善できると確信しています。私はそのように感じてsapplyおりfunction、非常に長く、それらを取り除くことができますが、どのように理解することはできません。入力は、標準表記の2文字の文字列です。

function(h,s=sum,l=c(11,8,5:2,6,!1:3)+99)s(length(h)>20,s(grepl('D',h))>5,'7D'%in%h,s(sapply(c('D','C','H','S'),function(i,r=c(7:2,'A','K','J','Q')%in%substr(h[grep(i,h)],1,1))s(l[r][1],-l[!r][1],na.rm=T)))>0)

1
Rゴルフチャットルームで助けを得ることができるかもしれません、digEmAllは仲間のイタリア人です!
ジュゼッペ

1
いくつかのアドバイスがありますが、セミコロンを改行(Rでは1バイトのように見えます)にスワップできる場合、それは答えをより読みやすくする無料のスワップです。また、オンラインのコードランナーである場合は、Try It Onlineをご覧ください。必須ではありませんが、繰り返しますが、使いやすいです。CGCC投稿を生成することもできます
ベスカ

1
253バイト -これがうまくいくかどうかは定かではありません。ほとんどの場合、通常のゴルフのセットを試していましたが、気軽にテストして知らせてください。
ジュゼッペ



2

JavaScript(ES6)、 171  163バイト

標準表現を使用して、入力を一連のカードとして受け取ります。

c=>(c.size>20)+((g=o=>[..."CHSD"].map(s=>[..."JQK2345A67"].map((v,i)=>(S=o^c.has(v+s))?m="111345679"[++n,i]||12:0,n=m=0)|(n?0:T=1,t-=m),T=t=4)|t*T)(1)>g``)+S+(n>5)

オンラインでお試しください!

コメント済み

c =>                                // c = set of cards
  (c.size > 20) + (                 // +1 point if we have more than 20 cards
    ( g = o =>                      // g is a function taking the flag o (for 'opponent')
      [..."CHSD"].map(s =>          // for each suit s, ending with diamonds:
        [..."JQK2345A67"]           //   for each rank v at position i, sorted from
        .map((v, i) =>              //   lowest to highest primiera score:
          (S = o ^ c.has(v + s)) ?  //     if the player owns this card, set S to 1 and:
            m = "111345679"[++n, i] //       increment n; update m to the score of this
                || 12               //       rank (we use the official score - 9)
          :                         //     else:
            0,                      //       do nothing
          n = m = 0                 //     start with n = m = 0
        ) |                         //   end of inner map()
        ( n ? 0 : T = 1,            //   if n = 0, set T to 1
          t -= m ),                 //   subtract m from t
        T = t = 4                   //   start with T = t = 4
      ) | t * T                     // end of outer map(); yield t * T
    )(1) > g``                      // +1 point if g(1) is greater than g(0)
  ) +                               // (we test this way because the scores are negative)
  S +                               // +1 point if we own the 7 of diamonds
  (n > 5)                           // +1 point if we own more than 5 diamonds

2

05AB1E、41バイト

39ÝsK‚εg9y@Oy0å•Dδ¿m(/d•₆вy.γT÷}è€àO)}`›O

オンラインそれを試してみたり、すべてのテストケースを確認してください

スーツDCHSはそれぞれによって表されます0123ます。ランク7A65432KJQはそれぞれによって表されます0123456789ます。これらは、チャレンジの必要に応じて、整数ではなく文字列として取得されます(ただし、05AB1Eは必要に応じて整数に変換します)。

他のソリューションと同様に、不足しているスーツのチェックを不要にするために、各プリミエラスコアに大きな定数(14)を追加します。

39Ý                      # range 0..39 (the list of all cards in the game)
   sK                    # remove all elements that appear in the input
      ‚                  # pair with the input: [player's hand, opponent's hand]

ε                     }  # map each hand to a list of its 4 subscores:
 g                       #  first subscore: length (number of cards)
 9y@O                    #  second subscore: count elements <= 9 (diamonds)
 y0å                     #  third subscore: is 0 (representing 7D) in the list
            y.γT÷}       #  group the hand by suit
 •Dδ¿m(/d•₆в      è      #  map each rank to its primiera score
                   ۈ    #  maximum primiera score in each suit
                     O   #  fourth subscore: the sum of those

`›                       # for each subscore: is player's > opponent's?
  O                      # sum
```

2

MS SQL Server 2017、525バイト

CREATE FUNCTION f(@ NVARCHAR(MAX))RETURNS TABLE RETURN
SELECT q/21+IIF(d>6,2,IIF(d=6,1,0))+IIF(m=0,IIF(n=0 AND a>b,1,0),IIF(n=0 OR a>b,1,0))p
FROM(SELECT SUM(q)q,MAX(IIF(s='D',q,0))d,SUM(a)a,MIN(q)m,SUM(b)b,MIN(10-q)n
FROM(SELECT s,COUNT(k)q,MAX(IIF(r=k,v,0))a,MAX(IIF(r=k,0,v))b
FROM(SELECT LEFT(value,1)r,s,ASCII(RIGHT(value,1))-38 v
FROM STRING_SPLIT('7;,68,A6,5,4,3,2,Q0,J0,K0',','),(VALUES('D'),('C'),('H'),('S'))s(s))d
LEFT JOIN(SELECT LEFT(value,1)k,RIGHT(value,1)u FROM STRING_SPLIT(@,','))a
ON r+s=k+u GROUP BY s)t)t

db <> fiddleで試してください。


1

Retina 0.8.2、334バイト

$
 ¶234567JQKA
r`.\G
$&C $&D $&H $&S 
+`((\w\w).*¶.*)\2 
$1
T`67AJQK`8960
%O$`(\w)(\w)
$2$1
m`^(?=(...)*)(.C )*(.D )*(.H )*(.S )*
$3;$#1 $#2 $#3 $#4 $#5;${2}${3}${4}$5
m`^(?=(9D))?...;
$#1;
(;(?!.*10).* 0.*;).*
$1
\d[C-S] 
1$&
19\w 
21$*@
\d+(\w )?
$*@
(@)?;(@*) @* (@*).*;(@*)¶@?;((?!\2))?@* @* ((?!\3))?.*;((?!\4))?.*
$#1$#5$#6$#7
1

オンラインでお試しください!リンクにはテストケースが含まれます。説明:

$
 ¶234567JQKA
r`.\G
$&C $&D $&H $&S 

40枚すべてのカードのリストを作成します。

+`((\w\w).*¶.*)\2 
$1

プレーヤーが保持しているカードを取り外します。

T`67AJQK`8960

各ランクをソート順で置き換えます。ソート順は、7他のカードの値よりも9 から10少ない値です。

%O$`(\w)(\w)
$2$1

スーツとランクでカードを並べ替えます。

m`^(?=(...)*)(.C )*(.D )*(.H )*(.S )*
$3;$#1 $#2 $#3 $#4 $#5;${2}${3}${4}$5

各スーツのカードの数を数え、各スーツの最高ランクのカードをキャプチャし、最高のダイヤモンドを2回キャプチャします。

m`^(?=(9D))?...;
$#1;

最高のダイヤモンドが7であったかどうかを確認します。

(;(?!.*10).* 0.*;).*
$1

スーツの1つにカードがない場合、最も高いカードをすべて削除します。

\d[C-S] 
1$&
19\w 
21$*@
\d+(\w )?
$*@

最も高いカードを単項スコアに変換し、それらを合計します。また、カードの総数とスーツの長さを単項に変換します。

(@)?;(@*) @* (@*).*;(@*)¶@?;((?!\2))?@* @* ((?!\3))?.*;((?!\4))?.*
$#1$#5$#6$#7

合計、ダイヤモンド、またはプリミエラが高い場合、ポイントを獲得します。

1

スコアを合計します。



1

AWK、235バイト

{s[9]=35;s[8]=32;s[7]=30;s[6]=29;s[5]=28;s[4]=27;s[3]=26;s[2]=s[1]=s[0]=24;a[$1 $2]=s[$1]}END{while(i++<4){D=0;for(j=0;j<10;j++){if(a[j i]<1){B[i]=s[j];D++}if(A[i]<a[j i])A[i]=a[j i]}x+=A[i];y+=B[i]}print(20<NR)+(D<5)+(1<a[9 4])+(y<x)}

オンラインでお試しください!

スーツは1234(4は菱形)にマップされ、値は0123456789にマップされます。このプログラムは、テストケースを受け入れ可能な形式に変換します。

BEGIN{RS=", ";FS="";t[7]=9;t[6]=8;t["A"]=7;t[5]=6;t[4]=5;t[3]=4;t[2]=3;t["Q"]=2;t["J"]=1;t["K"]=0;u["D"]=4;u["C"]=1;u["H"]=2;u["S"]=3}{gsub("[\\[\"\\]]","",$0);print t[$1],u[$2]}

私の目標は、Pythonの主要な実装を打ち負かすことだけでした:D


1

Pythonの3249の245 239 238バイト

@ovsのおかげで-4バイト

@movaticaのおかげで-6バイト

lambda C:sum([len(C)>20,'7D'in C,len([c for c in C if'E'>c[1]])>5,p(C)>p({n+s for n in'9876543210'for s in S}-C)])
p=lambda C:[not S.strip(''.join(C)),sum(max([(c[1]==s)*int('9gcdefil99'[int(c[0])],22)for c in C]+[0])for s in S)]
S='DcHS'

オンラインでお試しください!


1
図2は、少ないとバイトint('0734569c00'[int(x[0])],13)if x[1]<'E'のように書くことができるif'E'>x[1]
OVS

all(s in''.join(C)for s in S)に短縮できnot S.strip(''.join(C))、6バイト節約
-movatica
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.