spiral(X, Y) :-
	intlength(X*Y, IL),
	P is IL+1,
	spiral_list(X, Y, L),
	write_matrix(L, P).

intlength(I, L) :-
	L is floor(log(I)/log(10))+1.

write_matrix(L, P) :-
	write_matrix(1, L, P).

write_matrix(R, L, P) :-
	(
		write_row(R, 1, L, P) ->
			NR is R + 1,
			write_matrix(NR, L, P)
	).

write_row(R, C, L, P) :-
	lookup(L, (C, R), V),
	intlength(V, VL),
	NSP is P - VL,
	write_spaces(NSP),
	write(V),
	NC is C + 1,
	(
		write_row(R, NC, L, P)
	;
		write('\n')
	).

lookup([(K,V)|_], K, V) :- !.
lookup([_|Ls], K, V) :-
	lookup(Ls, K, V).

write_spaces(0) :- !.
write_spaces(N) :-
	write(' '),
	NN is N - 1,
	write_spaces(NN).
	

spiral_list(X, Y, [((1,1),1)|L]) :-
	M is X*Y,
	spiral_list(1, 1, 1, right, 1, 1, X, Y, M, L).

spiral_list(M, _, _, _, _, _, _, _, M, []).
spiral_list(A, I, J, D, K, L, X, Y, M, [((NI,NJ),NA)|R]) :-
	A < M,
	go(D, I, J, II, JJ),
	(
		onboard(II, JJ, K, L, X, Y) ->
			D = ND,
			go(none, II, JJ, NI, NJ),
			chbounds(none, K, L, X, Y, NK, NL, NX, NY)
	;
			next(D, ND),
			go(ND, I, J, NI, NJ),
			chbounds(ND, K, L, X, Y, NK, NL, NX, NY)
	),
	NA is A + 1,
	spiral_list(NA, NI, NJ, ND, NK, NL, NX, NY, M, R).

next(right, down).
next(down, left).
next(left, up).
next(up, right).

go(none, X, Y, X, Y).
go(right, X, Y, NX, Y) :-
	NX is X + 1.
go(left, X, Y, NX, Y) :-
	NX is X - 1.
go(up, X, Y, X, NY) :-
	NY is Y - 1.
go(down, X, Y, X, NY) :-
	NY is Y + 1.

chbounds(none, MinX, MinY, MaxX, MaxY, MinX, MinY, MaxX, MaxY).
chbounds(right, MinX, MinY, MaxX, MaxY, NMinX, MinY, MaxX, MaxY) :-
	NMinX is MinX + 1.
chbounds(left, MinX, MinY, MaxX, MaxY, MinX, MinY, NMaxX, MaxY) :-
	NMaxX is MaxX - 1.
chbounds(up, MinX, MinY, MaxX, MaxY, MinX, MinY, MaxX, NMaxY) :-
	NMaxY is MaxY - 1.
chbounds(down, MinX, MinY, MaxX, MaxY, MinX, NMinY, MaxX, MaxY) :-
	NMinY is MinY + 1.

onboard(I, J, K, L, X, Y) :-
	I >= K,
	J >= L,
	I =< X,
	J =< Y.
