斗地主之顺子
题目描述
在斗地主扑克牌游戏中, 扑克牌由小到大的顺序为: 3,4,5,6,7,8,9,10,J,Q,K,A,2
,
玩家可以出的扑克牌阵型有: 单张, 对子, 顺子, 飞机, 炸弹等.
其中顺子的出牌规则为: 由至少5张由小到大连续递增的扑克牌组成, 且不能包含2.
例如: 3,4,5,6,7
, 3,4,5,6,7,8,9,10,J,Q,K,A
都是有效的顺子; 而 J,Q,K,A,2
, 2,3,4,5,6
, 3,4,5,6
, 3,4,5,6,8
等都不是顺子.
给定一个包含13张牌的数组, 如果有满足出牌规则的顺子, 请输出顺子.
如果存在多个顺子, 请每行输出一个顺子, 且需要按顺子的第一张牌的大小 (必须从小到大) 依次输出.
如果没有满足出牌规则的顺子, 请输出 No
.
输入描述
13张任意顺序的扑克牌, 每张扑克牌数字用空格隔开, 每张扑克牌的数字都是合法的, 并且不包括大小王:
2 9 J 2 3 4 K A 7 9 A 5 6
不需要考虑输入为异常字符的情况
输出描述
组成的顺子, 每张扑克牌数字用空格隔开:
3 4 5 6 7
示例1
输入:
2 9 J 2 3 4 K A 7 9 A 5 6
输出:
3 4 5 6 7
说明: 13张牌中可以组成的顺子只有1组: 3 4 5 6 7
.
示例2
输入:
2 9 J 10 3 4 K A 7 Q A 5 6
输出:
2
3 4 5 6 7
9 10 J Q K A
示例3
输入:
2 9 9 9 3 4 K A 10 Q A 5 6
输出:
No
题解
Python
import sys
def num_to_card(num: int) -> str:
mapping = [
# 忽略无效的值
"", "", "",
# 从3到 A, 2
"3", "4", "5", "6", "7", "8", "9", "10",
"J", "Q", "K", "A", "2"
]
return mapping[num]
def card_to_num(card: str) -> int:
mapping = {
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9,
"10": 10,
"J": 11,
"Q": 12,
"K": 13,
"A": 14,
"2": 15,
}
return mapping[card]
def main():
# 读取所有的牌
cards = [card_to_num(card) for card in input().split()]
cards.sort()
assert len(cards) == 13
flash_list = []
last_flash_card = 15
first_card = 3
while first_card < 10:
if first_card not in cards:
first_card += 1
continue
temp_cards = []
for card in range(first_card, last_flash_card):
if card in cards:
temp_cards.append(card)
elif len(temp_cards) >= 5:
# 保存顺子
for card in temp_cards:
cards.remove(card)
flash_list.append(temp_cards)
temp_cards = []
else:
for card in temp_cards:
cards.remove(card)
temp_cards = []
# 检查最后一组顺子
if len(temp_cards) >= 5:
# 保存顺子
for card in temp_cards:
cards.remove(card)
flash_list.append(temp_cards)
temp_cards = []
# 给顺子排序
# 1. 基于顺子中的第一张牌
# 2. 基于顺子的长度
flash_list.sort(key = lambda flash: (flash[0], len(flash)))
# 打印结果
# 将数字转换成牌
if flash_list:
print(len(flash_list))
for flash in flash_list:
print(" ".join(num_to_card(num) for num in flash))
else:
print("No")
if __name__ == "__main__":
main()
Rust
use std::io::{stdin, BufRead}; use std::mem; fn num_to_card(num: i32) -> &'static str { match num { // 从3到 A, 2 // 忽略无效的值 3 => "3", 4 => "4", 5 => "5", 6 => "6", 7 => "7", 8 => "8", 9 => "9", 10 => "10", 11 => "J", 12 => "Q", 13 => "K", 14 => "A", 15 => "2", _ => panic!("Invalid card num"), } } // 将牌转换成整数 fn card_to_num(card: &str) -> i32 { match card { "3" => 3, "4" => 4, "5" => 5, "6" => 6, "7" => 7, "8" => 8, "9" => 9, "10" => 10, "J" => 11, "Q" => 12, "K" => 13, "A" => 14, "2" => 15, _ => panic!("Invalid card"), } } fn remove_slice<T: PartialEq>(list1: &mut Vec<T>, list2: &[T]) -> usize { let mut count = 0; for item in list2 { if let Some(pos) = list1.iter().position(|x| x == item) { list1.remove(pos); count += 1; } } count } fn main() { // 读取所有的牌 let mut line = String::new(); let ret = stdin().lock().read_line(&mut line); assert!(ret.is_ok()); let mut cards: Vec<i32> = line.split_ascii_whitespace().map(card_to_num).collect(); cards.sort_unstable(); assert_eq!(cards.len(), 13); let mut flash_list = Vec::new(); let last_flash_card = 15; let mut first_card = 3; // 找出所有的顺子 while first_card < 10 { // 顺子中的第一张牌. if !cards.contains(&first_card) { first_card += 1; continue; } let mut temp_cards = Vec::new(); for card in first_card..last_flash_card { if cards.contains(&card) { temp_cards.push(card); } else if temp_cards.len() >= 5 { // 有效顺子, 保存顺子 remove_slice(&mut cards, &temp_cards); let mut flash = Vec::new(); mem::swap(&mut flash, &mut temp_cards); flash_list.push(flash); } else { // 无效顺子 remove_slice(&mut cards, &temp_cards); temp_cards.clear(); } } // 检查最后一组顺子 if temp_cards.len() >= 5 { // 保存顺子 remove_slice(&mut cards, &temp_cards); flash_list.push(temp_cards); } } // 给顺子排序 // 1. 基于顺子中的第一张牌 // 2. 基于顺子的长度 flash_list.sort_by_key(|flash| (flash[0], flash.len())); // 打印结果 // 将数字转换成牌 if !flash_list.is_empty() { println!("{}", flash_list.len()); for flash in flash_list { let s = flash .into_iter() .map(num_to_card) .collect::<Vec<_>>() .join(" "); println!("{s}"); } } else { println!("No"); } }