Poker elini adlandırın - 7 kart baskısı


11

Meydan okuma:

Bu soruda: poker eli Ad Eğer bir beş kartlı poker elini alıp tanımlamak zorunda kaldı. Bu soru iki bükülme ile benzerdir:

İlk olarak, çıktı tüm küçük harf olacaktır. Bu, daha golf sağlar size büyük harf kullanımı konusunda endişelenmenize gerek yok gibi flushvestraight

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

İkincisi, Texas Hold'em ve 7 kart stud'ın popülaritesi ile, burada kod golf'de yedi kartlı bir poker eli kazanabiliyor muyum? Yedi kartlık bir el alırken, eliniz için en iyi beş kartı kullanın ve ihtiyacınız olmayan ikisini göz ardı edin.

Referans:

Poker elleri listesi: http://en.wikipedia.org/wiki/List_of_poker_hands

Giriş (doğrudan önceki iş parçacığından kaldırılır)

Stdin veya komut satırı bağımsız değişkenlerinden 7 kart . Kart, formdaki iki harfli bir dizedir RS, burada R sıralanır ve S uygundur. Rütbeleri şunlardır 2- 9(sayı kartları), T(on), J(Jack), Q(Kraliçe), K(Kral), A(As). Takım elbise vardır S, D, H, Csırasıyla maça, karo, kupa ve kulüpleri için.

Kart örneği

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

Girdi örneği => istenen çıktı

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

İkinci örnekte aslında üç çift olduğuna dikkat edin, ancak sadece beş kart kullanabilirsiniz, bu yüzden two pair. Beşinci bir örnekte, her ikisi de bulunmaktadır three of a kindve bir straightmümkün ama straightçıktı çok daha iyidir straight.

puanlama

Bu , bu yüzden en kısa kod kazanır!

Hatalar

  1. Harici kaynakları kullanamazsınız.
  2. Ace, düzlükler için hem yüksek hem de düşüktür.

Güzel; Gizlice birinin topu alacağını umuyordum. Sadece orijinal soruda (bir açıklamada açıklanmıştır) büyük harf kullanımı ile ilgili herhangi bir kısıtlama olmadığını not etmek istedim, Yani (ve çoğu / hepsi yaptı) çıktı "Düz Flush" olabilir. IMHO büyük harfle daha iyi görünüyor.
daniero

Giriş (doğrudan önceki iş parçacığından kaldırılmış) 5 kart diyorsunuz . Sanırım bunu 7 olarak değiştirmek
Level River St

@steveverrill Yığın değişiminde yayınları kendiniz düzenleyebilirsiniz. Burada senin için
yapmama

Harici kaynaklara izin veriliyor mu? Sadece eldeki her kartı aramanıza ve bir el gücü elde etmenize izin verecek arama tabloları vardır.
Kendall Frey

As, düzlükler için düşük olduğu kadar yüksek olabilir mi?
Nick T

Yanıtlar:


4

Yakut 353

Bu, Chron'un orijinal sorudan verdiği cevaba dayanıyordu .

Bu, girdiyi komut satırı bağımsız değişkenleri olarak alır. Temel olarak, ne tür bir el olduğunu elde etmek için tüm boyut 5 kombinasyonlarını tekrarlıyoruz. Her el tipi, bir sayı ile başlayacak şekilde değiştirildi. ("royal flush" -> "0 4 floş", "yüksek kart" -> "9 yüksek kart"). Bu, döndürülen dizeleri sıralamamızı sağlar. Sıralamadan sonraki ilk dize mümkün olan en iyi eldir. Bu yüzden dizeden tüm sayıları çıkardıktan sonra yazdırıyoruz.

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/,'')

Güzel. Sonunda gsub sadece bir alt doğru olabilir mi?
bazzargh

@bazzargh hayır tüm numaraları kaldırmak gerekiyor. Kod "0royal 4 flush" veya "1straight 4flush" elde etmek için 4flush değerini 1straight veya 0royal ile birleştirir. Yalnızca alt kullansak 4 kaldırılmaz.
FDinoff

İçin yanlış sonuç verir AS QS JS TS 9S 5H 5D. Bu sana bir karaktere mal olacak!

@ WumpusQ.Wumbley Hmm bu orijinal kodda bir hata gibi görünüyor. Sorunun daha sonra ne olduğunu anlamaya çalışacağım.
FDinoff

5

Haskell 618 603 598 525 512 504 480 464

Giriş hattı olarak alınan kartlar. Sanırım bunu ölümüne kadar golf oynadım, ancak aynı hileyi kullanarak yakut vb. türünü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

Satır içi "çift" olarak düzenlenmiş ve @ FDinoff'un girişini gördükten sonra sayı öneklerini kullanmış, ayrıca bir karakter daha tıraş etmek için harita işlevleri oluşturmuştur.


Eğer u kurtulmak kendinizi birkaç karakter (yaklaşık 5 sanırım) kaydedebilirsiniz. "one pair","two pair"daha kısau=" pair" ... "one"++u,"two++u
FDinoff

evet, sadece kodunuzu okuduktan sonra bu değişikliği yapıyordum. Ayrıca sayı önek tekniği beni başka bir 5 kurtardı
bazzargh

2

C ++, 622553 karakter

netlik için aşağıya dört gereksiz satır eklendi.

#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());}

Golf versiyonunda işler değişti:

Rev 1: Tüm sayısal değişkenleri __int64tek bir bildirim olarak değiştirdi.

Rev 1: Golf sahalarındaki artış ve fordöngülerin durumu

Rev 0: Sekizli sabitleri ondalık olarak değiştirdi.

Rev 0: ifKoşullu operatörle yapılan atamalardaki ifadeler değiştirildi . Rev 1: için tek bir ifadeye dönüştü t. Bu v, ara değerlerden biri için yeni değişken gerektirdi

Rev 0: Ayrıntılı çıktı silindi. Sadece en iyi genel eli verir.

Rev 0: Çıktı metnini sıkıştırmaya başladım (+ operatörünü kullanarak dizeleri birleştiremediğiniz için C'de zor.) "Flush" yazmak yalnızca bir kez beni 12 karakter kurtardı, ancak bana 15 karakter kazandırdı, bu da bana 3 karakter daha da kötüleştirdi. Bu yüzden sadece 3 kez yazdım. Rev 1: Kullanılan std::stringyerine char[]sahip BİRLEŞTİR mümkün kılar, FDinoff tarafından önerildiği gibi +.

Ungolfed sürümü, 714 uncomment boşluk olmayan karakterler.

7 karttan yapılabilen 21 elin hepsini döndürür ve her seferinde 2 kart reddeder. Seçilen beş kartın tür ve sırası, her bir takım / sıralama için farklı bir sekizlik sayı ile f ve p değişkenlerinde toplanır. El tipini belirlemek için çeşitli bit operasyonları gerçekleştirilir, bu daha sonra t'de saklanır (21 olasılık da çözümsüz versiyonda çıkar.) Son olarak mümkün olan en iyi el çıkarılır.

#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();
}

Kurtulmamış çıktı

resim açıklamasını buraya girin


C ++ kullandığınızı söylediğiniz <string>için dize birleştirme için destek + özelliğini kullanabilirsiniz . Bu da muhtemelen kullanabileceğiniz <iostream>ve kullanabileceğiniz anlamına gelir. coutAncak bunlardan herhangi birinin daha küçük karakter sayısına yol açıp açmayacağını bilmiyorum.
FDinoff

@FDinoff ne kaydedebilirim: " pair flush flush straight of a kind"= 35 karakter. #includeTasarruf ekledikten sonra minimumdur, o zaman ekstra ",=+ve sabit beyanlarını dikkate almanız gerekir . Ayrıca C ++ için yeniyim ve IDE ve derleyici ayarları ile mücadele ediyorum (beni kullanmaya zorlar scanf_sve printf_seski "güvensiz" sürümler yerine ve düzeltmeyle ilgili yardım çevrelerde dolaşıyor.) coutBiraz yardımcı olabilir, Yapılacaklar listesi, ama muhtemelen başka bir program için. coutBenim için öldüren şey, using namespace stdtüm bunları yazmaktan kaçınmanın bir yolu olup olmadığını bilmiyorum.
Level River St

C ++ kullandığınız için neredeyse hiçbir zaman printf ve scanf'e ihtiyacınız yoktur. Aynı şeyi başka (daha güvenli) yapmak da vardı. std::coutusing namespace std
FDinoff

@FDinoff uç için teşekkürler. En son düzenlememde 18 bayt w farklı dize işleme kaydettik: gets_s& puts, artı std::stringbirleştirmek için, bu da char*çıktıya dönüştürmek zorunda olduğum anlamına gelir . Ben yayınladı golf ile çalışır sadece stringya da sadece iostream.Bizarrely Ben & s <<>>ile operatörleri kullanmak için hem de içermelidir . Genel olarak, her iki s kullanarak 5 bayt daha kötü çalışır, düz-se bile bir olarak ilan ve ayrı bir bildirim kaçının . Tahmin edilebileceği gibi, yardımda olanların bir listesini bulamıyorum (veya operatör hakkında bir açıklama bulamıyorum )cin/coutstd::string#includehstd::stringcharnamespace std
Level River St

@FDinoff Kabul ediyorum, normalde kullanmazdım scanfve getsgolf hariç, programların yine de oldukça güvensiz olduğu yerlerde. Bunun yerine -s,99kullanabilsem 5 bayt kısaltabilirdim , ama derleyicinin bana izin vermesini sağlayamıyorum. Beni şaşırtan şey, güvenli olmayan C / C ++ 'ın genel olarak ne kadar güvenli olduğudur! Birkaç hafta önce , 31 yaşından büyük için yanlış cevabı verdiğini bulmak beni şok ederdi . Ama şimdi biraz rahatsız oldum. Dizi abonelikleri ile hata mesajı olmadan sınırların dışına çıkan şeyleri gördükten sonra, buna alıştım. Daha iyi kontrol yapmanın bir yolu var mı? getsgets_s_int64 x=1<<y
Level River St

2

Perl (> = 5.14), 411 403 , 400 397 , 400

Düzenleme : 8 karakter kaydederek yalnızca bir kez çağrılan bir alt satır çizdi.
Düzenleme 2 : .""erken bir denemeden kalan bir
düzenlemeyi kaldır Düzenleme 3 : orijinali koruyan geçici değişken yerine, $_gereksiz kılmak için birini kullanın. Net kazanç 3 karakter.
Edit 4 : Aşırı dolu full house (türünün 2x 3'ü) tespit edilemedi. 3 karakter maliyeti.

Tam olarak kazanan değil, ama düz dedektör ilginç bir kavram, sanırım.

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"

Genişletilmiş sürüm:

# 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 ile kullanım: 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")
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.