笔者最近开始玩儿起了Codewars ,这是一个类似LeetCode 的平台,不过题目的类型不限于算法,而且社区比LC 活跃。里有不少语言特性还有最佳实践向的题目,Passed 之后还能看到别人的solutions 并互相评价,一刷起来就容易停不下来。
Codewars 里面有一个特定的 Kata,就是「Multi Line Task」,大致就是限制每行的代码长度,限制行数,完成一个简单的代码问题,语言选择的话只有 Javascript。年前顺手把Voile 在里头发布的Kata 都做了,这里记录下思路。
Multi Line Task: Fizz Buzz\Multi Line Task: GCD Function
这两题基本上没有什么解题的障碍,因为一行能写三个字符之多,所以这类5 kyu 一下就能水过去了。 关键字:箭头函数。
Multi Line Task++: Hello World
这算是Multi Line 题里的分界线了,这个的题解你基本上会写这个:
$ = ''['slice']['bind']('Hello world!')
那你就距离答案只差几个转义符了。
关键字:bind
Multi Line Task: Hello World (Without Letters)
本以为1kyu Multi Line Task∞: Hello World 的才是最终boss,实质上No Letter 所包含的坑远远比我想得多。
第一直觉就是这直接转换为JSF**K,直接jsfuck即可,一气呵成地把:
$ = ''['slice']['bind']('Hello world!')
转换并优化成了
$ = `
`[
(![] + [])[3] +
(![] + [])[2] +
([][[]] + [])[5] +
([] + {})[5] +
([][[]] + [])[3]
][([] + {})[2] + ([][[]] + [])[5] + ([][[]] + [])[1] + ([][[]] + [])[2]](
"H" +
([][[]] + [])[3] +
(![] + [])[2] +
(![] + [])[2] +
([] + {})[1] +
([] + {})[7] +
[4 * 8][0][
(!![] + [])[0] +
([] + {})[1] +
$[0] +
(!!$ + "")[0] +
(!!$ + "")[1] +
([][[]] + [])[5] +
([][[]] + [])[1] +
$[2]
](9 * 4 - 3) +
([] + {})[1] +
(!![] + [])[1] +
(![] + [])[2] +
([][[]] + [])[2] +
`
!
`[1]
)();
所以很明显,这道题的核心难点在于如何得到 H 这个字符, jsfuck 源码中使用的 unescape 得到 H,但是这在node 环境下是做不到的,因为它得到 p 的方法是用location 的字符串形式得到当前网址,从http 中得到 p。脑洞虽大,但是在node 环境下不可用。于是过了一遍 jsfsck 的源码,还是很明确。
然后我的目标转向了fromCharCode,但是生成 fromCharCode 这几个字即使用上了初始提供的 let $ = 'CSg',也得用381个字符串,也就是381行,但是之前实现的基础部分已经使用了370行左右,所以剩余的代码量不能超过330行。
这时候的问题已经缩小到了如何减少行数,所以很简单:提前压缩好所需的字符串即可解题。
关键字:JSFuck,提前压缩变量
Multi Line Task∞: Hello World
作为一道1kyu 的题,这一题所需的知识点太少了,在之前的Multi Line 的技巧加上下面这个知识点你就能过关了。
[,a,,b,,,c] = ` a b c`;
console.log(a,b,c)
$ a b c
关键字:解构赋值
以上就基本上是现阶段CW 里Javascript 相关的Multi Line Task 题目了。