标签:
周末在微博上看到 coolshell 博主陈皓搞了一个编程小游戏的页面,过关制的。感觉很有趣,就打开看了看。有空没空搞了3天才算搞定,感觉眼界开阔了一些,但是对每一关涉及到的知识都了解的太浅,这里仅仅记录一下通关过程,至于涉及到的知识会在最近学习一下:)
首先,游戏地址是:coolshell 大闯关。
游戏规则很简单。每一关都需要得到一个结果,把这个结果填进 url 即可进入下一关。下面是通关攻略(强烈建议自己先试试,每一关如果20分钟都没思路就可以看看攻略了)
这一关由两部分组成:
当我打开这个页面的时候,感觉这啥玩意啊。难道是正则表达式提取?于是看了看+号,依次是1个,2个,3个……然后又找了各种规律找不到,很是郁 闷。于是就去干别的了。等我无聊的时候打开了这个页面的源代码,灵光一现发现上面不是纯文本,而是一段 code,那提示语应该跟 code 相关吧?于是就在网上开始搜,百度必应不出意料的呵呵呵(原谅我一直黑,但这是事实啊。。),于是用 google 开始搜,(⊙o⊙)…然后发现 fuck 被 google 过滤了,和简单,把安全过滤去掉就好了(中文版 google 是不能去掉安全过滤的,你懂的。所以切换到中文繁体,然后在右下方的设置里面去掉安全过滤之后拉到最下面保存即可)。然后看了几个网页,进了英文版的 wikipedia,然后答案就很明显了。原来有门编程语言叫做 brainfuck。之后就很 easy 了,可以看看这是静态还是动态的,静态的就找个编译器和解释器,动态的直接在网上找个解释器就好。我随手搜了个在线运行的网站,把代码贴进去。执行结果是welcome
,于是下一关就被打开了。
总结一下:
这关很简单的其实,根据等比数列,可以首先得到一个数字:18 * 108=1944。然后试一下,发现这个1944对了。但是还有其他答案,应该是在那句话里。这次聪明了直接 google,然后直接知道是42。然后发现也对了,但是没有进入下一关。从 X * Y 那个来看,难道是求一下乘积?尝试着 1944 * 42 = 81648。然后就过关了= =
总结一下:
一个硕大的键盘,鼠标滑过图片发现可以点击。然后会进入一个 wiki,大概看看介绍,这个布局是为了提高打字速度设计的,跟目前的布局也是一一对应的,然后自己人肉翻译一下即可,得到下面的代码:
1 main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
发现原来是一段 C 代码,用 gcc 编译执行后,输出 unix,得解。
总结一下:
出来一个二维码,用微信扫一下发现是一个字典。结合二维码下面那一段话,就非常简单了。写段程序翻译一下即可。随手写了一个:
1 #include<stdio.h>
2 #include<ctype.h>
3 #include<string.h>
4 #include<stdlib.h>
5
6 #define N 1000
7 char a[] = "abcdefghijklmnopqrstuvwxyz";
8 char b[] = "pvwdgazxubqfsnrhocitlkeymj";
9 char ci[N];
10
11 char find(char c) {
12 int i;
13 for(i = 0; i < 26; i++) {
14 if(c == b[i]) {
15 break;
16 }
17 }
18 return a[i];
19 }
20
21 int main() {
22 char *str = "Wxgcg txgcg ui p ixgff, txgcg ui p epm. I gyhgwt mrl lig txg ixgff wrsspnd tr irfkg txui hcrvfgs, nre, hfgpig tcm liunz txg crt13 ra \"ixgff\" tr gntgc ngyt fgkgf.";
23
24 int len = strlen(str);
25 for(int i = 0; i < len; ++i) {
26 char c = str[i];
27 if(isalpha(c) && islower(c)) {
28 ci[i] = find(c);
29 } else {
30 ci[i] = c;
31 }
32 }
33
34 printf("%s\n", ci);
35 return 0;
36 }/*output:
37 Where there is a shell, there is a way. I expect you use the shell command to solve this problem, now, please try using the rot13 of "shell" to enter next level.
38 */
发现输出需要用到 rot13,这是啥?!google 一下就知道了,原来就是一个简单的加密工具,因为英文字母有26个,13对,所以正好可以一一对应。然后 google 一下使用方法就可以了,或者懒得直接找一个在线 rot13转换的工具,输入 shell 后得到结果:furyy
总结一下:
因为以前在玩正则表达式的游戏时遇到个这个模式,瞬间就知道这个是考察正则的了。根据那个单词,知道是回文字符串。根据图示知道需要找出能匹配左边8个单词的模式,然后提示语说在源码中有东西。打开源代码拉到最下面有一大段文本,保存到一个文件中。
这时候思路已经很明显了,用找出来的模式去匹配这段文本。那么,首先就需要找出这个模式,如果以前学过正则表达式的话,应该是很 easy 的。如果不太会,在下面总结的时候我会推荐一个讲解正则表达式很好的地方,配套有一个练习的地方(额,难度略高)。
找出来这个模式也很简单,人肉看下就是:
所以,考察的就是最简单的正则表达式,其中回文也可以用正则中的()
来匹配。这样答案就出来了:
([A-Z])([0-9])[a-z]\2\1|([0-9])([A-Z])[a-z]\4\3
然后有输入了,有处理过程了,执行一下即可得到输出:
egrep -o ‘([A-Z])([0-9])[a-z]\2\1|([0-9])([A-Z])[a-z]\4\3‘ palindrome
然后就可以得到答案:
E1v1E
4FaF4
9XrX9
O3i3O
0MaM0
4GbG4
M5l5M
0WeW0
Y0s0Y
这几个都是回文串,我们根据 cat 是最中间小写字母的原则拿出来,得到答案:variables
总结一下:
妈蛋这个页面让我困了大半天,不知道想表达什么意思。我以为是那个数字有特殊的含义,google 了半天找到看起来靠谱的英文。好像是美国哪个州的 zipcode 啥的,填进去各种404,让我很是崩溃。。。 最后也没搞定,是看了网上已经出来的攻略才知道。。(这次写攻略才发现那句提示有点作用,让你 keep try...)
原来需要拿那个数字替换 url 中的2014,于是我就替换了,大概替换了10多次,还是需要替换。。估计要写个程序的样子,于是用 shell 写了个 while 循环,里面就是一个简单的 curl 命令,最后得到了答案:tree
总结一下:
这道题就简单了,就是一个树。扫了一眼就知道题意是由中序和后序还原树,然后求得最深路径。于是写了一段代码,特么由于好久没碰指针,各种凌乱,吭哧吭哧花了将近1个小时才搞定,,,真是弱爆了。。。。
1 #include<iostream>
2 #include<ctype.h>
3 #include<stdio.h>
4 #include<string.h>
5 using namespace std;
6
7 struct Node
8 {
9 char value;
10 Node *left;
11 Node *right;
12 };
13
14 string t_in, t_post;
15 char in[100], post[100];
16 char deep[100], final[100];
17 int maxlen;
18
19 void init() {
20 int p = 0;
21 for(int i = 0; i < t_in.length(); i++) {
22 if(isalnum(t_in[i]))
23 in[p++] = t_in[i];
24 }
25
26 p = 0;
27 for(int i = 0; i < t_post.length(); i++) {
28 if(isalnum(t_post[i]))
29 post[p++] = t_post[i];
30 }
31 }
32
33 Node* build(char *in, char *post, int len) {
34 if(len == 0)
35 return NULL;
36
37 Node *cur = new Node;
38 cur->value = post[len - 1];
39 int lenp = strchr(in, cur->value) - in;
40 cur->left = build(in, post, lenp);
41 cur->right