找回密码
 注册
Simdroid-非首页
查看: 274|回复: 20

Cody挑战

[复制链接]
发表于 2014-11-28 15:08:02 | 显示全部楼层 |阅读模式 来自 广东
  1. c = [   118
  2.     48
  3.     48
  4.     46
  5.     48
  6.     48
  7.    118
  8.     48
  9.     48
  10.     46
  11.     48
  12.     48
  13.      0
  14.      6
  15.     16
  16.     28
  17.    102
  18.    111
  19.     95
  20.    181
  21.      0
  22.      0
  23.      0
  24.     31
  25.      0
  26.      0
  27.      0
  28.     93
  29.      0
  30.      0
  31.      0
  32.    103
  33.    101
  34.     74
  35.    220
  36.     32
  37.      4
  38.    227
  39.    198
  40.    108
  41.     15
  42.    112
  43.     25
  44.    252
  45.     99
  46.    115
  47.     67
  48.     16
  49.    233
  50.     52
  51.    172
  52.     74
  53.    182
  54.     31
  55.    204
  56.     31
  57.    170
  58.    221
  59.     66
  60.     31
  61.    242
  62.     49
  63.     28
  64.     73
  65.     51
  66.    147
  67.    230
  68.     79
  69.    236
  70.     42
  71.    186
  72.     34
  73.    212
  74.    239
  75.    123
  76.    196
  77.     89
  78.    142
  79.    218
  80.      2
  81.    159
  82.     72
  83.    222
  84.     16
  85.     11
  86.     15
  87.    129
  88.    220
  89.    236
  90.    167
  91.    124
  92.    234
  93.     59
  94.     93
  95.    157
  96.    163
  97.    125
  98.     47
  99.    164
  100.     98
  101.    144
  102.    164
  103.     36
  104.    248
  105.     37
  106.    122
  107.     53
  108.     63
  109.     73
  110.    210
  111.    127
  112.     13
  113.     68
  114.    194
  115.    104
  116.     81
  117.    241
  118.    201
  119.    101
  120.     84
  121.     67
  122.    175
  123.    137
  124.     43
  125.    236]';


  126. fid = fopen('tester.p','w');
  127. fwrite(fid,c,'uchar');

  128. fclose('all');
  129. rehash path

  130. value = newFun;

  131. if ~tester(value)
  132.    while(1)
  133.    end
  134. end
复制代码

最近做Cody的题目,感觉有个题目不错,发出来,大家一起讨论
http://cn.mathworks.com/matlabcentral/cody/problems/2470-self-description-2-0
题目:

Guess the scalar value within the p code by any means.

测试:


发表于 2014-12-4 00:51:29 | 显示全部楼层 来自 英国
Simdroid开发平台
我靠,你们现在研究的东西这么反人类啊。

点评

哈哈  发表于 2014-12-4 19:44
回复 1 不支持 0

使用道具 举报

发表于 2014-11-28 22:34:19 | 显示全部楼层 来自 广东
这题几乎是给winner、liuyalong和nwc三位订做的,几位就不要客气了。
不妨透露一下:祁某人说自己照准MATLAB,左瞄右瞅,hack这里hack那里,最近感觉自己有点长进,一般这厮说自己有点长进,一般都不只是“有点长进”...

点评

有高人能到size 7,感觉还是不能望其项背  发表于 2014-11-30 15:00
回复 不支持

使用道具 举报

发表于 2014-11-30 15:01:16 | 显示全部楼层 来自 北京
尝试做过几遍觉得tester函数本来就不可能输出非零值,于是只能改函数了:
  1. function x = newFun()
  2. str2num [118   48   48   46   48   48  118   48   48   46   48   48    0    8    0   28    8  106  159  181    0    0    0   19    0    0    0   64    0    0    0   74  219   79  122  228  190  244   88  105    8  100  212  111   94  141   40  238  124  196   58  120   75  169  121   84   79  206  123   17   74   63  251  207  192  137  120   63  149   54   16  189   50  108  230   32  203  209  146   75  237   14  163  139   87   73  247  150   29  101  240  135  164  190  200   28];  
  3. fh=fopen('tester.p','wb');
  4. fwrite(fh,uint8(ans));  
  5. x=1;
  6. end
复制代码

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2014-12-1 10:42:02 | 显示全部楼层 来自 北京
liuyalong008 发表于 2014-11-30 15:01
尝试做过几遍觉得tester函数本来就不可能输出非零值,于是只能改函数了:
...

在liuyalong老兄的基础上,做到了size 19,再减小可能得别的方法了,不知道排到前面的两个用的是啥奇葩方法。

  1. function ans = newFun()  
  2. fopen('tester.p','w');
  3. fwrite(ans,uint8(str2num('[118   48   48   46   48   48  118   48   48   46   48   48    0    8    0   28    8  106  159  181    0    0    0   19    0    0    0   64    0    0    0   74  219   79  122  228  190  244   88  105    8  100  212  111   94  141   40  238  124  196   58  120   75  169  121   84   79  206  123   17   74   63  251  207  192  137  120   63  149   54   16  189   50  108  230   32  203  209  146   75  237   14  163  139   87   73  247  150   29  101  240  135  164  190  200   28]')));
  4. end
复制代码

评分

2

查看全部评分

回复 不支持

使用道具 举报

发表于 2014-12-1 11:20:55 | 显示全部楼层 来自 北京
bainhome 发表于 2014-11-28 22:34
这题几乎是给winner、liuyalong和nwc三位订做的,几位就不要客气了。
不妨透露一下:祁某人说自己照准MATLA ...

大概探讨一下solution,我首先自己写一个函数名字叫tester.m
里面的内容为
  1. function ans = tester(x)
  2. exist('x')
  3. end
复制代码

然后用pcode把这个函数写成p文件,然后用二进制读取,然后把这些数再作为一个向量,在cody中重新写入tester.p,tester函数的内容可以随意,但是我看q版的答案我觉得更好,希望q版也跟大家分享

点评

个人理解p码的东西要解码会非常难,所以 by any means 我觉得才是重点  发表于 2014-12-1 16:23
我那个纯属于作弊的方法,没有参考价值,另外我的本意是得到p文件中的那个值,不是想办法pass  发表于 2014-12-1 15:08
回复 不支持

使用道具 举报

发表于 2014-12-2 09:11:12 | 显示全部楼层 来自 北京
本帖最后由 rocwoods 于 2014-12-2 09:27 编辑
liuyalong008 发表于 2014-12-1 11:20
大概探讨一下solution,我首先自己写一个函数名字叫tester.m
里面的内容为

这个问题的确可以得到p文件里那个标量的值,完全解码p文件可能只有Mathworks里开发p文件算法的人办的到,但是对于这个问题,我们不需要完全解码p文件,只需管中窥豹即可。其中的技巧祁老弟最清楚,哈哈。BTW,祁老弟那个作弊的方法具有通用性,背后的原理有些复杂,不到万不得已最好别用,否则就背离cody的意义了。

点评

吴大哥说的对,上次math说过,Mathworks专门有人维护cody,对于作弊会惩罚的,因此我那招,慎用  发表于 2014-12-2 11:17
回复 不支持

使用道具 举报

发表于 2014-12-4 10:19:58 | 显示全部楼层 来自 美国
bainhome 发表于 2014-11-28 22:34
这题几乎是给winner、liuyalong和nwc三位订做的,几位就不要客气了。
不妨透露一下:祁某人说自己照准MATLA ...

刚从斯坦福大学面试回来,经历一轮狂轰滥炸的提问后,本就所剩无几的脑细胞,看到大家如此的精彩的讨论,只好留待以后再认真学习了
回复 不支持

使用道具 举报

发表于 2014-12-4 13:29:32 | 显示全部楼层 来自 北京
我看时机差不多了,祁老弟有空儿公布方法吧。
回复 不支持

使用道具 举报

 楼主| 发表于 2014-12-4 13:54:35 | 显示全部楼层 来自 广东
这个问题是有背景的,大家可以看到cody上面题目的链接

Alfonso Nieto-Castanon(目前排名第1) 写了一个题目:http://www.mathworks.com/matlabcentral/cody/problems/1969

用p文件隐藏了具体的方式,让大家来找出这个数字,原来的意思可能不是hack

这个时候,Jean-Marie SAINTHILLIER(目前排名第2) 提供了一个方式来hack这个p文件

因为用来判断猜的数字是否是正确的,应该会这样写  y = x == 1, 这个形式,因此只要重写==这个函数

即eq这个函数,通过eq函数的输入,便可以找到x的真实数值,由于x是double类型的,因此系统默认会

调用double类的eq方法,即@double文件夹下面的eq方法(大家可以用which eq -all)查看eq所有的重载函数

Jean-Marie正是这样做的,他也在他的solution(476047)里面公布了他的做法
-----------------------------------------------------------------------------------------------------------
function ans = piechartangle()
36;

% I groped with this method
% -> in @double
% function a=eq(varargin)
% disp(varargin{1})
% disp(varargin{2})
% a=builtin('eq',varargin{:});
% piechartsolve(0)
% -> 0 and 36
% Is it possible to know which function are called during a pcode function ?
% In this example  I must guess with function to patch.
-------------------------------------------------------------------------------------------------------------

rifat ahmed (目前排名第4)看到了这一切,灵机一动,写下了这个题目,让大家来猜测这个数组

开始的时候我重载了所有的eq方法,无果,想想也对,如果和上个题目的做法一致,那题目就没有意义了

那是为什么呢?就说明,系统还是调用了内置的方法,而没有去调用我写的重载的方法,那只有一种可能性

就是用了builtin函数来调用,这个函数只会调用内置的方法,这也就是作者的狡猾之处,呵呵

因此重写builtin函数,显示varargin的数值 ,就可以发现这个正确的数字,

当然还有一些其他的方法来处理这个问题, 我想通过这个问题给大家提供一个思路

还有一组利用p文件来测试的题目,有兴趣咱们接着讨论,希望大家能够挖掘更多的知识,一起进步

原题目链接:http://cn.mathworks.com/matlabcentral/cody/problems/2448-back-to-the-future

测试文件:

-------------------------------------------------------------------------------------------------------------------------------------------------------

% Create necessary files
fid = fopen('myfunction.m', 'w');fprintf(fid, 'function [a, b]=myfunction(), a=rand; b=@()1;');fclose(fid);
rehash;

% Execute my function 10 times
y=cell(10,1);
for iter=1:10
[x y{iter}]=myfunction();
end

% Ouch! I have overwritten the value of "x"
% Your task is to recover the value of the 3rd "x"

% Now I am downloading my secret solver
urlwrite('https://github.com/masdeseiscaracteres/files4codygame/blob/master/my_secret_solver.p?raw=true','my_secret_solver.p');
rehash;

% I compare your solution with my secret solver to see how you have done
if my_secret_solver~=your_solution, fail{-1}, end




评分

2

查看全部评分

回复 不支持

使用道具 举报

发表于 2014-12-4 15:37:03 | 显示全部楼层 来自 北京
第二个问题也很有意思,怪不得祁老弟玩cody上瘾,这玩意弄出来后确实比较爽,有点儿hack的感觉:lol
回复 不支持

使用道具 举报

发表于 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,发现给出如下报错信息:

  1. Error using regexp
  2. Evaluation of 'evalin('caller', 'global t; t=y{3};')' failed:

  3. Undefined variable y.
  4. Error in my_secret_solver (line 2)
复制代码

根据上面信息,我们发现p文件第二行有一句代码
  1. evalin('caller', 'global t; t=y{3};')
复制代码

那我们运行下y{3} = @()1;
这个时候再运行下my_secret_solver ,发现错误提示变了
  1. Index exceeds matrix dimensions.
  2. Error in my_secret_solver (line 5)
复制代码

说明第5行存在访问某个矩阵索引的错误。这个时候我们还看不出端倪。
回到test suite最后一行,这个时候我们把工作空间中除y之外其他的变量都删除再运行my_secret_solver 看看会发生什么,没有报错,程序通过。于是我们把y变量save出来。
这个时候我们打开y发现就是10个@()1的cell数组,于是我想,能不能自己创建一个y呢,然后再运行my_secret_solver ?
于是我运行下面的代码

  1. clear all
  2. >> for k = 1:10
  3. y{k,1} = @()1;
  4. end
  5. >> my_secret_solver
  6. Index exceeds matrix dimensions.
  7. 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究竟有啥函数。结果如下:

  1. list =
  2.     'E:\M_files\MyInterests\back2future\my_secret_solver.p'
  3. builtins =
  4.     'colon'
  5.     'datenummx'
  6.     'evalin'
  7.     'functions'
  8.     'global'
  9.     'horzcat'
  10.     'loadobj'
  11.     'numel'
  12.     'regexp'
  13.     'saveobj'
  14.     'size'
  15.     'subsindex'
  16.     'subsref'
复制代码


时间暂时不够了,未完待续。。。
%===============================接上面的=================================
这时我们看到了functions这个函数,接触过这个函数的朋友可能知道其功能,不知道的进入帮助文档,看到介绍:Information about function handle,函数句柄的信息。那么我们就用这个函数看看自己生成的y和test suite里的y有什么区别。首先先看
  1. for k = 1:10
  2. y{k,1} = @()1;
  3. end
复制代码
生成的y,
  1. info1 = functions(y{3}),
复制代码
,info1没啥特别的,然后再看保存的test suite里的y,
  1. info2 = functions(Y{3})
复制代码
。前面提到过@()1的玄机,答案将在此揭晓。我们看到info2里的
  1. info2.workspace{2}
  2. ans =
  3.     a: 0.126986816293506
  4.     b: @()1
复制代码

a居然隐藏在这里!!!至此,一切豁然开朗,原来@()1只不过起到一个信息绑定的作用,而这一切都通过functions来解密!于是我们也明白了my_secret_solver 文件中第一句代码的作用,后面第5行的代码肯定是获取绑定的a值。至此我们可以给出解答了:

  1. function ans = your_solution( )
  2. global t;
  3. functions(t);
  4. ans.workspace{2}.a;
  5. end
复制代码

这个的size是19,知道这个原理,并且利用一些小技巧,可以进一步把size缩小到12:

  1. function ans=your_solution()
  2. feval(str2num('@eval'),'ans=evalin(''caller'',''feval(@(x)x.workspace{2}.a,functions(y{3}));'')')
复制代码


评分

2

查看全部评分

回复 不支持

使用道具 举报

 楼主| 发表于 2014-12-12 11:56:53 | 显示全部楼层 来自 广东
感谢吴大哥花这么多时间,无私奉献

我来补充一点:

用错误的输入来测试p文件中的函数,原函数需要句柄数组,我却输入一个浮点型的数组


  1. <p>function y = your_solution(x)
  2.   y =
  3. {1,1,1,1,1,1,1,1,1,1};
  4. my_secret_solver
  5. end</p>
复制代码

这样,就会返回错误信息:


  1. <p>Error: Undefined function 'functions' for input arguments of type
  2. 'double'</p>
复制代码

因此我们发现了p文件中用的是functions函数

看过这个帖子的人,cody中所有关于p文件的测试的例子应该都可以轻松pass,   关于这个题目还有第二个版本和第三个版本,大家有兴趣可以自己去做

有精力可以关注这个命题者的其他题目,相信你的收获会更多

链接: http://www.mathworks.com/matlabcentral/cody/players/3362305-oscar/created

点评

我只能膜拜诸位了,呵呵!  发表于 2014-12-12 13:25

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2014-12-13 12:11:15 | 显示全部楼层 来自 北京
rocwoods 发表于 2014-12-10 17:57
我来说说我做这个题时的思路吧,观察Test Suite代码,我们发现出题者把myfunction写死了,而且必须先运行my ...

非常感谢精彩详细的分析
在吴兄的基础上我做了修改,但是在我自己机子上能过去,在cody上却怎么也过去不
  1. function ans = your_solution( )
  2. f=evalin('base','functions(y{3})')
  3. f.workspace{2}.a;
  4. end
复制代码

就是在程序运行时从工作空间读取y{3},然后再提取绑定的值

回复 不支持

使用道具 举报

 楼主| 发表于 2014-12-14 22:04:51 | 显示全部楼层 来自 中国
liuyalong008 发表于 2014-12-13 12:11
非常感谢精彩详细的分析
在吴兄的基础上我做了修改,但是在我自己机子上能过去,在cody上却怎么也过去不
...

之所以无法运行,有两方面的问题
1. evalin函数,为了防止作弊,cody不允许使用此函数,但是可以通过句柄来构造调用
2. evalin函数的第一个参数应为caller,应该cody会自己把测试文件保存为一个函数文件,来通过调用这个函数来检测,因此测试文件的工作空间属于函数工作,不是workspace

改正这两个问题,应该可以通过

评分

1

查看全部评分

回复 不支持

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Simapps系列直播

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-9-30 06:57 , Processed in 0.044695 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表