本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是:
-
无论用户说什么,首先把对方说的话在一行中原样打印出来;
-
消除原文中多余空格:把相邻单词间的多个空格换成 1
个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉; -
把原文中所有大写英文字母变成小写,除了 I;
-
把原文中所有独立的 can you、could you 对应地换成 I can、I could——
这里“独立”是指被空格或标点符号分隔开的单词; -
把原文中所有独立的 I 和 me 换成 you;
-
把原文中所有的问号 ? 换成惊叹号 !; 在一行中输出替换后的句子作为 AI 的回答。
输入格式:
输入首先在第一行给出不超过 10 的正整数 N,随后 N 行,每行给出一句不超过 1000 个字符的、以回车结尾的用户的对话,对话为非空字符串,仅包括字母、数字、空格、可见的半角标点符号。
输出格式:
按题面要求输出,每个 AI 的回答前要加上 AI: 和一个空格。
输入样例:
6
Hello ?
Good to chat with you
can you speak Chinese?
Really?
Could you show me 5
What Is this prime? I,don 't know
输出样例:
Hello ?
AI: hello!
Good to chat with you
AI: good to chat with you
can you speak Chinese?
AI: I can speak chinese!
Really?
AI: really!
Could you show me 5
AI: I could show you 5
What Is this prime? I,don 't know
AI: what Is this prime! you,don’t know
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
Reader.init(System.in);
int N = Reader.nextInt();
for (int i = 0; i < N; i++) {
String str = Reader.nextLine();
System.out.println(str);
StringBuilder ans = new StringBuilder();
ans.append("AI:");
// 初始化 在标点符号前加一个空格
str = init(str);
// 分割处理
String[] tmp = str.split(" ");
String pre = "";
for (String item : tmp) {
// 略过空字符串
if (!item.equals("")) {
// 大写转小写 和 ?转!
item = toLowCase(item);
if (start_char(item)) {// 把标点符号前面的空格删掉
ans.append(item);
} else {
if (item.equals("you")) { // can you could you转换
if(pre.equals("can")) {
ans.replace(ans.length() - 3, ans.length(), "I can");
}else if(pre.equals("could")) {
ans.replace(ans.length() - 5, ans.length(), "I could");
}else {
ans.append(" " + item);
}
}else if(item.equals("I")||item.equals("me")) {
ans.append(" you");
}else {
ans.append(" " + item);
}
}
pre = item;
}
}
// 判断是否是标点符号开头
if(!ans.toString().contains("AI: ")) {
ans.replace(0, 3, "AI: ");
}
System.out.println(ans.toString());
}
}
static String init(String s) {
StringBuilder temp = new StringBuilder();
char[] chs = s.toCharArray();
for (int j = 0; j < chs.length; j++) {
if (!isChar(chs[j])) {
temp.append(" " + chs[j]);
} else {
temp.append(chs[j]);
}
}
return temp.toString();
}
static boolean isChar(char c) {
if (c >= '0' && c <= '9')
return true;
if (c >= 'A' && c <= 'Z')
return true;
if (c >= 'a' && c <= 'z')
return true;
return false;
}
static String toLowCase(String s) {
char[] c = s.toCharArray();
for (int i = 0; i < c.length; i++) {
if (c[i] != 'I' && (c[i] >= 'A' && c[i] <= 'Z')) {
c[i] += 32;
} else if (c[i] == '?') {
c[i] = '!';
}
}
return new String(c);
}
static boolean start_char(String s) {
return !isChar(s.charAt(0));
}
}
// Class for buffered reading int and double values *//*
class Reader {
static BufferedReader reader;
static StringTokenizer tokenizer;
// ** call this method to initialize reader for InputStream *//*
static void init(InputStream input) {
reader = new BufferedReader(new InputStreamReader(input));
tokenizer = new StringTokenizer("");
}
static void init(File file) {
try {
reader = new BufferedReader(new FileReader(file));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
tokenizer = new StringTokenizer("");
}
// ** get next word *//*
static String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
// TODO add check for eof if necessary
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
static String nextLine() throws IOException {
return reader.readLine();
}
static int nextInt() throws IOException {
return Integer.parseInt(next());
}
static char nextChar() throws IOException {
return next().toCharArray()[0];
}
static float nextFloat() throws IOException {
return Float.parseFloat(next());
}
static Double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}
下面是后面再一次写这题的时候写的代码,虽然这次思路更加清晰,但是不知道为何有一个测试点一直过不去,上面写的那次却过去了。先留下了,后面再思考了。
总的思路还是先在标点符号前面加一个空格,方便分割。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
Reader.init(System.in);
Writer.init(System.out);
slove();
Writer.close();
}
// 解答入口
static void slove() throws IOException {
int n = Reader.nextInt();
while (n-- > 0) {
String str = Reader.nextLine();
// 不管用户说什么,先打印一次
Writer.println(str);
// 在每个标点符号前面加上空格来限制标点符号只能独立出现或者出现在字符串的开头
str = init(str);
// 处理字符串
Writer.println(deal(str));
}
}
// 初始化,在每个标点符号前面加上空格来限制标点符号只能独立出现或者出现在字符串的开头
static String init(String str) {
StringBuilder sb = new StringBuilder();
char[] chs = str.toCharArray();
for (char c : chs) {
if (!check(c) && c != ' ') {
sb.append(" " + c);
} else {
sb.append(c);
}
}
return sb.toString();
}
static String deal(String str) {
LinkedList<String> list = new LinkedList<String>();
// 第一步 分割字符串,分割结果中不包含空格,但是包含""和",word"
String[] datas = str.split(" ");
for (int i = 0; i < datas.length; i++) {
// 跳过空字符串
if (datas[i].equals(""))
continue;
// 第二步 大写转小写,?转!,后面就不需要判断大写字母(除了"I")
String _s = toLowerCase(datas[i]);
// 第三步
// *当前字符是独立的"can"|"could"?
// **查看后面一个是否是"you"?先加入一个字符串"I",然后加入自己,并跳过后面一个字符串:直接使用
// *独立的"I"|"me"?替换成"you":直接使用
if (_s.matches("[^a-zI\\d]?(can|could)")) {
// 这里可能出现空字符串,所以要找到第一个不为空的字符串来判断
while (datas[i + 1].equals("") && i + 1 < datas.length) {
i++;
}
String next = toLowerCase(datas[i + 1]);
if (next.matches("you")) {
String retain = "";
// 如果"can|could"前面有标点符号,则保留下来
char c = _s.charAt(0);
if (c != 'c') {
retain = c + "I " + _s.substring(1);
} else {
retain = "I " + _s;
}
list.add(retain);
i++;
} else {
list.add(_s);
}
} else if (_s.matches("[^a-zI\\d]?(I|me)")) {
// 同样,判断第一个是否是标点符号,是则保留
char c = _s.charAt(0);
if (c == 'I' || c == 'm') {
list.add("you");
} else {
list.add(c + "you");
}
} else {
list.add(_s);
}
}
// 接下来只需要在非标点符合开头的字串前面加入空格即可(除了第一个前面不加空格)
StringBuilder sb = new StringBuilder();
Iterator<String> iterator = list.iterator();
String current = iterator.next();
sb.append("AI: " + current);
while (iterator.hasNext()) {
current = iterator.next();
if (check(current.charAt(0))) {
sb.append(" " + current);
} else {
sb.append(current);
}
}
return sb.toString();
}
// 判断当前字符是否是数字或字母
static boolean check(char c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z');
}
// 大写转小写 ? !
static String toLowerCase(String str) {
StringBuilder sb = new StringBuilder();
for (char c : str.toCharArray()) {
if (c != 'I' && c >= 'A' && c <= 'Z') {
sb.append((char) (c + 'a' - 'A'));
} else if (c == '?') {
sb.append('!');
} else {
sb.append(c);
}
}
return sb.toString();
}
}
// 以下是输入输出模板和思路逻辑无关
class Reader {
static BufferedReader reader;
static StringTokenizer tokenizer;
// ** call this method to initialize reader for InputStream *//*
static void init(InputStream input) {
reader = new BufferedReader(new InputStreamReader(input));
tokenizer = new StringTokenizer("");
}
// ** get next word *//*
static String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
static String nextLine() throws IOException {
return reader.readLine();
}
static int nextInt() throws IOException {
return Integer.parseInt(next());
}
static long nextLong() throws IOException {
return Long.parseLong(next());
}
static char nextChar() throws IOException {
return next().toCharArray()[0];
}
static float nextFloat() throws IOException {
return Float.parseFloat(next());
}
static Double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}
class Writer {
static BufferedWriter writer;
static void init(OutputStream outputStream) {
writer = new BufferedWriter(new OutputStreamWriter(outputStream));
}
static void print(Object object) throws IOException {
writer.write(object.toString());
}
static void println(Object object) throws IOException {
writer.write(object.toString());
writer.write("\n");
}
static void close() throws IOException {
// TODO Auto-generated method stub
writer.close();
}
}