Show me the money
分类: C/C++
2011-09-08 15:29:00
1. 分析代码,当t < -72,-72 <= t < -50的时候,程序都会进入相同的分支,因此大胆揣测main(-81…) ,main(-87…) 和 main(-79…) 实现相同的功能;main(-61…)和main(-64…)也实现相同的功能。于是,将程序修改为:
const char *coding1 = "@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/"; const char *coding2 = "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"; int main(int t, int p, char *str) { int result, n; if( t > 1 ) { if(t < 3 ) { n = main(-80, 0, str +1); n = main(-80, 1-p, n + str ); result = main(-80, -13, str + n) ; } else result = 1; if(t < p ) main( t+1, p , str) ; if( main(-80, -27+t, str) && t == 2 ) if (p < 13) main (2, p +1, "%s %d %d\n"); return result; } else if(t < 0) { if(t < -72) result = main(p , t, coding1) ; else { if(t < -50) { if(p == *str ) result = putchar(31[ str ]); else result = main(-61, p , str +1); } else result = main((* str == '/') + t, p , str + 1 ) ; } } else if( t == 1 ) result = main (2, 2 , "%s") ; else { /* t == 0 */ if( *str == '/' ) { result = 1; } else { n = main(-61, *str , coding2); result = !! main(0, n, str+1); } } return result; } |
经过验证,我们的想法是正确的。(不知道怎么验证?修改过的程序和原始程序的运行结果做diff…)
2. 然后,我们继续分析代码。注意到t < -50 这个分支,只要某一次传入的参数进入这个分支,之后就会一直递归进入此分支,直到满足 p == *str 递归才结束。发挥一下想象力,这个像不像一个for循环?从字符串str中找到一个字符等于p,然后输出str[31]。于是,我们又把程序修改为:
const char *coding1 = "@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/"; const char *coding2 = "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"; int main(int t, int p, char *str) { int result, n; if( t > 1 ) { if(t < 3 ) { n = main(-80, 0, str +1); n = main(-80, 1-p, n + str ); result = main(-80, -13, str + n) ; } else result = 1; if(t < p ) main( t+1, p , str) ; if( main(-80, -27+t, str) && t == 2 ) if (p < 13) main (2, p +1, "%s %d %d\n"); return result; } else if(t < 0) { if(t < -72) result = main(p , t, coding1) ; else { if(t < -50) { int i; for(i=0; ;i++) { if(str[i] == p) { result = putchar(str[31 + i]); break; } } } else result = main((* str == '/') + t, p , str + 1 ) ; } } else if( t == 1 ) result = main (2, 2 , "%s") ; else { /* t == 0 */ if( *str == '/' ) { result = 1; } else { n = main(-61, *str , coding2); result = !! main(0, n, str+1); } } return result; } |
3. 继续,注意到t < -72这个分支,它的功能就是交换参数t, p的位置,以及将第3个参数换成coding1。于是,我们将程序修改为:
const char *coding1 = "@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/"; const char *coding2 = "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"; int main(int t, int p, char *str) { int result, n; if( t > 1 ) { if(t < 3 ) { n = main(0, -80, coding1); n = main(1-p, -80, coding1 ); result = main(-13, -80, coding1 ) ; } else result = 1; if(t < p ) main( t+1, p , str) ; if( main(-27+t, -80, coding1) && t == 2 ) if (p < 13) main (2, p +1, "%s %d %d\n"); return result; } else if(t < 0) { if(t < -50) { int i; for(i=0; ;i++) { if(str[i] == p) { result = putchar(str[31 + i]); break; } } } else /* -50 <= t < 0 */ result = main((* str == '/') + t, p , str + 1 ) ; } else if( t == 1 ) result = main (2, 2 , "%s") ; else { /* t == 0 */ if( *str == '/' ) { result = 1; } else { n = main(-61, *str , coding2); result = !! main(0, n, str+1); } } return result; } |
4. 继续,观察 -50 <= t < 0这个分支,如果 *str != '/';t的值不变,str+1;如果*str == '/',str+1;随着t的值不断增长,最终t=0;这实际上也相当于一个for循环,通过t去定位str中子字符串的位置,然后调用main(0,…)去完成相应的功能。所以,程序可以简化为:
const char *coding1 = "@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/"; const char *coding2 = "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"; int main(int t, int p, char *str) { int result, n; if( t > 1 ) { if(t < 3 ) { n = main(0, -80, coding1); n = main(1-p, -80, coding1 ); result = main(-13, -80, coding1 ) ; } else result = 1; if(t < p ) main( t+1, p , str) ; if( main(-27+t, -80, coding1) && t == 2 ) if (p < 13) main (2, p +1, "%s %d %d\n"); return result; } else if(t < 0) { if(t < -50) { int i; for(i=0; ;i++) { if(str[i] == p) { result = putchar(str[31 + i]); break; } } } else { /* -50 <= t < 0 */ int i; char *x; for(i = t, x = str; i < 0 ; i++) while( *x++ != '/' ) {} result = echo(0, p , x) ; } } else if( t == 1 ) result = main (2, 2 , "%s") ; else { /* t == 0 */ if( *str == '/' ) { result = 1; } else { n = main(-61, *str , coding2); result = !! main(0, n, str+1); } } return result; } |
5. 继续整理,删除一些无用代码,并提取函数
const char *coding1 = "@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/"; const char *coding2 = "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"; int echo1(int p, const char *str) { int i; for(i=0; ;i++) if(str[i] == p) return putchar(str[31 + i]); } int echo(int t, int p, const char *str) { int result, n; if( t > 1 ) { if(t < 3 ) { echo(0, -80, coding1); echo(1-p, -80, coding1 ); result = echo(-13, -80, coding1 ) ; } else result = 1; if(t < p ) echo( t+1, p , str) ; if( echo(-27+t, -80, coding1) && t == 2 ) if (p < 13) echo (2, p +1, "%s %d %d\n"); return result; } else if(t < 0) { if(t < -50) { result = echo1(p, str); } else { /* -50 <= t < 0 */ int i; const char *x; for(i = t, x = str; i < 0 ; i++) while( *x++ != '/' ) {} result = echo(0, p , x) ; } } else if( t == 1 ) result = echo (2, 2 , "%s") ; else { /* t == 0 */ if( *str == '/' ) { result = 1; } else { echo1(*str , coding2); result = !! echo(0, 0, str+1); } } return result; } int main() { return echo(1, 1, ""); } |
6. 分析t==0这个分支,如果*str != '/',则一直递归输出*str;如果*str == '/',则返回1。将递归改成for循环:
const char *coding1 = "@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/"; const char *coding2 = "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"; int echo1(int p, const char *str) { int i; for(i=0; ;i++) if(str[i] == p) return putchar(str[31 + i]); } int echo(int t, int p, const char *str) { int result, n; if( t > 1 ) { if(t < 3 ) { echo(0, -80, coding1); echo(1-p, -80, coding1 ); result = echo(-13, -80, coding1 ) ; } else result = 1; if(t < p ) echo( t+1, p , str) ; if( echo(-27+t, -80, coding1) && t == 2 ) if (p < 13) echo (2, p +1, "%s %d %d\n"); return result; } else if(t < 0) { if(t < -50) { result = echo1(p, str); } else { /* -50 <= t < 0 */ int i; const char *x; for(i = t, x = str; i < 0 ; i++) while( *x++ != '/' ) {} result = echo(0, p , x) ; } } else if( t == 1 ) result = echo (2, 2 , "%s") ; else { /* t == 0 */ if( *str == '/' ) { result = 1; } else { const char *x = str; while(*x != '/') { echo1(*x, coding2); x++; } result = !! 1; } } return result; } int main() { return echo(1, 1, ""); } |