PTA L1-064 估值一亿的AI核心代码,详解+每一个测试点的分析

这篇具有很好参考价值的文章主要介绍了PTA L1-064 估值一亿的AI核心代码,详解+每一个测试点的分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 题目说明:

作者 陈越        单位 浙江大学

本题要求你实现一个稍微更值钱一点的 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

注意本题有些坑(警示后人):

        I、此题的输入并不一定正常(如可能在字符串中穿插多个空格(前、中、后)、字符串可能以标点符号开头、标点符号前面的空格是不需要的)。

        II、可能会在第一次进行替换过后,恰好凑成了其他关键词(同一位置发生连续替换是错误行为)。
        如果成功解决以上问题,此题便解决了。

解题思路:      

        初级思路:

        看到这道题,首先的一个想法就是遍历字符串,遍历的同时看有无符合条件(即可替换的字符串),如若有可替换的字符串,立即替换即可。

#include<bits/stdc++.h>
using namespace std;
	string str;
string s1="can you",s11="I can";
string s2="could you",s22="I could";
string s31="I",s32="me",s33="you";
int isletter(char ch){
	if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z') return 1;
	return 0;
}

int main(){
	int N;cin>>N;getchar();
	for(int i=0;i<N;++i){
		getline(cin,str); 
		cout<<str<<endl;
		str=" "+str;
		//大写转小写 并格式化语句 
		for(int i=0;i<str.length();++i){
			if(str[i]==' '&&!isletter(str[i+1])&&!isdigit(str[i+1])){
				 str.erase(i,1); i--;
			}
			if(str[i]>='A'&&str[i]<='Z'&&str[i]!='I') str[i]+=32;
			if(str[i]=='?') str[i]='!';
		}
		//独立的 I 换成 you 	string s31="I",s32="me",s33="you";
		for(int i=0;i<str.length();++i){
			i=str.find(s31,i);
			if(i==-1) break;
			if(!(isletter(str[i-1])||isletter(str[i+s31.length()])))
				str.replace(i,s31.length(),s33);
		}
	//	cout<<"str换前:"+str<<"---------"<<endl; 
		//独立的 me 换成 you 	string s31="I",s32="me",s33="you";
		for(int i=0;i<str.length();++i){
			i=str.find(s32,i);
			if(i==-1) break;
			if(!isletter(str[i-1])){
				str.replace(i,s32.length(),s33);
			}
		}
	//	cout<<"str换后:"+str<<"---------"<<endl; 
		// can you 换成 I can  		string s1="can you",s11="I can";
		for(int i=0;i<str.length();++i){
			i=str.find(s1,i);
			if(i==-1) break;
			if(!(isletter(str[i-1])||isletter(str[i+s1.length()])))
				str.replace(i,s1.length(),s11); 
		}
		// could you 换成 I could  		string s2="could you",s22="I could";
		for(int i=0;i<str.length();++i){
			i=str.find(s2,i);
			if(i==-1) break;
			if(!(isletter(str[i-1])||isletter(str[i+s2.length()])))
				str.replace(i,s2.length(),s22);
		}
		cout<<"AI:"+str+"\n";
	}
}

        很显然,没有通过所有测试点。 仔细思考,发现错误样例:

1
can me

正确输出应为 :

can you

而以上程序会输出 I can ,这说明此程序在输入can me时,先将can me变成了can you,此时can you恰好是关键字,此时can you便会再次被替换成I can。由此输出了错误答案。

        初级思路bug的解决:

由此分析,不难想到解决方案:

        I、给字符串增加标记数组,当原字符串的某部分被替换过后,便用标记数组来记录此位置,此后需要替换此位置时先检查此位置是否曾被替换过,若为否,再进行替换。

        II、在替换时,不将 I、me 替换成you(因为这样会导致连续替换同一位置导致错误输出)。而是将 I、me 替换成yoU,这样一来就解决了替换过后会再次替换成I can的问题。最后在输出前再将所有的U转换成u即可。

        本人比较赞成第二种解决方案。下面给出写法。

#include<bits/stdc++.h>
using namespace std;
	string str; 
string s1="can you",s11="I can";
string s2="could you",s22="I could";
string s31="I",s32="me",s33="yoU";

//isletter函数用来判断当前字符是否为字母,1代表为字母 
int isletter(char ch){
	if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z') return 1;
	return 0;
}
int main(){ 
	int N;cin>>N;getchar();
	for(int i=0;i<N;++i){
		getline(cin,str); 
		cout<<str<<endl;
		str=" "+str;
		//大写转小写 并格式化语句 
		for(int i=0;i<str.length();++i){
			if(str[i]==' '&&!isletter(str[i+1])&&!isdigit(str[i+1])){
				 str.erase(i,1);
				 i--;
			}
			if(str[i]>='A'&&str[i]<='Z'&&str[i]!='I') str[i]+=32;
			if(str[i]=='?'){
				 str[i]='!';
			}
		}
		//独立的 I 换成 you 	string s31="I",s32="me",s33="you";
		for(int i=0;i<str.length();++i){
			i=str.find(s31,i);
			if(i==-1) break;
			if(!(isletter(str[i-1])||isletter(str[i+s31.length()]))){
				str.replace(i,s31.length(),s33);
			}
		}
	//	cout<<"str换前:"+str<<"---------"<<endl; 
		//独立的 me 换成 you 	string s31="I",s32="me",s33="you";
		for(int i=0;i<str.length();++i){
			i=str.find(s32,i);
			if(i==-1) break;
			if(!(isletter(str[i-1])||isletter(str[i+s32.length()]))){
				str.replace(i,s32.length(),s33);
			}
		}
	//	cout<<"str换后:"+str<<"---------"<<endl; 
		// can you 换成 I can  		string s1="can you",s11="I can";
		for(int i=0;i<str.length();++i){
			i=str.find(s1,i);
			if(i==-1) break;
			if(!(isletter(str[i-1])||isletter(str[i+s1.length()]))){
				str.replace(i,s1.length(),s11); 
			}
		}
		// could you 换成 I could  		string s2="could you",s22="I could";
		for(int i=0;i<str.length();++i){
			i=str.find(s2,i);
			if(i==-1) break;
			if(!(isletter(str[i-1])||isletter(str[i+s2.length()]))){
				str.replace(i,s2.length(),s22);
			}
		}
		for(int i=0;i<str.length();++i){
			if(str[i]=='U') str[i]='u';
		}
		if(str[0]!=' ') str=" "+str; 
		cout<<"AI:"+str+"\n";
	}
}

经过以上修改,此时AC了。 

此题小结:

        当遇到会连续反复替换的情况,不一定设置标记数组才可以解决bug。尝试使用假串来替换也是个不错的选择。

        此外,特别感谢  这篇博客给我的启发。这篇博客讲述了很不错的找出错误样例的方法,还提及到了本题的所有测试点,让我学到了很多东西。

初级小白(在校生)整理以用作学习,若有错误,还望指正,共勉!

初次书写,若存在侵权或其他问题,定立即改正,还望海涵。

 文章来源地址https://www.toymoban.com/news/detail-856439.html

到了这里,关于PTA L1-064 估值一亿的AI核心代码,详解+每一个测试点的分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • PTA L1-025 正整数A+B(详解)

    前言:本期是关于正整数A+B的详解,内容包括四大模块:题目,代码实现,大致思路,代码解读,今天你c了吗?   题的目标很简单,就是求两个正整数 A 和 B 的和,其中 A 和 B 都在区间[1,1000]。稍微有点麻烦的是,输入并不保证是两个正整数。 输入格式: 输入在一行给出

    2023年04月21日
    浏览(29)
  • 【2023团体程序设计天梯赛CCCC】GPLT2023,L1~L2部分(PTA,L1-089~L1-096,L2-045~L2-048)题解代码&复盘

    概要 L1部分:L1-089~L1-096 L2部分:L2-045~L2-048 L3部分:L3-033~L3-036 L1-089 最好的文档 5 L1-090 什么是机器学习 5 L1-091 程序员买包子 10 L1-092 进化论 10 L1-093 猜帽子游戏 15 L1-094 剪切粘贴 15 L1-095 分寝室 20 L1-096 谁管谁叫爹 20 L2-045 堆宝塔 25 L2-046 天梯赛的赛场安排 L2-047 锦标赛 25 L2-048

    2024年02月01日
    浏览(32)
  • L1-095 分寝室PTA

    学校新建了宿舍楼,共有 n 间寝室。等待分配的学生中,有女生 n0​ 位、男生 n1​ 位。所有待分配的学生都必须分到一间寝室。所有的寝室都要分出去,最后不能有寝室留空。 现请你写程序完成寝室的自动分配。分配规则如下: 男女生不能混住; 不允许单人住一间寝

    2024年02月10日
    浏览(32)
  • PTA L1-095 分寝室 (20 分)

    学校新建了宿舍楼,共有 n n n 间寝室。等待分配的学生中,有女生 n 0 n_0 n 0 ​ ​ 位、男生 n 1 n_1 n 1 ​ ​位。所有待分配的学生都必须分到一间寝室。所有的寝室都要分出去,最后不能有寝室留空。 现请你写程序完成寝室的自动分配。分配规则如下: 男女生不能混住; 不

    2023年04月23日
    浏览(28)
  • 【PTA】L1-059 敲笨钟(C++)

    题目链接:L1-059 敲笨钟 - 团体程序设计天梯赛-练习集 (pintia.cn)  题目要求:  输入格式: 输出格式: 输入样例: 输出样例: 思路:  代码: 测试结果: 微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉。为了增加敲钟的趣味性,还会糟改几句古

    2024年04月11日
    浏览(65)
  • 【PTA】L1-039 古风排版(C++)

    题目链接:L1-039 古风排版 - 团体程序设计天梯赛-练习集 (pintia.cn)  目录: 题目要求: 输入格式: 输出格式: 输入样例: 输出样例: 思路: 代码: 测试结果: ​编辑  中国的古人写文字,是从右向左竖向排版的。本题就请你编写程序,把一段文字按古风排版。 输入在第

    2024年03月26日
    浏览(82)
  • 【PTA】L1-043 阅览室(C++)

    题目链接:L1-043 阅览室 - 团体程序设计天梯赛-练习集 (pintia.cn)  目录: 题目要求: 输入格式: 输出格式: 输入样例: 输出样例:  思路: 代码:; 测试结果: 天梯图书阅览室请你编写一个简单的图书借阅统计程序。当读者借书时,管理员输入书号并按下 S 键,程序开始

    2024年04月15日
    浏览(72)
  • 2023 PTA天梯赛补题(L1 & L2)

    输入输出题 输入输出题 k == n 和 k == m 分别输出,题目怎么说就怎么做 判断一下c 等于a + b还是a*b或者都不是,分别按要求输出 针对每一群玩游戏的宝宝,枚举判断一下就好了 写的有点烦,基本就是一步一步模拟,思路在注释里写了 枚举分配方案,代码中a代表女生寝室的数

    2024年02月03日
    浏览(30)
  • PTA——L1-023 输出GPLT(c语言)

    给定一个长度不超过10000的、仅由英文字母构成的字符串。请将字符重新调整顺序,按 GPLTGPLT.... 这样的顺序输出,并忽略其它字符。当然,四种字符(不区分大小写)的个数不一定是一样多的,若某种字符已经输出完,则余下的字符仍按 GPLT 的顺序打印,直到所有字符都被输

    2024年02月13日
    浏览(29)
  • PTA L1-048 矩阵A乘以B

    前言:内容包括四大模块:题目,代码实现,大致思路,代码解读 给定两个矩阵A和B,要求你计算它们的乘积矩阵AB。需要注意的是,只有规模匹配的矩阵才可以相乘。即若A有Ra​行、Ca​列,B有Rb​行、Cb​列,则只有Ca​与Rb​相等时,两个矩阵才能相乘。 输入格式: 输入

    2024年02月04日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包