题目描述
石头剪刀布游戏有 3 种出拳形状:石头、剪刀、布。分别用字母A、B、C表示。
游戏规则:
- 出拳形状之间的胜负规则如下:
A > B;
B > C;
C > A;">" 左边一个字母,表示相对优势形状。右边一个字母,表示相对劣势形状。
- 当本场次中有且仅有一种出拳形状优于其他出拳形状,则该形状的玩家是胜利者。否则认为是平局。
例如1:三个玩家出拳分别是A,B,C。由于三方优势循环(即没有任何一方优于其他出拳者),判断为平局。
例如2:三个玩家出拳分别是A,B,B。出拳A的获胜。
例如3:三个玩家出拳全部是A。判为平局。
- 当发生平局,没有赢家。有多个胜利者时,同为赢家。
输入描述
在一场游戏中,每个玩家的信息为一行。玩家数量不超过1000。每个玩家信息有2个字段,用空格隔开;
- 玩家ID:一个仅由英文字母和数字组成的字符串
- 出拳形状:以英文大写字母表示,A、B、C形状。
出拳时间:正整数,越小表示时间越早
例如:
abc1 A
xyz B
解释:玩家abc1出拳为石头(A)。玩家xyz出拳为剪刀(B)
输出描述
输出为赢家的玩家ID列表(一个或多个),每个ID一行,按字符串升序排列。如果没有赢家,输出为”NULL“字符串。
例如:
abc1
用例
输入 | abc1 A xyz B |
输出 | abc1 |
说明 | A比B有优势,abc1胜出 |
输入 | abc1 A xyz A |
输出 | NULL |
说明 | 没有优胜的出拳形状,平局 |
输入 | abc1 A def A alic A xyz B |
输出 | abc1 alic def |
说明 | A为优胜方,有三个赢家 |
题目解析
本题可以定义三个数组,分别统计出手势A、B、C的人名。
统计完后,再计数下非空数组的个数:
- 如果有三个,则说明三个手势都存在,平局
- 如果有一个,则说明只有一个手势,平局
- 如果有两个,则需要继续检查:
- 如果只有手势A,B,那么赢家就是手势A的玩家
- 如果只有手势A,C,那么赢家就是手势C的玩家
- 如果只有手势B,C,那么赢家就是手势B的玩家
最后将赢家人名进行字典序升序即可。
2023.12.19
对于Java,JS,Python这类自带字典结构的编程语言,我们可以用字典来统计出某个手势(key)的所有人名(ele)。
这样最后字典key的数量就是手势数量,如果key只有2个,那么就判断:
字典没有'A'的key => 只有手势B,C,那么赢家就是手势B的玩家
字典没有'B'的key => 只有手势A,C,那么赢家就是手势C的玩家
字典没有'C'的key => 只有手势A,B,那么赢家就是手势A的玩家
JS算法源码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
// 输入输出处理
void (async function () {
const map = new Map();
while (true) {
try {
const [player, gesture] = (await readline()).split(" ");
// 如果有人不按套路出,则此局作废
if (gesture < "A" && gesture > "C") {
console.log("NULL");
return;
}
// 统计各个手势的人名
if (!map.has(gesture)) {
map.set(gesture, []);
}
map.get(gesture).push(player);
} catch (e) {
break;
}
}
switch (map.size) {
case 1:
case 3:
// 只有一种手势,或者三种手势都有,则平局
console.log("NULL");
break;
case 2:
let ans;
if (!map.has("A")) {
// 没有A手势,只有B、C手势,则B赢
ans = map.get("B");
} else if (!map.has("B")) {
// 没有B手势,只有A、C手势,则C赢
ans = map.get("C");
} else {
// 没有C手势,只有A、B手势,则A赢
ans = map.get("A");
}
ans.sort().forEach((a) => console.log(a));
break;
}
})();
Java算法源码
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
public class Main {
// 输入输出处理
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
HashMap<Character, ArrayList<String>> map = new HashMap<>();
while (sc.hasNext()) {
String player = sc.next();
char gesture = sc.next().charAt(0);
// 如果有人不按套路出,则此局作废
if (gesture < 'A' || gesture > 'C') {
System.out.println("NULL");
return;
}
// 统计各个手势的出派人
map.putIfAbsent(gesture, new ArrayList<>());
map.get(gesture).add(player);
}
switch (map.size()) {
case 1:
case 3:
// 只有一种手势,或者三种手势都有,则平局
System.out.println("NULL");
break;
case 2:
ArrayList<String> ans;
if (!map.containsKey('A')) {
// 没有A手势,只有B、C手势,则B赢
ans = map.get('B');
} else if (!map.containsKey('B')) {
// 没有B手势,只有A、C手势,则C赢
ans = map.get('C');
} else {
// 没有C手势,只有A、B手势,则A赢
ans = map.get('A');
}
ans.sort(String::compareTo);
ans.forEach(System.out::println);
break;
}
}
}
Python算法源码
def getResult():
dic = {}
while True:
try:
player, gesture = input().split()
# 如果有人不按套路出,则此局作废
if gesture < 'A' or gesture > 'C':
print("NULL")
return
# 统计各个手势的人名
dic.setdefault(gesture, [])
dic[gesture].append(player)
except:
break
kinds = len(dic)
if kinds == 1 or kinds == 3:
# 只有一种手势,或者三种手势都有,则平局
print("NULL")
else:
ans = None
if 'A' not in dic:
# 没有A手势,只有B、C手势,则B赢
ans = dic['B']
elif 'B' not in dic:
# 没有B手势,只有A、C手势,则C赢
ans = dic['C']
else:
# 没有C手势,只有A、B手势,则A赢
ans = dic['A']
ans.sort()
for an in ans:
print(an)
# 算法调用
getResult()
C算法源码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_SIZE 1000
#define MAX_NAME_LENGTH 100
int cmp(const void *a, const void *b) {
return strcmp(((char *) a), ((char *) b));
}
int main() {
char A[MAX_SIZE][MAX_NAME_LENGTH];
int A_size = 0;
char B[MAX_SIZE][MAX_NAME_LENGTH];
int B_size = 0;
char C[MAX_SIZE][MAX_NAME_LENGTH];
int C_size = 0;
while (1) {
char s[MAX_NAME_LENGTH * 2] = {'