数值分析课程需要在 Grader 上提交代码,但是在做“Runge-Kutta 方法”这一题时,老师少给了一个函数,所以思考怎么在不问老师的情况下获得函数定义。Grader 上可以使用 error
函数,将需要的信息返回到前端,于是我通过提交测试代码(error(ls(...))
),发现标准答案在 +reference/RK4.p
,已经使用 pcode 进行了加密,因此想到了两个方案:
- 将自己的函数加密后,提交到网站覆盖 p 文件,即修改标准答案;
- 读取 p 文件,然后在本地多次试验代码,绕过提交次数的限制。
经过测试,以上两个方案均可行,于是我选择了较为温和的第二个方案进行实际测试,通过 data = readp('RK4')
获取加密文件,如下代码中的 data
变量,之后通过 writep('RK4', data)
保存到本地后,与自己代码的结果进行比对,从而获得函数定义。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 | %% RK4.p in grader
data = [118;48;49;46;48;48;118;48;48;46;48;48;0;3;176;28;68;199;255;177;0;0;0;106;0;0;0;158;0;0;0;219;162;242;130;186;91;205;75;116;100;208;18;176;142;50;60;25;27;84;190;124;83;176;154;228;91;143;4;176;23;85;61;180;72;223;17;167;19;51;173;207;216;146;158;220;85;171;122;59;135;147;244;164;18;9;64;186;255;138;4;92;106;132;160;21;35;214;158;244;13;43;145;58;134;104;9;225;10;154;14;142;91;67;82;48;254;241;178;241;173;249;29;236;123;196;242;158;182;55;97;175;31;46;190;60;111;189;145;216;244;0;32;148;153;162;142;146;175;56;179;117;208;223;25;36;100;85;9;86;169;211;205;177;43;40;68;172;119;220;170;117;16;34;230;57;7;172;181;215;142;118;243;253;234;215;115;54;70;221];
writep('RK4', data);
%% test RK4
[Dh, Derr] = deal(0, 0);
for n = 1: 5
[h1, err1] = RK4(2^(n-1));
[h2, err2] = RK4v2(2^(n-1));
[Dh, Derr] = deal(Dh+abs(h1-h2), Derr+abs(err1-err2));
end
fprintf('Δh=%f, Δerr=%f\n', Dh, Derr); % Δh=0.000000, Δerr=0.000000
%% utilities
function output(data) %#ok
% Get output in Grader
%
% Argument:
% data: vector
error(mat2str(data));
end
function data = readp(name) %#ok
% Read pcode files in binary mode
%
% Argument:
% name: str
%
% Output:
% data: vector
fid = fopen(['+', 'reference', '/', name, '.p'], 'rb');
data = fread(fid);
fclose(fid);
end
function writep(name, data)
% Write pcode files in binary mode
%
% Argument:
% name: str
% data: vector
%
fid = fopen([name, '.p'], 'wb');
fwrite(fid, data);
fclose(fid);
end
function [h, err] = RK4v2(n)
% Runge-Kutta 4 for y'=y and y(0)=1
%
% Argument:
% n: int
%
% Output:
% h: float
% err: float
%
h = 1 / n;
y = polyval([1/24, 1/6, 1/2, 1, 1], h) ^ n;
err = abs(y - exp(1));
end
|