sub foo {[$#{$_[!$||$|]}*@{$_[!!$_^!$_]}?@{$_[!$..!!$.]}[$_[@--@+]%
@{$_[$==~/(?=)//!$`]}..$#{$_[$??!!$?:!$?]},($)?!$):!!$))..$_[$--$-]%@{
$_[$]/$]]}-(!!$++!$+)]:@{$_[!!$^^^!$^^]}]}
update: I thought the word "puzzle" would imply this, but: I know what it does - I wrote it. If the puzzle doesn't interest you, please don't waste any time on it.
更新:我认为“拼图”这个词会暗示这一点,但是:我知道它的作用 - 我写了它。如果拼图不感兴趣,请不要浪费任何时间。
3 个解决方案
#1
19
Here is how you figure out how to de-obfuscate this subroutine.
Sorry for the length
对不起,长度
First let's tidy up the code, and add useful comments.
首先让我们整理代码,并添加有用的注释。
sub foo {
[
(
# ($#{$_[1]})
$#{
$_[
! ( $| | $| )
# $OUTPUT_AUTOFLUSH === $|
# $| is usually 0
# ! ( $| | $| )
# ! ( 0 | 0 )
# ! ( 0 )
# 1
]
}
*
# @{$_[1]}
@{
$_[
!!$_ ^ !$_
# !! 1 ^ ! 1
# ! 0 ^ 0
# 1 ^ 0
# 1
# !! 0 ^ ! 0
# ! 1 ^ 1
# 0 ^ 1
# 1
]
}
)
?
# @{$_[1]}
@{
$_[
!$. . !!$.
# $INPUT_LINE_NUMBER === $.
# $. starts at 1
# !$. . !!$.
# ! 1 . !! 1
# 0 . ! 0
# 0 . 1
# 01
]
}
[
# $_[0]
$_[
# @LAST_MATCH_START - @LAST_MATCH_END
# 0
@- - @+
]
%
# @{$_[1]}
@{
$_[
$= =~ /(?=)/ / !$` #( fix highlighting )`/
# $= is usually 60
# /(?=)/ will match, returns 1
# $` will be ''
# 1 / ! ''
# 1 / ! 0
# 1 / 1
# 1
]
}
..
# $#{$_[1]}
$#{
$_[
$? ? !!$? : !$?
# $CHILD_ERROR === $?
# $? ? !!$? : !$?
# 0 ? !! 0 : ! 0
# 0 ? 0 : 1
# 1
# 1 ? !! 1 : ! 1
# 1 ? 1 : 0
# 1
]
}
,
# ( 0 )
(
$) ? !$) : !!$)
# $EFFECTIVE_GROUP_ID === $)
# $) ? !$) : !!$)
# 0 ? ! 0 : !! 0
# 0 ? 1 : 0
# 0
# 1 ? ! 1 : !! 1
# 1 ? 0 : 1
# 0
)
..
# $_[0]
$_[
$- - $- # 0
# $LAST_PAREN_MATCH = $-
# 1 - 1 == 0
# 5 - 5 == 0
]
%
# @{$_[1]}
@{
$_[
$] / $]
# $] === The version + patchlevel / 1000 of the Perl interpreter.
# 1 / 1 == 1
# 5 / 5 == 1
]
}
-
# ( 1 )
(
!!$+ + !$+
# !! 1 + ! 1
# ! 0 + 0
# 1 + 0
# 1
)
]
:
# @{$_[1]}
@{
$_[
!!$^^ ^ !$^^
# !! 1 ^ ! 1
# ! 0 ^ 0
# 1 ^ 0
# 1
# !! 0 ^ ! 0
# ! 1 ^ 1
# 0 ^ 1
# 1
]
}
]
}
Now let's remove some of the obfuscation.
现在让我们删除一些混淆。
sub foo{
[
(
$#{$_[1]} * @{$_[1]}
)
?
@{$_[1]}[
( $_[0] % @{$_[1]} ) .. $#{$_[1]}
,
0 .. ( $_[0] % @{$_[1]} - 1 )
]
:
@{$_[1]}
]
}
Now that we have some idea of what is going on, let's name the variables.
现在我们已经知道发生了什么,让我们命名变量。
sub foo{
my( $item_0, $arr_1 ) = @_;
my $len_1 = @$arr_1;
[
# This essentially just checks that the length of $arr_1 is greater than 1
( ( $len_1 -1 ) * $len_1 )
# ( ( $len_1 -1 ) * $len_1 )
# ( ( 5 -1 ) * 5 )
# 4 * 5
# 20
# 20 ? 1 : 0 == 1
# ( ( $len_1 -1 ) * $len_1 )
# ( ( 2 -1 ) * 2 )
# 1 * 2
# 2
# 2 ? 1 : 0 == 1
# ( ( $len_1 -1 ) * $len_1 )
# ( ( 1 -1 ) * 1 )
# 0 * 1
# 0
# 0 ? 1 : 0 == 0
# ( ( $len_1 -1 ) * $len_1 )
# ( ( 0 -1 ) * 0 )
# -1 * 0
# 0
# 0 ? 1 : 0 == 0
?
@{$arr_1}[
( $item_0 % $len_1 ) .. ( $len_1 -1 ),
0 .. ( $item_0 % $len_1 - 1 )
]
:
# If we get here, @$arr_1 is either empty or has only one element
@$arr_1
]
}
Let's refactor the code to make it a little bit more readable.
让我们重构代码,使其更具可读性。
sub foo{
my( $item_0, $arr_1 ) = @_;
my $len_1 = @$arr_1;
if( $len_1 > 1 ){
return [
@{$arr_1}[
( $item_0 % $len_1 ) .. ( $len_1 -1 ),
0 .. ( $item_0 % $len_1 - 1 )
]
];
}elsif( $len_1 ){
return [ @$arr_1 ];
}else{
return [];
}
}
#2
9
I found this command helpful, when working on my other answer.
在处理我的其他答案时,我发现此命令很有用。
perl -MO=Concise,foo,-terse,-compact obpuz.pl > obpuz.out
perl -MO = Concise,foo,-terse,-compact obpuz.pl> obpuz.out
#3
7
It takes two arrayrefs and returns a new arrayref with the contents of the second array rearranged such that the second part comes before the first part, split at a point based on the memory location of the first array. When the second array is empty or contains one item, just returns a copy of the second array. Equivalent to the following:
它需要两个arrayref并返回一个新的arrayref,第二个数组的内容重新排列,使得第二个部分位于第一个部分之前,根据第一个数组的内存位置分割。当第二个数组为空或包含一个项时,只返回第二个数组的副本。相当于以下内容:
sub foo {
my ($list1, $list2) = @_;
my @output;
if (@$list2 > 0) {
my $split = $list1 % @$list2;
@output = @$list2[$split .. $#$list2, 0 .. ($split - 1)];
} else {
@output = @$list2;
}
return \@output;
}
$list1 % @$list2
essentially picks a random place to split the array, based on $list
which evaluates to the memory address of $list when evaluated in a numeric context.
$ list1%@ $ list2基本上选择一个随机位置来拆分数组,基于$ list,在数值上下文中计算时,它会计算$ list的内存地址。
The original mostly uses a lot of tautologies involving punctuation variables to obfuscate. e.g.
原文主要使用大量涉及标点符号变量的重言式来进行混淆。例如
-
!$| | $|
is always 1 -
@- - @+
is always 0
!$ | | $ |永远是1
@ - - @ +始终为0
Updated to note that perltidy
was very helpful deciphering here, but it choked on !!$^^^!$^^
, which it reformats to !!$^ ^ ^ !$^ ^
, which is invalid Perl; it should be !!$^^ ^ !$^^
. This might be the cause of RWendi's compile error.
更新后注意perltidy在这里解密是非常有用的,但它窒息!! $ ^^^!$ ^^,它重新格式化为!! $ ^ ^ ^!$ ^ ^,这是无效的Perl;它应该是!! $ ^^ ^!$ ^^。这可能是RWendi编译错误的原因。
#1
19
Here is how you figure out how to de-obfuscate this subroutine.
Sorry for the length
对不起,长度
First let's tidy up the code, and add useful comments.
首先让我们整理代码,并添加有用的注释。
sub foo {
[
(
# ($#{$_[1]})
$#{
$_[
! ( $| | $| )
# $OUTPUT_AUTOFLUSH === $|
# $| is usually 0
# ! ( $| | $| )
# ! ( 0 | 0 )
# ! ( 0 )
# 1
]
}
*
# @{$_[1]}
@{
$_[
!!$_ ^ !$_
# !! 1 ^ ! 1
# ! 0 ^ 0
# 1 ^ 0
# 1
# !! 0 ^ ! 0
# ! 1 ^ 1
# 0 ^ 1
# 1
]
}
)
?
# @{$_[1]}
@{
$_[
!$. . !!$.
# $INPUT_LINE_NUMBER === $.
# $. starts at 1
# !$. . !!$.
# ! 1 . !! 1
# 0 . ! 0
# 0 . 1
# 01
]
}
[
# $_[0]
$_[
# @LAST_MATCH_START - @LAST_MATCH_END
# 0
@- - @+
]
%
# @{$_[1]}
@{
$_[
$= =~ /(?=)/ / !$` #( fix highlighting )`/
# $= is usually 60
# /(?=)/ will match, returns 1
# $` will be ''
# 1 / ! ''
# 1 / ! 0
# 1 / 1
# 1
]
}
..
# $#{$_[1]}
$#{
$_[
$? ? !!$? : !$?
# $CHILD_ERROR === $?
# $? ? !!$? : !$?
# 0 ? !! 0 : ! 0
# 0 ? 0 : 1
# 1
# 1 ? !! 1 : ! 1
# 1 ? 1 : 0
# 1
]
}
,
# ( 0 )
(
$) ? !$) : !!$)
# $EFFECTIVE_GROUP_ID === $)
# $) ? !$) : !!$)
# 0 ? ! 0 : !! 0
# 0 ? 1 : 0
# 0
# 1 ? ! 1 : !! 1
# 1 ? 0 : 1
# 0
)
..
# $_[0]
$_[
$- - $- # 0
# $LAST_PAREN_MATCH = $-
# 1 - 1 == 0
# 5 - 5 == 0
]
%
# @{$_[1]}
@{
$_[
$] / $]
# $] === The version + patchlevel / 1000 of the Perl interpreter.
# 1 / 1 == 1
# 5 / 5 == 1
]
}
-
# ( 1 )
(
!!$+ + !$+
# !! 1 + ! 1
# ! 0 + 0
# 1 + 0
# 1
)
]
:
# @{$_[1]}
@{
$_[
!!$^^ ^ !$^^
# !! 1 ^ ! 1
# ! 0 ^ 0
# 1 ^ 0
# 1
# !! 0 ^ ! 0
# ! 1 ^ 1
# 0 ^ 1
# 1
]
}
]
}
Now let's remove some of the obfuscation.
现在让我们删除一些混淆。
sub foo{
[
(
$#{$_[1]} * @{$_[1]}
)
?
@{$_[1]}[
( $_[0] % @{$_[1]} ) .. $#{$_[1]}
,
0 .. ( $_[0] % @{$_[1]} - 1 )
]
:
@{$_[1]}
]
}
Now that we have some idea of what is going on, let's name the variables.
现在我们已经知道发生了什么,让我们命名变量。
sub foo{
my( $item_0, $arr_1 ) = @_;
my $len_1 = @$arr_1;
[
# This essentially just checks that the length of $arr_1 is greater than 1
( ( $len_1 -1 ) * $len_1 )
# ( ( $len_1 -1 ) * $len_1 )
# ( ( 5 -1 ) * 5 )
# 4 * 5
# 20
# 20 ? 1 : 0 == 1
# ( ( $len_1 -1 ) * $len_1 )
# ( ( 2 -1 ) * 2 )
# 1 * 2
# 2
# 2 ? 1 : 0 == 1
# ( ( $len_1 -1 ) * $len_1 )
# ( ( 1 -1 ) * 1 )
# 0 * 1
# 0
# 0 ? 1 : 0 == 0
# ( ( $len_1 -1 ) * $len_1 )
# ( ( 0 -1 ) * 0 )
# -1 * 0
# 0
# 0 ? 1 : 0 == 0
?
@{$arr_1}[
( $item_0 % $len_1 ) .. ( $len_1 -1 ),
0 .. ( $item_0 % $len_1 - 1 )
]
:
# If we get here, @$arr_1 is either empty or has only one element
@$arr_1
]
}
Let's refactor the code to make it a little bit more readable.
让我们重构代码,使其更具可读性。
sub foo{
my( $item_0, $arr_1 ) = @_;
my $len_1 = @$arr_1;
if( $len_1 > 1 ){
return [
@{$arr_1}[
( $item_0 % $len_1 ) .. ( $len_1 -1 ),
0 .. ( $item_0 % $len_1 - 1 )
]
];
}elsif( $len_1 ){
return [ @$arr_1 ];
}else{
return [];
}
}
#2
9
I found this command helpful, when working on my other answer.
在处理我的其他答案时,我发现此命令很有用。
perl -MO=Concise,foo,-terse,-compact obpuz.pl > obpuz.out
perl -MO = Concise,foo,-terse,-compact obpuz.pl> obpuz.out
#3
7
It takes two arrayrefs and returns a new arrayref with the contents of the second array rearranged such that the second part comes before the first part, split at a point based on the memory location of the first array. When the second array is empty or contains one item, just returns a copy of the second array. Equivalent to the following:
它需要两个arrayref并返回一个新的arrayref,第二个数组的内容重新排列,使得第二个部分位于第一个部分之前,根据第一个数组的内存位置分割。当第二个数组为空或包含一个项时,只返回第二个数组的副本。相当于以下内容:
sub foo {
my ($list1, $list2) = @_;
my @output;
if (@$list2 > 0) {
my $split = $list1 % @$list2;
@output = @$list2[$split .. $#$list2, 0 .. ($split - 1)];
} else {
@output = @$list2;
}
return \@output;
}
$list1 % @$list2
essentially picks a random place to split the array, based on $list
which evaluates to the memory address of $list when evaluated in a numeric context.
$ list1%@ $ list2基本上选择一个随机位置来拆分数组,基于$ list,在数值上下文中计算时,它会计算$ list的内存地址。
The original mostly uses a lot of tautologies involving punctuation variables to obfuscate. e.g.
原文主要使用大量涉及标点符号变量的重言式来进行混淆。例如
-
!$| | $|
is always 1 -
@- - @+
is always 0
!$ | | $ |永远是1
@ - - @ +始终为0
Updated to note that perltidy
was very helpful deciphering here, but it choked on !!$^^^!$^^
, which it reformats to !!$^ ^ ^ !$^ ^
, which is invalid Perl; it should be !!$^^ ^ !$^^
. This might be the cause of RWendi's compile error.
更新后注意perltidy在这里解密是非常有用的,但它窒息!! $ ^^^!$ ^^,它重新格式化为!! $ ^ ^ ^!$ ^ ^,这是无效的Perl;它应该是!! $ ^^ ^!$ ^^。这可能是RWendi编译错误的原因。