#!/usr/local/bin/perl -W

use List::Util qw(shuffle);
use strict;
use integer;

my $SIZE = $ARGV[0];
$SIZE = 6 unless defined $ARGV[0];
my $TOTAL=$SIZE*$SIZE;
my $SUM=($TOTAL-1)*$TOTAL/2/$SIZE;

my $s = $SIZE-1;
my @set = 0..$TOTAL-1;

my $exit = $SIZE+$SIZE+2;

my (@xy,$x,$y,$diag,$diag2,@sumx,@sumy,$ok,$i,$j);

while (1){
    @set = shuffle(@set);

    $ok=$i=0;
    for $x (0..$s){
	for $y (0..$s){
	    $xy[$x][$y] = $set[$i++];
	}
    }
    
    for (1..100000){
	$ok=0;
	$i=$j=$s;
	@sumx=();
	for $x (0..$s){
	    for $y (0..$s){
		$sumx[$x] += $xy[$x][$y]; 
	    }
	    if ($sumx[$x] == $SUM) {
		$ok++;
	    }elsif ($sumx[$x]<$SUM){
		$i = $x;
	    }else{
		$j = $x;
	    }
	}
	if ($ok<$SIZE){
	    $y = int rand $SIZE;
	    ($xy[$i][$y],$xy[$j][$y]) = ($xy[$j][$y],$xy[$i][$y]);
	}
	
	$i=$j=$s;
	@sumy=();
	for $y (0..$s){
	    for $x (0..$s){
		$sumy[$y] += $xy[$x][$y];
	    }
	    if ($sumy[$y] == $SUM){
		$ok++;
	    }elsif ($sumy[$y] < $SUM) {
		$j = $y;
	    }else{
		$i = $y;
	    }
	}
	if ($ok<$SIZE*2){
	    $x = int rand $SIZE;
	    ($xy[$x][$i],$xy[$x][$j]) = ($xy[$x][$j],$xy[$x][$i]);
	}
	    
	$diag=$diag2=0;
	for $x (0..$s){
	    $diag += $xy[$x][$x];
	    $diag2 += $xy[$x][$s-$x];
	}
	$ok++ if $diag == $SUM;
	$ok++ if $diag2 == $SUM;
	
	last if $ok==$exit;
	
	$i = int rand $SIZE;
	$j = int rand $SIZE;
	@xy[$i,$j] = @xy[$j,$i];
	
    }
    last if $ok==$exit;
}

for $x (0..$s){
    for $y (0..$s){
	printf("  %03d  ", $xy[$x][$y]);
    }
    printf("[%03d]\n", $sumx[$x]);
}
for $y (0..$s) {
    printf " [%03d] ", $sumy[$y];
}
printf "[%03d/%03d]\n\n", $diag,$diag2;
exit 0;

__END__

Este script genera cuadrados mágicos, esto es, en los que la sucesión de 
  números puede ser colocada para que filas, columnas y las dos diagonales
  sumen lo mismo. Es un problema combinatorio y aquí se utiliza una 
  heurística, de forma que aunque tarda más para los cuadrados pequeños 
  (2< n <=6) puede alcanzar números más altos (i.e. 10).

  036    075    048    072    038    025    057    065    012    067  [495]
  034    069    043    092    035    031    022    085    044    040  [495]
  058    047    009    087    061    000    046    017    079    091  [495]
  010    095    029    002    078    084    098    070    014    015  [495]
  054    037    068    093    050    083    005    006    096    003  [495]
  086    053    094    011    020    032    081    089    013    016  [495]
  023    019    027    004    071    077    076    056    080    062  [495]
  049    060    039    042    082    051    064    059    021    028  [495]
  055    033    041    026    052    088    045    018    063    074  [495]
  090    007    097    066    008    024    001    030    073    099  [495]
 [495]  [495]  [495]  [495]  [495]  [495]  [495]  [495]  [495]  [495] [495/495]
  
