我正在尝试解决一个代码高尔夫练习,其中需要输入测试用例的数量,然后每个测试用例的每行输入一个整数。
为了使我的解决方案尽可能地简短,我找到了这个解决方案:
#!perl -lp
use bigint;$_=???<>+1:bnok{2*$_}$_
我对perl非常陌生,因此不明白这段代码的实际运作方式。如果有人能帮我解决这个问题,我将不胜感激。
我正在尝试解决一个代码高尔夫练习,其中需要输入测试用例的数量,然后每个测试用例的每行输入一个整数。
为了使我的解决方案尽可能地简短,我找到了这个解决方案:
#!perl -lp
use bigint;$_=???<>+1:bnok{2*$_}$_
我对perl非常陌生,因此不明白这段代码的实际运作方式。如果有人能帮我解决这个问题,我将不胜感激。
有一些用于解决 Perl golf 的工具。其中一个是 perlsecret,它记录了许多 Perl golf 玩家使用的“秘密操作符”和技巧。
对于这个特定的代码,理解 -p
做什么 也很重要。它将代码包装在一堆其他代码中,可以用于高尔夫比赛。
最后,解开 Perl golf 的终极工具是 B::Deparse。它将 Perl 对代码的理解转换回可读的 Perl 代码,并进行缩进等处理。-p 选项使 B::Deparse 即使不必要也添加括号,这有助于澄清优先级。-d 选项提供了更准确的对象表示。哪些对象?观察即可。
$ perl -MO=Deparse,-p,-d
#!perl -lp
use bigint;$_=???<>+1:bnok{2*$_}$_
Use of ?PATTERN? without explicit operator is deprecated at - line 2.
BEGIN { $/ = "\n"; $\ = "\n"; }
use bigint;
LINE: while (defined(($_ = <ARGV>))) {
chomp($_);
BEGIN {
$^H{'bigint'} = '1';
$^H{'binary'} = 'CODE(0x7fc88ba3d580)';
$^H{'float'} = 'CODE(0x7fc88ba3d478)';
$^H{'integer'} = 'CODE(0x7fc88b298428)';
}
($_ = (?? ? (<ARGV> + bless( {"sign" => "+","value" => [1]}, 'Math::BigInt' )) : (bnok {
(bless( {"sign" => "+","value" => [2]}, 'Math::BigInt' ) * $_)
} $_)));
}
continue {
(print($_) or die("-p destination: $!\n"));
}
- syntax OK
??
是?PATTERN?
运算符和?:
三元运算符的结合,具体来说,??
是三元条件语句的条件。??
的工作方式与//
相同,但它只匹配一次,直到调用reset
。因为在这个程序中没有调用reset,所以它只会匹配一次。而//
将匹配任何内容。use bigint
将所有整数转换为Math::BigInt对象。bnok
是来自Math::BigInt的二项式系数方法。bnok
被用作对整数(实际上是Math::BigInt对象)的间接方法调用。间接方法调用的格式为method $object @args
,因此bnok{2*$_}$_
实际上是(2*$_)->bnok($_)
,即中心二项式系数。(
$_ =
(?? ? (<ARGV> + bless( {"sign" => "+","value" => [1]}, 'Math::BigInt' ))
: (bnok {(bless( {"sign" => "+","value" => [2]}, 'Math::BigInt' ) * $_) } $_)
)
);
??
只会在整个程序中匹配一次,它用于跳过第一行,该行是测试数量。??
将为false,这将触发bnok
计算。有一个细节我还没有解决。为什么是<>+1
而不是<>
?它似乎抑制了一个空行,但我不知道为什么。