1024 HackGame 第四关面壁人这些题目是怎么想出来的?

Viewed 12364

「红岸的呼唤」里第四关 13 位面壁人的“信息都传递的比较隐蔽”,感觉大部分破壁人都是在蒙答案。面壁人都来把自己的题目给大家解一下吧。

guide.a1416302.png

剛想出來正確的解題思路就沒機會了(哭。。。

正確的解題思路不是純用腦計算也不是純手打代碼,而是。。。大腦提取關鍵部分(不好確定的),手打代碼得到結果,帶回去繼續大腦計算~

这个问题很赚声望呐

12 Answers

出题内幕

  1. 并非面壁人希望出javascript的题,而是只能出javascript的题
  2. 破壁人原本只有30秒的时间,后来几经改动
  3. 本人并不十分精通javascript,无法像其他大神那样又是语言基础又是算法的,于是决定弄点技巧性的

我的题目

function(){
    var str = ")fodpefVSJ",f=[];
    for(var s in str){
        f.push(String.fromCharCode(str.charCodeAt(s)-1))
    }
    return eval(f.join('')+'("挖掘机哪家强中国山东找蓝翔").length)%10');
}

答案为:7

出题思路

首先想到的是考中文url编码,因为大家知道一个中文汉字的url编码(UTF-8)大致是%E6%XX%XX,于是有两个考点,一个是考%E6中的E,另一个是考长度,几经考虑后决定考长度,由于答案在1-10之间,所以%10就很顺利成章了:

(encodeURI("挖掘机哪家强中国山东找蓝翔").length)%10

看到这里答案就很明显了,13个汉字,每个经过encodeURI后,长度扩充为9,那么(13*9)%10=7

题目发到面壁人讨论组后,大神说30秒能通过键盘敲下来,于是,打算加点料:由于encodeURI是个很明显的函数,为了隐藏这个函数,通过ASCII的偏移构造了一个字符串)fodpefVSJ,这个字符串的每一个字符的ASCII值-1再转回字符即可得到(encodeURI,于是有了这个代码:

var str = ")fodpefVSJ",f=[];
for(var s in str){
    f.push(String.fromCharCode(str.charCodeAt(s)-1))
}

感想

站在出题人的角度,由于思路是清晰的,当然会觉得题目简单,但是在短短的60秒内,有些题确实很难找到出题人的意图,我自己在破壁的时候,感觉就是在做英语完形填空似的,哪个像选哪个。。

您对本题有何感想,欢迎交流

当时看到这道题“山东找蓝翔”,被雷倒了几秒,但javascript学习不足,然后使用了“瞎猜大法”。 T-T,本来想着答完之后, 再做一次的,想不到不能做两次

大家好~
我是面壁人Dont,编码:0x0A
防守属性:智力脑残型。
目前战绩(截止至2014-10-31 14:35 被破壁 14 次, 成功守护 67 次)


当晚还在纠结怎么出题来着,看到encodeURIcharCodeAt,我觉得有点想法了。(观众们看完题目再砸鸡蛋哈。)


请听题

function(){
   var t = encodeURI('你一定没女朋友.(逃……');
  return ((t[7].charCodeAt(0)+'').split().reduce(function(a,b){return a-0+(b-0)})+'')[1];
}

首先,encodeURI那个,其实因为后面只是取了结果字符串的第7位。如果你用过encodeURI,大概就知道规律了。如下:
图片描述

呐,其实呢第一个汉字encode出来就是9个字符啦,所以解题的时候只要知道encodeURI('你')就够了。

这里其实就是 A (好像颜文字= =

其次呢,charCodeAt>>就获取'A'的unicode编码

The charCodeAt() method returns the numeric Unicode value of the character at the given index (except for unicode codepoints > 0x10000).

A 对应的是65哦。

后面呢,是个人的歪想,如果你用过split,是否有试过忘了给参数的情况?(我就是这么干过。

str.split([separator][, limit])

separator

Specifies the character(s) to use for separating the string. The separator is treated as a string or a regular expression. If separator is omitted, the array returned contains one element consisting of the entire string. If separator is an empty string, str is converted to an array of characters.

所以呢,我脑洞大开觉得观众们可能会出现两种猜测: spilt得到 65 和 6,5 两种组合;
然后我用reduce其实只是做分割后的数字计算,得到两种猜测结果: 65 or 11
然后取最后一位的数字即 5 or 1 (哈哈哈,脑补太多了,等等先打我)

花絮

原本想着调皮点弄个这样的:

String.fromCharCode(encodeURI('你没女朋友?y/n')[7].charCodeAt(0)+56);//答案: y

他们说好贱,最后得知要结果是1-10的其中一个,所以后来左思右想就有了上面的split脑洞乱开。


谢幕。请砸蛋…… (逃……

2 B continue

当工作人员把一颗红色药丸和蓝色药丸放在我面前时,我果断接下了面壁者的任务。

作为一个踩过诸多 js 坑的过来人,坑人自然有很多法子。

但是我想既然出的是 js 题,万一别人直接把代码复制到 console 一跑,答案不就出来了么——所以我推断应该是以图片展示的方式出题。于是脑洞一开,我让你丫看不明白题目不就行了!

这很好办:由于 js 是兼容 unicode 变量名的,我只要选两个长得一模一样的字符就可以达到目的了。于是我选了一个和 3 很像的西里尔字母 ʒ 和 ӡ :

http://shapecatcher.com/unicode/info/439
http://shapecatcher.com/unicode/info/1248

于是迷一样的题目出现了!

我想要的

不料第二天起来,工作人员说我的代码乱码了——

结果变成这样

啊!这不是我想要的生活!自己竟然被字体坑了!

外星文竟然如此不给力,只好拿国粹了——找来两个汉字凑数吧:“壼壺”,
于是就有了你们最后看到的题目。

至于答案嘛,上面的底裤都被脱得一览无余了,不需要解释了吧。

提示 ~[] // -1

难怪当时见到那么乱的代码,分析起来挺头疼的。

大家好,我是面壁人Snooze
我的防守属性:唬人型
题目不难,先上代码:

图片描述

扯一下出题背景。
题目是受前几天刷LeetCode一道题目:Triangle的启发,改编而来。

图片描述

Triangle这个题目的原意,是要求用动态规划(Dynamic Programing)算法去求解一个数组三角形的最小路径。
------背景结束------

好了,回到面壁者-破壁者这个问题,和Online Judge考察撸代码能力不同,这里是考察破壁者的代码阅读能力。
我就把上面的题目进行了改编,改成求解三角形中“最平坦的路径”(即整条路径上相邻数字的差值之和最小),并且给出了求解这个问题的动态规划的实现(题目代码中的两个for循环)。

不少人刚看到这个题,可能会吐槽:
坑爹啊!!这么大的一个三角型当成参数传给两个for循环,让我30秒怎么算啊!!我大脑内存哪有那么大啊!!

千万不要被那个三角形唬到了,trick就在这里。
其实破壁者只要明白了代码中两个for循环是在求解“最平坦路径”,那么根本没必要具体去算,瞟一眼我给出的三角形就能轻松发现,“最平坦路径”非常明显嘛!(如下图所示)
图片描述

好了,到这里,我们就拿到了“最平坦路径”的高度差之和(variation[0] = 1),进入了return环节。
到这个环节,用了几个位运算符号干扰破壁人,其实对最终结果无影响,然后1%10+1=2,就是这道题的答案啦!


设计这个题的动机,是想突出人之于计算机的优势之一:人对与小规模数据的信息归纳、模式识别能力,远远强于计算机

Ps.其实一开始的题目更难一些,经面壁群里的小伙伴建议,我把干扰信息去掉了,提高了代码的可读性,三角形的路径和在return处的干扰也弄简单了。
想想只有30s的时间,破壁者也挺不容易的,没必要故意刁难嘛,毕竟做人最要紧开心。
图片描述

这配图真是“最要紧开心”(╯‵□′)╯︵┴─┴

    function fib(seq) {
        return seq.shift().filter(function(n) {return n}).shift()
             * (seq.length - 1 ? fib(seq) : seq.shift().pop() );
    }
    fib( [ [1,1,2,3], [0,1,2,3], [0,0,2,3], [0,0,0,3] ] );

我的题目其实很简单,先把二维数组的参数格式化一下你就会发现它其实就是一个矩阵,而且是具有下三角特性的矩阵(其实我觉得说到这里应该有人知道答案了):

fib( [
        [1,1,2,3],
        [0,1,2,3],
        [0,0,2,3],
        [0,0,0,3]
    ] )

另外要说的是shift()pop()函数都有直接改变原对象的特性,所以每次的操作都会把二维数组改变。函数的结果应该是几个数相乘,取名为fib 其实是想用斐波那契迷惑一下大家,每个数组的元素也正好是斐波那契的前几项,不知道有没有人上钩,不过其实好像如果直接用斐波那契的话也恰好是正确答案(感觉有点聪明反被聪明误的感觉,2333)。

seq.shift().filter(function(n){return n}).shift()这个其实就是想要取二维数组的第一个数组并返回第一个非0数字。其实完全可以用lastIndexOf()写的,不过感觉如果用这个写的话一下就被你们看穿了有点太LOW了。第二个乘数是判断如果是二维数组最后一个了就返回该数组的最后一项(也就是3,因为前面全是0了,其实和上一句的作用相同也是返回第一个非0字符),如果不是的话就递归函数。

所以总的来说函数的目的就是递归返回二维数组的每一个数组第一个非0数字并相乘,所以结果就是 1 * 1 * 2 * 3 = 6。说到这里估计有人看出来了,其实目的就是行列式求值而已(迹相乘)。所以如果有人能看出是下三角的话惯性思维下去也能直接得到答案了。当然有人如果认为是斐波那契额相乘也是能误打误撞得到答案的。

以上。

谢邀

图片描述

function (){
    return "选3的木有小JJ".charCodeAt(1)%8;
}

相信我的题目坑了大家。

我跟其他面壁人的思路不一样。我为什么要写一个优雅的、开发智力的函数?我出题的唯一目的就是让更少的人答出题啊。从结果来看也是一样的。有多少人能够在60中间看出一道题的玄机?最后榜单前十还不是一堆马甲,靠蒙靠把代码手打一遍爬上去的?

所以我的思路很明确:
1. 去误导那些蒙的人。
2. 对抗手打代码的人。

所以我在3前面插入了一个零宽空格。在JavaScript中也可以表示为\ufeff。可惜SegmentFault工作人员的代码高亮软件把零宽空格显示出来了。

在被破壁人们骂死之前,我想说,不要多琢磨这些题……有好多值得看的书呢……

----------------------补充---------------------

还是加一点正能量吧,其实是有解题思路的。第一次放弃小JJ回答3错误以后,你必然会想,为什么不是3呢?我觉得很容易得出3前面有其他字符这个结论。那么,为什么3前面有其他字符,却看不见呢?下面的同学回答的很好,“可能是一个特殊的Unicode字符”。很多Unicode字符都无法正常显示,会显示成方框或者空白,但是这里没有啊。如果你知识够渊博的话,你就会猜到是零宽空格这个神奇的东西了。

————向放弃小JJ又拿不到分的各位致敬。

蟹妖 :D
我是面壁人dashuo

题目:

function() {
return 1 
    + ( "The ultimate answer is " 
    + [(0<<(0==0))+([0]+[(0==0)+(0==0)]^0)]*[(0^[(0==0)+(0==0)]+[0])+((0==0)>>0)] 
    + "!" ).length  
    % ([(0==0)+0]+[0]);
}

这题如果知道《银河系漫游指南》里的典故的话,一分钟内还是有机会做出来的 :P
涉及到很多隐式类型转换,在booleannumberstring之间

  • 答案是7,因为:

    • 我喜欢7这个数字 :P
    • 1 + ( "The ultimate answer is " + [(0<<(0==0))+([0]+[(0==0)+(0==0)]^0)]*[(0^[(0==0)+(0==0)]+[0])+((0==0)>>0)] + "!" ).length % ([(0==0)+0]+[0]) === 7 因为:

      • [(0<<(0==0))+([0]+[(0==0)+(0==0)]^0)]*[(0^[(0==0)+(0==0)]+[0])+((0==0)>>0)] === 42 因为:

      • [(0==0)+0]+[0] === "10" 因为:

        • (0==0) === true
        • true + 0 === 1
        • [1] + [0] === "10"
      • 1 + "The ultimate answer is 42!".length % 10 === 7 因为:

恭喜蒙对的同学们~

当时一看就知道是42,无奈js不熟,手慢了

本是照着120秒的时限出的- =

题目:

图片描述

出题思路:

通过两个function之间多次互相调用,最终把传入的任意数字转化为一个数字输出出去。

解这道题最好的办法就是:相信直觉

假设i=5,b(5)输出5,a(5)也是5。。。

为了不被随机数迷惑,还专门给了注释。

图片描述
认真看了题的应该都能猜到答案。

恩,的确解出来了,不算难

大家好,我是面壁人,冉坤坤坤,oh yeah。。。。。

好吧,下面是我的出题思路:

  • 出题要看似简单,解题人只有30s的时间答题
  • 在简单的代码里面,埋坑

于是就有了如下的代码

function gl(){
    a = new Array(5,8,9,7,4,2,3,6,0,1);
    return a[a[(function(i){i++;return (i!=0) ? false : true;}) ? 0 : 2]];
}

一开始,很多人可能会去注意这个

(function(i){i++;return (i!=0) ? false : true;})

认为它的结果是false,但相反,它运行出来不会输出什么...,我么变换一下

function test(i){i++;return (i!=0) ? false : true;}

这一段test()如果不给参数确实是false
但,我们去掉了函数名之后,结果就不一样了哦
ok,所以语句变成了

a[a[true ? 0 : 2]
a[a[0]]
a[5]

很简单吧


小弟才艺不佳,也就做到这个地步咯。

Have fun & Enjoy Yourself

谢邀。
我是面壁人cnfuyu

题目概述

function() {
    var fault = [1, 8, 6, 1, 8, 1, 9, 3, 2, 4, 5, 9, 4]; //len=13
    try{
        fault = (segment = function(fault) {
            return fault.length === !fault + false ? [] : [].concat(
                segment(fault.filter(function(m) {return m < fault[0]})),
                fault[0],
                segment(fault.filter(function(m) {return m > fault[0]}))
            );
        }) (fault)[fault[12]];
    }
    catch(error) {return fault[12];}
    return fault;
}

这就是我的题目,答案是5

我的题目有个特点就是把sf给出的512个字符全部占满了。其实本意没有想把512个字符全部用满,但是最后敲定题目的时候才发现刚刚好512个字符。

因为本人非专业js玩家,绞尽脑汁都不知道出什么题好,所以就用js写了个简易的排序+去重的函数,然后就拿来坑大家了。。。

题目难点

这个题目其实不是很难,个人觉得有三个坑:

  1. fault.length === !fault + false这个地方可能对于不是太了解js的人(其实我也不了解)会产生一些疑惑。
  2. segment这个函数的功能一下子可能无法看出来。
  3. segment这个函数的功能看出来了,但是容易忽略细节。

当然,在大神面前,这简直就是轻而易举的事情。

解题思路

首先,fault这个数组大家只需要知道它的长度是13,题中也已经好心的给出来了。然后就是弄懂segment这个函数是干了什么。

segment函数前面的那段fault.length === !fault + false是用于判断fault的长度是否为0,如果为0则直接返回[]。值得一提的是在jsfalse在加减乘除操作中是当作0处理的,所以!fault + false等于0.

segment函数在return的时候调用了两次segment函数,第一次调用是先过滤出小于fault[0]的数,第二次调用是先过滤出大于fault[0]的数,然后再将他们通过concat函数连接起来,生成一个新的数组,所以segment函数主要是实现了排序的功能,其次,由于在判断大小的时候没有加等于号,所以会将数组中重复出现的数字去除掉。

最后想说

很庆幸自己在面壁人和破壁人中选择了面壁人,现在看到其他童鞋出的题目,尤其是那些坑爹的编码问题,真是太!尼!玛!变!态!了!

面壁人tsunami42,昨天下午就写了一半,然后就拖着不想写……

function challege4() {
    challege2 = [0, 0, 0, 8, 6, 0, 0, 8, 0, 9, 3, 2, 4, 5, 9, 4]

    segment =
        (fault =
            function(index, arr) {
                return [].concat(
                    arr.slice(0, index - 1).reverse(),
                    arr.slice(index - 1, arr.length).reverse()
                ).reverse()[arr.length - index]
            });

    return segment(challege2[fault(14, challege2)], challege2)
}

我的题目相较于其他几位的题目,可以说一是一览无遗。由于几乎没有js的经验,所以当接到面壁人的任务的时候,第一反应就是 一定不能和js的语法有关 ,只涉及 简单的算法

3个reverse的作用其实很简单,就是将arr数组循环左移index位,最后取出[arr.length - index],即为原数组的最后一位

设计这个题目时,就希望构造一个函数,输出结果不随输入改变。本打算在return时直接random作为index,后来转念一想,如果这样肯定就会有人去猜结果,没有人看题目了。
所以我故意在return那里多加了层嵌套,目的就是为了让破壁人通过理解我代码的意图去解题

用3个reverse来对数组进行循环移位,其实是我上数据结构课时印象很深的一道课后习题,如何用o(1)的空间复杂度完成对数组的循环移位,相关解释的google一搜一大把。当然,说出来就没啥意思了。


其实吧,单看我这一道题还是属于在60s内可以看出的,但是在加上其他几位破壁的人题目,我猜大家看到我这题的时候,应该已经没心思集中精力看了吧。

* 最后,这个编辑器用着还挺舒服的,但是发现一个设计缺陷,不知道是不是我打开的方式不对。
就是分割线的快捷键提示是Ctrl+R,这不是浏览器reload的快捷键么。脑子抽了按了一下,脸一黑啊-_-!!!,还好有自动保存,不然我这篇题解就不想再写了 *

看来用的不是Chrome?!我记得应该会屏蔽浏览器快捷键效果的=w=。

我的确用的是chrome,还有,我最后的斜体怎么没了。。。

那不应该啊,我这边测试Ctrl+R不会reload的,而且我也有记得SF有加event.preventDefault()。那个斜体我改的..整段的斜体看着好不舒服就...你要觉得需要你再自己改回来吧OwQ...sorry

是啊这些题做得真是太累了。

Related Questions