题目名称
Quiz #3 - Heaviest Prime Words
题目内容:
背景
单词由52个字母组成,包括26个大写字母和26个小字母,以及两种类型的标点符号,连字符(-)和撇号(')。
字母的权重由其与字母 a 的距离(以字母表表示)来定义。所以 weight(a) = 0, weight(b) = 1 ...重量(z) = 25。
大写字母的权重等于其小写字母。所以重量(a)=重量(A)。
所有标点符号都没有权重。
单词的权重是每个字母和标点符号的总和。所以 weight(cat) = 21, weight(I'm) = 20。
素数词是权重为素数的单词,例如,be 因为 weight(be) = 5。
问题
你能找到前3个最重的素数词出现在诗歌 《If》 中吗?
If you can keep your head when all about you Are losing theirs and blaming it on you, If you can trust yourself when all men doubt you, But make allowance for their doubting too; If you can wait and not be tired by waiting, Or being lied about, don’t deal in lies, Or being hated, don’t give way to hating, And yet don’t look too good, nor talk too wise: If you can dream — and not make dreams your master; If you can think — and not make thoughts your aim; If you can meet with Triumph and Disaster And treat those two impostors just the same; If you can bear to hear the truth you’ve spoken Twisted by knaves to make a trap for fools, Or watch the things you gave your life to, broken, And stoop and build ’em up with worn-out tools: If you can make one heap of all your winnings And risk it on one turn of pitch-and-toss, And lose, and start again at your beginnings And never breathe a word about your loss; If you can force your heart and nerve and sinew To serve your turn long after they are gone, And so hold on when there is nothing in you Except the Will which says to them: ‘Hold on!’ If you can talk with crowds and keep your virtue, Or walk with Kings — nor lose the common touch, If neither foes nor loving friends can hurt you, If all men count with you, but none too much; If you can fill the unforgiving minute With sixty seconds’ worth of distance run, Yours is the Earth and everything that’s in it, And — which is more — you’ll be a Man, my son!
解题思路:
- 通过字符输入流 BufferedReader 逐行读取 txt 文件。
- 通过正则表达式将单词从字符串中分割,并存储到 set 中,根据集合特性使得无重复值。
- 遍历 set 集合,将单词中的字母(排除掉其他字符并忽略大小写)对应字母表的下标并求和,即为权重。
- 权重中排除2与5的倍数后,将单词作为 key ,权重作为 value 保存在 map 中。
- 将权重保存到 List 中进行排序。
- 将排序得到的最大权重依次进行判断,是否为素数。
- 若为素数,作为 value 遍历 map 得到 key 并输出,并记录打印输出的次数。
- 当打印输出的次数等于3时,程序停止运行。
Java代码:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
public class HPW {
public static void main(String[] args) {
// 获取文件中的单词
Set charSet = getCharSet("E:\\Java300\\untitled\\src\\hpw.txt");
// 计算单词权重的键值对
Map<String, Integer> map = new TreeMap<>(); // 权重键值对
List heaviestList = new ArrayList(); // 权重列表(用来排序)
for (Object str : charSet) {
int heaviest = calcHeaviest((String) str);
if (heaviest != 0) { // 权重不为0表示已排除掉2和5的倍数
map.put((String) str, heaviest);
heaviestList.add(heaviest);
}
}
// 按照 heaviestList(权重)降序,找到素数权重排名前3的字符串
Collections.sort(heaviestList);
int printCount = 0; // 打印次数
for (int i = heaviestList.size()-1; i > 0; i--) {
// 判断是否是素数
if (isPrimeNumber((Integer) heaviestList.get(i))) {
// 输出value对应的key
for (String getKey : map.keySet()) {
if (map.get(getKey).equals(heaviestList.get(i))) {
System.out.println(getKey+"---->"+heaviestList.get(i));
}
}
printCount++;
}
if (printCount >= 3) { // 打印三个字符串后退出
break;
}
}
}
/**
* 获取文件中的单词列表
*
* @return 不重复的单词的集合
*/
private static Set getCharSet(String fileName) {
Set set = new HashSet<>();
try {
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line;
while ((line = br.readLine()) != null) {
for (String s : line.split("\\s+")) {
if (s.length() > 2) {
set.add(s);
}
}
}
br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return set;
}
/**
* 计算权重
*
* @param str
* @return
*/
public static int calcHeaviest(String str) {
// 构建字母表
List<Character> c = new ArrayList<>();
for (int i = 0; i < 26; i++) {
c.add((char) (97 + i));
}
// 遍历单词的每个字母,计算权重Heaviest
int heaviest = 0;
for (int i = 0; i < str.length(); i++) {
// 找到单词每个字母(忽略大小写)对应字母表的下标并求和,即为权重
char s = str.toLowerCase().charAt(i);
if (s >= 'a' && s <= 'z' || s >= 'A' && s <= 'Z') {
heaviest += c.indexOf(s);
}
}
// 排除2和5的倍数
if (heaviest % 2 == 0 & heaviest % 5 == 0) {
return 0;
}
return heaviest;
}
/**
* 判断素数
*
* @param nums
* @return boolean
*/
public static boolean isPrimeNumber(int nums) {
boolean flag = true;
for (int i = 3; i < nums; i++) {
if (nums % i == 0) {
flag = false;
break;
}
}
return flag;
}
}
End
在做题过程中,解题思路很快有了明确的方向,但容器的特性与方法的使用尚不熟练,应在之后的题目中多加练习。
转载请声明,谢谢!