Problem Analysis
The spiral writes the integers 1, 2, 3, ... outward from the centre in a clockwise direction, and we are asked only for the sum of the numbers lying on the two diagonals of the final square. The naive route is to construct the entire grid and add up the diagonal cells - but building an N by N grid is an O(N^2) operation (quadratic in the side length, since the grid has N^2 cells). A little arithmetic on the structure of the spiral collapses the problem to a single formula evaluated in O(1) - constant time, independent of N.
The key observation is that the diagonal entries form a regular pattern, ring by ring. The centre holds 1. Each subsequent "ring" is a square frame whose side length s grows by 2 each step: s = 3, 5, 7, ... up to N. A ring of side s ends exactly at the perfect square s^2, because the spiral fills outward and that ring's last and largest value sits at its bottom-right corner. The four corners of a ring are its only contributions to the diagonals, and travelling counter-clockwise from the bottom-right corner each step decreases the value by s - 1 (the number of cells along one side minus the shared corner). So the four corners are s^2, s^2 - (s-1), s^2 - 2(s-1), and s^2 - 3(s-1), summing to 4s^2 - 6(s-1). Summing this over every odd s from 3 to N and adding the central 1 reduces, via standard summation identities, to the single closed-form expression (N * (N * (4*N + 3) + 8) - 9) / 6. The numerator is always divisible by 6 for odd N, so integer arithmetic is exact throughout - no floating point, no rounding concerns.
Solution Approach
Closed-Form Formula with Optional Spiral Simulation
Both p0028_s0.py and p0028_s0.c implement one design with two paths. The production path is a single closed-form evaluation; the diagnostic path is an O(N^2) spiral simulation that runs only when --show is passed and the grid is small (size <= 10). The simulation exists purely as an independent correctness check and a way to visualise the spiral - it never runs in normal use.
The fast path evaluates the polynomial using nested multiplication: compute 4*N + 3, then N * (...) + 8, then N * (...) - 9, then divide by 6. This is Horner's method - it evaluates a degree-3 polynomial with exactly three multiplications and never forms large intermediate powers like N**3. Before returning, both solutions also validate that the formula equals the value the simulation produced, printing a coloured pass/fail marker.
The simulation reproduces the spiral without tracking a heading or turn rules. Starting at the origin with value 1, for each successive number it inspects the four neighbours (right, down, left, up), discards any already occupied, and moves to the unoccupied neighbour with the smallest squared distance from the origin (x*x + y*y). This "nearest free neighbour" rule reproduces the clockwise outward walk because the spiral's geometry guarantees the next correct cell is always the nearest empty one. After filling the grid, the diagonal sum is the total over every cell where col == row (main diagonal) or col == -row (anti-diagonal).
The two languages differ only in storage. Python uses a dict keyed by (col, row) tuples, so occupancy is a simple in test and the origin-centred coordinate system needs no offset. C uses a flat 1-D array of dim * dim ints allocated with calloc (so every cell starts at 0, meaning "empty"), mapping signed coordinate (col, row) to index (row + half) * dim + (col + half). The C layout is compact and cache-friendly; the Python dict is more convenient but heavier per cell - an acceptable trade, since the simulation only ever runs on tiny grids.