没什么比ModTen的好游戏


27

免责声明:ModTen是一款虚构的纸牌游戏,其创建完全是为了应对这一挑战。

ModTen的规则

ModTen使用标准的52张卡片组播放。由于尚未制定全部规则,因此我们将仅专注于手排名。

杰克&三,适合

ModTen中的胜者。维基百科上的图形。

卡值

卡具有以下值:

  • 29:值得他们的面值
  • :0分
  • 杰克:3分
  • 皇后国王:8分
  • 王牌:9分

手值

  • 一个ModTen手由两张卡组成。通过将两张纸牌的值相乘并仅保留最后一位(即应用模数10)来获得手的基值。

    6(7×8)mod10=6

  • ModTen中的唯一其他规则是,适合的卡片比不适合的卡片价值更高。按照惯例,如果两张卡牌都相同,我们将在值后附加一个“ s”

    例如,9-5 the的值将被记为“ ”,因为且卡适合。5s(9×5)mod10=5

手排名和获胜者

上述规则导致18个不同的手牌等级,下表从最强到最低(或从稀有到最常见)进行了总结。给出的概率仅供参考。

给定两只手,则排名最低的手获胜。如果两只手的排名相同,那就是平局(没有平局)。

 hand rank | hand value(s) | deal probability
-----------+---------------+------------------
     1     | 9s            | 0.30%
     2     | 3s            | 0.60%
     3     | 1s            | 0.90%
     4     | 7s            | 1.21%
     5     | 5s            | 1.51%
     6     | 3             | 1.81%
     7     | 9             | 2.26%
     8     | 8s            | 2.71%
     9     | 6s            | 3.02%
    10     | 1 or 7        | 3.62% each
    11     | 2s or 4s      | 3.92% each
    12     | 5             | 4.98%
    13     | 0s            | 5.43%
    14     | 8             | 8.14%
    15     | 6             | 9.95%
    16     | 2             | 11.76%
    17     | 4             | 13.57%
    18     | 0             | 16.74%

挑战

给定两只ModTen指针,输出您选择的三个一致值之一来判断是否:

  • 第一位玩家获胜
  • 第二名玩家获胜
  • 这是一个平局

适用以下规则:

  • A卡必须由它以大写字母等级来描述(23,..., ,9T,,J 或),其次是其小写套装(,,或为梅花,方块,红心和黑桃)。QKAcdhs
  • 您可以使用"10"代替,"T"但禁止任何其他替代。
  • 只要遵守上述规则,您就可以采取任何合理且明确的格式。允许您将等级和西装视为两个不同的字符,而不是一个字符串。

    一些有效的输入格式是:

    • "7c Qh 8s Ks"
    • [["7c","Qh"], ["8s","Ks"]]
    • [[['7','c'], ['Q','h']], [['8','s'], ['K','s']]]
    • 等等
  • 除了使用3个一致的不同值之外,您的输出也可以为。请指定答案中使用的输出格式。

  • 这是

测试用例

玩家1获胜

["Js","3s"], ["Ks","Kh"]
["7h","9h"], ["9s","7c"]
["Ah","5s"], ["Ts","8s"]
["Ts","8s"], ["Jh","2s"]
["4h","8s"], ["Qh","Ks"]

玩家2获胜

["Th","8d"], ["6s","Kd"]
["Jc","5c"], ["3s","9s"]
["Jc","Jd"], ["9h","Ah"]
["2d","4d"], ["3h","3s"]
["5c","4c"], ["3c","2c"]

["Js","3s"], ["3d","Jd"]
["Ah","Ac"], ["3d","9s"]
["Qc","Kc"], ["6d","4d"]
["2d","3d"], ["3s","2s"]
["Ts","9c"], ["4h","5d"]

如何将枚举作为输入?Haskell有一个非常强大的类型系统 ; 我相当确定可以在其中直接制作类似的内容。
wizzwizz4

这不是Haskell,但{{J, s}, {3, s}}可以吗?
wizzwizz4

1
@ wizzwizz4是的,很好。
Arnauld

2
使用“具有匹配的套装的牌手”而不是“套装的牌”可能会更清楚。
chrylis-罢工-

Answers:


13

Python 3中114个 110字节

lambda m,n:p(*n)-p(*m)
R=b"T 2J45UNK9RL<3SLM;QAK:O>=/678"
v=R.find
p=lambda i,s,j,t:R[s==t::2][v(j)*v(i)%10+3]

在线尝试!

@Arnauld提出了合并卡值和等级表字符串的想法。经过一些尝试,我设法制作了一个合并的字符串R="T 2J45UNK9RL<3SLM;QAK:O>=/678",该字符串的长度与原始卡值字符串的长度相同。该字符串R[6:25]="UNK9RL<3SLM;QAK:O>=/"作为排名表,以及一个卡值的查找表39AK,和Q。新排名表的ASCII值解码具有与先前排名表相同的排名效果。

使用字节字符串作为输入可节省4个字节。

cmp@ xnor's solution所示,在Python 2中使用可以将解决方案减少到102个字节。


Python 3中165个 142 130 129字节

lambda m,n:p(*n)-p(*m)
v="T 23456789   J    QA        K".find
p=lambda i,s,j,t:ord("HC92FA51GAB4E893D760"[s==t::2][v(j)*v(i)%10])

在线尝试!

-23个字节,感谢@Jonathan Allan

-2个字节,感谢@ovs

-1个字节感谢@mypetlion

取消高尔夫:

f = lambda hand1, hand2: get_rank(*hand2) - get_rank(*hand1)
def get_rank(v1, suit1, v2, suit2):
    get_card_value = "T 23456789   J    QA        K".find
    # rank_table = [[17,9,15,5,16,11,14,9,13,6],[12,2,10,1,10,4,8,3,7,0]]
    # rank_table = ("H9F5GBE9D6","C2A1A48370") # Base-18 encoding of ranks
    rank_table = "HC92FA51GAB4E893D760" # Interleaved base-18 encoding

    # ASCII-value decoding has the same ranking effect as base-18 decoding
    return ord(rank_table[suit1 == suit2::2][get_card_value(v2) * get_card_value(v1) % 10])

该函数f采用代表玩家1和玩家2的手的两个参数。在玩家1获胜,玩家2获胜或平局的情况下,该函数返回正值,负值或零值。每只手都编码为单个字符串,例如“ 7cQh”。


3
嗨,乔尔,欢迎您来到CGCC!将手排名数组一分为二的非常聪明的主意!让他们来吧!
640KB

1
@乔纳森·艾伦谢谢。我已经使用略有不同的方法来整合您的想法。
乔尔

1
您可以通过将排名表存储在单个字符串中来节省2个字节:"HC92FA51GAB4E893D760"[s==t::2]
ovs,

1
而另4个字节的短,如果你愿意转换到Python 2(cmp在Python 3不可用)
OVS

1
您可以使用str.find而不是str.index保存一个字节。这两种方法之间的唯一行为不同的是,index当找不到的元素抛出一个错误,而find回报-1。因此,这不会对您的代码造成影响。
mypetlion

11

x86-16组装, 87 83个字节

二进制:

00000000: e807 0050 e803 005a 3ac2 ad2c 3092 ad2c  ...P...Z:..,0..,
00000010: 30bb 3501 3af4 7503 bb3f 01e8 0a00 92e8  0.5.:.u..?......
00000020: 0600 f6e2 d40a d7c3 b106 bf49 01f2 aee3  ...........I....
00000030: 038a 4504 c312 0a10 0611 0c0f 0a0e 070d  ..E.............
00000040: 030b 020b 0509 0408 0124 1a21 1b11 0003  .........$.!....
00000050: 0808 09                                  ...

未组装:

E8 010A         CALL GET_HAND           ; score first hand, ranked score into AL 
50              PUSH AX                 ; save score
E8 010A         CALL GET_HAND           ; score second hand 
5A              POP  DX                 ; restore first hand into DL 
3A C2           CMP  AL, DL             ; compare scores - result in CF, OF and ZF

            GET_HAND PROC               ; 4 char string to ranked score ("9s7c" -> 6)
AD              LODSW                   ; load first card string 
2C 30           SUB  AL, '0'            ; ASCII convert 
92              XCHG DX, AX             ; store in DX 
AD              LODSW                   ; load second card string 
2C 30           SUB  AL, '0'            ; ASCII convert 
BB 0139         MOV  BX, OFFSET R       ; first, point to non-suited table 
3A F4           CMP  DH, AH             ; is it suited?
75 03           JNZ  NO_SUIT 
BB 0143         MOV  BX, OFFSET RS      ; point to suited table 
            NO_SUIT: 
E8 012C         CALL GET_VALUE          ; get face card value in AL 
92              XCHG DX, AX             ; swap first and second cards 
E8 012C         CALL GET_VALUE          ; get face card value in AL 
F6 E2           MUL  DL                 ; multiply values of two cards 
D4 A0           AAM                     ; AL = AL mod 10
D7              XLAT                    ; lookup value in rank score table 
C3              RET 
            GET_HAND ENDP

            GET_VALUE PROC              ; get value of a card (2 -> 2, J -> 3, A -> 9)
B1 06           MOV  CL, 6              ; loop counter for scan
BF 014D         MOV  DI, OFFSET V       ; load lookup table 
F2/ AE          REPNZ SCASB             ; scan until match is found 
E3 03           JCXZ NOT_FOUND          ; if not found, keep original numeric value
8A 45 04        MOV  AL, BYTE PTR[DI+4] ; if found, get corresponding value 
            NOT_FOUND:
C3              RET                     ; return to program 
            GET_VALUE ENDP

R   DB 18, 10, 16, 6, 17, 12, 15, 10, 14, 7     ; unsuited score table
RS  DB 13, 3, 11, 2, 11, 5, 9, 4, 8, 1          ; suited score table
V   DB 'J'-'0','Q'-'0','K'-'0','A'-'0','T'-'0'  ; face card score table
    DB 3, 8, 8, 9, 0

输入是一个字符串,例如Js3sKsKhin中的指针SI。输出是ZF = 0 and SF = OF(与测试JG如果播放器1胜), SF ≠ OF(与测试JL如果播放器2胜)或ZF(与测试JE如果平局)。

使用DOS测试程序输出:

在此处输入图片说明

下载并测试DOS的MODTEN.COM


7

05AB1E41 37 字节

•V›{₆Ÿ&∊WÍj¸•19вyεø`Ës‘ߌQ‘ŽćS‡Pθ«}èÆ

-4个字节感谢@Grimy

输入为字符列表列表,类似于挑战说明中的第三个示例输入格式。即P1 7c Qh和P2 8s Ks将输入为[[["7","c"],["Q","h"]],[["8","s"],["K","s"]]]。(并"10"用于10。)

如果玩家1获胜,则输出负整数;否则,输出负数。如果玩家2获胜,则为正整数;或0(如果是平局)。

在线尝试验证所有测试用例

说明:

V›{₆Ÿ&∊WÍj¸•  # Push compressed integer 36742512464916394906012008
 19в           # Convert it to base-19 as list:
               #   [18,10,16,6,17,12,15,10,14,7,13,3,11,2,11,5,9,4,8,1]
Iε             # Push the input, and map each of its hands to:
  ø            #  Zip/transpose the hand; swapping rows/columns
               #   i.e. [["8","s"],["K","s"]] → [[["8","K"],["s","s"]]
   `           #  Push them separated to the stack
    Ë          #  Check if the two suits in the top list are equal (1/0 for truthy/falsey)
    s          #  Swap to get the list with the two values
     ‘ߌQ     #  Push dictionary string "JAKEQ"
     ŽćS       #  Push compressed integer 39808
              #  Transliterate these characters to these digits
      P        #  Now take the product of the two values in the list
       θ       #  Only leave the last digit (basically modulo-10)
    «          #  And merge it to the 1/0
               #  (now we have the hand values of both players,
               #   where instead of a trailing "s" we have a leading 1)
             # After the map: index each value into the earlier created integer-list
               # (now we have the hand rank of both players)
   Æ           # And then reduce the resulting integers by subtracting
               # (after which the result is output implicitly)

请参阅我的05AB1E技巧(如何使用字典? 如何压缩大整数?如何压缩整数列表?以了解为什么•V›{₆Ÿ&∊WÍj¸•is 36742512464916394906012008•V›{₆Ÿ&∊WÍj¸•19вis [18,10,16,6,17,12,15,10,14,7,13,3,11,2,11,5,9,4,8,1]‘ߌQ‘is "JAKEQ"ŽćSis 39808


该问题明确允许输入T10,因此您可以删除Tfrom JTQKA(并使用压缩整数3889而不是30889)。另外,T* ... +可能是... «
Grimmy

1
@Grimy啊,我的确知道10而不是T被允许,但是没有想到!而幸福,现在我看到它是明显的。>>谢谢!10nmod10=0T*...+...«
凯文·克鲁伊森

1
37(现在可以正常工作!)
Grimmy

@Grimy啊,很好地使用字典!
凯文·克鲁伊森

3

PHP212 185 178 149字节

while($p=$argv[++$x])$$x=ord(rjpfqlojngmckbkeidha[(($v=[J=>3,Q=>8,K=>8,A=>9])[$p[0]]?:$p[0])*($v[$p[2]]?:$p[2])%10+($p[1]==$p[3])*10]);echo${1}-${2};

在线尝试!

  • -7个字节感谢@ Night2!
  • -29字节,通过ASCII编码表而不是数组

通过命令行输入。如果玩家1获胜,则输出STDOUT;如果玩家2获胜,则输出为正;如果并列,0则输出为。例:

$ php modten.php Js3s KsKh
-1

1
@夜间2我想,如果我是愿意给我们的飞船运营商(我的意思是,你怎么经常做用呢?),我可以-2个字节,就回到正,负或零,而不是-110
640KB

我很惊讶(以一种很好的方式)在先前的答案中看到了太空飞船的操作员。
夜间2

2

果冻,46个字节

“T0J3Q8K8A9”yⱮZV€P$Eƭ€)%⁵UḌị“©N¿!Æßvṅ?żṀ’b18¤I

在线尝试!

以完整程序为例["7h","Ks"],["4s","Ts"],如果两个玩家都抽奖,则打印零;如果玩家1获胜,则打印正;如果玩家2获胜,则打印负。


2

C(GCC) 172个 167 165 164字节

p(l,v)char*l,*v;{v="T 23456789   J    QA        K";return"A<92?:51@:;4>893=760"[(l[1]==l[3])+(index(v,l[2])-v)*(index(v,*l)-v)%10*2];}f(char*s){return p(s+5)-p(s);}

在线尝试!

@ceilingcat减少了2个字节!

基本上是@Joel的Python3解决方案的端口,但没有base18编码。期望输入为一个字符串,并用空格分隔两个玩家的手,并输出一个正数,负数或零的整数,以表示玩家1获胜,玩家2获胜或平局。


2

Perl 6的101个 100 94 88字节

-1字节感谢Jo King

{[-] .map:{'HC92FA51GAB4E893D76'.ords[[*](.[*;0]>>.&{TR/JQKA/3889/})%10*2+[eq] .[*;1]]}}

在线尝试!

需要输入作为f(((<J ♠>, <3 ♠>), (<10 ♠>, <K ♥>)))使用10的十。如果玩家1获胜,则返回值<0;如果玩家2获胜,则返回值0;如果是平局,则返回0。

说明

{
  [-]  # subtract values
  .map:{  # map both hands
    'HC92FA51GAB4E893D76'.ords[  # lookup rank in code point array
      [*](  # multiply
        .[*;0]  # card ranks
        >>.&{TR/JQKA/3889/}  # translate J,Q,K,A to 3,8,8,9
      )
      %10*2  # mod 10 times 2
      +[eq] .[*;1]  # plus 1 if suited
    ]
  }
}

1

木炭,97字节

≔”)¶&sNψU↓”ζF¹³F¹³F⁻⁴⁼ικ⊞υ⁺÷λ³⊗﹪Π⁺§ζι§ζκχ≔”A↘τ[⁵PkxτG”ε≔⁰δF⟦θη⟧≦⁻№υ⁺⁼§ι¹§ι³⊗﹪Π⁺§ζ⌕ε§ι⁰§ζ⌕ε§ι²χδIδ

在线尝试!链接是详细版本的代码。将输入作为两个4个字符的字符串,例如,QcKc 6d4d并输出一个有符号整数。说明:

≔”)¶&sNψU↓”ζ

压缩的字符串2345678903889代表卡的值。

F¹³F¹³

遍历每个可能的值对。

F⁻⁴⁼ικ

遍历每个可能的第二张西服。在不失一般性的前提下,我们可以假设第一张卡片的花色为3,因此第二张卡片花色的取值范围为0到3,除非值相同,在这种情况下,它的取值范围只能为0到2。

⊞υ⁺÷λ³⊗﹪Π⁺§ζι§ζκχ

计算手牌的修改分数,即手牌价值的两倍,如果花色相同,则加1(即,第二张牌的花色为3)。

≔”A↘τ[⁵PkxτG”ε

压缩字符串23456789TJQKA表示卡字符。在此字符串中查找输入卡,然后使用该位置索引第一个字符串以获取卡的值。

≔⁰δ

将结果初始化为0。

F⟦θη⟧

循环两只手。

≦⁻№υ⁺⁼§ι¹§ι³⊗﹪Π⁺§ζ⌕ε§ι⁰§ζ⌕ε§ι²χδ

计算手的修改分数,从而计算出手的频率,并从中减去结果。

Iδ

输出频率差。



0

Perl -p 5,107个字节

$a=A;y/ATJQK/90388/;${$a++}=substr"IAG6HCFAE7D3B2B59481",($1eq$3).$&*$2%10,1while/.(.) (.)(.)/g;$_=$A cmp$B

在线尝试!

输入:

As 4d,Th 8c

(实际上,逗号可以是任何字符。)

输出:

-1  Player one wins
 0  Draw
 1  Player two wins
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.