选择手中的最后一张卡


31

扑克牌从好到坏排名如下:

  1. 同花顺-顺序排名的五张牌,都相同
  2. 四种-相同等级的四张牌和另一等级的另一张牌
  3. 满屋子-一等三张,另一等两张
  4. 同花顺-五张相同的牌
  5. 顺子-五张连胜
  6. 三种-相同等级的三张牌和另外两个等级的两张牌
  7. 两对-两张同等级的牌,两张另一等级的牌和一张第三等级的牌
  8. 一对-两张相同级别的牌和三张其他三个级别的牌
  9. 高位卡-五张并非顺序相同或完全相同的卡,且均不属于同一等级

  • 等级=卡上的数字(A,K,Q,J,10、9、8、7、6、5、4、3、2)。您可以选择使用T而不是10。
  • 套装=心(h),黑桃(s),球棒(c)和钻石(d)。

请注意,Ace A既可以是最高编号,也可以是最低编号(1或14)。

可以通过两个字母As(黑桃A),Jc(杰克俱乐部),7h(红心7 )来识别卡。


挑战:

您从发牌人那里得到四张牌(四个输入字符串)。查找并输出您可能获得的最好的最后一张卡。

如果有同样不错的卡片,那么您可以选择要挑选的卡片。

输入和输出格式是可选的,但必须如上所述Jc和标识单个卡2h


测试用例:

Ah Kh Jh 10h
Qh

7d 8h 10c Jd
9d (or 9h, 9c, 9s)

Js 6c 10s 8h
Jc (or Jh, Jd)

Ac 4c 5d 3d
2h (or 2d, 2c, 2s)

5s 9s Js As
Ks

2h 3h 4h 5h
6h

Js Jc Ac Ah
As (or Ad)  <- Note that AAAJJ is better than AAJJJ because A is higher than J

10d 9d 5h 9c
9h (or 9s)

Ah Ac Ad As
Ks (or Kd, Kh, Kc)

4d 5h 8c Jd
Jc (or Js, Jh)

这是代码高尔夫,因此以字节为单位的最短提交获胜。

Answers:


13

Pyth,73个字节

eo_S+*-5l@\AN}SPMJ+NZSM.:+\AT5+-4l{eMJlM.gPkJ-sM*=T+`M}2Tc4"JQKA""hscd"=Zc

这太可怕了。解析卡,对值进行排序,...一切都需要这么多字符。但是这种方法很有趣。

在线尝试:演示测试套件

说明:

我生成所有52张卡,删除输入的四张卡,为每张卡(手的分数)生成一个分数,然后以最大分数打印该卡。

分数有点奇怪。如果我比较两只完全不同的牌的得分,可能会选错获胜者。例如,平局将击败4个A。但是,如果前四张牌的双手相同,则可以使用。我计算出的分数实际上不是一个值,而是一个值列表:

  • G:首先,我将5张牌按等级分组并取长度: 5h 5d 6c 5s Jd -> [3, 1, 1]
  • F:然后我在列表中加上4减去不同套件的数量。Flush -> 3被附加,not flush -> 2/1/0被附加。
  • S:添加另一个号码。0如果不是直线,4则为A2345,或者5为较高的直线。

这些4-7个数字的列表以降序排序,并选择具有最大值的列表。

为什么这样做?在这里,您会看到所有类型的可能配置。数字旁边的字母告诉您该数字是根据哪个规则生成的。

  • 直冲洗:[5S, 3F, 1G, 1G, 1G, 1G, 1G][4S, 3F, 1G, 1G, 1G, 1G, 1G]
  • 同一样四个: [4G, 1G, 0F, 0S]
  • 满屋子:[3G, 2G, 1F, 0S][3G, 2G, 0F, 0S]
  • 冲洗: [3F, 1G, 1G, 1G, 1G, 1G, 0S]
  • 顺子:[5S, 2F, 1G, 1G, 1G, 1G, 1G][5S, 1F, 1G, 1G, 1G, 1G, 1G][5S, 1G, 1G, 1G, 1G, 1G, 0F][4S, 2F, 1G, 1G, 1G, 1G, 1G][4S, 1F, 1G, 1G, 1G, 1G, 1G][4S, 1G, 1G, 1G, 1G, 1G, 0F]
  • 一种三:[3G, 1G, 1G, 1F, 0S][3G, 1G, 1G, 0F, 0S]
  • 两对:[2G, 2G, 2F, 1G, 0S][2G, 2G, 1F, 1G, 0S][2G, 2G, 1G, 0F, 0S]
  • 一对:[2G, 2F, 1G, 1G, 1G, 0S][2G, 1G, 1G, 1G, 1F, 0S][2G, 1G, 1G, 1G, 0F, 0S]
  • 高牌:[2F, 1G, 1G, 1G, 1G, 1G, 0S][1F, 1G, 1G, 1G, 1G, 1G, 0S][1G, 1G, 1G, 1G, 1G, 0S, 0F]

Pyth按元素比较列表。因此很明显,同花顺将总是击败同类的四。这些列表中大多数典型的扑克规则都很明显。有些似乎是矛盾的。

  • 直行者将赢得四人或满屋子:这不是问题。如果您有机会获得带有河牌的四张/满屋子,那么您将无法同时到达一个顺子(因为您手中已经有2或3个不同的套房)。
  • 直路将赢得同花顺。如果您可以用河牌获得同花和顺子,那么您也可以得到同花。而且同花顺比同花顺和同花都有更好的分数。
  • 一对[2G, 2F, 1G, 1G, 1G, 0S]将赢得大约两对牌。也没问题。如果您用河牌得到两对,那么河牌前至少要有一对。但这意味着,您可以将其中的三个改进为更好。因此,两对实际上将永远不是答案。
  • 高牌[2F, 1G, 1G, 1G, 1G, 1G, 0S]将赢得一对对手。如果这是您能达到的最高成绩,那么在河牌之前,您将获得3张一套房的卡和另一张套房的卡。但是随后您可以选择带有这两个套件之一并且已经出现的值的卡,最后得到score [2F, 2G, ...],这也更好。

因此,这选择了正确的解决方案类型。但是如何获得最佳一对(从4种可能性中选出),如何选择最佳对子,...?因为两个不同的一对解决方案可以具有相同的分数。

这很简单。Pyth保证稳定的排序(当取最大值时)。所以我简单地按顺序生成卡片2h 2s 2c 2d 3h 3s ... Ad。因此,具有最高值的卡将自动成为最大值。

实施细节

=Zc分割输入字符串并将卡片列表存储在中Z=T+`M}2Tc4"JQKA"生成等级列表['2', ..., '10', 'J', 'Q', 'K', 'A']并将其存储在中T-sM*T..."hscd"Z随套件生成等级的每个组合,并删除的卡片Z

o...通过以下方式lM.gPkJ对剩余的牌进行排序:等级组的长度,+-4l{eMJlM附加4-长度(套装),+*-5l@\AN}SPMJ+NZSM.:+\AT5附加0/4/5(取决于套件)(生成长度为5的每个“ A” + T的子字符串,请检查手形其中之一(需要对手进行排序并对所有子集进行排序),再乘以5-卡中“ A”的数量),_S对递减的列表进行排序。

e 选择最大值并打印。


2
非常有创造力,而且很好的解释!
格雷格·马丁

4

JavaScript(ES6),329 324 317 312 309字节

H=>[..."cdhs"].map(Y=>[...L="AKQJT98765432"].map(X=>~H.indexOf(X+=Y)||([...H,X].map(([R,S])=>a|=eval(S+'|=1<<L.search(R)',F|=S!=H[0][1]),F=a=c=d=h=s=0),x=c|d,y=h|s,c&=d,h&=s,p=c|x&y|h,t=c&y|h&x,(S=a-7681?((j=a/31)&-j)-j?F?c&h?2e4+a:t?t^p?3e4+t:7e4:p?8e4+p:M:4e4+a:F?5e4+a:a:F?6e4:1e4)<M&&(R=X,M=S))),M=1/0)&&R

怎么运行的

对于卡片组中其余的每张纸牌,我们计算出手分数S。分数越低,手感越好。

用于计算分数的变量

  • F:如果手齐平则为假
  • c:俱乐部的位掩码
  • d:钻石的位掩码
  • h:Hearts的位掩码
  • s:黑桃的位掩码
  • x = c | d:俱乐部或钻石的位掩码
  • y = h | s:Hearts or Spades的位掩码
  • a:所有组合套装的位掩码
  • p = c & d | x & y | h & s:对位掩码(1)
  • t = c & d & y | h & s & x:三种位掩码(1)

(1) 几年前,我写了这些公式,并在几个扑克引擎中使用了它们。他们工作。:-)

其他公式

  • c & d & h & s:四种位掩码
  • a == 7681:测试特殊直线“ A,2、3、4、5”(0b1111000000001)
  • ((j = a / 31) & -j) == j:测试其他所有平直

得分表

Value    | Hand
---------+--------------------------------------------
0   + a  | Standard Straight Flush
1e4      | Special Straight Flush "A, 2, 3, 4, 5"
2e4 + a  | Four of a Kind
3e4 + t  | Full House
4e4 + a  | Flush
5e4 + a  | Standard Straight
6e4      | Special Straight "A, 2, 3, 4, 5"
7e4      | Three of a Kind
8e4 + p  | Pair
Max.     | Everything else

注意:我们不必担心两对不可能成为我们的最佳选择。(如果我们已经有一对,我们可以将其变成一种三。如果已经有两对,我们可以将它们变成一个满屋。)

测试用例


3

JavaScript(ES6),307349

这非常笨重,我不确定这是最好的方法。也许还有一点可打高尔夫球。

h=>(r='_23456789TJQKAT',R=x=>r.search(x[0]),M=i=>[...'hcds'].some(s=>h.indexOf(j=h[i][0]+s)<0)&&j,[u,v,w,y]=h.sort((a,b)=>R(a)-R(b)).map(x=>R(x)),[,,d,e,f,g,k]=[...new Set(h+h)].sort(),q=10-u-v-w,s=(z=y>12)&q>0?q:y-u<5&&u*5+q-y,d>r?z?'Kh':'Ah':f>r?M((e>r?v<w:u<v)+1):s?r[s]+g:k?M(3):r[13-z-(w>11)-(v>10)]+g)

少打高尔夫球

h=>(
  // card rank, 1 to 13, 0 unused
  // fake rank 14 is T, to complete a straight JQKA?
  // as I always try to complete a straight going up
  r = '_23456789TJQKAT', 

  // R: rank a card
  R = x => r.search(x[0]),  

  // M: find a missing card (to complete a same-rank set like a poker)
  // look for a card with the same rank of the card at position i
  // but with a suit not present in the hand
  M = i => [...'hcds'].some(s => h.indexOf(j=h[i][0]+s) < 0) && j,
  h.sort((a, b) => R(a)-R(b) ), // sort hand by rank
  [u,v,w,y] = h.map(x=>R(x)),   // rank of cards 0..3 in u,v,w,y

  // Purpose: look for duplicate rank and/or duplicate suits
  // Put values and suits in d,e,f,g,k, with no duplicates and sorted
  // suits are lowercase and will be at right end
  [,,d,e,f,g,k] = [...new Set(h+h)].sort(),

  // Only if all ranks are different: find the missing value to get a straight
  // or 0 if a straight cannot be obtained
  // The first part manages the A before a 2
  q = 10-u-v-w, s = y>12&q>0 ? q : y - u < 5 && u * 5 + q - y,

  d > r // d is lowercase -> all cards have the same rank
    ? u < 13 ? 'Ah' : 'Kh' // add a K to a poker of A, else add an A
    : e > r // e is lowercase -> 2 distinct ranks
      ? M(v<w ? 2 : 1) // go for a poker or a full house
      : f > r // f is lowercase -> 3 distinct ranks, we have a pair
        ? M(u<v ? 2 : 1) // find the pair and go for 3 of a kind
        : s // all different ranks, could it become a straight?
          ? r[s] + g // if there is only a suit, it will be a flush straight too
          : k // if there are 2 or more different suits
            ? M(3) // go for a pair with the max rank
            : r[13-(y>12)-(w>11)-(v>10)]+g // flush, find the max missing card
)

测试

F=
h=>(r='_23456789TJQKAT',R=x=>r.search(x[0]),M=i=>[...'hcds'].some(s=>h.indexOf(j=h[i][0]+s)<0)&&j,[u,v,w,y]=h.sort((a,b)=>R(a)-R(b)).map(x=>R(x)),[,,d,e,f,g,k]=[...new Set(h+h)].sort(),q=10-u-v-w,s=(z=y>12)&q>0?q:y-u<5&&u*5+q-y,d>r?z?'Kh':'Ah':f>r?M((e>r?v<w:u<v)+1):s?r[s]+g:k?M(3):r[13-z-(w>11)-(v>10)]+g)

output=x=>O.textContent+=x+'\n'

;`Ah Kh Jh Th -> Qh
7d 8h Tc Jd -> 9d 9h 9c 9s
Js 6c Ts 8h -> Jc Jh Jd
Ac 4c 5d 3d -> 2h 2d 2c 2s
5s 9s Js As -> Ks
2h 3h 4h 5h -> 6h
Js Jc Ac Ah -> As Ad
Td 9d 5h 9c -> 9h 9s
Ah Ac Ad As -> Ks Kd Kh Kc
4d 5h 8c Jd -> Jc Js Jh`
.split('\n')
.forEach(s=>{
  var o = s.match(/\w+/g) // input and output
  var h = o.splice(0,4) // input in h, output in o
  var hs = h+''
  var r = F(h)
  var ok = o.some(x => x==r)
  
  output((ok?'OK ':'KO ')+ hs + ' -> ' + r)
})
<pre id=O></pre>


有趣的是,我们的两种方法似乎都趋向于非常相似的规模。:-)明智的选择是,您肯定会更快。
Arnauld

@Arnauld我设法剃了一些4字节。轮到您了
edc65 '16
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.