Порівняйте дві руки в покер


14

Виклик:

Давши дві руки на п’ять карт, визначте, яка з них виграє за стандартним рейтингом рук в покер .

Вхід:

Десять карток, розділених пробілами від stdin або як аргументи командного рядка, що б вам не було зручніше. Перші п'ять карт - це гравець 1, а останні п'ять - гравець 2. Кожна картка буде двома літерами форми RS, де R - ранг, а S - масть. Ранги складають від 2-9, Т на десять, а J, Q, K і A для Джека, Королеви, Кінга та Туза відповідно. Костюми - H, D, C, S для Hearts, Diamonds, Clubs і Spades відповідно. Ви повинні вивести номер гравця, який виграв: '1' або '2'.

Приклади карток:

AS - the Ace of Spades
QD - the Queen of Diamonds
2C - the Two of Clubs
TH - the Ten of Hearts

Приклади введення для вихідних даних:

5H 5C 6S 7S KD 2C 3S 8S 8D TD -> 2

Пояснення: У гравця 1 є пара п'яти, а у гравця 2 - пара восьми.

5D 8C 9S JS AC 2C 5C 7D 8S QH -> 1

Пояснення: Жоден гравець не має нічого особливого, але висока картка гравця 1 - це туз, тоді як висока карта гравця 2 - королева.

2D 9C AS AH AC 3D 6D 7D TD QD -> 2

Пояснення: У гравця 1 є три тузи, у гравця 2 - флеш алмазів.

4D 6S 9H QH QC 3D 6D 7H QD QS -> 1

Пояснення: Обидва гравці мають пару королів, але другою найвищою карткою гравця 1 є дев'ять, тоді як гравця 2 - це сім.

Правила та уточнення:

  • Детальну інформацію про порівняння рук див. У стандартному рейтингу рук у покер .
  • Ви можете припустити, що в кожній парі рук немає повторних карт.
  • Ви можете припустити, що у кожному конкретному випадку є певний переможець.
  • Костюм не враховує рейтинг руки. Наприклад, два королівські флеші різних костюмів рівні (тому будь-який вхід, коли обидва гравці мають королівський флеш, недійсний за попереднім правилом).
  • Оскільки це кодовий гольф, найкоротша відповідь виграє.

Примітки:


Вибачте, якщо я щось пропустив! Це моє перше питання про гольф з кодом.
командос

Це схоже на недавнє запитання codegolf.stackexchange.com/q/23743/15599 та 5-карту версію, на яку посилається всередині нього. Однак ці питання вимагають лише назвати тип руки. Велика різниця тут полягає в тому, що якщо обидва гравці мають один і той же тип рук, ми повинні визначити, який кращий за рангом карти (наприклад, для двох пар, хто має кращу першу пару, другу пару та за потреби одну карту.) Тому це не дублікат. Завжди шукайте подібні запитання, зв’язуйте їх (я бачу, що ви зробили) і будьте готові захищати, чому це не дублікат перед публікацією.
Річка Рівня Св.

Що робити, якщо флоп і рука однакові?
Ісмаїл Мігель

@IsmaelMiguel У цій версії немає флопу. Існують просто дві окремі руки, які треба оцінювати один проти одного.
командос

1
Раніше вирішено на 10 карт тут
Hasturkun

Відповіді:


2

Haskell - 352 339 символів

import Data.List
v h=10*(sum$map(\l->l*l)g)+b g:k where
  (g,k)=unzip$reverse$sort$map(\r->(length r,head r))$group$sort$map(maybe 0 id.(`elemIndex`"23456789TJQKA").head)h
  b(1:_)=f(map(!!1)h)+t k;b _=0
f(y:z)|all(==y)z=75;f _=0
t[y,_,_,_,z]|y-z==4=70;t[12,3,2,1,0]=65;t _=0
w(a,b)|v a>v b="1\n";w _="2\n"
main=interact$w.splitAt 5.words

Виконує:

& echo "5H 5C 6S 7S KD 2C 3S 8S 8D TD" | runhaskell 25056-Poker.hs 
2

& echo "5D 8C 9S JS AC 2C 5C 7D 8S QH" | runhaskell 25056-Poker.hs 
1

& echo "2D 9C AS AH AC 3D 6D 7D TD QD" | runhaskell 25056-Poker.hs 
2

& echo "4D 6S 9H QH QC 3D 6D 7H QD QS" | runhaskell 25056-Poker.hs 
1

Ungolf'd і прокоментував, щоб ви могли побачити техніку:

import Data.List

value :: [String] -> [Int]
value hand = 10 * (sum $ map (\l->l*l) groups) + bonus groups : kicker
    -- ^ Value of a hand is 10 times the sum of the squares of the group lengths
    -- plus the straight & flush bonus, followed by the kicker (to break ties)
    -- This 10 * sum-of-squares + bonus works out to put the hands in category
    -- order, and then they only need to be ordered by card ranks.
  where
    -- | The cards are sorted into groups by matching rank, then the groups
    -- sorted by length and rank: For example: "7C 7D 7H QS 2S" will becomes
    -- [(3,7),(1,Q),(1,2)]. This is like a run-length encoding. Finally, the
    -- groups lengths, and the kicker ranks are taken apart into two lists.
    -- N.B: kicker here includes the ranks of the groups, unlike the poker term.

    (groups,kicker) = unzip             -- split apart
        $ reverse $ sort                -- reverse sort by (length,rank)
        $ map (\r->(length r,head r))   -- turn groups into (length,rank) pairs
        $ group $ sort                  -- group sorted ranks
        $ map (maybe 0 id . (`elemIndex`"23456789TJQKA") . head) hand
            -- take first letter of each card in the hand, and map to [0..12]

    -- | Give a bonus for flush and straight to hands with five cards,
    -- or equivalently hands where the largest group length is just 1
    bonus (1:_ ) = flush (map (!!1) hand)   -- flush takes the suits of the hand
                   + straight kicker        -- straight takes the ranks
    bonus _      = 0

    -- | A flush is if all suits match the first suit
    flush (y:z) | all (==y) z = 75
                | otherwise   =  0

    -- | There are two kinds of straight.
    -- N.B: If there are five groups, then there are no duplicate ranks
    straight [y,_,_,_,z] | y-z == 4 = 70    -- normal, high to low
    straight [12,3,2,1,0]           = 65    -- ace is low, but it sorts high
    straight _                      =  0

wins :: ([String], [String]) -> String
wins (a,b) | value a > value b = "1\n"
           | otherwise         = "2\n"

main = interact $ wins . splitAt 5 . words

2

Пітон - 774 722 707 698 685 символів

import sys
t,q,e,u='--23456789TJQKA','SDCH',enumerate,len
_=lambda c,i=0:chr(97+c[i])
def j(s):
 v,g,l=[0]*15,[0]*4,''
 for c in s:
  r,s=c[0],c[1];v[t.find(r)]+=1;g[q.find(s)]+=1
 c,h,k,m,f=0,0,[0,0,[],[],[]],0,0
 for x,i in e(v):
  for b in[2,3,4]:
   if i==b:k[b]+=[x]
 v[1]=v[14]
 for x,i in e(v):
  if i:
   c+=1
   if c==5:m,h=1,x
   if i==1:l+=_([x])
  else:c=0
 f,l,d=max(g)//5*2,l[::-1],'';z=f+m
 if z==3:d='z'+l
 if k[4]:d='y'+_(k[4])+l
 if k[2] and k[3]:d='x'+_(k[3])+_(k[2])
 if z==2:d='w'+l
 if z==1:d='v'+_([h])
 if k[3]:d='u'+_(k[3])+l
 if u(k[2])>1:d='t'+_(k[2],1)+_(k[2])+l
 if u(k[2])==1>u(k[3]):d='s'+_(k[2])+l
 return d or l
p=sys.argv
print(1+(j(p[1:6])<j(p[6:])))

Я вирішив створити рядок для кожної руки, яка її представляє, починаючи з символу для типу руки, а потім символи, що описують конкретні зміни типу (наприклад, на якій картці у вас було лише 4?), А потім значення решти карт у разі вирівнювання (якщо обидва гравці мають однакову подвійну пару, 5-а карта повинна буде вирішити, хто виграє). Я перевірив це досить широко, але насправді я не граю в покер, тому сподіваюся, що я все зрозумів. Крім того, я знаю, що це ще не повністю гольф, я, певно, згодом можу відголити кілька десятків.


Убити 5 символів с _=lambda c:chr(97+c). Крім того, у вас є кілька зайвих пробілів після :s і =s. Нарешті, використовуйте ;замість нових рядків окремі оператори, щоб зменшити пробіл, який використовується для відступу.
користувач12205

Гарний з лямбда, дякую!
Тал-

2

JavaScript - 526 508

function a(b){b=b.split(" ");var c=b.splice(5,5),d=[],e=[],r=[8,9,5,6,1,2,3,10,4,7],A=14,K=13,Q=12,J=11,S={"S":1,"C":2,"H":4,"D":8};for(i=0;i<5;i++){d.push(b[i].split('')[1]);b[i]=b[i].split('')[0];e.push(c[i].split('')[1]);c[i]=c[i].split('')[0]}function p(w,m){var v,i,o,s=1<<w[0]|1<<w[1]|1<<w[2]|1<<w[3]|1<<w[4];for(i=-1,v=o=0;i<5;i++,o=Math.pow(2,w[i]*4)){v+=o*((v/o&15)+1)}v=v%15-((s/(s&-s)==31)||(s==0x403c)?3:1);v-=(m[0]==(m[1]|m[2]|m[3]|m[4]))*((s==0x7c00)?-5:1);return r[v]}alert(p(b,d)>p(c,e)?1:2)}

використання:

a("5H 5C 6S 7S KD 2C 3S 8S 8D TD");

неозорений:

function a(b) {
b = b.split(" ");
var c=b.splice(5,5),
        d=[],
        e=[],
        r=[8,9,5,6,1,2,3,10,4,7],
        A=14,
        K=13,
        Q=12,
        J=11,
        S={"S":1,"C":2,"H":4,"D":8};

    for (i=0;i<5;i++) {
        d.push(b[i].split('')[1]);
        b[i] = b[i].split('')[0];
        e.push(c[i].split('')[1]);
        c[i] = c[i].split('')[0];   
    }

function p(w,m){
  var v, i, o, s = 1<<w[0]|1<<w[1]|1<<w[2]|1<<w[3]|1<<w[4];
  for (i=-1, v=o=0; i<5; i++, o=Math.pow(2,w[i]*4)) {v += o*((v/o&15)+1);}
  v = v % 15 - ((s/(s&-s) == 31) || (s == 0x403c) ? 3 : 1);
  v -= (m[0] == (m[1]|m[2]|m[3]|m[4])) * ((s == 0x7c00) ? -5 : 1);
  return r[v];
}

alert(p(b,d)>p(c, e)?1:2);
}

джерело


1

perl, 801 733 символів

Я вважаю, що це досить пряма реалізація. В основному для кожної руки ми сортуємо костюми та обличчя окремо. Тоді ми робимо ще одну копію обличчя з тузами, що може бути низькою, щоб ми могли перевірити наявність прямих з низькими тузами. Тоді ми визначаємо, чи є у нас флеш або прямо, і що таке висока карта. Потім ми просто перевіряємо на матчі в порядку забивання (спочатку перевіряємо на прямі флеші, потім на чотири види тощо). Фактична оцінка - це лише з'єднання типу руки з наступними номіналами карт у тому порядку, який вони мають значення (це _s () у неопущеній версії, u () у версії для гольфу). Ось:

@l{2..9,qw(T J Q K A)}=2..14;sub u{join"",map{$_>9?$_:"0$_"}shift,ref$_[0]?$$_[0]:map{$h[$_]}@_}sub e{$p[$_[0]-1]-1==$p[$_[0]]}sub f{@p=@_;e(1)&&e(2)&&e(3)&&e 4}sub h{$h[$_[0]]==$h[$_[1]]}sub i{h(@_[0,1])&&h @_[2,3]}sub t{@s=sort map{substr($_,1)}@_;$f=$s[0]eq$s[4];@l=@h=sort{$b<=>$a}map{$l{substr($_,0,1)}}@_;@l=(@l[1..4],1)while$l[0]==14;$s=0;if(f@l){$s=1;$h=$l[0]}else{$h=$h[0];$s=1 if f@h}$f&&$s?u 9,\$h:h(4,1)?u 7,4,0:h(3,0)?u 7,3,4:i(4,3,2,0)?u 6,0,4:i(4,2,1,0)?u 6,4,0:$f?u 5,0:$s?u 4,\$h:h(4,2)?u 3,4,0,1:h(3,1)?u 3,3,0,4:h(2,0)?u 3,2..4:i(4,3,2,1)?u 2,2,4,0:i(4,3,1,0)?u 2,1,4,2:i(3,2,1,0)?u 2,1,3,4:h(4,3)?u 1,4,0,1,2:h(3,2)?u 1,3,0,1,4:h(2,1)?u 1,2,0,3,4:h(1,0)?u 1,1..4:u 0,0..4}print t(@ARGV[0..4])gt t(@ARGV[5..9])?1:2

А ось і менш гольф-еквівалент:

use strict;
use warnings;

# ace high or low in straights, otherwise high
# T = ten, J = jack, Q = queen, K = king, A = ace

# 0 high card
# 1 one pair
# 2 two pair
# 3 3 of a kind
# 4 straight
# 5 flush
# 6 full house
# 7 four of a kind
# 9 straight flush (royal flush a subclass of straight flush)

my %l;@l{2..9,qw(T J Q K A)}=2..14;
sub score {
  my @suits = sort map { substr($_,1) } @_;
  my @faces_h = sort { $b <=> $a } map { $l{substr($_,0,1)} } @_;
  my @faces_l = @faces_h;
  @faces_l = (@faces_l[1..4], 1) while $faces_l[0] eq 14;
  my $is_flush = $suits[0] eq $suits[4];
  my ($is_straight, $high_card);
  if($faces_l[0]-1==$faces_l[1] &&
     $faces_l[1]-1==$faces_l[2] &&
     $faces_l[2]-1==$faces_l[3] &&
     $faces_l[3]-1==$faces_l[4]) {
    $is_straight=1;
    $high_card = $faces_l[0];
  } else {
    $high_card = $faces_h[0];
    if($faces_h[0]-1==$faces_h[1] &&
       $faces_h[1]-1==$faces_h[2] &&
       $faces_h[2]-1==$faces_h[3] &&
       $faces_h[3]-1==$faces_h[4]) {
      $is_straight=1;
    }
  }
  return _s(9, \$high_card) if $is_flush && $is_straight;
  return _s(7, 4,0) if $faces_h[4] == $faces_h[1];
  return _s(7, 3,4) if $faces_h[3] == $faces_h[0];
  return _s(6, 0,4) if $faces_h[4] == $faces_h[3] && $faces_h[2] == $faces_h[0];
  return _s(6, 4,0) if $faces_h[4] == $faces_h[2] && $faces_h[1] == $faces_h[0];
  return _s(5, 0) if $is_flush;
  return _s(4, \$high_card) if $is_straight;
  return _s(3, 4,0,1) if $faces_h[4] == $faces_h[2];
  return _s(3, 3,0,4) if $faces_h[3] == $faces_h[1];
  return _s(3, 2,3,4) if $faces_h[2] == $faces_h[0];
  return _s(2, 2,4,0) if $faces_h[4] == $faces_h[3] && $faces_h[2] == $faces_h[1];
  return _s(2, 1,4,2) if $faces_h[4] == $faces_h[3] && $faces_h[1] == $faces_h[0];
  return _s(2, 1,3,4) if $faces_h[3] == $faces_h[2] && $faces_h[1] == $faces_h[0];
  return _s(1, 4,0,1,2) if $faces_h[4] == $faces_h[3];
  return _s(1, 3,0,1,4) if $faces_h[3] == $faces_h[2];
  return _s(1, 2,0,3,4) if $faces_h[2] == $faces_h[1];
  return _s(1, 1,2,3,4) if $faces_h[1] == $faces_h[0];
  return _s(0, 0..4);
}

sub _s {
  join "", map { $_ > 9 ? $_ : "0$_" } shift,
    ref $_[0] ? $$_[0] : map { $faces_h[$_] } @_
  # my @a=@_;
  #  if(ref $a[1]) {
  #    $a[1]=${$a[1]};
  #  } else {
  #    $a[$_]=$faces_h[$a[$_]] for 1..$#a;
  #  }
  #  join "", map { $_ < 10 ? "0$_" : $_ } @a;
}

my @p1 = @ARGV[0..4];
my @p2 = @ARGV[5..9];

my $s1 = score(@p1);
my $s2 = score(@p2);
print $s1 gt $s2 ? 1 : 2;

AH 2C 3S 4S 5D 6C 7S 7C 7D TDдає результат 2, але я думаю, що пряма б'є трійку подібних
r3mainer
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.