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++) {
...