命名扑克手-7张牌


11

挑战:

在这个问题中:命名您必须拿出五张牌的扑克手并识别它。这个问题很相似,有两个不同之处:

首先,输出将全部为小写。这样您就可以进行更多的高尔夫球运动,因为您不必担心flush和的大小写。straight

high card
one pair
two pair
three of a kind
straight
flush
full house
four of a kind
straight flush
royal flush

其次,随着德州扑克和7张牌梭哈的流行,我们在代码高尔夫这里应该能够得分7张扑克牌,对吗?当得分为7张牌时,请使用5张最好的牌,而忽略不需要的2张。

参考:

扑克手名单:http : //en.wikipedia.org/wiki/List_of_poker_hands

输入(直接从上一个线程中提取)

来自stdin或命令行参数的7 张卡片。卡片是表格上的两个字母的字符串RS,其中R是等级,S是西装。该队伍2- 9(号卡), T(十个),J杰克(Jack),(Q皇后), K(王),A(ACE)。该套装SDHC为黑桃,方块,分别心和俱乐部。

卡示例

5H - five of hearts
TS - ten of spades
AD - ace of diamonds

输入示例=>所需输出

3H 5D JS 3C 7C AH QS => one pair
JH 4C 2C 9S 4H JD 2H => two pair
7H 3S 7S 7D AC QH 7C => four of a kind
8C 3H 8S 8H 3S 2C 5D => full house
AS KC KD KH QH TS JC => straight

请注意,在第二个示例中,实际上有三对,但您只能使用五张卡,因此为two pair。在第五个示例中,同时存在a three of a kind和a straight,但是a straight更好,因此output straight

计分

这是,所以最短的代码获胜!

勘误

  1. 您可能不使用外部资源。
  2. 直道的Ace值高低。

好 我暗中希望有人能接球。只是想指出,我对原始问题的大写字母没有任何限制(在评论中已阐明),因此您可以(而且大多数/全部都这样做)输出“ Straight Flush”。恕我直言大写看起来更好。
daniero 2014年

您说输入(直接从上一个线程中提取)5张卡。我觉得你的意思更改为7
级圣河

@steveverrill您可以自己编辑堆栈交换中的帖子。尽管我在这里为您做到了
durron597 2014年

是否允许外部资源?有一些查找表,使您可以简单地查找手中的每张牌并获得手的力量。
Kendall Frey 2014年

ace的高低可以高低吗?
尼克T

Answers:


4

红宝石353

这是基于Chron原始问题的答案得出的。

这将输入作为命令行参数。基本上,我们只是遍历5号的所有组合,以得到哪种手牌。每种手型均已修改,因此以数字开头。(“皇家同花顺”->“ 0皇家4同花顺”,“高牌”->“ 9高牌”)。这使我们可以对返回的字符串进行排序。排序后的第一个字符串是最好的一手牌。因此,我们从字符串中删除所有数字后将其打印出来。

o,p=%w(4flush 1straight)
f=/1{5}|1{4}0+1$/
puts $*.combination(5).map{|z|s=[0]*13;Hash[*z.map{|c|s['23456789TJQKA'.index c[0]]+=1;c[1]}.uniq[1]?[f,'5'+p,?4,'2four'+a=' of a kind',/3.*2|2.*3/,'3full house',?3,'6three'+a,/2.*2/,'7two pair',?2,'8one pair',0,'9high card']:[/1{5}$/,'0royal '+o,f,p+' '+o,0,o]].find{|r,y|s.join[r]}[1]}.sort[0].gsub(/\d/,'')

真好 最后的gsub可以是sub吧?
bazzargh 2014年

@bazzargh不,它需要删除所有数字。该代码将4flush与1straight或0royal连接起来,以获得“ 0royal 4 flush”或“ 1straight 4flush”。如果我们仅使用sub,则不会删除4。
FDinoff 2014年

给出错误的结果AS QS JS TS 9S 5H 5D。那会花掉你一个角色!

@ WumpusQ.Wumbley嗯,这似乎是原始代码中的错误。稍后,我将尝试找出问题所在。
FDinoff 2014年

5

Haskell的618 603 598 525 512 504 480 464

卡作为输入行。我想我已经把它打死了,但是使用相同的技巧很容易被红宝石打败:如果生成所有排列,就会得到想要寻找直线的前向排序,以及想要测试N的反向排序一种。

import Data.List
m=map
z=take 5
q=m(\x->head[n|(f,n)<-zip"A23456789TJQK"[1..],f==x!!0])
l=m length
v=" of a kind"
w="flush"
y="straight"
c f s p r|f&&r="9royal "++w|f&&s='8':y++" "++w|f='5':w|s||r='4':y|True=case p of 4:_->"7four"++v;3:2:_->"6full house";3:_->"3three"++v;2:2:_->"2two pair";2:_->"1one pair";_->"0high card"
d x=c([5]==l(group$m(!!1)x))(q x==z[head(q x)..])(l$group$q x)$q x==1:[10..13]
k h=tail$maximum$m(d.z)$permutations$words h
main=interact k

在看到@FDinoff的条目后,编辑为内联“成对”并使用数字前缀,还组成了映射函数以剃除一个以上的char。


如果您摆脱了你,可以为自己省下几个字符(我想大约五个)。"one pair","two pair"则短一些u=" pair" ... "one"++u,"two++u
FDinoff 2014年

是的,我只是在阅读代码后进行了更改。同样,数字前缀技术还为我节省了5分
bazzargh 2014年

2

C ++,622 553个字符

为了清楚起见,在下面添加了四个不必要的换行符。

#include"stdafx.h"
#include"string"
std::string c=" flush",d=" of a kind",e="straight",z[10]={"high card","one pair","two pair","three"+d,e,c,"full house","four"+d,e+c,"royal"+c},
x="CDHSA23456789TJQK";char h[99];int main(){__int64 f,p,t,g,u,v,w,l=1,a=78517370881,b=a+19173960,i,j,q=0;gets_s(h,99);for(i=28;i-->7;){f=p=0;
for(j=7;j--;)if(j!=i%7&j!=(i+i/7)%7){f+=l<<x.find(h[j*3+1])*6;p+=l<<x.find(h[j*3])*3-12;}
v=p&b*2;u=v&v-1;w=p&p/2;g=p*64&p*8&p&p/8&p/64;f&=f*4;t=f&&p==a?9:f&&g?8:p&b*4?7:u&&w?6:f?5:g||p==a?4:w?3:u?2:v?1:0;
q=t>q?t:q;}puts(z[q].c_str());}

高尔夫版本发生了一些变化:

修订版1:将所有数值变量更改__int64为单个声明。

Rev 1:打高尔夫球的增量和for循环条件

修订版0:将八进制常量更改为十进制。

修订版0:if使用条件运算符将语句更改为赋值。修订版1:进一步将其重新排列为一个表达式t。这需要v中间值之一的新变量

修订版0:删除了详细输出。仅输出最佳的总手牌。

修订版0:放弃压缩输出文本(在C语言中比较困难,因为您无法使用+运算符来连接字符串。)只写一次“ flush”就为我节省了12个字符,却花了我15个字符,使我的整体效率降低了3个字符。所以我只写了3次。版本1:std::string代替char[]FDinoff的建议使用,可以与串联+

Ungolfed版本,714个非注释非空白字符。

循环使用21张可能由7张牌组成的牌,每次拒绝2张牌。五张所选牌的花色和等级在变量f和p中总计,每个花色/等级的八进制数字不同。执行各种位操作以确定指针的类型,然后将其存储在t中(所有21种可能性都以非高尔夫形式输出)。最后,输出可能的最佳指针。

#include "stdafx.h"
#include "string.h"

char x[] = "CDHSA23456789TJQK", h[99], z[10][99] = 
{ "high card", "one pair", "two pair","three of a kind", "straight","flush","full house","four of a kind","straight","royal" };

int main(void)
{
        int i,j,q=0;                  //i,j:loop counters. q:best possible hand of 7 card   
        scanf_s("%s/n", &h, 99); getchar();
        for (i = 7; i < 28; i++){

          //f,p: count number of cards of each suit (2 octal digits) and rank (1 octal digit.)
          //t: best hand for current 5 cards. g:straight flag. u,w: flags for pairs and 3's.   
          //l: constant 1 (64bit leftshift doesn't work on a literal.) 
          //octal bitmasks: a=ace high straight, b=general purpose

            __int64 f=0,p=0,t=0,g,u,w,l=1,a=01111000000001,b=a+0111111110;

           for (j = 0; j < 7; j++){
               if (j != i %7 & j != (i+i/7) %7){

                   f += l << (strchr(x,h[j*3+1])-x)*6;
                   p += l << (strchr(x,h[j*3])-x-4)*3;

                   printf_s("%c%c ",h[j*3], h[j*3+1]);
               }
           }

           w=p&b*2;                          //if 2nd bit set we have a pair
           if (w) t=1;
           u= w & w-1;                       //if there is only one pair w&w-1 evaluates to 0; +ve for 2 pair.
           if (u) t=2;
           w = p & p/2;                      // if 2nd and 1st bit set we have 3 of kind. 
           if (w) t=3;
           g = p*64 & p*8 & p & p/8 & p/64;  // detects all straights except ace high. pattern for ace high in a.
           if (g||p==a) t=4;
           f&=f*4;                           //for a flush we want 5 cards of the same suit, binary 101
           if (f) t=5;
           if (u&&w) t=6;                    //full house meets conditions of 2 pair and 3 of kind
           if (p & b*4) t=7;                 //four of a kind
           if (f && g) t=8;                  //straight flush
           if (f && p==a) t=9;               //royal flush
           printf_s("%s %s \n",z[t],t>7?z[5]:"");
           q=t>q?t:q;
        }   
        printf_s("%s %s",z[q],q>7?z[5]:"");
        getchar();
}

非高尔夫输出

在此处输入图片说明


既然您说您正在使用c ++,则可以使用<string>不支持+的字符串连接。这意味着您可能可以使用<iostream>并使用。cout但是,我实际上不知道其中任何一个是否会导致较小的字符数。
FDinoff 2014年

@FDinoff我可以保存的是:" pair flush flush straight of a kind"= 35个字符。一旦#include节省下来的钱很少,那么您就必须考虑额外",=+的常量声明。另外,我是C ++的新手,并且在IDE和编译器设置方面苦苦挣扎(这迫使我使用它scanf_sprintf_s而不是使用旧的“不安全”版本,并且解决该cout问题的请求也绕了一圈。)可能会有所帮助,这在我身上列出,但可能用于其他程序。cout对我来说致命的是using namespace std我不知道是否有办法避免编写所有内容。
级圣河

由于您正在使用c ++,因此几乎永远不需要printf和scanf。还有其他(更安全)的人可以做同样的事情。您可以std::cout用来绕过using namespace std
FDinoff 2014年

@FDinoff thx为小费。在我的最新编辑中,我保存了18个字节,带不同的字符串处理:gets_sputs,加上std::string连接,这意味着我必须转换char*为输出。我发布的高尔夫球只适用于string或仅适用于iostream.奇异产品,我必须同时包括两者,才能使用<<>>带有cin/coutstd::strings的运算符。总的来说,#include即使我可以声明h为a std::string并避免单独的char声明,使用两个s的结果却要差5个字节。可以预见,我找不到帮助中的清单namespace std(或有关操作员的说明。)
Level River St

@FDinoff我同意,我通常不会使用scanfgets,除了打高尔夫球之外,因为高尔夫总是很不安全。-s,99如果可以使用gets代替,我可以缩短5个字节gets_s,但是我无法让编译器让我这样做。令我惊讶的是,总体上,不安全的C / C ++多么不安全!几周前,我发现_int64 x=1<<y给y大于31的错误答案而感到震惊。但是现在我有点生气了。看到数组下标超出范围而没有错误消息的事情,我已经习惯了。有什么办法可以更好地进行检查吗?
级圣河

2

perl的(> = 5.14),411 403 400 397 400

编辑:内联仅被调用一次的子,节省8个字符。
编辑2:删除了.""早期尝试遗留下来的a。
编辑3:代替保留原始内容的temp变量$_,使用一个使其不必要。净收益3个字符。
编辑4:修复了无法检测到满屋子的情况(2 x 3种类)。花费3个字符。

我认为这并不是一个赢家,但是直检测器是一个有趣的概念。

sub
j{join"",sort@_}sub
o{j(map{{A=>10}->{$_},11+index(j(2..9).TJQKA,$_)}$h=~/(.(?=@_))/g)=~/.*(..)(??{j
map$1+$_.'.*',1..4})/?$1:()}$h=$_=<>;if(j(/(\S)\b/g)=~/(.)\1{4}/){$w=$_==19?royal:straight
for
o$f=$1}$_=j(/\b(\S)/g)=~s/(.)\1*/length$&/rge;$k=" of a kind";print$w?"$w flush":/4/?four.$k:/3.*2|[23].*3/?"full house":$f?flush:(o".")?straight:/3/?three.$k:/2.*2/?"two pair":/2/?"one pair":"high card"

扩展版本:

# We'll be doing a lot of sorting and joining
sub j {
  return join "", sort @_;
}

# r() expects $_ to contain a rank, and converts it to a numeric code. The
# code starts at 10 so the numbers will sort correctly as strings, and a list
# of 2 values is returned because A is both 10 and 23. All other ranks have
# undef as the first value and their proper 11..22 value as the second value.
sub r {
  return ({A=>10}->{$_}, 11+index(j(2..9).TJQKA,$_));
}

# Sequence-detector. Factored into a sub because it's run twice; once over
# the ranks in the flush suit to find a straight flush and once over all the
# ranks to find a straight. On successful match, returns the lowest rank of
# the straight (in the 10..23 representation).
# Required parameter: the suit to search, or "." for all suits.
sub o {
  j(map r,$h=~/(.(?=@_))/g)          # The list of ranks, in increasing order,
                                     # with ace included at both ends...
    =~                               # ...is matched against...
  /.*(..)(??{j map$1+$_.'.*',1..4})/ # ...a pattern requiring 5 consecutive
                                     # numbers.
  ?$1:()
  # A note about this regexp. The string we're matching is a bunch of numbers
  # in the range 10..23 crammed together like "121314151619" so you might
  # worry about a misaligned match starting on the second digit of one of the
  # original numbers. But since that would make every pair of digits in the
  # match end with a 1 or a 2, there's no way 5 of them will be consecutive.
  # There are no false matches.
  # Another note: if we have a royal flush and also have a 9 in the same
  # suit, we need to return the T rank, not the 9, which is why the regexp
  # starts with a .*
}

# Read a line into $_ for immediate matching with /.../ and also save it into
# $h because $_ will be clobbered later and we'll need the original string
# afterwards.
$h = $_ = <>;

if(j(/(\S)\b/g) =~ /(.)\1{4}/) { # flush detector: sorted list of all suits
                                 # contains 5 consecutive identical chars
  # $f=$1 comes first, so $f will be true later if there's a flush.
  # Then o() is called with the flush suit as arg to detect straight flush.
  # If there's no straight flush, o() returns the empty list and for loop
  # runs 0 times, so $w is not set. If there is a straight flush, the return
  # value of o() is compared to 19 to detect royal flush.
  $w = ($_==19 ? "royal" : "straight")
    for o($f=$1);
}

$_ =
  j(/\b(\S)/g)                 # Get the sorted+joined list of ranks...
    =~ s/(.)\1*/length $&/rge; # ... and turn it into a list of sizes of
                               # groups of the same rank. The /r flag
                               # requires perl 5.14 or newer.

print
  $w             ? "$w flush" :
  /4/            ? "four of a kind" :
  /3.*2|[23].*3/ ? "full house" :
  $f             ? "flush" :
  (o".")         ? "straight" :
  /3/            ? "three of a kind" :
  /2.*2/         ? "two pair" :
  /2/            ? "one pair" :
                   "high card"

1

JavaScript 600

nodeJS的用法: node code.js "7H 3S 7S 7D AC QH 7C"

function a(o){s="";for(k in o)s+=o[k];return s}
b=process.argv[2]
c={S:0,H:0,D:0,C:0}
v={A:0,K:0,Q:0,J:0,T:0,"9":0,"8":0,"7":0,"6":0,"5":0,"4":0,"3":0,"2":0}
d=b.split(" ")
for(i=d.length;i--;){e=d[i];c[e[1]]++;v[e[0]]++}
c=a(c);v=a(v)
f=g=h=j=k=l=m=false
if((st=c.indexOf(5))!=-1)g=!g
if(v.match(/[1-9]{5}/))h=!h
if(st==0)f=!f
if(v.indexOf(4)!=-1)j=!j
if(v.indexOf(3)!=-1)k=!k
if(n=v.match(/2/g))if(n)if(n.length>=2)m=!m;else l=!l
p=" of a kind"
q="Flush"
r="Straight"
console.log(f&&g?"Royal "+q:h&&g?r+" "+q:j?"Four"+p:k&&(l||m)?"Full House":g?q:h?r:k?"Three"+p:m?"Two pairs":l?"Pair":"High card")
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.