所以,我碰巧注意到last.fm正在我的地区招聘,因为我认识了一些人who worked there,但我申请了。
但我想我最好首先看一下current staff。
该页面上的每个人都有一个可爱/聪明/愚蠢的标语,比如“生命不是我们自己的一千倍太短了吗?”。事实上,在我达到这个目标之前,它非常有趣:
perl -e'print+pack+q,c*,,map$.+=$_,74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21, 18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34'
我无法抗拒粘贴到我的终端(也许是一种愚蠢的事情),但它打印出来了:
另一个Last.fm黑客,
我认为弄清楚Perl单线程如何工作会相对容易。但我真的无法理解文档,我不知道Perl,所以我甚至不确定我是否正在阅读相关文档。
所以我尝试修改数字,这让我无处可去。所以我认为它真的很有趣,值得一试。
所以,“它是如何工作的”有点模糊,我的问题主要是,
这些数字是多少?为什么有负数和正数,否定性或积极性是否重要?
运营商+=$_
的组合是什么?
pack+q,c*,,
在做什么?
答案 0 :(得分:29)
这是“Just another Perl hacker”的一个变种,一个Perl meme。随着JAPH的到来,这个相对温和。
您需要做的第一件事是弄清楚如何解析perl程序。它缺少函数调用的括号,并以有趣的方式使用+
和类似引号的运算符。原始程序是这样的:
print+pack+q,c*,,map$.+=$_,74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21, 18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34
pack
是一个函数,而print
和map
是list operators。无论哪种方式,紧跟一个加号的函数或非空运算符名称都不能使用+
作为二元运算符,因此开头的+
个符号都是unary operators。这种奇怪的行为在manual。
如果我们添加括号,请使用map
的块语法,并添加一些空格,我们得到:
print(+pack(+q,c*,,
map{$.+=$_} (74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21,
18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34)))
下一个棘手的问题是q
这里是q
quote-like operator。它通常用单引号编写:
print(+pack(+'c*',
map{$.+=$_} (74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21,
18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34)))
请记住,一元加号是一个无操作(除了强制标量上下文),因此现在应该看起来更熟悉了。这是对pack
函数的调用,格式为c*
,表示“任意数量的字符,由当前字符集中的数字指定”。另一种写这个的方法是
print(join("", map {chr($.+=$_)} (74, …, -34)))
map
函数按顺序将提供的块应用于参数列表的元素。对于每个元素,$_
设置为元素值,map
调用的结果是通过对连续元素执行块返回的值列表。编写此程序的更长方法是
@list_accumulator = ();
for $n in (74, …, -34) {
$. += $n;
push @list_accumulator, chr($.)
}
print(join("", @list_accumulator))
$.
变量包含运行的总数。选择数字以使运行总数为作者想要打印的字符的ASCII代码:74 = J
,74 + 43 = 117 = u
,74 + 43-2 = 115 = s
等等。取决于每个字符是按照ASCII顺序在前一个字符之前还是之后,它们都是负数或正数。
为了您的下一个任务,请解释此JAPH(由EyesDrop生成)。
''=~('(?{'.('-)@.)@_*([]@!@/)(@)@-@),@(@@+@)'
^'][)@]`}`]()`@.@]@%[`}%[@`@!#@%[').',"})')
请勿在生产代码中使用任何此类内容。
答案 1 :(得分:22)
这背后的基本思想非常简单。您有一个包含字符的ASCII值的数组。为了使事情变得更复杂,你不要使用绝对值,而是使用相对的值,除了第一个。因此,我们的想法是将特定值添加到前一个值,例如:
J
u
s
即使$.
是Perl中的特殊变量,但在这种情况下并不意味着什么特别的。它仅用于保存以前的值并添加当前元素:
map($.+=$_, ARRAY)
基本上它意味着将当前列表元素($_
)添加到变量$.
。这将返回一个新数组,其中包含新句子的正确ASCII值。
Perl中的q
函数用于单引号的文字字符串。例如。你可以使用像
q/Literal $1 String/
q!Another literal String!
q,Third literal string,
这意味着pack+q,c*,,
基本上是pack 'c*', ARRAY
。 c*
中的pack
修饰符将值解释为字符。例如,它将使用该值并将其解释为字符。
它基本归结为:
#!/usr/bin/perl
use strict;
use warnings;
my $prev_value = 0;
my @relative = (74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21, 18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34);
my @absolute = map($prev_value += $_, @relative);
print pack("c*", @absolute);