- 积分
- 57
- 注册时间
- 2006-1-10
- 仿真币
-
- 最后登录
- 1970-1-1
|
发表于 2014-12-10 17:57:28
|
显示全部楼层
来自 北京
本帖最后由 rocwoods 于 2014-12-11 11:04 编辑
我来说说我做这个题时的思路吧,观察Test Suite代码,我们发现出题者把myfunction写死了,而且必须先运行myfunction,myfunction很简单,调用rand返回一个随机值,同时返回一个常量匿名函数——@()1,可能很多同学觉得这个@()1比较奇怪,一开始我也是这么认为,其实这个@()1大有玄机,后面我们会看到。
接下来的test suite开始调用10次myfunction,每次x都会被覆盖。调用完成后,开始从github上下载my_secret_solver.p并运行。my_secret_solver.p里应该隐藏了第三次调用myfunction时返回的x值,我们要完成的就是写your_solution,使其“猜”到第三次调用myfunction时返回的x的值。
整个题目对于不熟悉MATLAB或者cody的人都来说都比较晦涩,可能刚开始一头雾水,那么我们只能先尝试做些测试工作。
一般这样的问题思路无非是作弊(不提倡),在your_solution里重写my_secret_solver.p(出题者本意不是如此),重置随机数发生器(这个解答者里有这么做的)。当然出题者本意是让我们真真切切得到这个第三次的x。首先我把test suite copy到本地,先在本地测试。在最后一行设置断点,在得到my_secret_solver.p后我们先看看这个p函数到底干了些啥。
首先我们clear workspace,直接运行my_secret_solver,发现给出如下报错信息:
- Error using regexp
- Evaluation of 'evalin('caller', 'global t; t=y{3};')' failed:
- Undefined variable y.
- Error in my_secret_solver (line 2)
复制代码
根据上面信息,我们发现p文件第二行有一句代码- evalin('caller', 'global t; t=y{3};')
复制代码
那我们运行下y{3} = @()1;
这个时候再运行下my_secret_solver ,发现错误提示变了- Index exceeds matrix dimensions.
- Error in my_secret_solver (line 5)
复制代码
说明第5行存在访问某个矩阵索引的错误。这个时候我们还看不出端倪。
回到test suite最后一行,这个时候我们把工作空间中除y之外其他的变量都删除再运行my_secret_solver 看看会发生什么,没有报错,程序通过。于是我们把y变量save出来。
这个时候我们打开y发现就是10个@()1的cell数组,于是我想,能不能自己创建一个y呢,然后再运行my_secret_solver ?
于是我运行下面的代码
- clear all
- >> for k = 1:10
- y{k,1} = @()1;
- end
- >> my_secret_solver
- Index exceeds matrix dimensions.
- Error in my_secret_solver (line 5)
复制代码
奇怪了,创建的y看起来和保存的y一模一样,居然报错。这个时候我把原来的y,load进来,用Y代替,isequal(y,Y)也不一样,看来原来的y和后来生成的y还真的不一样。
到此似乎又没有路了。别急,depfun可以看下p文件里的函数调用。于是我们用[list,builtins] = depfun('my_secret_solver.p')看下my_secret_solver究竟有啥函数。结果如下:
- list =
- 'E:\M_files\MyInterests\back2future\my_secret_solver.p'
- builtins =
- 'colon'
- 'datenummx'
- 'evalin'
- 'functions'
- 'global'
- 'horzcat'
- 'loadobj'
- 'numel'
- 'regexp'
- 'saveobj'
- 'size'
- 'subsindex'
- 'subsref'
复制代码
时间暂时不够了,未完待续。。。
%===============================接上面的=================================
这时我们看到了functions这个函数,接触过这个函数的朋友可能知道其功能,不知道的进入帮助文档,看到介绍:Information about function handle,函数句柄的信息。那么我们就用这个函数看看自己生成的y和test suite里的y有什么区别。首先先看- for k = 1:10
- y{k,1} = @()1;
- end
复制代码 生成的y,,info1没啥特别的,然后再看保存的test suite里的y,。前面提到过@()1的玄机,答案将在此揭晓。我们看到info2里的
- info2.workspace{2}
- ans =
- a: 0.126986816293506
- b: @()1
复制代码
a居然隐藏在这里!!!至此,一切豁然开朗,原来@()1只不过起到一个信息绑定的作用,而这一切都通过functions来解密!于是我们也明白了my_secret_solver 文件中第一句代码的作用,后面第5行的代码肯定是获取绑定的a值。至此我们可以给出解答了:
- function ans = your_solution( )
- global t;
- functions(t);
- ans.workspace{2}.a;
- end
复制代码
这个的size是19,知道这个原理,并且利用一些小技巧,可以进一步把size缩小到12:
- function ans=your_solution()
- feval(str2num('@eval'),'ans=evalin(''caller'',''feval(@(x)x.workspace{2}.a,functions(y{3}));'')')
复制代码
|
评分
-
2
查看全部评分
-
|