http://www.perlmonks.org?node_id=1001394

For the last week I've been trying to figure out an algorithm for JPEG's zig-zag spacefilling curve. Specifically, I wanted an algorithm that maps all elements in an NxN matrix to a N*N array given their x and y values. I finally figured it out with the help of my analysis 101 TA. He's not a computer scientist, but he knows what pairing functions are. Anyway, after a few hours messing with perl, I made this subroutine:

sub getPos{ ($x,$y,$s)=@_;($d=$x+$y)*($d++)/2 +($d%2?$y:$x)-($d>$s)*($d-$s)**2 }

To use it, you do something like this:

for(my $x = 0; $x < $size; $x++){ for(my $y = 0; $y < $size; $y++){ print getPos($x, $y, $size)." "; } print "\n"; }

For $size = 10 the loop will yield:

0 1 5 6 14 15 27 28 44 45 2 4 7 13 16 26 29 43 46 63 3 8 12 17 25 30 42 47 62 64 9 11 18 24 31 41 48 61 65 78 10 19 23 32 40 49 60 66 77 79 20 22 33 39 50 59 67 76 80 89 21 34 38 51 58 68 75 81 88 90 35 37 52 57 69 74 82 87 91 96 36 53 56 70 73 83 86 92 95 97 54 55 71 72 84 85 93 94 98 99

The body of getPos has 65 (non-whitespace) characters, any ideas on how to get it even smaller?


UPDATE: This prints a JPEG zig-zag when $ARGV[0] is the size of the matrix:
$==pop;print map{$y=$_;map(($d=$y+$_)*$d++/2-($d>$=)*($d-$=)**2+($d&1? +$_:$y).$",@m),$/}@m=0..$=-1
97 characters! I started at 125!