L1-064 估值一億的AI核心代碼 (2019天梯賽 1-8)

L1-064 估值一億的AI核心代碼 (20 分)

AI.jpg

以上圖片來自新浪微博。

本題要求你實現一個稍微更值錢一點的 AI 英文問答程序,規則是:

  • 無論用戶說什麼,首先把對方說的話在一行中原樣打印出來;
  • 消除原文中多餘空格:把相鄰單詞間的多個空格換成 1 個空格,把行首尾的空格全部刪掉,把標點符號前面的空格刪掉;
  • 把原文中所有大寫英文字母變成小寫,除了 I
  • 把原文中所有獨立的 can youcould you 對應地換成 I canI 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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章