Bash, 126 109 87 chars
87:
q()(printf %$[9+$1%9]s\\n $[$2*$2];[ 7 -lt $1 ]||(q $[$1+1] ${2}1;q $[$1+9] $2))
q 0 1
As it usually goes, changing from iterative to recursive solution helps us win additional bytes.
Meaning of parameters to q:
$1 How much to remove from 8 to get the number of spaces in the beginning. Note value modulo 9 counts here (actual value is also a hint to quit recursion).
$2 The current chain of 1s to be squared and output by printf.
The modus operandi is:
- output the sequence (ie. if $2 is 11111, output 123454321)
(if not yet at 12..9..21 - the recursive step)
2.1. output the next sequence (here: 111111 > $2 , output 12345654321
2.2. output the sequence once again (123454321).
In the step 2.2 , we pass (indent value + 9) instead of indent value however, so that the algoritm "knows" we are printing the row for the second time. Without this, the [ 7 -lt $1 ]
would be false, causing us to retrigger the recursive step 1. This would never finish then.
The recursion goes like this:
q 0 1: 1
q 1 11: 121
q 2 111: 12321
q 3 1111: 1234321
q 4 11111: 123454321
q 5 111111: 12345654321
q 6 1111111: 1234567654321
q 7 11111111: 123456787654321
q 8 111111111: 12345678987654321
q 16 11111111: 123456787654321
q 15 1111111: 1234567654321
q 14 111111: 12345654321
q 13 11111: 123454321
q 12 1111: 1234321
q 11 111: 12321
q 10 11: 121
q 9 1: 1
109:
p()(printf "%$[8+i]s\n" $[k*k])
k=;for i in `seq 9`;do k+=1;p;done;for i in `seq 8 -1 1`;do k=${k:1};p;done;
"k+=1" is much cheaper as k=$[10*k+1] , and for k being a string of ones it's the same. Same goes for ${k:1} and $[k/10] .
126:
p() (printf "%$[$1+i]s\n" $[k*k];)
k=1;for i in `seq 8`;do p 8;k=$[10*k+1];done;for i in `seq 8 -1 0`;do p 9;k=$[k/10];done;
I guess there may be even shorter solution, but weather is glorious, I can't stand sitting in front of computer any more :).