Beri nama tangan poker - edisi 7 kartu

11

Tantangan:

Dalam pertanyaan ini: Beri nama tangan poker Anda harus mengambil tangan lima kartu poker dan mengidentifikasinya. Pertanyaan ini serupa, dengan dua tikungan:

Pertama, hasilnya akan dalam huruf kecil semua. Hal ini memungkinkan untuk lebih banyak bermain golf, karena Anda tidak perlu khawatir dengan kapitalisasi flushdanstraight

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

Kedua, dengan popularitas Texas Hold'em dan 7 kartu stud, kita di sini di golf kode harus mampu mencetak tujuh kartu poker tangan aku benar? Saat mencetak tujuh kartu, gunakan lima kartu terbaik untuk kartu Anda dan abaikan dua kartu yang tidak Anda butuhkan.

Referensi:

Daftar tangan poker: http://en.wikipedia.org/wiki/List_of_poker_hands

Input (diangkat langsung dari utas sebelumnya)

7 kartu dari argumen stdin atau commandline. Kartu adalah string dua huruf pada formulir RS, di mana R adalah peringkat dan S sesuai. The jajaran yang 2- 9(kartu angka), T(sepuluh), J(Jack), Q(Queen), K(Raja), A(Ace). The jas yang S, D, H, Cuntuk sekop, berlian, hati dan klub masing-masing.

Contoh kartu

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

Contoh input => output yang diinginkan

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

Perhatikan pada contoh kedua sebenarnya ada tiga pasangan, tetapi Anda hanya dapat menggunakan lima kartu, jadi begitu two pair. Pada contoh kelima, ada a three of a kinddan straightkemungkinan, tetapi a straightlebih baik, jadi hasilnya straight.

Mencetak gol

Ini , jadi kode terpendek menang!

Kesalahan

  1. Anda tidak boleh menggunakan sumber daya eksternal.
  2. Ace tinggi dan rendah untuk lurus.
durron597
sumber
Bagus; Diam-diam saya berharap seseorang akan mengambil bola. Hanya ingin mencatat bahwa saya tidak memiliki batasan kapitalisasi pada pertanyaan awal (diklarifikasi dalam komentar), Jadi Anda bisa (dan sebagian besar / semua) mengeluarkan "Straight Flush". IMHO dikapitalisasi terlihat lebih baik.
daniero
Anda mengatakan input (diangkat langsung dari utas sebelumnya) 5 kartu. Saya pikir Anda bermaksud mengubahnya ke 7.
Level River St
@steveverrill Anda dapat mengedit posting sendiri di pertukaran tumpukan. Meskipun saya melakukannya untuk Anda di sini
durron597
Apakah sumber daya eksternal diizinkan? Ada tabel pencarian yang akan memungkinkan Anda untuk hanya melihat setiap kartu di tangan dan mendapatkan kekuatan tangan.
Kendall Frey
Bisakah ace rendah dan tinggi untuk lurus?
Nick T

Jawaban:

4

Ruby 353

Ini didasarkan pada jawaban Chron dari pertanyaan awal.

Ini mengambil input sebagai argumen baris perintah. Pada dasarnya kami hanya mengulangi semua kombinasi ukuran 5 untuk mendapatkan jenis tangan apa itu. Setiap jenis tangan telah dimodifikasi sehingga dimulai dengan angka. ("royal flush" -> "0royal 4flush", "high card" -> "9high card"). Ini memungkinkan kami untuk mengurutkan string yang dikembalikan. String pertama setelah pengurutan adalah tangan terbaik. Jadi kami mencetaknya setelah menghapus semua angka dari string.

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/,'')
FDinoff
sumber
Bagus. GSS pada akhirnya hanya bisa menjadi sub kan?
bazzargh
@bazzargh tidak perlu menghapus semua angka. Kode ini menggabungkan 4flush dengan 1st straight atau 0royal untuk mendapatkan "0royal 4 flush" atau "1st straight 4flush". Jika kita hanya menggunakan sub, 4 tidak akan dihapus.
FDinoff
Memberikan hasil yang salah untuk AS QS JS TS 9S 5H 5D. Itu akan dikenakan biaya karakter!
@ WumpusQ.Wumbley Hmm ini sepertinya bug dalam kode asli. Saya akan mencoba dan mencari tahu apa masalahnya nanti.
FDinoff
5

Haskell 618 603 598 525 512 504 480 464

Kartu diambil sebagai jalur input. Saya pikir saya sudah bermain golf ini sampai mati, tetapi akan dengan mudah dikalahkan oleh ruby ​​dll menggunakan trik yang sama: jika Anda menghasilkan semua permutasi, Anda mendapatkan jenis maju yang Anda ingin mencari lurus, ditambah jenis terbalik yang Anda inginkan untuk pengujian N sejenis.

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

Diedit ke inline "pair" dan menggunakan awalan nomor setelah melihat entri @ FDinoff, juga menyusun fungsi peta untuk mencukur satu lagi char.

bazzargh
sumber
Anda dapat menyimpan sendiri beberapa karakter (kira-kira 5 saya kira) jika Anda menyingkirkan Anda. "one pair","two pair"lebih pendeku=" pair" ... "one"++u,"two++u
FDinoff
ya, saya baru saja melakukan perubahan itu setelah membaca kode Anda. Juga teknik awalan angka menyelamatkan saya 5
bazzargh
2

C ++, 622 553 karakter

empat baris baru yang tidak perlu ditambahkan di bawah ini untuk kejelasan.

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

Hal-hal berubah dalam versi golf:

Rev 1: Mengubah semua variabel numerik ke __int64untuk deklarasi tunggal.

Rev 1: Peningkatan golf dan kondisi forloop

Rev 0: Mengubah konstanta oktal ke desimal.

Rev 0: Mengubah ifpernyataan menjadi tugas dengan operator bersyarat. Rev 1: Mengatur ulang lebih jauh menjadi satu ekspresi untuk t. Ini membutuhkan variabel baru vuntuk salah satu nilai menengah

Rev 0: Output verbose terhapus. Hanya menampilkan hasil keseluruhan terbaik.

Rev 0: Mengompresi teks output (sulit dalam C karena Anda tidak dapat menggabungkan string menggunakan operator +.) Menulis "flush" hanya sekali menyelamatkan saya 12 karakter tetapi biaya saya 15, membuat saya 3 chars lebih buruk dari keseluruhan. Jadi saya hanya menulisnya 3 kali. Rev 1: digunakan std::stringbukan char[]seperti yang disarankan oleh FDinoff, sehingga memungkinkan untuk digabungkan dengan +.

Versi tidak dikoleksi, 714 karakter non-spasi noncomment.

Loop melalui semua 21 kartu yang mungkin dibuat dari 7 kartu dan setiap kartu ditolak 2 kali. Suit dan pangkat dari lima kartu yang dipilih dijumlahkan dalam variabel f ​​dan p dengan digit oktal yang berbeda untuk setiap suit / pangkat. Berbagai operasi bit dilakukan untuk menentukan tipe tangan, yang kemudian disimpan dalam t (semua 21 kemungkinan merupakan output dalam versi yang tidak diklik.) Akhirnya tangan terbaik adalah output.

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

Output tidak terkendali

masukkan deskripsi gambar di sini

Level River St
sumber
Karena Anda mengatakan Anda menggunakan c ++ Anda bisa menggunakan <string>yang mendukung + untuk rangkaian string. Yang kemudian berarti Anda mungkin bisa menggunakan <iostream>dan menggunakan coutNamun saya tidak benar-benar tahu apakah ada yang akan menyebabkan jumlah karakter lebih kecil
FDinoff
@FDinoff apa yang bisa saya simpan: " pair flush flush straight of a kind"= 35 karakter. Setelah Anda menambahkan #includetabungan minimal, maka Anda harus mempertimbangkan tambahan ",=+dan deklarasi konstanta. Saya juga baru mengenal C ++ dan berjuang dengan pengaturan IDE dan compiler (memaksa saya untuk menggunakan scanf_sdan printf_sbukannya versi "tidak aman" lama dan bantuan untuk memperbaikinya berputar-putar.) coutMungkin membantu sedikit, ada di saya untuk lakukan daftar, tetapi mungkin untuk program lain. Hal yang membunuh coutbagi saya adalah using namespace stdsaya tidak tahu apakah ada cara untuk menghindari menulis semua itu.
Level River St
Anda seharusnya hampir tidak pernah membutuhkan printf dan scanf karena Anda menggunakan c ++. Ada yang lain (lebih aman) adalah melakukan hal yang sama. Anda dapat menggunakan std::coutuntuk berkelilingusing namespace std
FDinoff
@FDinoff terima kasih atas tipnya. Dalam pengeditan terakhir saya, saya menyimpan 18 byte dengan penanganan string yang berbeda: gets_s& puts, ditambah std::stringke concatenate, yang berarti saya harus mengonversi ke char*ke output. Golf yang saya posting berfungsi dengan adil stringatau hanya iostream.Aneh, saya harus menyertakan keduanya untuk menggunakan <<>>operator dengan cin/cout& std::strings. Secara keseluruhan, menggunakan kedua #includes bekerja 5 byte lebih buruk, meskipun saya dapat mendeklarasikan hsebagai a std::stringdan menghindari chardeklarasi yang terpisah . Bisa ditebak, saya tidak dapat menemukan daftar apa yang ada namespace stddalam bantuan (atau penjelasan tentang operator.)
Level River St
@FDinoff Saya setuju, saya biasanya tidak akan menggunakan scanfdan gets, kecuali untuk bermain golf, di mana program-programnya cukup tidak aman. Saya dapat mempersingkat 5 byte -s,99jika saya bisa menggunakan, getsbukan gets_s, tapi saya tidak bisa mendapatkan kompiler untuk membiarkan saya. Yang mengejutkan saya adalah betapa tidak amannya C / C ++ secara umum! Beberapa minggu yang lalu itu akan mengejutkan saya untuk menemukan yang _int64 x=1<<ymemberikan jawaban yang salah untuk Anda lebih dari 31. Tapi sekarang saya hanya sedikit kesal. Setelah melihat hal-hal dengan subscript array keluar dari batas tanpa pesan kesalahan, saya sudah terbiasa. Apakah ada cara untuk mengaktifkan pemeriksaan yang lebih baik?
Level River St
2

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

Sunting : sebaris sub yang hanya dipanggil sekali, menyimpan 8 karakter.
Sunting 2 : menghapus .""yang tersisa dari upaya awal
Sunting 3 : alih-alih variabel temp yang mempertahankan yang asli $_, gunakan satu untuk membuatnya tidak perlu. Keuntungan bersih 3 karakter.
Sunting 4 : kegagalan tetap untuk mendeteksi rumah penuh terlalu penuh (2x 3-of-a-kind). biaya 3 karakter.

Bukan pemenang, tetapi detektor lurus adalah konsep yang menarik, saya pikir.

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"

Versi yang diperluas:

# 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"

sumber
1

JavaScript 600

penggunaan dengan 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")
guy777
sumber