views:

1036

answers:

10
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.

+26  A: 

It confuses me.

Epaga
We need to vote more to get this over the accepted answer!
Tetha
+5  A: 

This is why Perl gets a bad rap for being a "write only" language. (Even though it is possible to write obfuscated functions in any language.)

Kevin
Actually most of the obfuscation comes from adding a mathematical operation, where a simple number would suffice.
Brad Gilbert
+9  A: 

I suspect the point is "just for fun". Not sure if it's in the spirit of stackoverflow though, is it? If I'm looking for answers to genuine programming problems, I don't want to have to wade through obfu puzzles..

castaway
A: 

compile error?? :)

RWendi
For the record, Perl doesn't compile, ever, so somehow I don't think so :(
Matthew Scharley
Wow really? That's intersting... Nvr touched perl in my life... I've touched similar language like python, then again it was like back on uni days... :)
RWendi
http://perldoc.perl.org/perlglossary.html#compilerhttp://perldoc.perl.org/perlglossary.html#interpreter
ysth
Um, monoxide, Perl *does* compile. To bytecode, before execution.
Daren Thomas
At least, Perl 5 way back in 1999 did, but that's still the stuff, right?
Daren Thomas
Yes Perl still does do compile to bytecode before execution.
Brad Gilbert
A: 

Why don't people answer less and downvote the "question" more? ;)

Rob Cooper
Better yet, go weigh in on http://stackoverflow.com/questions/34257/posting-programmingalgorithmic-puzzles-on-so (where Rob is currently in the minority).
ysth
Because you can answer with 0 reputation, but votedown needs 100 and bleeds you 1. It was pretty hard for me to get my first 15 because I only wanted to "second"the solutions where I saw a good one. Nope! That's not the way stackoverflow is built.
Axeman
+6  A: 

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:

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.

The original mostly uses a lot of tautologies involving punctuation variables to obfuscate. e.g.

  • !$| | $| is always 1
  • @- - @+ is always 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.

nohat
What happens when the first parameter is not an arrayref?
ysth
also, the > 0 there isn't correct.
ysth
+6  A: 

I found this command helpful, when working on my other answer.

perl -MO=Concise,foo,-terse,-compact obpuz.pl > obpuz.out

B::Concise

Brad Gilbert
+14  A: 

Here is how you figure out how to de-obfuscate this subroutine.

Sorry for the length

First lets 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 lets 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, lets 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
  ]
}

Lets 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 [];
  }
}
Brad Gilbert
The if( $len_1 ) part is wrong; the raw code is checking two different conditions.
ysth
Err, and so the else clause isn't correct. And the $arr_1->[] syntax is not equivalent to the @{}[].
ysth
Fixed the afore mentioned errors.
Brad Gilbert
Thanks. Testing with print @{foo($_,[qw/y s t h/])},"\n" for -4..4; gives identical output to the original now.
ysth
Actually I never tested any of it.
Brad Gilbert
+1  A: 

It brutally injures my cerebral cortex.

Ed Swangren
A: 

Is it really obfuscated? It looks like pretty standard Perl to me.

Tnilsson
Nah, most Perl uses at least some of those unsightly alphanumeric characters.
ysth
then try learning Perl. start with http://www.slideshare.net/osfameron/readable-perl-presentation/
Alexandr Ciornii