Doppelkopfスコアの計算


9

前書き

Doppelkopfは、4人用の伝統的なドイツのカードゲームです。デッキは48枚のカード(すべてのカードがゲームに2度ある間、各スーツの9、10、ジャック、クイーン、キング、エース)で構成されているため、ラウンドの開始時に各プレイヤーは12枚を受け取ります。

クイーンズオブクラブの配分によって決定されるチームは常に2つあります。クイーンズを保持している2人のプレーヤーがチームを形成し、他の2人のプレーヤーと対戦します。クィーンズオブクラブのチームは「リ」チームと呼ばれ、ないチームは「コントラ」チームと呼ばれます。
ラウンドの開始時には、誰がどのチームにいるかは誰にもわかりません。チームの分布はラウンドの進行中に明らかになり、ゲームに多くの戦略が追加されます。

ゲームは12のトリックで構成されています。トリックを獲得したプレーヤーは、その中に4枚すべてのカードを取得します。すべてのカードには特定の値(たとえば、キングカウント4、エースカウント11)があり、すべてのカードを合計すると240ポイントになり、最高の結果になります。

ラウンドの終了時にポイントがカウントされ、ポイントが最も多いチームがラウンドに勝利します。その後、次のラウンドが始まります...

チャレンジ

各ラウンドには、勝利チームが獲得したポイントの量と潜在的なアナウンスによって決定される特定のスコアがあります。ポイントの分布と潜在的なアナウンス(以下の説明を参照)を入力として受け取り、ラウンドと勝者のスコアを出力するプログラムを作成する必要があります。

スコア計算

前述のように、再チームとコントラチームがあります。また、1ラウンドで最大240ポイントが可能です。Retraチームは121ポイントを獲得する必要がありますが、Contraチームは120ポイントしか必要としません。ゲームに勝つと思われる場合は、ラウンドの開始時に「Re」または「Contra」を発表する可能性もあります。 。これを行うことにより、あなたはスコアを上げています。

スコアリングルールは次のとおりです。

  • ゲームに勝つための+1
  • 負けたチームのポイントが90 未満の場合は+1 ( "Keine 90")
  • 負けたチームのポイントが60 未満の場合は+1 ( "Keine 60")
  • 負けたチームのポイントが30 未満の場合は+1 ( "Keine 30")
  • 負けたチームの得点が0の場合は+1( "Schwarz")
  • +2 Contraの発表
  • +2 Reの発表
  • コントラチームが勝利した場合は+1( "Gegen die Alten")

注:受賞者に関係なく、Re / Contra-Announcementsは常に適用されます。以下のテストケースの例を参照してください。

入出力

プログラムへの入力は、リチームのスコアと、リまたはコントラの潜在的なアナウンスになります。ゲームには常に240ポイントあるので、コントラチームのスコアを簡単に計算できます。

入力は、最初にリチームのスコアがあり、その後に潜在的なアナウンスが続く単一の文字列になりますが、「R」はRe、「C」はContraです。両方が発表された場合、Reは常に最初に来るでしょう。

出力は、勝利チームが後に続くゲームのスコアになります(コントラの場合は「C」、Reの場合は「R」)

ルール

  • 提出物は、完全なプログラムまたは関数にすることができます。後者を選択する場合は、それを呼び出す方法の例を含めてください。
  • 入力は、関数またはコマンドライン引数またはユーザー入力によって提供できます。
  • 出力は戻り値として提供するか、画面に出力できます。
  • 標準の抜け穴が適用されます。
  • 最小バイト数の勝利!

テストケース

Input -> Output (Explanation)

145R  -> 3R  (Re won, +1 for winning, +2 for Re-Announcement)
120   -> 2C  (Contra won, +1 for winning, +1 for winning as Contra)
80C   -> 5C  (Contra won, +1 for winning, +1 for no 90, +1 for winning as Contra, +2 for Contra-Announcement)
240R  -> 7R  (Re won, +1 for winning, +1 for no 90, +1 for no 60, +1 for no 30, +1 for no points for the losing team, +2 for Re-announcedment)
90    -> 2C  (Contra won, +1 for winning, +1 for winning as Contra)
110RC -> 6C  (Contra won, +1 for winning, +1 for winning as Contra, +2 for Re-Announcement, +2 for Contra-Announcement)
110R  -> 4C  (Contra won, +1 for winning, +1 for winnins as Contra, +2 for Re-Announcement)
184C  -> 5R  (Re won, +1 for winning, +1 for no 90, +1 for no 60, +2 for Contra-Announcement)

短いメモ:チャレンジをシンプルにするために、意図的にいくつかのルール(ソロやボーナスポイントなど)を省略しました。だからあなたがすでにゲームに精通しているなら、混乱しないでください:)

ハッピーコーディング!

回答:



4

ラビリンス136 103 94 92 87 84 76 74 69 61バイト

 (}?
;)
,)
`
2
0:
 {
_-+}}82"
}"     {{"(#0/#--!.@
 -=-)}67 )

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

ああ、Labyrinthを使ってから長すぎる。ゴルフをするのはいつもとても楽しいです。:)

説明

これは少し時代遅れです。プログラムの全体的な構造は同じですが、いくつかの詳細が変更されています。これは後で更新します。参考までに、これは以前のソリューションです。

 (}?
;)
,)
`
2
0 }82{_240{- ("
{ ;        #;`"~#0/#--!.@
:}-"-))}67{{
  ;#

スコアを少し分解してみましょう:

  • 入力で数字の後ろの文字を数える場合M、それをと呼びましょう。2M+1最終スコアには、勝利、Re、およびContraのポイントがあります。
  • スコアが120以下の場合、Contraが勝ち、スコアはずつ増加し1ます。
  • 負けたスコアを見て、それを(整数)30で割って追加のポイントを決定できます。ただし、3つの問題があります。1.値が間違った方向に増加するため、スコアから減算する必要があります(それを補正するには、3を加算します)。2.これにより、正確に120の結果が得られますが、これを取り除く必要があります。3. 0(負けた側)の結果はまだ処理していませんが、0を-1に変換することで含めることができます(ラビリンスの整数除算はに丸められるため-∞)。

これがコードの動作方法です。Sp3000は今日Labyrinthの優れた入門書を投稿したので、私はそれを盗むことにしました。:)

  • ラビリンスはスタックベースで2次元で、最初に認識された文字から実行が始まります。メインスタックと補助スタックの2つのスタックがありますが、ほとんどのオペレーターはメインスタックでのみ動作します。どちらのスタックも底なしで、ゼロで埋められています。
  • 迷路のすべての分岐で、スタックの最上部がチェックされ、次に進むべき場所が決定されます。マイナスは左折、ゼロは直進、プラスは右折です。
  • 数字はそれ自体をプッシュしません(Befunge、> <>、またはPreludeのように)-代わりに、数字の上部に10を掛けて加算することにより、スタックの上部に「自身を追加」します。

したがって(、最初の行のから実行が開始され、命令ポインター(IP)が右に移動します。(ちょうどにメインスタックの最上部を回す-1}、我々はそれについて忘れることができる補助スタック、それをオフにシフトします。プログラムは実際には?、STDINから整数を読み取るで始まります。その後、IPは行き止まりになり、向きを変えます。

}入力を補助スタックにシフトし、(別のゼロをに減らします-1。これが最終的なスコアになります。ここで、非常にタイトな時計回りのループに入ります。

;)
,)

))2インクリメントスコア(ので、我々はループを通過する最初の時間は、スコアがなり1、勝利のためのスコア)。次に,、文字を読み取ります。EOFでない限り、ループは継続します。;破棄キャラクター、それがあった場合、我々は気にしないためRか、Cそして))再び得点に2を追加します。これは、入力に応じて0、1、または2回繰り返されます。

ループを抜け、EOFに到達すると、スタックの最上位はになります-1。次に、この線形部分を実行します。

`20{:}-

`我々が得るので、単項否定され1、その後20に変換します120{:}補助スタックから入力整数のコピーを取得し、と-の差を計算し120ます。この結果のサインを使用して、誰が勝ったかを判断できます。

  1. 結果が負の場合、Reが勝ち、北側の経路をたどり、次のように実行します。

    ;}82{_240{-#;
    

    ;この結果を破棄し}、スコアをずらし、82それ自体(文字コードR)をメインスタックの一番下に置き{、スコアを上に戻し_240{-、整数入力を240から差し引いて、コントラ(負けた側)のポイントを処理できるようにします。

    これ#;は、両方のパスを確実に結合できるように、スタックにゼロ以外の値があることを確認するためのものです。

  2. 結果が肯定的である場合、コントラが勝利し、次のように実行して南部の道を進みます。

    ;#"-))}67{{#;
    

    #あるスタックの深さをプッシュ1。これは、で追加2する前にスコアから差し引かれ))ます。67自分自身(の文字コードC)をメインスタックの一番下に置きます。{{他の値を取得します。

  3. 結果がゼロの場合でも、コントラは勝ちました。ただし、これは120/120の場合であり、最終スコアにポイントを追加する必要があります(上記を参照)。そのため、このパスはで1をプッシュせず#、代わりにゼロをそのまま残して-、スタックから単にそのゼロを削除します。

これでスタックが結合され、30で除算する部分を除くすべてを考慮しました。ただし、最初にゼロスコアを-1に変換する必要があります。それがこの小さな回り道がすることです:

("
`"~

`ゼロには影響しない、"何もしませんし、~ビット単位の否定です。のビット単位のNOT 0-1必要に応じてです。スコアは代わりに陽性であった場合、`それは負になり、(ことによってそれをデクリメント1し、~両方の一回でこれらの操作を元に戻します。

#0/#--!.@

スタックの深さが3(勝った側のキャラクター、これまでの合計スコア、負けた側のポイント)になったので、を#押し3ます。0それを回す30/除算を行います。引き算される#別の3ものをプッシュし、その結果が最終スコアから引き算されます。!それを整数として.出力し、勝者側を文字として出力し@、プログラムを終了します。


3

JavaScript(ES6)、106

非ゴルフ言語で約100バイト。

x=>([,r,t]=x.match`(\\d+)(.*)`,t=1+t.length*2,w=r>120?(r=240-r,'R'):(++t,'C'),t+!r+(r<30)+(r<60)+(r<90)+w)

テスト

f=x=>(
  [,r,t]=x.match`(\\d+)(.*)`,
  t=1+t.length*2,
  w=r>120?(r=240-r,'R'):(++t,'C'),
  t+!r+(r<30)+(r<60)+(r<90)+w
)

console.log=x=>O.textContent+=x+'\n'

test=[
['145R', '3R'], //(Re won, +1 for winning, +2 for Re-Announcement)
['120',  '2C'], //(Contra won, +1 for winning, +1 for winning as Contra)
['80C',  '5C'], //(Contra won, +1 for winning, +1 for no 90, +1 for winning as Contra, +2 for Contra-Announcement)
['240R', '7R'], //(Re won, +1 for winning, +1 for no 90, +1 for no 60, +1 for no 30, +1 for no points for the losing team, +2 for Re-announcedment)
['90',   '2C'], //(Contra won, +1 for winning, +1 for winning as Contra)
['110RC','6C'], //(Contra won, +1 for winning, +1 for winning as Contra, +2 for Re-Announcement, +2 for Contra-Announcement)
['110R', '4C'], //(Contra won, +1 for winning, +1 for winnins as Contra, +2 for Re-Announcement)
['184C', '5R'], //(Re won, +1 for winning, +1 for no 90, +1 for no 60, +2 for Contra-Announcement)
]
  
test.forEach(t=>{
  var i=t[0],k=t[1],r=f(i)
console.log((k==r?'OK ':'KO ')+i+' -> '+r+(k!=r?' (expected: '+k+')':''))
})
<pre id=O></pre>


CJamの答えだけの約2倍のバイトカウント...悪くない^^
Denker

2

ES6、92バイト

s=>(p=s.match(/\d+|./g),n=+p[0],r=n>120,p.length*2-r+!(n%120)+3-((r?240-n:n)/30|0)+"CR"[+r])

p.length*2Reが勝った場合、スコアを1だけ過大評価するため、rもう一度減算する必要があります。!(n%120)+3-((r?240-n:n)/30|0)「Keine」のスコアリングのルールをカプセル化するために私が思いついたものです。境界が31、61、91であったとしたら、それが公式になったと思い4-((r?269-n:29+n)/30|0)ます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.