Couldn't figure out how to get the #! to work, but it's not really necessary. Uses the open 0 trick, so save it to a file before running

use strict ;my@f; use warnings ; open 0;$/= \11;my $i= 0; while ( <0>){chop; push@{$f [ $i]},$_;$i =($i+1)%3} close 0;$~ ="it"; my( $l,$m,$r)= map{$f[$_] }(0 .. 2); for(0..$#{ $l}){$m->[ $_]||= ''; $r-> [$_ ] ||=''; #$l }){ $m ->[ format it= @<<<<<<<<< @<<<<<<<<< @<<<<<<<<< $l-> [$_], $m-> [$_], $r-> [$_], . write;}

print pack("A25",pack("V*",map{1919242272+$_}(34481450,-49737472,6228,0,-285028276,6979,-1380265972)))

Replies are listed 'Best First'.
Re: Format quine (slightly obfu)
by pmonk4ever (Friar) on Dec 03, 2009 at 18:08 UTC
    bv,

    Ok, the output I get in Windoze Perl 5.10.0 is that the file prints. Is that correct?

    I'd think not, based on the format it= line. I have just begun to peruse these delightful nodes and can get some of them to run ok here at $work, but it's clear that I'll have to run some of these @ $home to get the full effect!

    Thanks for the fun code!

    pmonk4ever

    "No trees were harmed in the creation of this node. However, a rather large number of electrons were somewhat inconvenienced."

      Thank you! You're correct in that it prints out itself. It's not strictly a true quine, since it reads in its own file, but fun nonetheless. Read on for a breakdown of how it works:

      First, check it out with syntax highlighting: http://pastebin.com/m4ae94ecb. You can see that part of line 7 is a comment, just there to throw you off, and to fill up the columns. Line 6 doesn't have a comment, but pastebin's syntax highlighting doesn't understand what's going on. It's important to note that there's some significant trailing whitespace on lines 8 and 11, and that all whitespace is important because of the way it's read in. More on this later.

      use strict; my @f; use warnings;

      The first line invokes the strict and warnings pragmas, and declares an array, @f

      open 0; $/= \11;

      This next part makes use of the open 0 trick mentioned in japhy's Obfuscation Review to open the script on the filehandle 0. Then, the input record separator ($/) is set to a reference to the integer 11, meaning "read 11 bytes at a time." This is why each line is made of 10-character chunks separated by spaces (or newlines).

      my $i = 0; while (<0>) { chop;

      Next, we create a loop to read in the file (filehandle 0, remember), and chop off the last character of each 11 bytes, which ought to be a space or a newline. I'm not sure if this would work on Windows, since newlines are "\r\n", two bytes, but on Linux, the single byte newline gets chopped off.

      push @{ $f[$i] }, $_; $i = ( $i + 1 ) % 3 } close 0;

      The next statement treats the $ith element of @f as an array ref, dereferences it, and pushes the current 10-byte value of $_ onto it. Then $i is incremented modulo 3, because of the three columns of the original file. This ends the input loop.

      $~ = "it";

      $~ is the name of the current format for output, so we set it to "it", defined later.

      my ($l, $m, $r) = map { $f[$_] }(0 .. 2);

      This map assigns the three columns of the @f array of arrays to variables for the left, middle, and right columns of output.

      for ( 0 .. $#{ $l } ) {

      Here, we loop over the values from 0 to the length of the array referred to by $l.

      $m->[$_] ||= ''; $r->[$_] ||= '';

      These statements make sure that the values in the $_th row of the middle and right columns are not undef, to avoid pesky warnings. The rest of line 7 is a comment

      format it= @<<<<<<<<< @<<<<<<<<< @<<<<<<<<< $l->[$_], $m->[$_], $r->[$_], .

      Here we define the format "it" to contain left-justified values of the left, middle, and right columns for this line of the output. I would have put more comments on lines 8 and 11, but Perl doesn't allow anything after a format declaration, and won't end it unless the "." is the only thing on the last line. Of course, whitespace is insignificant to the interpreter, but it does matter for this program.

      write; }

      Finally, we use write to print the values out according to the format.

      Hope that helps!


      @_=qw; Just another Perl hacker,; ;$_=q=print "@_"= and eval;