热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于数据对拍

数据对拍是一种通过找到错误输出数据寻找bug的方法;首先,我们可以跟据题意通过bfs,暴力等方法写出一份正确的代码,然后写个随机生成数据

数据对拍是一种通过找到错误输出数据寻找bug的方法;

首先,我们可以跟据题意通过bfs,暴力等方法写出一份正确的代码,然后写个随机生成数据和验证输入输出的代码

我们可以拿一道题来熟悉这个流程:

路径规划(route)

题意很好理解,就是给出起点,和终点,求出起点到终点的所需的步数,其中上下左右,斜着走八个方向都算一步;

大致思路就是,优先斜着走,因为斜着走即在水平方向有位移,在竖直方向也有位移;

这里有一份根据该思路的错误代码:

//01.cpp
#include
#include
#include
#define ll long long
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
int main()
{int a,b,c,d;scanf("%d %d %d %d",&a,&b,&c,&d);int dx = abs(c - b);int dy = abs(d - b);printf("%d\n",max(dx,dy));return 0;
}

1.这时候如果我们想用数据对拍来找bug的话我们可以写一个用bfs思路的正确代码,以下是bfs的正确代码;

//02.cpp
#include
#include
#include
#include
#define ll long long
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
const int INF = 0x3f3f3f3f;
struct node
{int x,y,step;node (){}node(int p_x,int p_y,int p_step){x = p_x;y = p_y;step = p_step;}
};
int dir[9][2] = {1,0,0,1,-1,0,0,-1,1,1,1,-1,-1,-1,-1,1};
int n,m;
int mark[305][305];
int main()
{int a,b,c,d;scanf("%d %d %d %d",&a,&b,&c,&d);queue que;que.push(node(a,b,0));int res &#61; 0;while(!que.empty()){node fro &#61; que.front();if(fro.x &#61;&#61; c && fro.y &#61;&#61; d){res &#61; fro.step;break;}que.pop();for(int i &#61; 0; i <8; i&#43;&#43;){int tx &#61; fro.x &#43; dir[i][0];int ty &#61; fro.y &#43; dir[i][1];if(tx >&#61; -100 && tx <&#61; 100 && ty >&#61; -100 && ty <&#61; 100 && mark[tx&#43;105][ty&#43;105] &#61;&#61; 0){mark[tx &#43; 105][ty &#43; 105] &#61; 1;que.push(node(tx,ty,fro.step &#43; 1));}}}printf("%d\n",res);return 0;
}

2.如果我们想通过验证输入数据来找出错误数据的话,我们需要讲以上两份代码的输入输出重定向到文件流。

也就是把输入的数据通过文件输入&#xff0c;并将输出的数据输出到文件&#xff1b;

以下&#xff1a;

//01.cpp
#include
#include
#include
#define ll long long
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
int main()
{freopen("input0.in","r",stdin);freopen("ouput1.out","w",stdout);int a,b,c,d;scanf("%d %d %d %d",&a,&b,&c,&d);int dx &#61; abs(c - b);int dy &#61; abs(d - b);printf("%d\n",max(dx,dy));fclose(stdin);fclose(stdout);return 0;
}

//02.cpp
#include
#include
#include
#include
#define ll long long
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
const int INF &#61; 0x3f3f3f3f;
struct node
{int x,y,step;node (){}node(int p_x,int p_y,int p_step){x &#61; p_x;y &#61; p_y;step &#61; p_step;}
};
int dir[9][2] &#61; {1,0,0,1,-1,0,0,-1,1,1,1,-1,-1,-1,-1,1};
int n,m;
int mark[305][305];
template
T RandomData(T a, T b,T c)
{if(c <&#61; b ){return rand() % (b - a &#43; 1) &#43; a;}else {T temp;while(true){temp &#61; rand() % (b - a &#43; 1) &#43; a;if(temp !&#61; c){return temp;}}}
}
int main()
{freopen("input0.in","r",stdin);freopen("output2.out","w",stdout);int a,b,c,d;scanf("%d %d %d %d",&a,&b,&c,&d);queue que;que.push(node(a,b,0));int res &#61; 0;while(!que.empty()){node fro &#61; que.front();if(fro.x &#61;&#61; c && fro.y &#61;&#61; d){res &#61; fro.step;break;}que.pop();for(int i &#61; 0; i <8; i&#43;&#43;){int tx &#61; fro.x &#43; dir[i][0];int ty &#61; fro.y &#43; dir[i][1];if(tx >&#61; -100 && tx <&#61; 100 && ty >&#61; -100 && ty <&#61; 100 && mark[tx&#43;105][ty&#43;105] &#61;&#61; 0){mark[tx &#43; 105][ty &#43; 105] &#61; 1;que.push(node(tx,ty,fro.step &#43; 1));}}}printf("%d\n",res);fclose(stdin);fclose(stdout);return 0;
}

可以看到&#xff0c;两份代码都是通过input0.in输入数据的&#xff0c;这里的input0.in的数据我们可以通过第3步的随机数据来获得。然后错误

代码的数据输出到output1.out里面&#xff0c;正确代码的数据输出到output2.out里面。

3.我们需要造出随机数据来作为正确代码和错误代码的输入&#xff0c;然后对别两份代码的输出文件进行寻找错误数据

如下&#xff1a;

//03.cpp
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
using namespace chrono;
const int INF &#61; 0x3f3f3f3f;
mt19937 rng; //声明一个随机生成器 template
T RandomData(T a, T b,T c)
{uniform_int_distribution dist6(a, b); //指定范围 if(c > b){return dist6(rng);}else {T temp;while(true){temp &#61; dist6(rng);if(temp !&#61; c){return temp;}}}}void makeData()
{FILE* fp&#61;fopen("input0.in","w");int a &#61; RandomData(-100,100,INF);int b &#61; RandomData(-100,100,INF);int c &#61; RandomData(-100,100,INF);int d &#61; RandomData(-100,100,INF);fprintf(fp,"%d %d %d %d\n",a,b,c,d);printf("%d %d %d %d\n",a,b,c,d); fclose(fp);
}
int main()
{rng.seed(time(0)); //将时间作为随机生成器随机种子 for(int i &#61; 1; i <500; i&#43;&#43;){makeData();system("01.exe");system("02.exe");printf("Number:%d\n",i);if(system("fc output1.out output2.out")){printf("Wrong Asnwer\n");while(1); //使程序暂停1毫秒 } }return 0;
}

该代码会造出499组数据用来通过验证两个输出文件的差异来寻找bug;

当有差异的话该程序会自动停下并输出有差异的数据

请注意03.cpp中的53行代码和63行代码&#xff0c;47行是为了给随机函数通过当前时间设置一个随机种子&#xff0c;57行是通过使程序“休眠”

1毫秒使得随机种子起作用。

 

 

注意&#xff0c;在运行03.cpp之前&#xff0c;必须保证

1.三个cpp文件必须在同一文件夹下

2.01.cpp和02.cpp必须通过编译

如果想要生成小数的话&#xff0c;随机函数应该这样写

//03.cpp
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
using namespace chrono;
const double INF &#61; 0x3f3f3f3f;
std::mt19937 rng; //声明一个随机生成器 template
T RandomData(T a, T b,T c)
{uniform_real_distribution dist6(a, b); //指定范围 if(c <&#61; b){return dist6(rng);}else {T temp;while(true){temp &#61; dist6(rng);if(temp !&#61; c){return temp;}}}}int main()
{rng.seed(time(0));while(true){printf("%lf\n",RandomData(-10.0,25.0,INF));}return 0;
}

如果想生成随机字符应该这样写

//03.cpp
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define mmset(a,b) memset(a,b,sizeof(a))
using namespace std;
using namespace chrono;
const double INF &#61; 0x3f3f3f3f;
std::mt19937 rng; //声明一个随机生成器 template
T RandomData(T a, T b,T c)
{uniform_int_distribution dist6(a, b); //指定范围 if(c <&#61; b){return dist6(rng);}else {T temp;while(true){temp &#61; dist6(rng);if(temp !&#61; c){return temp;}}}}int main()
{rng.seed(time(0));while(true){printf("%c",RandomData(&#39;a&#39;,&#39;y&#39;,&#39;c&#39;));}return 0;
}


推荐阅读
author-avatar
门板班不查询只
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有