notes.html

problem 8 · 13 lines

<article>
<h3>Problem Analysis</h3>
<p>This problem asks for the maximum product of any run of <code>length</code> consecutive digits inside a fixed 1000-digit number. The structure is a classic <a class="reference-source" href="https://en.wikipedia.org/wiki/Sliding_window_protocol" rel="noopener noreferrer" target="_blank">sliding window</a> problem: I slide a window of fixed width across the sequence, compute a quantity — here the product of the digits — for each position, and track the best value seen. There is no number theory or combinatorics hidden here; the difficulty is purely about doing the obvious thing correctly while watching for two pitfalls: integer overflow and the presence of zero digits.</p>
<p>The search space is tiny. For a string of length N and a window of width L there are exactly <code>N - L + 1</code> window positions, and each costs up to L multiplications, giving O(N · L) complexity — the product of input size and window width. With N = 1000 and L = 13 that is under 13,000 operations, effectively instantaneous, so a plain <a class="reference-source" href="https://en.wikipedia.org/wiki/Brute-force_search" rel="noopener noreferrer" target="_blank">brute-force search</a> over every window is entirely sufficient. The one structural fact worth exploiting is that any window containing the digit <code>'0'</code> has a product of zero, which can never beat a window of non-zero digits. The other thing I must reason about up front is the magnitude of the answer: thirteen nines multiply to 9^13 = 2,541,865,828,329, which exceeds the range of a 32-bit integer, so the accumulator must be at least 64 bits wide.</p>
<h3>Solution Approach</h3>
<h4><a class="reference-source" href="https://en.wikipedia.org/wiki/Sliding_window_protocol" rel="noopener noreferrer" target="_blank">Sliding-Window</a> Scan (Python and C)</h4>
<p>Both the Python and C solutions implement the same <a class="reference-source" href="https://en.wikipedia.org/wiki/Sliding_window_protocol" rel="noopener noreferrer" target="_blank">sliding window</a> scan: visit every window position, compute its product, and keep the maximum. The two versions differ only idiomatically.</p>
<p>I store the 1000-digit number as a compile-time string constant in both languages — a Python <code>str</code> literal and a C <code>static const char *</code>. In C, adjacent string literals are concatenated by the compiler at no runtime cost, so I can break the number across many lines for readability while still producing one contiguous string. There is no I/O, no parsing, and no allocation for the data itself.</p>
<p>For each starting index <code>i</code> from 0 to <code>N - length</code> inclusive, the algorithm does two things. First it checks whether the window contains a <code>'0'</code>, skipping it if so. Second, for surviving windows it multiplies the <code>length</code> digits together and updates the running best. In C I extract each digit with the idiom <code>number[j] - '0'</code>, which converts an <a class="reference-source" href="https://en.wikipedia.org/wiki/ASCII" rel="noopener noreferrer" target="_blank">ASCII</a> character to its numeric value because the C standard guarantees the digits <code>'0'</code> through <code>'9'</code> have consecutive codes. The product accumulator and the return type are both <a class="reference-source" href="https://en.wikipedia.org/wiki/C_data_types#Main_types" rel="noopener noreferrer" target="_blank">long long</a> to hold the worst-case 9^13 safely.</p>
<p>The Python version expresses the same logic in a single <a class="reference-source" href="https://docs.python.org/3/reference/expressions.html#generator-expressions" rel="noopener noreferrer" target="_blank">generator expression</a>: each window substring <code>number[i:i+length]</code> is produced lazily, a guard clause <code>if "0" not in sequence</code> filters out zero-containing windows, <a class="reference-source" href="https://docs.python.org/3/library/math.html#math.prod" rel="noopener noreferrer" target="_blank">math.prod</a> over <code>(int(d) for d in sequence)</code> computes each product, and the outer <code>max(...)</code> selects the largest. Python's <a class="reference-source" href="https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic" rel="noopener noreferrer" target="_blank">arbitrary-precision</a> integers mean overflow is never a concern, so no type reasoning is needed.</p>
<p>In both solutions the window length is a parameter rather than a hard-coded constant — read from <code>argv</code> in C and passed as a positional argument in Python. This lets the development case (<code>length = 4</code>, expected 5832) and the main case (<code>length = 13</code>, expected 23514624000) run against the same untouched source.</p>
</article>