题目54:在扑克游戏中玩家1能赢多少局?
Poker hands
In the card game poker, a hand consists of five cards and are ranked, from lowest to highest, in the following way:
[*]High Card: Highest value card.
[*]One Pair: Two cards of the same value.
[*]Two Pairs: Two different pairs.
[*]Three of a Kind: Three cards of the same value.
[*]Straight: All cards are consecutive values.
[*]Flush: All cards of the same suit.
[*]Full House: Three of a kind and a pair.
[*]Four of a Kind: Four cards of the same value.
[*]Straight Flush: All cards are consecutive values of same suit.
[*]Royal Flush: Ten, Jack, Queen, King, Ace, in same suit.
The cards are valued in the order:
2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.
If two players have the same ranked hands then the rank made up of the highest value wins; for example, a pair of eights beats a pair of fives (see example 1 below). But if two ranks tie, for example, both players have a pair of queens, then highest cards in each hand are compared (see example 4 below); if the highest cards tie then the next highest cards are compared, and so on.
Consider the following five hands dealt to two players:
The file, poker.txt, contains one-thousand random hands dealt to two players. Each line of the file contains ten cards (separated by a single space): the first five are Player 1's cards and the last five are Player 2's cards. You can assume that all hands are valid (no invalid characters or repeated cards), each player's hand is in no specific order, and in each hand there is a clear winner.
How many hands does Player 1 win?
题目:
在扑克游戏中,一局牌由五张牌组成,组成的牌的大小由低向高如下:
[*]High Card: 最高值的牌.
[*]One Pair: 两张面值一样的牌.
[*]Two Pairs: 两个值不同的One Pair.
[*]Three of a Kind: 三张面值一样的牌.
[*]Straight: 所有的牌面值为连续数值.
[*]Flush: 所有的牌花色相同.
[*]Full House: Three of a Kind 加一个One Pair.
[*]Four of a Kind: 四张牌面值相同.
[*]Straight Flush: 所有的牌花色相同并且为连续数值.
[*]Royal Flush: 10,J,Q,K和A,并且为相同花色。
牌的面值大小排序如下:
2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.
如果两个玩家的牌具有同样的排序(上面介绍的几种),那么他们牌的大小由手中最大的牌决定。例如,一对 8 比一对 5 大(见下面例一);但是如果两个玩家都用一对 Q,那么他们手中最大的牌就用来比较大小(见下面例四);如果他们最高面值的牌也相等,那么就用次高面值的牌比较,以此类推。
考虑下面的几个例子:
文件包含一千局随机牌。每一行包含十张牌(用空格分隔);前五张是玩家 1 的牌,后五张是玩家 2 的牌。 所有的牌都是合理的(没有非法字符或者重复的牌)。每个玩家的牌没有顺序,并且每一局都有明确的输赢。
其中玩家 1 能赢多少局?
这题不是难,是很烦,要考虑很多种情况,写不同条件.
帖子长度关系,省略牌组数据,可以自行粘贴。
376
pokerdata = ['8C','TS','KC','9H','4S','7D','2S','5D','3S','AC','5C','AD','5D','AC','9C','7C','5H','8D','TD','KS','3H','7H','6S','KC','JS','QH','TD','JC','2D','8S','TH','8H',
######################
######################
###~~~省略牌组数据~~~###
######################
######################
'2D','JS','QD','AC','9C','JD','7C','6D','TC','6H','6C','JC','3D','3S','QC','KC','3S','JC','KD','2C','8D','AH','QS','TS','AS','KD','3D','JD','8H','7C','8C','5C','QD','6C']
def evalHand(hand):
values = ['2','3','4','5','6','7','8','9','T','J','Q','K','A']
flush = 1
suit = hand
for card in hand:
if card <> suit:
flush = 0
break
indices = []
royal = 1
straight = 1
for card in hand:
indices.append(values.index(card))
indices.sort()
if indices - indices <> 4 \
or indices.count(indices) > 1 \
or indices.count(indices) > 1 \
or indices.count(indices) > 1 \
or indices.count(indices) > 1 \
or indices.count(indices) > 1:
straight = 0
if indices <> 8:
royal = 0
kinds = []
for value in indices:
count = indices.count(value)
if count > 1:
kind =
if kind not in kinds:
kinds.append(kind)
if royal and flush:
# return "royal flush"
return
if straight and flush:
# return "straight flush"
return ]
if len(kinds) == 1 and kinds == 4:
# return "four of a kind"
return ]
if len(kinds) == 2 and (kinds + kinds == 5):
# return "full house"
return ]
if flush:
# return "flush"
return ]
if straight:
# return "straight"
return ]
if len(kinds) == 1 and kinds == 3:
# return "three of a kind"
return ]
if len(kinds) == 2 and (kinds + kinds == 4):
# return "two pair"
return , kinds)]
if len(kinds) == 1 and kinds == 2:
# return "one pair"
return ]
# return "high card"
return
rounds = []
for rd in range(1000):
rounds.append(pokerdata)
count = 0
for r in rounds:
p1 = evalHand(r)
p2 = evalHand(r)
if p1 > p2 or (p1 == p2 and p1 > p2):
count = count + 1
print count 本帖最后由 王小召 于 2019-6-25 13:25 编辑
总共进行了: 1000 次比赛
P1赢了: 379 次!
P2赢了: 621 次!
用时:0.156001 秒import re
import time
# 计算手牌属于哪种组合以及特征值
def cal_max(cards):
color = ', cards))]
value = ', cards)[:-1])]
for i in range(5):
if value == 'T':
value = 10
elif value == 'J':
value = 11
elif value == 'Q':
value = 12
elif value == 'K':
value = 13
elif value == 'A':
value = 14
else:
value = int(value)
value.sort()
if len(set(color)) == 1:
# # Case 9: 同花顺
if len(set() - int(value) for i in range(1, 5)])) == 1:
return
else:
# Case 6: 同花
return
else:
single_values = []
single_counts = []
for each_value in set(value):
single_values.append(each_value)
single_counts.append(value.count(each_value))
# Case 8: 炸弹
if 4 in single_counts:
return ]
# Case 7: 三条加一对
elif 3 in single_counts and 2 in single_counts:
return ]
# Case 4: 三条
elif 3 in single_counts:
return ]
# Case 3: 两个对子
elif 2 in single_counts and single_counts.count(2) == 2:
tmp = []
for i in range(len(single_counts)):
if single_counts == 2:
tmp.append(single_values)
tmp.sort()
return ]
# Case 2: 单个对子
elif 2 in single_counts:
max_value = single_values
single_values.remove(max_value)
single_values.sort()
return
# Case 5: 顺子
elif len(set() - int(value) for i in range(1, 5)])) == 1:
return
# Case 1: 单牌
else:
return
with open(r'C:\Users\wangyongzhao\Desktop\p054_poker.txt') as f:
cases = f.readlines()
total_games = len(cases)# 总胜场计数
count1 = 0# p1 胜场计数
count2 = 0# p2 胜场计数
for each in cases:
p1 = cal_max(each.strip()[:14])
p2 = cal_max(each.strip())
if p1 > p2:
count1 += 1
elif p1 < p2:
count2 += 1
else:
# 都是对子或者都是顺子,从第一结果看平局了, 分情况讨论
# 第一种情况,都是单牌(从大到小逆序挨个作比较,有不同值就产生结果)
if p1 == 1:
for i in range(4, -1, -1):
if p1 < p2:
count2 += 1
break
elif p1 > p2:
count1 += 1
break
# 第二种情况,都有对子(实际9个case都要分类讨论,但是file里只涉及这两种!)
elif p1 == 2:
if p1 > p2:
count1 += 1
elif p1 < p2:
count2 += 1
else:
for i in range(2, -1, -1):
if p1 < p2:
count2 += 1
break
elif p1 > p2:
count1 += 1
break
else:
print("未分类平局对决", p1, "《--》", p2)
print("总共进行了: {} 次比赛\nP1赢了: {} 次!\nP2赢了: {} 次!\n用时:{} 秒".format(total_games, count1, count2, time.process_time()))
vm = {'T' : 10, 'J' : 11, 'Q' : 12, 'K' : 13, 'A' : 14}
for i in range(2, 10):
vm = i
sm = {'C' : 0, 'D' : 1, 'S' : 2, 'H' : 3}
def fun(x):
v = * 15
s = * 4
for i in x:
v]] += 1
s]] += 1
r = * 9
r = max(map(lambda x: x if x != 0 else 0, enumerate(v)))
r = max(map(lambda x: x if x == 2 else 0, enumerate(v)))
r = r if len(list(filter(lambda x: x == 2, v))) == 2 else 0
r = max(map(lambda x: x if x == 3 else 0, enumerate(v)))
tmp = list(map(lambda x: 1 if x != 0 else 0, v))
r = max(map(lambda x: x if x == 5 else 0,
enumerate(map(lambda x: sum(tmp), range(5, 15)), start = 1)))
r = r if len(list(filter(lambda x: x == 5, s))) == 1 else 0
r = r if r != 0 and r != 0 else 0
r = max(map(lambda x: x if x == 4 else 0, enumerate(v)))
r = r if r != 0 and r != 0 else 0
return r
f = open('54.txt', 'r')
hand = list(map(lambda x: x.split(), filter(lambda x: len(x) != 0, f.read().split('\n'))))
print(len(list(filter(lambda x: fun(x[:5]) > fun(x), hand))))
https://github.com/devinizz/project_euler/blob/master/page02/54.py
持续更新中... 376
Process returned 0 (0x0) execution time : 0.058 s
Press any key to continue.
十分赞同2#的看法……本题思维难度不大,但极为复杂,情况众多,很容易犯错
我想我的代码或许可以再优化些……
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<string>
#include<cctype>
#include<map>
using namespace std;
const int M = 1000;
const string royal("TJQKA");
const string STRAIGHT("A23456789TJQKA");
string value,suit;
bool cmp(char i,char j);
int posi(char x){
for (int i = 0;i < 5;i++)
if (x == royal)return i;
}
void erase_char(char c,string & s){
do{
s.erase(find(s.begin(),s.end(),c) );
}while(find(s.begin(),s.end(),c) != s.end() );
}
bool p1win(const string & s1,const string & s2){
for (int i = s1.length() - 1; i >= 0;i--){
if (s1 == s2) continue;
if (!cmp(s1,s2) )return true;
if (cmp(s1,s2) )return false;
}
}
char dom(int p){
map<char,int> times;char domin;
int mx = 0;
for (int i = 0;i < value.length();i++){
char t = value;
if (!times.count(t) )times = 1;
else times++;
}
for (map<char,int>::iterator it = times.begin();it != times.end();++it)
if (it->second > mx){mx = it->second; domin = it->first;}
return domin;
}
bool cmp(char i,char j){
if (isdigit(i) && isdigit(j)) return i < j;
if (isdigit(i) && isalpha(j)) return true;
if (isdigit(j) && isalpha(i)) return false;
return posi(i) < posi(j);
}
bool is_straight(string & s){
sort(s.begin(),s.end(),cmp);
for (int i = 0;i < 10;i++)
if (s == STRAIGHT.substr(i,5)) return true;
return false;
}
bool isflush(string s){
for (int i = 0;i < s.length() - 1;i++)
if (s != s) return false;
return true;
}
int others(string s){
map<char,int> times;
for (int i = 0;i < s.length();i++){
char t = s;
if (!times.count(t) )times = 1;
else times++;
}
int sz = times.size();
if (sz == 5)return 0;
if (sz == 4)return 1;
if (sz == 2){
for (map<char,int>::iterator it = times.begin();it != times.end();++it){
if (it->second == 4)return 7;
if (it->second == 3)return 6;
}
}
if (sz == 3){
for (map<char,int>::iterator it = times.begin();it != times.end();++it){
if (it->second == 2)return 2;
if (it->second == 3)return 3;
}
}
return -1;//error
}
int judge_type(int p){
bool f = isflush(suit);
bool st = is_straight(value);
if (f && st)return 8;
if (!f && st) return 4;
if (f && !st) return 5;
return others(value);
return -1;//error
}
/*0:High Card 1:One Pair2:Two Pairs
3:Three of a Kind 4:Straight5:Flush
6:Full House 7:Four of a Kind
8:Straight Flush
*/
void print(){
cout << value << " " << value << endl;
cout << suit << " " << suit << endl << endl;
}
void ini(){
for (int i = 0;i < 2;i++){
value.clear();
suit.clear();
}
}
int main(){
freopen("i.in","r",stdin);
int cnt = 0;
for (int r = 0;r < M;r++){
ini();
for (int i = 0;i < 2;i++){
for (int j = 0;j < 5;j++){
string s;
cin >> s;
value.push_back(s);
suit.push_back(s);
}
}
//print();
int p1 = judge_type(0),p2 = judge_type(1);//此后,点数序列有序
//cout << p1 << " " << p2 << endl;cout << value << " " << value << endl;
if (p1 > p2) {cnt++;continue;}
if (p1 == p2){
switch(p1){
case 0:
case 5: if (p1win(value,value) )cnt++;
break;
case 4:
case 8: if (cmp(value,value) )cnt++;
break;
case 1:
case 3: {
char c1 = dom(0),c2 = dom(1);
if (c1 == c2) {
string s1 = value,s2 = value;
erase_char(c1,s1);sort(s1.begin(),s1.end(),cmp);
erase_char(c2,s2);sort(s2.begin(),s2.end(),cmp);
if (p1win(s1,s2)) {cnt++; break;}
}
if (cmp(c2,c1) ) cnt++;
break;
}
case 6:
case 7: {
char c1 = dom(0),c2 = dom(1);
if (c1 == c2){
char d1,d2;
for (int i = 0;i < 5;i++){
if (value != c1) {d1 = value; break;}
if (value != c2) {d2 = value; break;}
}
if (cmp(d2,d1) ){cnt++; break;}
}
if (cmp(c2,c1) ) cnt++;
break;
}
case 2: map<char,int> times;
string mypair;
char d;
for (int i = 0;i < 2;i++){
for (int j = 0;j < 5;j++){
char t = value;
if (!times.count(t) )times = 1;
else times++;
if (times == 2)mypair.push_back(t);
}
for (map<char,int>::iterator it = times.begin();it != times.end();++it)
if (it->second = 1) {d = it->first;break;}
sort(mypair.begin(),mypair.end(),cmp);
}
if (cmp(mypair,mypair) ){cnt++; break;}
else if (mypair == mypair){
if (cmp(mypair,mypair) ){cnt++; break;}
else if(mypair == mypair){
if (cmp(d,d) ){cnt++; break;}
}
}
}
}
}
cout << cnt << endl;
return 0;
}
实 际 开 发 实 况
我连题目都看不懂 import time as t
import numpy as np
start = t.perf_counter()
def evaluate_cards(suits, values):
# Scores. Pair: 3; Three of a kind: 7; Straight: 8; Flush: 9; Four of a Kind: 11; Royal Flush: 18
cards_value = 0
set_values = set(values)
is_straight = True
if len(set(suits)) == 1:
cards_value += 9
if set_values == (8, 9, 10, 11, 12):
cards_value += 9
for value in range(4):
if not (values - values == 1):
is_straight = False
if is_straight:
cards_value += 8
dict_cards = {value: values.count(value) for value in values}
pair_count, three_count, four_count = 0, 0, 0
for value in dict_cards:
if dict_cards == 2:
pair_count += 1
elif dict_cards == 3:
three_count += 1
elif dict_cards == 4:
four_count += 1
cards_value += (pair_count * 3 + three_count * 7 + four_count * 11)
return cards_value, dict_cards
def compare_cards(cards_list_1, cards_list_2):
cards_order = ['2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A']
values_1, suits_1, values_2, suits_2 = [], [], [], []
for card in range(5):
values_1.append(cards_order.index(cards_list_1))
suits_1.append(cards_list_1)
values_2.append(cards_order.index(cards_list_2))
suits_2.append(cards_list_2)
values_1.sort()
values_2.sort()
cards_value_1, cards_dict_1 = evaluate_cards(suits_1, values_1)
cards_value_2, cards_dict_2 = evaluate_cards(suits_2, values_2)
if cards_value_1 > cards_value_2:
return True
elif cards_value_1 < cards_value_2:
return False
elif cards_value_1 == 17 or cards_value_1 == 9 or cards_value_1 == 8 or cards_value_1 == 0:
for max_value in range(-1, -6, -1):
if values_1 > values_2:
return True
elif values_1 < values_2:
return False
elif cards_value_1 == 3 or cards_value_1 == 6 or cards_value_1 == 7 or cards_value_1 == 10 or cards_value_1 == 11:
while True:
if max(cards_dict_1.values()) > 1:
max_value_1 = max(cards_dict_1, key=lambda x: cards_dict_1)
max_value_2 = max(cards_dict_2, key=lambda x: cards_dict_2)
else:
max_value_1 = max(cards_dict_1)
max_value_2 = max(cards_dict_2)
if max_value_1 > max_value_2:
return True
elif max_value_1 < max_value_2:
return False
else:
cards_dict_1 = 0
cards_dict_2 = 0
hands = np.loadtxt('C:/Users/wuhw/Desktop/p054_poker.txt', dtype=str)
count_1_win = 0
for all_cards in hands:
cards_list = list(all_cards)
res = compare_cards(cards_list[:5], cards_list)
if res:
count_1_win += 1
print(count_1_win)
print("It costs %f s" % (t.perf_counter() - start))
376
It costs 0.038529 s
浪费一个小时做这个破题,我真的是个傻逼
页:
[1]