Jetbrains Quest第二弹第三弹解法

上篇文章我介绍了Jetbrains20周年赠送的福利,3个月全家桶的使用权。虽然需要一定的解密,但是整个解密非常有趣。解密之后,还有另外两次解密,我顺便也给大家介绍一下。


第二弹解密


首先看看推特代码。

Jetbrains Quest第二弹第三弹解法

仔细观察可以发现,这就是字符串逆序而已。所以解密就很简单。

<code>fun twitterCode2() {
val twitterCode =
".spleh A+lrtC/dmC .thgis fo tuo si ti semitemos ,etihw si txet nehw sa drah kooL .tseretni wohs dluohs uoy ecalp a si ,dessecorp si xat hctuD erehw esac ehT .sedih tseuq fo txen eht erehw si ,deificeps era segaugnal cificeps-niamod tcudorp ehT"
println(twitterCode.reversed())
}/<code>

解密之后得到的密文如下。

The product domain-specific languages are specified, is where the next of quest hides. The case where Dutch tax is processed, is a place you should show interest. Look hard as when text is white, sometimes it is out of sight. Cmd/Ctrl+A helps.

这段密文指的就是Jetbrains的另一款创建领域特定语言的工具MPS,经过寻找可以在MPS的文档页面找到关于荷兰税收的例子。

Jetbrains Quest第二弹第三弹解法

点击之后,发现文章中什么都没有,这时候注意到提示里让我们使用全选来寻找白色的隐藏文字。操作之后发现右边确实隐藏了文字。

Jetbrains Quest第二弹第三弹解法

复制出来之后得到结果。这段密文提示我们到Jetbrains20周年年报中寻找信息,分享关于18650这个数字的章节即可获得信息。

This is our 20th year as a company,
we have shared numbers in our JetBrains
Annual report, sharing the section with
18,650 numbers will progress your quest

在年报里寻找相关数字的信息,可能翻遍整个页面都找不到。其实这个18650是如下章节的所有数字之和。点击这里的分享即可获得下一个提示。

Jetbrains Quest第二弹第三弹解法

这个提示很简单,直接给了我们一个网页,并让我们注意Haskell编写的HelloWorld。

Jetbrains Quest第二弹第三弹解法

翻一下网页即可看到这张图片,密文就是图中的黑板报上的字符。这里我寻找的一直不确定是不是,因为手动将图中的字符写下来简直太麻烦了。其实网页里源代码已经明确给出了密文的字符串,因此毫无疑问就是它了。

Jetbrains Quest第二弹第三弹解法

以下就是密文了,这次不是什么加密的密码了。仔细观察可以发现下面的密文很多字符就是用相近的字符做了替换,可以简单看做英文版的火星文。

d1D j00 kN0w J378r41n2 12 4lW4Y2 H1R1N9? ch3CK 0u7 73h K4r33r2 P493 4nD 533 1f 7H3r3 12 4 J08 F0r J00 0R 4 KW357 cH4LL3n93 70 90 fUr7h3r @ l3457.

正确的密文如下,这次指引我们去Jetbrains的招工页面寻找线索。

Did you know Jetbrains is always hiring? Check our ten careers page and see if there is a job for you or a quest challenge to go further at least.

在招工页面里有很多职位,在其中还真找到了一个Quester。

Jetbrains Quest第二弹第三弹解法

点击看看这个职位的要求,可以看到这个用人要求非常有趣,要我们明白Konami游戏的作弊指令。

Jetbrains Quest第二弹第三弹解法

这次在按着提示访问Jetbrains的游戏开发页面,输入经典的游戏作弊码上上下下左右左右BA,即可看到弹出了一个游戏框,完成游戏即可获得兑换码PlayGames,兑换可得3个月Jetbrains全家桶或者6个月的IDEA。

Jetbrains Quest第二弹第三弹解法

第三弹解密

好了,来看看最后一组解密吧。这次的推特代码不太一样,是没有任何规律的字符串。之前我研究过某个软件的分享配置功能,它用的是base64加密配置文件的方式,这次的字符串看着也挺像base64的编码。

Jetbrains Quest第二弹第三弹解法

试一试看看能不能解出有意义的字符串,果然成功了。

<code>fun twitterCode3() { 

val sss = "SGF2ZSB5b3Ugc2VlbiB0aGUgcG9zdCBvbiBvdXIgSW5zdGFncmFtIGFjY291bnQ/"
println(Base64.getDecoder().decode(sss).map { it.toChar() }.joinToString(separator = ""))
}/<code>

解出来的内容如下。

Have you seen the post on our Instagram account?

这次要我们去Instagram看看,那我们就去看看吧。果然有一幅图片,图片旁边的备注要我们去看看另外一个网页。

Jetbrains Quest第二弹第三弹解法

这次是一个Kotlin编码,如果你解过第一个谜题的话,应该可以很容易的发现n是3,就算不知道也可以很轻松的编码尝试出来。

<code>fun tryDecrypt() {
val tryFunc = fun(n: Int) {
val s =
"Zh#kdyh#ehhq#zrunlqj#552:#rq#wkh#ylghr#iru#wkh#iluvw#hslvrgh#ri#wkh#SksVwrup#HDS1#Li#zh#jdyh#|rx#d#foxh/#lw#zrxog#eh#hdv|#dv#sl1"
for (c in s) {
print(c - n)
}
println()
}
(1..3).forEach { tryFunc(it) }
}/<code>

这次解出来的密文如下。

We have been working 22/7 on the video for the first episode of the PhpStorm EAP. If we gave you a clue, it would be easy as pi.

大意是说我们在PhpStorm EAP的视频里弄了点东西,你们去看看,提示是圆周率π。谷歌一下,找到了这个YouTube上的视频,这是2月份发的一个PhpStorm介绍视频。在视频3分14秒的时候,有一秒钟左右的时间闪出了另外一个地址。

Jetbrains Quest第二弹第三弹解法

访问该地址,发现这是一个答题页面,需要我们回答正确5道题,答案就在前面的Jetbrains20周年年报里,重点关注以下信息即可。

  • 创始人图片
  • Jetbrains雇员数目
  • Jetbrains主要工作国家
  • 接受额外基金支持
  • 最新推出的Jetbrains产品
  • 增长最快的国家和地区

回答正确就会看到下面的提示,告诉我们在某个Jetbrains IDEA社区版的每日提示中隐藏了信息,但是版本号并不清除。想知道版本号需要解开第二段的谜题。

Jetbrains Quest第二弹第三弹解法

这个第二段是写的不明不白的一段英文,我在谷歌翻译里对照着看了半天也没搞清楚。但是注意到每个单词的首字母都是大写的,尝试把首字母连接起来,然后分一下词,发现这是一段话。

.Net day call for speakers blog post image hides the next clue.

跟随着线索,谷歌搜索一下关键词,发现这是Jetbrains .NET的一篇博客,标题是Call for speakers,其中的图片暗藏玄机,查看网页源代码即可发现隐藏信息。

Jetbrains Quest第二弹第三弹解法

现在知道了版本号,就可以访问Confluence查找这个版本的IDEA软件了。不过其实也不用专门查找,因为Jetbrains Quests热度的关系,这个版本号已经被顶到第一位了。

Jetbrains Quest第二弹第三弹解法

下载安装软件,查看每日提示即可看到最后一个谜题。这次要我们想办法获得斐波那契数列的第五千万项的前4位和最后4位数字。

JETBRAINS QUEST: LAST PUZZLE
You have discovered our JetBrains Quest! If you don’t know what this is, you should start from the beginning.
This is it. The last puzzle. You are just one step away from glory!
Now you just need the Key to unlock the Quest page.


The Key is the first and last 4 digits of the 50 * 10^6 position of the Fibonacci sequence (F(50 Million)).
As you may know by now, not all that glitters is gold, and to solve this puzzle you should not go straight for the obvious answer. May you make a glorious choice.
Remember that you have until the 15th of March 12:00 CEST.

这个问题可以说是相当有难度,没有高深数学知识是完全无法做出来的,因为不论是常规的递归还是循环,还是保存了计算结果的递归,都无法得出这个结果。因为这项的数量级是10的一千万次方,就算保存成文本也足足有10兆大小。所以偷懒的同学可以使用Wolfram Alpha搜索fib(5e7)以及fib(5e0)mod10000来获取结果。


如果硬要计算的话也不是没办法,需要利用一种优化过的斐波那契数列解法,计算的时候是平方下降的,极大的降低了计算难度。在我的电脑上,这个算法仅需35秒就可以得到结果。

<code>// https://www.maplesoft.com/applications/download.aspx?SF=154362/fibonaccinumbers.pdf
// duplication formula
// f(2n) = f(n)^2 + 2f(n-1)f(n)
// f(2n-1)= f(n)^2 + f(n-1)^2
fun fibonacci2(n: Int, cache: HashMap): BigInteger {
if (n <= 1) {
return BigInteger.valueOf(n.toLong())
}

return if (n % 2 == 0) {
val b = cache.getOrPut(n / 2, { fibonacci2(n / 2, cache) })
val a = cache.getOrPut(n / 2 - 1, { fibonacci2(n / 2 - 1, cache) })
b * b + BigInteger.TWO * b * a
} else {
val b = cache.getOrPut((n + 1) / 2, { fibonacci2((n + 1) / 2, cache) })
val a = cache.getOrPut((n - 1) / 2, { fibonacci2((n - 1) / 2, cache) })
a * a + b * b
}


}
fun main() {
val profile = fun(task: () -> Unit) {
val t1 = LocalDateTime.now()
task()
val t2 = LocalDateTime.now()
println(Duration.between(t1, t2))
}
val c = HashMap()
val n = 5e7.toInt()
//profile { println(fibonacci1(n)) }
profile { println(fibonacci2(n, c)) }
}
/<code>

最终结果的前4位是4602,最后4位是3125,所以最终结果是46023125,这就是本次谜题的答案。利用它可以获得Jetbrains全家桶的八折优惠券,可以说是很良心了。


分享到:


相關文章: