Number spiral

by Tim Ko

JavaScript

const n = 5;
const r = -1;

// Parameters are:
// n: Print the values in a spiral from 1 to n^2
// rowNumber: Which row in the spiral to to print
// r: Number of spaces to rotate each layer of the spiral counter-clockwise
const computeRow = (n, rowNumber, r=0) => {

  const computeSum = (n) => {
    // The first number not in the top row is n^2 - n
    // The opposite number to it is n-2 steps down (not counting itself and the 0th row), n-1 steps to the right, and n-2 steps back up.
    // (i.e. for a n=5 problem, column 0 has value 20 and column 4 has value 17)
    // Putting this together, the sum is (n^2 - n) + [(n^2 - n) - (n - 2) - (n - 1) - (n - 2)]
    // Simplifying, we get:
    return 2 * n * n - 5 * n + 5;
  }

	const rotateValue = (value) => {
    // Each layer of the spiral has values between n^2 and (n-2)^2
    // Calculate the bounds to get the number of numbers in the layer
    // We will use this as the modulo to re-arrange each number
    const upperBound = n * n;
    const lowerBound = (n - 2) * (n - 2);
    const mod = upperBound - lowerBound;

    // To handle negative rotation, note that -(x mod n) == (n - (x mod n) mod n)
    const positiveR = ((r % mod) + mod) % mod;

    // Map the numbers in the layer to be between 0 and the mod
    // Then, shift the values by the rotation amount positiveR
    // Then, reverse the map back to the corresponding value in the layer
    return (value - (lowerBound + 1) + positiveR) % mod + lowerBound + 1;
  }

	// The top left value is always n^2 - n + 1 because the top row is a trivial sequence.
  // The left column is also in sequence, so we can just subtract by the 0-indexed row number.
  const firstColValue = n * n - n + 1 - rowNumber;
  
  // Recursive solution computing left and right values going inwards
	let row = new Array(n);
  if (n === 1) {
  	// Base case
  	row[0] = 1;
  } else if (rowNumber === 0) {
  	// Every "top row" is trivially [(n^2-n+1), ..., n^2]
  	for (let i = 0; i < n; i++) {
   ...