本題要求你實現一個稍微更值錢一點的 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();
}
}