L1-064 估值一億的AI核心代碼 (20 分)
以上圖片來自新浪微博。
本題要求你實現一個稍微更值錢一點的 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
解題思路:一個億的代碼,就是考驗語文功底好不好。。。規則7個,其中的5個是需要我們處理的。。。通過對樣例的分析,發現第四條規則應該是在第二條規則的基礎上進行修改,也就是說要先處理空格。。。那麼就先將第二、三、六規則進行一次轉換。。。四和五留在後面。。。那麼問題來了,兩個規則是有先後之分,還是說同時進行呢。。。如果不是同時進行也許就會出現此類情況:[(can I)->(can you)->(I can)] ,經過後面測試發現,兩條規則是同時進行的,不會出現這種情況。。。那麼就同時進行判斷,然後輸出。。。
此外還有幾個坑(個人覺得是坑):
(1)如果輸入的是全部是空格,那麼全部刪除,沒有內容。。。此坑出現在樣例4
(2)aaa .,,,,,:應該輸出:aaa.,,,,,(沒有空格)
(3)....... .,,,,,:應該輸出:........,,,,,(沒有空格)
(4)....... aaa:應該輸出:....... aaa(一個空格)
代碼如下:
#include<stdio.h>
#include<string.h>
const int maxn = 1e4 + 5;
char s[10004], s1[10004];
int t = 0;
///大寫轉換成小寫
char f(char c)
{
return (c >= 'A'&&c <= 'Z'&&c != 'I') ? c + 32 : c;
}
///是否屬於字符
int check(char c)
{
return (c >= 'A'&&c <= 'Z') || (c <= 'z'&&c >= 'a');
}
///是否屬於數字
int checkNum(char c)
{
return (c >= '0'&&c <= '9');
}
///字母或者數字
int check1(char s)
{
return check(s) || checkNum(s);
}
///字符串判斷
int ff(int x, char str[])
{
int i, l = strlen(str);
for (i = 0; i < l&&x < t; i++, x++)
if (s1[x] != str[i]) return 0;
return i == l ? 1 : 0;
}
///初步處理,大寫轉小寫、符號轉換、處理空格
void fun()
{
t = 0;
memset(s1, 0, sizeof(s1));
int l = strlen(s);
int i = 0;
while (s[i] == ' '&&s[i] != '\0')
i++;
while (s[l - 1] == ' '&&l >= i)
l--;
int flag = 0;
for (; i < l; i++)
{
if (s[i] == '?')
s1[t++] = '!';
else if (s[i] == ' ')
{
if (!flag)
{
if (check1(s[i + 1]))
s1[t++] = s[i];
}
else
{
if (check1(s[i + 1]))
{
s1[t++] = s[i];
}
}
}
else
{
flag = check1(s[i]);
s1[t++] = f(s[i]);
}
}
s1[t] = 0;
}
int main()
{
int n;
scanf("%d", &n);
getchar();
while (n--)
{
gets(s);
fun();
printf("%s\nAI: ", s);
for (int i = 0; i < t; i++)
{
///‘I’的前面要麼沒有字符,要麼不是數字也不是字母,後面同樣的
if (s1[i] == 'I' && (!i || !check1(s1[i - 1])) && !check1(s1[i + 1]))
printf("you");
else if ((!i || !check1(s1[i - 1])) && s1[i] == 'm'&&s1[i + 1] == 'e' && !check1(s1[i + 2]))
{
printf("you");
i++;
}
else if ((!i || !check1(s1[i - 1])) && s1[i] == 'c'&&s1[i + 1] == 'a')
{
///判斷是否會出現“can youooo”此類情況
if (ff(i, "can you") && !check1(s1[i + 7]))
{
printf("I can");
///此處不加7而是加6是因爲,for循環內的i++,會加1
i += 6;
}
else
printf("%c", s1[i]);
}
else if ((!i || !check(s1[i - 1])) && s1[i] == 'c'&&s1[i + 1] == 'o')
{
if (ff(i, "could you") && !check1(s1[i + 9]))
{
printf("I could");
i += 8;
}
else
printf("%c", s1[i]);
}
else
{
printf("%c", s1[i]);
}
}
printf("\n");
}
return 0;
}