Холдем или Фолдем?

17

Ваш друг пригласил вас в последнюю минуту в покер с высокими ставками, и, как ученый, вы решили использовать свои навыки, чтобы получить преимущество в игре. Ваша задача будет заключаться в том, что с учетом 2 cards(вашей руки) и 0, 3, 4 or 5 cards( раздачи карт) вы должны решить, какую наилучшую возможную руку вы сможете получить. Если все 7 карт приведены в качестве аргументов, ответ довольно ясен. Если дать меньше, проблема становится более сложной. Однако этого недостаточно для того, чтобы дать вам необходимое преимущество, вы также должны рассчитать наилучшую возможную комбинацию из оставшихся карт, чтобы понять, что также могут иметь ваши оппоненты.


Холдем освежающий

Если вы не знаете о холдеме, каждый игрок в игре начинает с 2 картами в качестве «руки». В течение 3 ходов раскрываются дополнительные карты для всех игроков. Первый ход, 3 карты раскрыты. Во второй, еще 1 и в третий раз раскрывается финальная карта. Две карты, указанные вначале, представляют вашу руку, в то время как последняя представляет 0, 3, 4 или 5 карт, выдаваемых последовательными ходами.


Возможные номера:

[2,3,4,5,6,7,8,9,T(10),J,Q,K,A]

Возможные костюмы:

[S,C,H,D]

Полная колода:

[2S,3S,4S,5S,6S,7S,8S,9S,TS,JS,QS,KS,AS, # Spades.
 2C,3C,4C,5C,6C,7C,8C,9C,TC,JC,QC,KC,AC, # Clubs.
 2H,3H,4H,5H,6H,7H,8H,9H,TH,JH,QH,KH,AH, # Hearts.
 2D,3D,4D,5D,6D,7D,8D,9D,TD,JD,QD,KD,AD] # Diamonds.

Ранжирование рук:

1:Royal Flush    (A-K-Q-J-10, all from the same suit).
2:Straight Flush (Sequential cards, all from the same suit).
3:Four-of-a-Kind (Self explanatory).
4:Full House     (3-of-a-kind and a 2-of-a-kind).
5:Flush          (All cards are from the same suit).
6:Straight       (Sequential Cards, any suits).
7:3-of-a-Kind    (Self explanatory).
8:2-Pair         (Double 2-of-a-Kind).
9:Pair           (2-of-a-Kind).
10:High Card     (You have absolutely nothing except a single card).

Давайте возьмем пример или два и пройдемся по ним:

Простой пример:

[AS, AC],[AH,AD,9S,9C,9H]-> 3(Четверо в своем роде), 3(Четверо в своем роде)

Лучшая возможная рука, которую вы будете иметь в этой настройке - это рука четверки. Лучшая возможная рука, которую могли иметь ваши оппоненты, это также 4-из-в-роде, так как вы не можете иметь KQJ10 в их двухкарточных руках.


[5C,2C],[6C,4C,JH,JD]-> 2(Стрит-флеш), 3(4 вида)

Вы рискуете для стрит-флеша, но, поскольку у вас в руке 2 / 5C, больше никто не может быть, потому что вы держите обе средние карты. Лучшее, на что они могут надеяться - это иметь 2 карманных валета и получить Джек на флопе.


[JS,JC],[]-> 1(Роял Флэш), 1(Роял Флэш)

Никакой информации, которую вы можете использовать против них, не было предоставлено, все, что вы можете сказать на данный момент, это то, что у них может быть только флеш-рояль в алмазах / сердцах, но вполне возможно, что вы получите флеш-рояль, как и они. Фактически, все входные данные, где флоп еще должен произойти, должны давать ответ 1-1.


[2C,4S],[3C,7S,9D,AH,JD]-> 10(старшая карта), 7(3-в-роде)

Это пример того, где вы абсолютно сбиты с толку, и нет возможности стрита или флеша на ривере. Под лучшей рукой здесь подразумеваются карманные тузы, в результате чего получается 3-в-роде.


Требования к вводу / выводу

  • Вклад должен быть разделен между тем, что у вас на руках, и тем, что является общедоступным знанием; Это, вероятно, будет проще, независимо от реализации.
    • Карты могут быть кортежами или струнами, на ваше усмотрение.
    • Рука и игровое поле могут быть массивами или строками с разделителями.
  • Выходными данными должны быть два индекса из предоставленного мною списка рук (EG [2,1]).
    • Он может быть возвращен как часть функции, распечатан на консоль или выведен подходящим способом.
    • Должно быть два разных значения: одно для вашей лучшей руки, другое для лучшей.
  • 10 может быть представлен как Tили как 10, что имеет смысл для вас.
  • Стандартные лазейки запрещены.

Критерии победы

  • Это , самый низкий счетчик байтов с тай-брейком после даты поста.
Урна волшебного осьминога
источник
2
Не должен ли быть только один из Aи 1в возможных разрешенных картах? Кроме того, я не думаю, что есть действительно веская причина требовать сокращения лица над числовыми значениями, такими как 11.
FryAmTheEggman
9
Я никогда не видел колоду с Aи 1. Все остальное выглядит хорошо.
Исаак
1
Для нас, не являющихся игроками в покер, объясните в вопросе, что вторая группа карт распределяется между вами и вашим оппонентом, тогда как у них есть две собственные карты, которые вы не видите. Быстрый глоссарий определения терминов карман , флоп , и река будет полезно.
DLosc
1
Также полезно: объяснение всей последовательности раунда. (Каждый игрок начинает с двух карт, известных только ему, затем сдаются три карты лицом вверх, затем четвертая, затем пятая, после чего каждый игрок формирует «руку» из любых пяти карт из семи видимых им .) Для кого-то может быть непонятно, почему есть семь карт, а рука состоит из пяти.
DLosc

Ответы:

3

Haskell , 433 430 425 байт

-5 байт благодаря @Laikoni

import Data.List
q="23456789TJQKA"
e=elem
l=length
b=map
r p|z,elem 'A'u,elem 'K'u=1|z=2|e 4t=3|v<3=4|w=5|y=6|e 3t=7|v<4=8|v<5=9|1>0=10where u=[n!!0|n<-p];v=l$nub u;t=b(\n->l[x |x<-u,x==n])q;w=all(==(last$p!!0))[last s|s<-p];y=elem""[u\\s|s<-b(take 5.flip drop('A':q))[0..10]];z=y&&w
0%_=[[]]
n%(x:y)=b(x:)((n-1)%y)++n%y
_%_=[]
h#t|let p=h++t;c i=minimum$b r$concat$b(5%)$b(++i)((7-l i)%([n:[s]|n<-q,s<-"SCHD"]\\p))=(c p,c t)

Попробуйте онлайн!

Ungolfed (та же идея, немного другая структура):

import Data.List -- for (\\)
numbers = "23456789TJQKA"

e=elem

rank_hand hand
    |royal_flush=1
    |straight_flush=2
    |four_of_a_kind=3
    |full_house=4
    |flush=5
    |straight=6
    |three_kind=7
    |two_pair=8
    |pair=9
    |1>0=10
    where nums = [head n | n<-hand]
          unique = length $ nub nums
          counts = map (\n->length [x | x<-nums, x==n]) numbers
          pair = unique < 5
          two_pair = unique < 4 -- could also be 3 of a kind, but that's ok
          three_kind = e 3 counts
          flush = all (==(last$hand!!0)) [last s|s<-hand]
          straight = elem "" [nums\\s | s <- map (take 5.flip drop ('A':numbers))[0..10]]
          full_house = unique < 3
          four_of_a_kind = e 4 counts
          straight_flush = straight && flush
          royal_flush = straight_flush && elem 'A' nums && elem 'K' nums

-- taken from /codegolf//a/34496/66460
-- k%l finds combinations of size k from a list l
0%_=[[]]
n%(x:y)=map(x:)((n-1)%y)++n%y
_%_=[]

-- find every combination available to each player, and rank each one. 
-- could be golfed a lot more.
h#t=let p=h++t
        a=[n:[s]|n<-numbers,s<-"SCHD"]\\p
        c i=minimum $ map rank_hand $ concat $ map (5%) $ map (++i) ((7-length i)%a)
    in(c p,c t)

Очень медленный, так как специального корпуса вообще нет (например, если карты не были показаны, всегда возможен флеш-рояль). Большая часть моих усилий в гольфе ушла на эту rank_handфункцию; #можно играть в гольф намного больше, комбинируя карты и тому подобное.

hand#tableрассчитывает оптимальные оценки для вас и вашего оппонента. Не проверяет ошибки.

vroomfondel
источник
Я думаю, что вы забыли s/elem/e/gпосле определения e=elem, так что вы должны сэкономить 9 байт. Я думаю, что вы также можете удалить некоторые пробелы, особенно там, где идентификаторы следуют непосредственно за числами
Julian Wolf
@JulianWolf Я все еще новичок в Haskell, но по какой-то причине он выглядит как e=elemвыведенный тип Int-> Bool, поэтому он не компилировался, когда я использовал e для нецелых вызовов elem. Я пытаюсь понять, почему, что было. Спасибо за подсказку на местах!
vroomfondel
Ах, ты прав. У Хаскелла иногда возникают проблемы с распознаванием полиморфных типов - я не уверен, что есть простое решение, кроме добавления флага гибких типов
Джулиан Вольф,
1
h#t=let[...]in[...]можно сократить до h#t|let[...]=[...]. И head nесть n!!0. У охранника &&может быть просто ,.
Лайкони