<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged math</title>
<link>https://coderlegion.com/tag/math</link>
<description>Powered by Question2Answer</description>
<item>
<title>The Alphabet as a Sequence Engine: A Census of What Letter Names Generate &amp; What the OEIS Missed.</title>
<link>https://coderlegion.com/32744/the-alphabet-as-sequence-engine-census-of-what-letter-names-generate-what-the-oeis-missed</link>
<description>&lt;p&gt;&lt;strong&gt;Abstract&lt;/strong&gt;&lt;br&gt;
We evaluate the integer sequences generated across 36 human writing systems under the Engineering of Alphabets (EOA) operator. Auditing all 1,056 resulting sequences against the On-Line Encyclopedia of Integer Sequences (OEIS), three facts survive every check we could devise. First, the growth rates of these sequences cluster on a small set of exact algebraic numbers 2.618…, 3.414…, 2.414…, 2, and 3, with 2.618… (φ²) the single largest cluster. Second, several of the generated sequences are, term for term, classics of mathematics: the powers of two, the Fibonacci bisections, the Lucas bisection, the Pell family, the Mersenne numbers, and the bare counting numbers, each verified against the full published OEIS record (up to 90 terms) from our 500-term exact sequences. Third, 388 distinct generated sequences appear in no catalogue, although every one satisfies an explicit integer linear recurrence. To test whether these observations arise by chance, we evaluate two random-baseline controls: random alphabets of matched size never form the tiny cores that natural scripts form (0 of 250 simulations), and the English E5 spectrum splits into two equal halves, a pattern random alphabets never produce (0 of 100 simulations). We release the full census, the matrices, and the verification code, and we pose two challenges to the sequence community.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. THE RULE, IN ONE PARAGRAPH&lt;/strong&gt;&lt;br&gt;
Every letter has a name. Apply a fixed recursive expansion rule to each letter name, and repeat round after round. This produces an endless string of letters. Count how long the string becomes at each round: that growing list of numbers is the letter’s sequence. The counts obey a fixed recipe fixed by the script’s letter names alone; no tuning, no search. The mathematical engine behind every sequence is the script’s incidence matrix, and the growth rate of the counts is the Perron eigenvalue of that matrix. The matrices for all 36 scripts are open data; everything below was recomputed from them in exact integer arithmetic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. WHAT WE MEASURED&lt;/strong&gt;&lt;br&gt;
This census covers 36 different writing systems, totaling 1,056 individual letters. We chose these scripts based on their documented historical names and to include a wide mix of different writing styles from unconnected parts of the world. We did not cherry-pick this list to force a result. We deliberately kept all the 'failures' in our dataset: 8 scripts that matched nothing in the OEIS at all (seven formed massive, tangled graphs, while Georgian collapsed), along with several scripts that produced completely trivial, flat sequences. If we had filtered the data to keep only the 12 scripts that generated the non-trivial mathematical families, two-thirds of the dataset would have been thrown out. Because we kept them in, you can trust that the patterns we found emerged naturally from the raw data.&lt;br&gt;
The 1,056 letter-sequences collapse into 402 distinct sequences, because letters that share a naming pattern share their sequence (Appendix, Tables A1–A2). For each distinct sequence we computed its exact recurrence order and its growth rate. Two summaries:&lt;br&gt;
• Recurrence orders run from 1 to more than 14. The most common orders are 13 (47 sequences), 5 (41), 4 (29), and 11 (23); 176 sequences need order above 14.&lt;br&gt;
• Growth rates cluster tightly: 78 sequences grow at φ² = 2.618…, 44 at 2+√2 = 3.414…, 27 at 1+√2 = 2.414…, 20 near 3.1416 (English), 19 near 4.21 (Ogham), 19 at exactly 2 (the Mersenne regime), 8 at exactly 3 (Korean), and 30 distinct sequences are flat (rate 1), matched by 176 letters total.&lt;br&gt;
This census is not a sample; it is the whole population of distinct sequences the 36 scripts can produce. Growth at φ² is the most common outcome in the entire dataset.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. WHAT MATCHED THE OEIS, AND SURVIVED VERIFICATION&lt;/strong&gt;&lt;br&gt;
While all our sequences were generated to 500 terms, published OEIS records cut off much earlier; we kept only identities that hold term-by-term across the entire available OEIS entry (up to 90 terms) under an exact recurrence check. These are exact structural identities, not coincidental prefix agreements or numerical approximations. Six families pass:&lt;br&gt;
• The powers of two, A000079: generated by four Hebrew letters (bet, tet, mem, nun), and by the same naming pattern in Phoenician, Aramaic, Syriac, Arabic, Japanese-pronounced Latin, Sanskrit and Amharic. (1, 2, 4, 8, 16 … to 2⁸⁹, exact.)&lt;br&gt;
• The Fibonacci bisection, A001906: generated in Ge’ez and Thai (1, 3, 8, 21, 55 …). Its recurrence t(n+2) = 3•t(n+1) − t(n) is the polynomial x²−3x+1 ,  the same equation behind the φ² growth above. The odd Fibonacci numbers, A001519, appear the same way in both scripts.&lt;br&gt;
• The odd-index Lucas numbers, A002878: two Thai letters (1, 4, 11, 29, 76 …), same polynomial, different seeds.&lt;br&gt;
• The Pell family, A094723 and A048739: generated in Arabic. Their growth rate is the silver ratio 1+√2 ,  which is exactly why the Arabic core grows at 1+√2.&lt;br&gt;
• The Mersenne numbers 2ⁿ−1, A000225: generated in Japanese-pronounced Latin, Aramaic and Sanskrit.&lt;br&gt;
• The bare counting numbers: one Syriac letter group generates 1, 2, 3, 4, 5 … with no offset and no error, through all 90 published OEIS terms and continuing through all 500 generated terms.&lt;br&gt;
Table A1 lists all fourteen catalogued sequences, including the further matches beyond these six (the shifted counting variant, the odd numbers, the cake numbers A000125, A000295, and the Burmese silver-square recurrence A007070).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. WHAT MATCHED NOTHING, THE UNCATALOGUED HALF&lt;/strong&gt;&lt;br&gt;
388 distinct sequences have no OEIS entry (Table A2 lists the per-script breakdown; every sequence is released with its recurrence in census.csv and uncatalogued_sequences.csv). Each one satisfies an explicit integer linear recurrence of small order, derived from its matrix, and each is released with that recurrence, its matrix, its script and its letters. They concentrate in the large-core scripts: every letter of English E5, Greek, Gothic, Runic, Ogham and Glagolitic is uncatalogued. We make no claim that they are important; we claim only that they are generated, that their recurrences are known, and that no catalogue records them. Whether that gap is worth filling is precisely Challenge I below.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. TWO CONTROLS THAT MAKE THE ABOVE MEAN SOMETHING&lt;/strong&gt;&lt;br&gt;
(a) The small-core anomaly. The six verified families come from tiny closed loops of letters: Hebrew and Arabic have dominant cores of 3 letters, Thai of 2, Japanese of 4. Is that usual? We built 250 random 26-letter alphabets with the same name lengths (2–5 letters per name) and computed their cores. Every random alphabet entangled into one giant loop: core sizes ran from 21 to 26, and not one fell below 21 (0 of 250). Natural scripts, in other words, do something random name systems never do: they isolate their growth into loops of two to four letters. This is the quantitative backbone of our name-structure conjecture, and it is reproducible with one script run.&lt;br&gt;
(b) The English split. The English E5 matrix factors as thirteen linear factors and one irreducible polynomial of degree exactly 13, a spectrum split into equal halves. We generated 100 random 26-letter alphabets of matched shape: none produced such a split (0 of 100). Generic random matrices have one large irreducible factor of degree 20 to 26 and almost no linear factors. The English split is a genuine structural anomaly, not a presentation choice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. THE CHALLENGES&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;I.&lt;/strong&gt; To the uncatalogued 388. Each is released with its recurrence, matrix and attestation. We ask the community for an adjacency audit: is a sequence’s recurrence family already represented in the OEIS? Our own flagship example was, the Hebrew pair dalet and lamed: they generate 1, 4, 12, 34, 94, 256, 690 …, which is 2•F(2n) − 2^(n−1): an order-3 cousin of two catalogued families, whose sibling F(2n+2) − 2ⁿ is A105693. We had called it missing; the record corrected us, and we print the correction. Where a family is genuinely unrepresented and of independent interest, we support inclusion. Where it is catalogued, we ask only that the census record the correspondence. A reasoned rejection will be published with the same care as a match.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;II&lt;/strong&gt;. To the matched six families. Is the hit rate itself remarkable, or do small integer matrices match the OEIS at high rates regardless? We designed a random-matrix control, density-matched, row-shuffled, and degree-preserving, at match windows from 10 to 40 terms, and released the protocol and code. We have not run it to completion. The interpretation rules are fixed in advance: if real scripts match above all controls, naming structure selects catalogued sequences; if they match at control levels, the census rests on the verified identities and the controls alone; if real beats the density control but not the degree-preserving one, the driver is name length and degree structure. Whichever outcome occurs, we pre-commit to publishing it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7. WHAT WE CLAIM, AND WHAT WE DO NOT&lt;/strong&gt;&lt;br&gt;
We present an objective measurement: the first complete census of the integer sequences generated by 36 human writing systems, with two verified structural anomalies (small cores, and the English split) and six exact term-for-term matches to named sequences. We do not claim that ancient scribes intentionally encoded mathematics into letter names, nor that these mathematical matches are surprising in number, or that the uncatalogued 388 are profound. The honest open question is the one the census poses and cannot answer: why does the same handful of polynomials,  x²−3x+1 above all, organize naming systems that never met?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VERIFICATION AND MATERIALS&lt;/strong&gt;&lt;br&gt;
Every sequence was computed to 500 terms in exact BigInt arithmetic from the open matrices, and identities in Section 3 were verified against the full published OEIS entries up to 90 terms. The pre-computed census tables (census.csv, uncatalogued_sequences.csv, census_summary.json) and verification scripts ship directly with the release: audit.py (generates the 402-sequence census), verify_wows.py (reproduces the term-exact OEIS identity checks), baseline_oeis_lookup.py (hit-rate control protocol), and e5_split_test_sage.sage (E5 spectral split null).&lt;br&gt;
Matrices: &lt;a rel=&quot;nofollow&quot; href=&quot;https://doi.org/10.5281/zenodo.23440579&quot;&gt;https://doi.org/10.5281/zenodo.23440579&lt;/a&gt;. &lt;br&gt;
Main technical paper: &lt;a rel=&quot;nofollow&quot; href=&quot;https://doi.org/10.5281/zenodo.23449728&quot;&gt;https://doi.org/10.5281/zenodo.23449728&lt;/a&gt;. &lt;br&gt;
Appendices: &lt;a rel=&quot;nofollow&quot; href=&quot;https://doi.org/10.5281/zenodo.23695751&quot;&gt;https://doi.org/10.5281/zenodo.23695751&lt;/a&gt;.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/32744/the-alphabet-as-sequence-engine-census-of-what-letter-names-generate-what-the-oeis-missed</guid>
<pubDate>Tue, 27 Oct 2026 21:09:02 +0000</pubDate>
</item>
<item>
<title>Where do squared error and cross-entropy actually come from?</title>
<link>https://coderlegion.com/30983/where-do-squared-error-and-cross-entropy-actually-come-from</link>
<description>&lt;p&gt;&lt;strong&gt;Short answer: maximum likelihood. Choose a distribution for the output, then:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Read its parameter as the network's output → output function&lt;/li&gt;
&lt;li&gt;Take −log of it → error function&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Gaussian (regression)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Output: ŷ = Wᵀh + b (the mean)&lt;/li&gt;
&lt;li&gt;Error: −log N(y; ŷ, σ²) → squared error (constants drop out)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bernoulli (binary classification)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Output: exponentiate + normalize → ŷ = σ(z)&lt;/li&gt;
&lt;li&gt;Error: −log P(y) → cross-entropy = softplus((1 − 2y)z)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why the pairing matters: with cross-entropy, the log cancels the sigmoid's exponential, so ∂J/∂z = σ(z) − y. With squared error, σ′(z) stays in the gradient and goes to ~0 when the model is confidently wrong, so learning stalls.&lt;/p&gt;
&lt;p&gt;Full derivations: &lt;a rel=&quot;nofollow&quot; href=&quot;https://husseinmahdi.xyz/writing/series/math-behind-neural-networks/&quot;&gt;https://husseinmahdi.xyz/writing/series/math-behind-neural-networks/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next up: softmax + cross-entropy for k classes.&lt;/p&gt;
</description>
<category>Discussions</category>
<guid isPermaLink="true">https://coderlegion.com/30983/where-do-squared-error-and-cross-entropy-actually-come-from</guid>
<pubDate>Wed, 14 Oct 2026 05:20:00 +0000</pubDate>
</item>
<item>
<title>What Math Actually Buys You: Optimizing a Rock-Paper-Scissors Game in C</title>
<link>https://coderlegion.com/27721/what-math-actually-buys-you-optimizing-a-rock-paper-scissors-game-in-c</link>
<description>&lt;p&gt;I was looking through my old projects and found a couple of Rock-Paper-Scissors games I wrote in C a few years back. Why more than one? Because programming is fun, but also because I was experimenting. We're going to look at both versions and talk about how math actually shows up in code. This will not be some generic &quot;you should know math&quot; lecture, but a before/after comparison grounded in my humble experience. &lt;/p&gt;
&lt;h3 id=&quot;why-this-matters-if-you-re-self-taught&quot;&gt;Why this matters if you're self-taught&lt;/h3&gt;
&lt;p&gt;If you're a fresh CS student or a self-taught developer, there's a decent chance you don't fully buy that math concepts matter day to day. Fair. Here's how I think about it: programming gives you a lot of room to be creative in how you solve problems, but your creativity is powered by what you actually know. Knowledge is the raw material here and math is one of the biggest sources of that raw material.&lt;/p&gt;
&lt;p&gt;Here's an example: if you wanted to write a loop in Rust with unusual control flow, and you didn't know that Rust's &lt;code&gt;while&lt;/code&gt; is really just shorthand for the common pattern using &lt;code&gt;loop&lt;/code&gt; + &lt;code&gt;if&lt;/code&gt; + &lt;code&gt;else&lt;/code&gt; + &lt;code&gt;break&lt;/code&gt;, you'd spend a long time fighting &lt;code&gt;while&lt;/code&gt; to do something it wasn't built for. If you knew that, you'd just build the custom loop you actually need.&lt;/p&gt;
&lt;p&gt;Or the other direction: a senior dev once took a buggy 12-line React component I wrote and refactored it into 3 correct lines, because he knew which hooks and methods to reach for. Your imagination still needs building blocks to arrange. Math, at a certain stage, is where a lot of those blocks come from. It gives you a precise, calculable, universal way to reason about and express a problem instead of just poking at it until it works.&lt;/p&gt;
&lt;p&gt;Let's look at actual code. The full source code for both implementations is public on GitHub &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/davidessien925/rock-paper-scissors&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;iteration-1-the-naive-version&quot;&gt;Iteration 1: the naive version&lt;/h3&gt;
&lt;p&gt;Here's the &lt;code&gt;main&lt;/code&gt; function of the first version I wrote:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;int main(void) {
  srand(time(NULL));
  int random_int = (rand() % ((length_options + 1) - 1)) + 1;

  int option;

  printf(&quot;Let's play Rock Paper Scissors!\n&quot;);
  printf(&quot;First to 3 points wins!\n&quot;);

  while ((option != 1 &amp;amp;&amp;amp; option != 2 &amp;amp;&amp;amp; option != 3) ||
         (player_score != 3 &amp;amp;&amp;amp; my_score != 3)) {

    round_number += 1;

    printf(&quot;\n===============\n&quot;);
    printf(&quot;Round %d\n&quot;, round_number);

    printScores();
    printOptions();

    scanf(&quot;%d&quot;, &amp;amp;option);

    if (option == 0 || option &amp;gt; length_options) {
      printf(&quot;\nPlease select a number ranging from 1 to 3 according to your &quot;
             &quot;desired option.\n\n&quot;);
    } else {
      printf(&quot;\nYou picked %s\n&quot;, options[option - 1].name);
      printf(&quot;I picked %s\n&quot;, options[random_int - 1].name);
      declare_round_winner((option - 1), (random_int - 1));
    }
    printf(&quot;\n===============\n&quot;);
  }

  printScores();
  declare_overall_winner();
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Quick heads up before I explain anything: there's a bug in this loop condition. &lt;code&gt;option&lt;/code&gt; is declared but never given a value before the &lt;code&gt;while&lt;/code&gt; check reads it:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;while ((option != 1 &amp;amp;&amp;amp; option != 2 &amp;amp;&amp;amp; option != 3) || ...)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reading an uninitialized variable in C is undefined behavior. It happens to &quot;work&quot; here because whatever garbage value is sitting in that memory slot almost never equals 1, 2, or 3, so the loop starts anyway. But that's luck, not correctness. If you're newer to C, this is a good example of a bug that won't show up as a crash, it'll just quietly rely on the right garbage value. Moving on.&lt;/p&gt;
&lt;p&gt;The supporting pieces are what you'd expect: an &lt;code&gt;Option&lt;/code&gt; struct holding a name and value, an array of three options (Rock, Paper, Scissors), score counters, a &lt;code&gt;printScores&lt;/code&gt; function, a &lt;code&gt;printOptions&lt;/code&gt; function that loops over the array so adding a fourth option later doesn't require touching the print logic, and input validation that re-prompts on an out-of-range choice.&lt;/p&gt;
&lt;p&gt;The main focal point for this post is how the winner gets decided:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;int check_rules(int player_option, int my_option) {
  switch (player_option) {
  case 0:
    if (my_option == 0) return 0;
    else if (my_option == 1) return 1;
    else return -1;
  case 1:
    if (my_option == 0) return -1;
    else if (my_option == 1) return 0;
    else return 1;
  case 2:
    if (my_option == 0) return 1;
    else if (my_option == 1) return -1;
    else return 0;
  default:
    return 0;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This checks every possible value of &lt;code&gt;player_option&lt;/code&gt; against every possible value of &lt;code&gt;my_option&lt;/code&gt; and returns -1 (loss), 0 (draw), or 1 (win). It's ugly, but it's also the most direct solution I could think of at the time. It also doesn't scale. Let's say you wanted to play the more advanced and respected version of the game: Rock-Paper-Scissors-Lizard-Spock, you'd have to add Lizard and Spock. You'd also have to rewrite every branch. Sheldon wouldn't approve.&lt;/p&gt;
&lt;h3 id=&quot;iteration-2-what-changed-and-why&quot;&gt;Iteration 2: what changed, and why&lt;/h3&gt;
&lt;p&gt;Instead of guessing which part needed optimizing, I looked at the code and realized the winner-check was the ugliest and least scalable part of it so I wrote out every possible outcome as a table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Rock          &lt;/th&gt;&lt;th&gt;Paper        &lt;/th&gt;&lt;th&gt;Scissors&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Rock     &lt;/td&gt;&lt;td&gt;Draw          &lt;/td&gt;&lt;td&gt;Rock Loss    &lt;/td&gt;&lt;td&gt;Rock Win&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Paper    &lt;/td&gt;&lt;td&gt;Paper Win     &lt;/td&gt;&lt;td&gt;Draw         &lt;/td&gt;&lt;td&gt;Paper Loss&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Scissors &lt;/td&gt;&lt;td&gt;Scissors Loss &lt;/td&gt;&lt;td&gt;Scissors Win &lt;/td&gt;&lt;td&gt;Draw&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Then I substituted numbers for the outcomes (Win = 1, Draw = 0, Loss = -1):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Rock &lt;/th&gt;&lt;th&gt;Paper &lt;/th&gt;&lt;th&gt;Scissors&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Rock     &lt;/td&gt;&lt;td&gt;0    &lt;/td&gt;&lt;td&gt;-1    &lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Paper    &lt;/td&gt;&lt;td&gt;1    &lt;/td&gt;&lt;td&gt;0     &lt;/td&gt;&lt;td&gt;-1&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Scissors &lt;/td&gt;&lt;td&gt;-1   &lt;/td&gt;&lt;td&gt;1     &lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;That's a lookup table. I originally called this &quot;a matrix,&quot; but I want to be more precise here than I was when I first wrote this, because the interesting math isn't that it has a nice grid-looking shape. It's that the values in this grid aren't arbitrary. Notice the pattern. It's skew-symmetric (flip any cell across the diagonal and the sign flips), and it repeats in a cycle. This is called modular arithmetic. If you assign Rock = 0, Paper = 1, Scissors = 2, the outcome of any matchup is:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;outcome = (player - opponent + 3) % 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where a result of 1 means the player wins, 2 means the player loses, and 0 is a draw (you'd remap those three values to +1/0/-1 to match the table above). That's the math concept doing the work here: a cyclic relationship expressed with the modulo operator, the same operation that underlies clock arithmetic, hashing, and a good chunk of the number theory that shows up in cryptography (RSA leans on modular exponentiation directly). A 3x3 lookup table is one way to encode that relationship.&lt;/p&gt;
&lt;p&gt;In code, the lookup table version looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;int rules_matrix[3][3] = {{0, -1, 1}, {1, 0, -1}, {-1, 1, 0}};

int check_rules_matrix(int x, int y) {
  return rules_matrix[x][y];
}

void update_scores(int outcome) {
  switch (outcome) {
  case 1:
    computer_score += 1;
    printf(&quot;\nI won this round!\n&quot;);
    break;
  case -1:
    player_score += 1;
    printf(&quot;\nYou won this round!\n&quot;);
    break;
  default:
    printf(&quot;\nDraw\n&quot;);
    break;
  }
}

void declare_round_winner(int c_option, int p_option) {
  update_scores(check_rules_matrix(c_option, p_option));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Determining a winner is now a single array access instead of nine branches. Add Lizard and Spock, and you're extending a 3x3 table to a 5x5 table and updating the &lt;code&gt;options&lt;/code&gt; array. No switch statements to rewrite.&lt;/p&gt;
&lt;h3 id=&quot;does-it-actually-matter-&quot;&gt;Does it actually matter?&lt;/h3&gt;
&lt;p&gt;I wanted to check the performance claim instead of just asserting it, so I benchmarked both approaches directly, 100 million calls each, isolated from I/O:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;#define ITERATIONS 100000000

int check_rules_switch(int player_option, int my_option) {
  switch (player_option) {
  case 0:
    if (my_option == 0) return 0;
    else if (my_option == 1) return 1;
    else return -1;
  case 1:
    if (my_option == 0) return -1;
    else if (my_option == 1) return 0;
    else return 1;
  case 2:
    if (my_option == 0) return 1;
    else if (my_option == 1) return -1;
    else return 0;
  default:
    return 0;
  }
}

static const int rules_matrix[3][3] = {
    { 0, -1,  1},
    { 1,  0, -1},
    {-1,  1,  0}
};

int check_rules_matrix(int x, int y) {
  return rules_matrix[x][y];
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Results, run three times:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;1. Switch/Branching Method: 0.343620 seconds (3.44 ns per call)
2. Matrix Lookup Method:    0.275987 seconds (2.76 ns per call)

3. Switch/Branching Method: 0.342246 seconds (3.42 ns per call)
4. Matrix Lookup Method:    0.272867 seconds (2.73 ns per call)

5. Switch/Branching Method: 0.340185 seconds (3.40 ns per call)
6. Matrix Lookup Method:    0.272581 seconds (2.73 ns per call)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The lookup table wins consistently, by about 0.7 nanoseconds per call, roughly a 20% improvement in this specific isolated benchmark. But let's be clear on what that means. 0.7 nanoseconds is nothing in absolute terms. In a real Rock-Paper-Scissors game bottlenecked by &lt;code&gt;scanf&lt;/code&gt; waiting on a human, this difference is completely invisible.&lt;/p&gt;
&lt;p&gt;So yeah this isn't exactly going to save your production system (unless that's a specific problem your system has). The main point is that recognizing the modular structure of the problem gave me a solution that was simultaneously simpler to read, easier to extend, and measurably faster, all from the same insight. And that's how math helps. Besides making code faster, it also changes what kind of solution occurs to you in the first place.&lt;/p&gt;
&lt;p&gt;This is the fact I keep noticing as I move further into security work. A lot of what looks like &quot;cleverness&quot; in an optimized or exploited system is really just someone noticing the underlying structure before anyone else bothered to look for it.&lt;/p&gt;
&lt;h3 id=&quot;addendum-what-if-you-skip-the-table-entirely-&quot;&gt;Addendum: what if you skip the table entirely?&lt;/h3&gt;
&lt;p&gt;If the outcome is really just modular arithmetic, why store a table at all? You can compute the result directly:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;int check_rules_mod(int x, int y) {
  return ((x - y + 4) % 3) - 1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Same return convention as &lt;code&gt;check_rules_matrix&lt;/code&gt; (1 if &lt;code&gt;x&lt;/code&gt; wins, -1 if &lt;code&gt;y&lt;/code&gt; wins, 0 for a draw). I checked this against all 9 possible matchups by brute force and it matches exactly, so correctness isn't in question.&lt;/p&gt;
&lt;p&gt;Performance is where this got more interesting than I expected, and where I want to be upfront about the limits of what I actually understand.&lt;/p&gt;
&lt;p&gt;While putting this post together, I recompiled the exact same switch-vs-matrix benchmark file from above with the &lt;code&gt;-O2&lt;/code&gt; optimization flag, mostly out of curiosity, and the ranking completely inverted:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;1. Switch/Branching Method: 0.119248 seconds (1.19 ns per call)
2. Matrix Lookup Method:    0.133597 seconds (1.34 ns per call)
 
1. Switch/Branching Method: 0.120751 seconds (1.21 ns per call)
2. Matrix Lookup Method:    0.128811 seconds (1.29 ns per call)
 
1. Switch/Branching Method: 0.122600 seconds (1.23 ns per call)
2. Matrix Lookup Method:    0.132499 seconds (1.32 ns per call)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The only thing I changed was adding the build flag, and switch went from consistently losing to consistently winning. I don't yet know enough about what the compiler is actually doing under &lt;code&gt;-O2&lt;/code&gt; to explain that properly, branching, inlining, and instruction-level optimization are a whole subject I haven't put real time into, and I'd rather say that plainly than dress up a guess as an explanation.&lt;/p&gt;
&lt;p&gt;I also wanted numbers for the modular version above, not just correctness. Getting a fair three-way comparison meant controlling for whether the compiler inlines each function, which isn't something I know how to force myself yet, so I had AI help write a benchmark harness that pins that down explicitly. I compiled and ran it on my own machine, these are the numbers I got:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;All three functions forced to inline (best case):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;1. Switch/Branching Method: 1.293 ns per call
2. Matrix Lookup Method:    1.339 ns per call
3. Modular Arithmetic:      1.261 ns per call
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;All three functions forced to be real function calls:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;1. Switch/Branching Method: 2.261 ns per call
2. Matrix Lookup Method:    1.697 ns per call
3. Modular Arithmetic:      1.793 ns per call
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Same story as the &lt;code&gt;-O2&lt;/code&gt; flip: which one wins depends on a compiler decision, not on the code itself. Inlined, switch is fastest and mod edges out matrix. Forced into real function calls, matrix takes over and switch falls behind badly. Mod never loses badly either way, but I'm not going to dress that up as &quot;modular arithmetic is the safe choice performance-wise&quot; when I can't yet explain why the ranking moves the way it does.&lt;/p&gt;
&lt;p&gt;Consider this a flag rather than a finding: something real is going on here, across two separate build decisions, it's outside what I currently know, and it's on the list for a proper, dedicated post once I've actually built the compiler knowledge to back it up instead of just reporting numbers I can't fully explain.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;small&gt;Cover photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@hyson?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot;&gt;Antony Hyson Seltran&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/photos/a-pen-sitting-on-top-of-a-piece-of-paper-7RgWuLlea24?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/27721/what-math-actually-buys-you-optimizing-a-rock-paper-scissors-game-in-c</guid>
<pubDate>Sat, 19 Sep 2026 12:32:40 +0000</pubDate>
</item>
<item>
<title>The Math Behind Neural Networks, Explained Like Nobody Did for Me — Part 1.4</title>
<link>https://coderlegion.com/26429/the-math-behind-neural-networks-explained-like-nobody-did-for-me-part-1-4</link>
<description>&lt;p&gt;&lt;em&gt;Part 1.4 — Which Loss to Choose, and Why. A calm, sequential guide for anyone entering the field. The article is divided into smaller chapters to make it easier to understand.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Part 1.3 ended on a quiet victory. The mean squared error, which we had simply assumed back in Part 1.1 and optimized in Part 1.2, was no longer an assumption. We had derived it — from a single principle, maximum likelihood, and a single modelling choice, that the model’s output is a Gaussian centred on its prediction. The loss we had trusted for two parts was finally standing on a foundation we could see through. The recipe was built: choose the output distribution, and the cost follows.&lt;/p&gt;
&lt;p&gt;But a recipe that produces one dish invites an obvious question about all the others. We chose the Gaussian, and squared error came out. That was a choice — the introduction to Chapter 9 said as much and then set the point aside. This part picks it back up. If a different output distribution is chosen, a different cost comes out, and it predicts a different summary of the data. Squared error was never the only item on the menu; it was the first one we happened to order.&lt;/p&gt;
&lt;p&gt;There is also a problem hiding inside the loss we derived, one that Part 1.3 had no reason to expose. In the very common case of a yes-or-no prediction, squared error can go quiet at exactly the wrong moment — its gradient falling nearly to zero while the model is still confidently wrong, leaving gradient descent with nothing to follow. The fix is not to patch squared error but to derive a different cost, cross-entropy, from a different distribution, and watch the problem dissolve on its own. This is where the slope idea from Part 1 returns for the last time, and where the choice of loss and the choice of output finally reveal themselves as one decision, not two.&lt;/p&gt;
&lt;p&gt;So this part is about reading the menu that Part 1.3 built. We look at what other distributions give, why the loss you pick quietly decides which statistic your model chases, and why practitioners so often reach past the squared error we worked so hard to justify.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=7036423332948010965&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Chapter 10: When the Gradient Lies&lt;/strong&gt;&lt;br&gt;
We built the general recipe, and we chose the Gaussian, and squared error came out. So we could stop. But the practitioners’ literature contains a quiet recommendation that seems, at first, to contradict everything we just did: for many problems, do not use squared error. Use cross-entropy instead. This chapter explains why, and the explanation reaches all the way back to the slope idea from Part 1.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What Is Actually Being Compared&lt;/strong&gt;&lt;br&gt;
Putting squared error next to cross-entropy can look like a category mistake, so it is worth being clear about what is being compared. They are the same kind of object — both are cost functions, both are numbers measuring how wrong the model is, both are handed to us by the recipe once we pick an output distribution (Gaussian gives squared error; the binary distribution we will meet in Part 2 gives cross-entropy). So comparing them is fair. The reason they come into conflict is not the costs themselves. It is what sits in front of them.&lt;/p&gt;
&lt;p&gt;The conflict appears in a specific and very common situation: a binary classification task, where the model must output a yes-or-no probability. To produce a number between 0 and 1, the output is almost always passed through a sigmoid first. And it is the sigmoid, wedged between the network and the cost, that causes the trouble. As we will see, the sigmoid has flat regions, and when squared error is stacked on top of a sigmoid, those flat regions leak into the gradient and flatten it too. During back-propagation — the backward pass we built in Part 1.2 and will extend across layers later — a flat gradient means the update is negligibly small, so the model barely changes even when it is badly wrong. Cross-entropy is the cost whose shape cancels that flattening. That is the whole subject of this chapter: not “which cost is better in the abstract,” but “which cost survives contact with the sigmoid.”&lt;/p&gt;
&lt;p&gt;One note before the mechanics. Below, a term written σ′(z) will appear — the slope of the sigmoid. Do not worry about where it comes from in detail here; it is simply the sigmoid’s own steepness at a point, and it enters through the chain rule exactly as the slope did in Part 1.2. We are using it only to see the effect. The full story of the sigmoid, its slope, and the binary (Bernoulli) distribution that makes cross-entropy the derived cost for this task belongs to Part 2.1, where output units are the main subject. Here we only need to watch what σ′(z) does to the gradient.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Two Reasons a Gradient Can Be Small&lt;/strong&gt;&lt;br&gt;
Recall from Part 1.2 that training lives or dies by the gradient. If the slope of the loss goes flat, gradient descent has nothing to follow and learning stalls, like standing on a flat plateau in fog with no sense of which way is downhill.&lt;/p&gt;
&lt;p&gt;Now here is the subtlety. A gradient can go small for two completely different reasons, and only one of them is benign.&lt;/p&gt;
&lt;p&gt;The first is the good kind. In your worked example in Part 1.2, as w approached its true value of 2, the errors shrank and the gradient shrank with them. A small gradient there means you have essentially arrived — take smaller steps. Nothing is wrong.&lt;/p&gt;
&lt;p&gt;The second is the disaster. The gradient can go nearly to zero while the model is still badly wrong. When this happens, the small gradient is lying: it whispers “nothing to fix here” at exactly the moment the model is confidently mistaken and most needs a shove. This second case has a name. It is called saturation, and avoiding it is the reason cross-entropy is preferred.&lt;br&gt;
&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=3850005165800335206&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where Saturation Comes From, With Numbers&lt;/strong&gt;&lt;br&gt;
To see saturation appear, we need an output that can be confidently wrong. Binary outputs are the clean example, and this is exactly the setting flagged above: the model must answer yes-or-no, so it produces a probability ....... .&lt;/p&gt;
&lt;p&gt;To read the full article, please visit the link : &lt;a rel=&quot;nofollow&quot; href=&quot;https://husseinmahdi.xyz/writing/math-behind-nn-1-4/&quot;&gt;https://husseinmahdi.xyz/writing/math-behind-nn-1-4/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;or this : &lt;a rel=&quot;nofollow&quot; href=&quot;https://blog.gopenai.com/the-math-behind-neural-networks-explained-like-nobody-did-for-me-87f299008ffb&quot;&gt;https://blog.gopenai.com/the-math-behind-neural-networks-explained-like-nobody-did-for-me-87f299008ffb&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Refrences&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Goodfellow, I., Bengio, Y., &amp;amp; Courville, A. (2016). Deep Learning. MIT Press. Relevant chapter: Chapter 6 (Deep Feedforward Networks), Section 6.2.1 — Cost Functions. Available free at deeplearningbook.org.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/26429/the-math-behind-neural-networks-explained-like-nobody-did-for-me-part-1-4</guid>
<pubDate>Mon, 07 Sep 2026 17:57:26 +0000</pubDate>
</item>
<item>
<title>The Math Behind Neural Networks, Part 1.3 — Where the Loss Function Comes From</title>
<link>https://coderlegion.com/24863/the-math-behind-neural-networks-part-1-3-where-the-loss-function-comes-from</link>
<description>&lt;p&gt;A calm, sequential guide for anyone entering the field. The article is divided into smaller chapters to make it easier to understand.&lt;/p&gt;
&lt;p&gt;Part 1.2 left us with a working method but an unexamined assumption. We had a loss, the mean squared error, and we had turned it into a training procedure through the derivative and gradient descent. We watched the loss fall from 18.67 to 0.297 in a single step and then converge to the true relationship in the data. Everything worked. But we never asked where the mean squared error itself came from. We wrote it down as a reasonable way to measure error — square the gap, average it — and moved on. Because it worked, the question never surfaced.&lt;/p&gt;
&lt;p&gt;Look again at how it entered. In Part 1.2, the model gave us a form for the line, ŷ = wx + b, but no way to judge whether a particular guess of w and b was any good. The equation described the model and contained no built-in measure of its quality. Faced with that gap, the article said, in as many words: “So we invented one.” We compared the prediction to the truth across all the data and summarized the gap into a single number. Squaring came along because it was reasonable — it makes every error positive and punishes large misses — not because anything forced it.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;chapter-7-what-a-cost-function-really-measures&quot;&gt;Chapter 7: What a Cost Function Really Measures&lt;/h3&gt;
&lt;p&gt;A Note on Three Names&lt;br&gt;
At the end of Part 1.2 we had a complete loop: predict, measure the loss, compute the gradient, take a step. The loss at the centre of that loop was&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=15754441794189971062&quot; alt=&quot;&quot;&gt;&lt;br&gt;
A quick word on names first, because this article introduces a third one and I do not want it to look like a third thing. &lt;strong&gt;In Part 1.1 we called this the error function.&lt;/strong&gt; In Part 1.2 we called it the loss. In this part, and in most textbooks, you will also see it called the cost function, written &lt;strong&gt;J(θ).&lt;/strong&gt; These are not three different objects. They are three names for the same idea — a single number that measures how wrong the model is and that training tries to make small. “Cost function” is simply the more general term the literature settles on once the measure is no longer tied to one particular formula, which is exactly the situation this article is about to put us in. Wherever you read “cost” below, you may &lt;strong&gt;read “error” or “loss” and lose nothing&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Assumption We Never Examined&lt;/strong&gt;&lt;br&gt;
With the naming settled: as the introduction recalled, this measure entered the story as an invention — the reasonable thing we reached for when the model gave us no measure of its own quality. Squaring makes every error positive, so overshooting and undershooting both count as wrong, and it punishes a large miss far more than a small one. These are good properties, and they were enough to justify the formula for a first encounter.&lt;/p&gt;
&lt;p&gt;But “good properties” is not the same as “forced.” An invention fills a gap; it does not prove it was the only thing that could have filled it. A reader who accepts squared error should be able to answer the harder question that the invention quietly left open: out of all the ways to measure a gap, why this one? Some of that question we have in fact already answered. In Part 1.1 we asked the most natural competing question — &lt;strong&gt;why not the absolute gap |y − ŷ|, which also removes the sign — and we ruled it out for a concrete reason: the absolute value has a sharp corner at zero where its slope jumps from −1 to +1 with no value in between, and gradient descent, which lives or dies by reading a clean slope, receives contradictory signals at exactly the point it is trying to settle into.&lt;/strong&gt; So the absolute value is not an open door; Part 1.1 already closed it, on grounds of the slope.&lt;/p&gt;
&lt;p&gt;What Part 1.1 did not close is the deeper question. Ruling out the absolute value tells us squaring is better-behaved than one rival. It does not tell us that squaring is right — that out of every smooth, well-behaved measure we could have invented, this is the one the problem actually calls for. For that we need to stop justifying squared error from the outside and find the principle that produces it from the inside. This chapter goes looking for that principle.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;From a Point Guess to a Distribution&lt;/strong&gt;&lt;br&gt;
In Part 1.2, the model produced a single number: ŷ = wx + b. Given an input, it committed to one answer. This is the natural picture, and it is also the picture that hides the principle we are looking for.&lt;/p&gt;
&lt;p&gt;The more honest picture is this. A model is uncertain. Given an input x, it does not truly believe the answer is exactly one number. It believes the answer is probably near some number, with smaller and smaller chances the further you move away. In other words, the model does not output a point. It outputs a distribution — a spread of belief over all the answers that could occur. We write this distribution as&lt;/p&gt;
&lt;p&gt;This part is about where that invention actually came from. Why squared error, and not the plain distance, or the cube? The honest answer is that the mean squared error is not a starting point at all. It is a consequence. It is what you are forced to when you begin from a deeper and more general principle about what it means for a model to be good. In this part we start from that principle, watch it produce a single general recipe for building cost functions, and then watch the mean squared error fall out of that recipe on its own.&lt;/p&gt;
&lt;p&gt;Readers of Part 1.1 were promised this. Its closing note mentioned, almost in passing, that minimizing the mean squared error is equivalent to maximum likelihood estimation under the assumption of Gaussian noise. That sentence was a debt. This part pays it: everything below is the unpacking of that one line. Part 1.4 then asks the next question — whether the loss we just derived is the one we should actually use.&lt;br&gt;
....&lt;br&gt;
....&lt;/p&gt;
&lt;p&gt;Read the full article at the official link: &lt;a rel=&quot;nofollow&quot; href=&quot;https://husseinmahdi.xyz/writing/math-behind-nn-1-3/&quot;&gt;https://husseinmahdi.xyz/writing/math-behind-nn-1-3/&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/24863/the-math-behind-neural-networks-part-1-3-where-the-loss-function-comes-from</guid>
<pubDate>Tue, 18 Aug 2026 19:57:05 +0000</pubDate>
</item>
<item>
<title>The Math Behind Neural Networks, Explained Like Nobody Did for Me - Part 1.2</title>
<link>https://coderlegion.com/23605/the-math-behind-neural-networks-explained-like-nobody-did-for-me-part-1-2</link>
<description>&lt;p&gt;&lt;em&gt;A calm, sequential guide for anyone entering the field, The article will also be divided into smaller chapters to make it easier to understand.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;part-1-2-the-mathematics-of-learning&quot;&gt;Part 1.2: The Mathematics of Learning&lt;/h3&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/23416/the-math-behind-neural-networks-explained-like-nobody-did-for-me&quot;&gt;Part 1.1&lt;/a&gt; ended at a precise standing point: we had built a model, ŷ = wx + b, and we had a single number, the mean squared error, that told us how wrong that model was on average. What we did not have was a way to act on that number. A loss of 4.67 tells you the model is wrong; it does not tell you whether to push w up or down, and it does not tell you by how much. Part 1.2 is where that missing piece arrives.&lt;/p&gt;
&lt;p&gt;We will introduce the derivative, derive the gradient of the loss with respect to w and b by hand, and then turn those gradients into an actual update rule through gradient descent. By the end of this part, the same three data points from Chapter 2 will be used in a full training example, and you will watch the loss fall step by step until the model converges to the true underlying relationship. The slope idea from Chapter 1 does not change. It simply gets sharpened into the tool that makes learning possible.&lt;/p&gt;
&lt;p&gt; &lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=6217155208928513122&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;chapter-4-the-derivative-the-slope-of-the-error&quot;&gt;Chapter 4: The Derivative — The Slope of the Error&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Why a Number Alone Is Not Enough&lt;/strong&gt;&lt;br&gt;
At the end of Chapter 3 we had a single number, L, that summarized how wrong the model was. With w = 1 and b = 0, the loss was 4.67. We know the goal is to make this number as small as possible. What we do not yet know is how.&lt;/p&gt;
&lt;p&gt;A reader might suggest trying different values of w and b until the loss becomes small. With two parameters and a simple dataset, this is not impossible, but consider what it involves. Should w be increased or decreased? By how much? Should b be changed at the same time or held steady? A real neural network has millions of parameters, not two, and trying random combinations would take longer than the age of the universe.&lt;/p&gt;
&lt;p&gt;The deeper issue is that the loss value, taken on its own, does not contain a direction. The number 4.67 tells you that you are wrong, but it does not tell you which way is less wrong. If I handed you only the number 4.67 and asked you whether to increase or decrease w, you could not answer. You would have to guess. The loss is a position, not a direction. These are two fundamentally different kinds of information, and you cannot extract one from the other by rearranging the same data. You have to ask a new question.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Equations Have Been Building Toward This&lt;/strong&gt;&lt;br&gt;
To see why the derivative is the only thing that fits here, it helps to trace the logic of every equation we have written so far. Each one was forced into existence by a problem the previous one could not solve.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;We began with the slope formula:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=16107154320584636332&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This worked perfectly when the data lay on a clean line, because the slope could be read off directly from any two points. But real data scatters, and the slope formula stopped applying. Different pairs of points gave different slopes, and none of them represented the whole dataset.&lt;/p&gt;
&lt;p&gt;So we wrote a candidate line with unknowns to be learned:&lt;br&gt;
&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=9608775106319036076&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This solved the previous problem by giving us a form for the line, but it created a new one. The values of w and b were unknown, and we had no way to evaluate whether a particular guess was good. The equation describes the model but contains no built-in measure of its quality.&lt;/p&gt;
&lt;p&gt;So we invented one. We compared the prediction ŷ to the truth y across all data points and summarized the gap into a single number:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=3436137266483135989&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This solved the evaluation problem by giving us one number that measures total error. But it created the deepest problem of all, the one we are now standing at. The loss tells us that we are wrong but not which way to change w or b to be less wrong. The information we need is not contained in L. It is contained in how L changes when w changes, which is a different quantity entirely.&lt;/p&gt;
&lt;p&gt;To extract that quantity, we need a new equation, one that asks the loss a question the loss formula on its own never asks: if w were slightly different, by how much and in what direction would L change ? The mathematical object that answers this question is the derivative.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;from-slope-to-derivative&quot;&gt;From Slope to Derivative&lt;/h3&gt;
&lt;p&gt;We already have the tool we need, in a simpler form. In Chapter 1, slope told us how y changes when x changes. The derivative is the same idea applied to a different setting. Instead of asking how y changes with x in the data, we now ask how the loss L changes with the parameters w and b in the model. The variables have changed, but the underlying question — how does one thing change as another changes? — is identical.&lt;/p&gt;
&lt;p&gt;There is one refinement. The slope formula in Chapter 1 measured the rate of change between two distinct points. The derivative measures the instantaneous rate of change at a single point, which is what you get when those two points move infinitely close together:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=844295223454502176&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is not a different concept from slope. It is slope made precise. As the gap between the two points shrinks to zero, the slope of the line connecting them becomes the slope of the curve at that exact point.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why the Derivative and Nothing Else&lt;/strong&gt;&lt;br&gt;
It is worth addressing directly why the derivative is the right tool here, rather than some other technique. The honest answer is that the derivative is not the only conceivable approach, but it is the only approach ....... .&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;To complete the article, you can visit the blogs and view the entire series on :&lt;/em&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://husseinmahdi.xyz/writing/series/math-behind-neural-networks/&quot;&gt;https://husseinmahdi.xyz/writing/series/math-behind-neural-networks/&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/23605/the-math-behind-neural-networks-explained-like-nobody-did-for-me-part-1-2</guid>
<pubDate>Mon, 27 Jul 2026 18:20:40 +0000</pubDate>
</item>
<item>
<title>The Math Behind Neural Networks, Explained Like Nobody Did for Me</title>
<link>https://coderlegion.com/23416/the-math-behind-neural-networks-explained-like-nobody-did-for-me</link>
<description>&lt;p&gt;&lt;em&gt;A calm, sequential guide for anyone entering the field. The article is divided into smaller chapters to make it easier to understand.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Deep learning can feel overwhelming at first. You encounter words like gradient, derivative, loss function, activation, and backpropagation, and it is rarely clear how they relate to each other or where they come from. This article builds the full picture from the ground up, starting from the simplest idea in mathematics, slope, and showing how that single idea grows into everything that powers a modern neural network. No step is skipped, and no formula appears without explanation.&lt;/p&gt;
&lt;p&gt;By the end of Part 1.1, three concepts — slope, regression, and error — will form one continuous idea in your mind. You will understand what slope is and why it matters, what linear regression is trying to do, and what the error function measures. Part 1.2 then continues the journey with the derivative and gradient descent, the tools that turn a measurement of error into an actual improvement. Part 2 goes further still, introducing activation functions, multiple layers, and backpropagation, showing how everything here scales into deep networks.&lt;/p&gt;
&lt;h3 id=&quot;section&quot;&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=2405181283146062159&quot; alt=&quot;&quot;&gt;&lt;/h3&gt;
&lt;h3 id=&quot;chapter-1-slope-the-foundation-of-everything&quot;&gt;Chapter 1: Slope — The Foundation of Everything&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;What Is Slope?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Slope answers one question: how much does the output change when the input changes?&lt;/p&gt;
&lt;p&gt;If you drive 100 kilometers in 2 hours, your speed — the rate of change of distance with respect to time — is 50 km/h. That is a slope. If a ramp rises 3 meters over a horizontal distance of 6 meters, its steepness is 3/6 = 0.5. That is also a slope.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=5760804451094831815&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Formally, the slope between two points (x₁, y₁) and (x₂, y₂) is defined as:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=11897751242004574030&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is called rise over run. The Greek letter Δ (delta) simply means change in.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A Concrete Example&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Consider these three data points:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=6546799812274831330&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Taking points (1, 2) and (3, 6):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=16744912882691530157&quot; alt=&quot;&quot;&gt;&lt;br&gt;
 The slope is 2. Every time x increases by 1, y increases by 2. The relationship is perfectly linear and described by:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=12101358665492126687&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In real problems, however, we do not know the slope in advance. We have to discover it from data. That discovery process is called regression.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;chapter-2-linear-regression-learning-the-slope-from-data&quot;&gt;Chapter 2: Linear Regression — Learning the Slope from Data&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;From Knowing the Slope to Learning It&lt;/strong&gt;&lt;br&gt;
In Chapter 1 we had three neat data points that fell perfectly on a line, and we computed the slope directly with a formula. and the question this article exists to answer is how mathematics learns from data that does not fall on a clean line at all.&lt;/p&gt;
&lt;p&gt;Real data is not like that. When you collect measurements from the world — house prices against square footage, patient weight against medication dosage, temperature against electricity demand — the points do not land on a single clean line. They scatter. No two points give you the same slope, and no formula can hand you the answer.&lt;/p&gt;
&lt;p&gt;This is where regression begins. Instead of computing the slope from two chosen points, we ask a different question: what is the single straight line that best represents all of the scattered points at once ? That line will not pass through every point, but it will come as close as possible to all of them. Finding it means learning its slope and its vertical position from the data itself, rather than reading them off with a formula.&lt;/p&gt;
&lt;p&gt; &lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=13277951927564334297&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;.....................&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;To read the full article, check out my blog: &lt;a rel=&quot;nofollow&quot; href=&quot;https://husseinmahdi.xyz/writing/math-behind-nn-1-1/&quot;&gt;https://husseinmahdi.xyz/writing/math-behind-nn-1-1/&lt;/a&gt;&lt;br&gt;
This is part of the &quot;math-behind-neural-networks&quot; series&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Or on GoPenAI: &lt;a rel=&quot;nofollow&quot; href=&quot;https://blog.gopenai.com/the-math-behind-neural-networks-explained-like-nobody-did-for-me-cda519ef63e8&quot;&gt;https://blog.gopenai.com/the-math-behind-neural-networks-explained-like-nobody-did-for-me-cda519ef63e8&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/23416/the-math-behind-neural-networks-explained-like-nobody-did-for-me</guid>
<pubDate>Sat, 25 Jul 2026 00:02:30 +0000</pubDate>
</item>
<item>
<title>We Dug Up Our Own Fake-Physics Artifact — and Rebuilt It Into Something You Can Check</title>
<link>https://coderlegion.com/21011/we-dug-up-our-own-fake-physics-artifact-and-rebuilt-it-into-something-you-can-check</link>
<description>&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=7182322320887322452&quot; alt=&quot;title&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;why-there-is-a-second-post&quot;&gt;Why there is a second post&lt;/h3&gt;
&lt;p&gt;About six months ago we built and published the original QSOT artifact. The name — &lt;em&gt;Quantum State Over Time&lt;/em&gt; — promised a deeper link between quantum evolution and temporal structure than the thing underneath could actually support.&lt;/p&gt;
&lt;p&gt;Then last week we published a post-mortem with an uncomfortable title: &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/20084/we-made-a-high-formality-fake-physics-slop-artifact-qsot-quantum-state-over-time-compiler?show=20084#q20084&quot;&gt;&lt;strong&gt;&quot;We Made a High-Formality, Fake Physics Slop Artifact.&quot;&lt;/strong&gt;&lt;/a&gt; A quiet admission that we had been wrong, and that the original claims did not survive scrutiny.&lt;/p&gt;
&lt;p&gt;It was not a marketing move and not self-flagellation. It was a confession: we had shipped a repository with a DOI, two LaTeX papers, a project page, release notes, plots, and tests — the full visual grammar of serious science — around a core claim that was hollow underneath.&lt;/p&gt;
&lt;p&gt;That post diagnosed the failure. It did not repair it. This is the repair.&lt;/p&gt;
&lt;p&gt;If we made the mess, we clean it up.&lt;/p&gt;
&lt;p&gt;The repair is called &lt;strong&gt;QSOT2&lt;/strong&gt;. It is smaller, narrower, and far less ambitious than the original — and that is the point: the goal is no longer to look impressive, only to keep the claims we can actually justify.&lt;/p&gt;
&lt;p&gt;You do not need to have read the first post. I will rebuild the context and show what changed, using evidence rather than adjectives.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;for-readers-who-never-met-qsot&quot;&gt;For readers who never met QSOT&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;QSOT&lt;/strong&gt; stands for &lt;strong&gt;Quantum State Over Time&lt;/strong&gt; — a real idea from the physics literature (Lie &amp;amp; Fullwood) that treats time inside quantum mechanics as a first-class object rather than an external dial.&lt;/p&gt;
&lt;p&gt;Our &lt;em&gt;implementation&lt;/em&gt; of that idea — QSOT Compiler v1 — tried to map curved-spacetime backgrounds (Schwarzschild, de Sitter, AdS, Gödel) into single-qubit noise channels, then report whether the channels stayed physically valid, whether curvature showed up as decoherence, and whether quantum-information signals changed between backgrounds.&lt;/p&gt;
&lt;p&gt;That is an ambitious sentence. It was ambitious in the wrong order.&lt;/p&gt;
&lt;p&gt;The foundations were real — standard quantum-channel mathematics, Kraus operators, CPTP conditions. Those are not in dispute. The problem was everything we stacked on top of them.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-was-actually-wrong&quot;&gt;What was actually wrong&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=5407994082750156865&quot; alt=&quot;2&quot;&gt;&lt;/p&gt;
&lt;p&gt;The original problem was not that the repository looked broken. It was the opposite: it looked credible. The code ran, the paper compiled, the plots looked scientific, and the project carried the surface markers of serious work.&lt;/p&gt;
&lt;p&gt;But the chain from claim to evidence was not disciplined enough.&lt;/p&gt;
&lt;p&gt;The clearest example was the project's theoretical heart: Kirkwood-Dirac negativity. In the actual run, that number was a placeholder. So was the memory-depth signal. The curved-spacetime metrics were named in the papers, but not executed in the way the prose implied.&lt;/p&gt;
&lt;p&gt;The form had outrun the evidence. QSOT2 begins by refusing to let that happen again.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;why-dig-up-our-own-grave-six-months-later&quot;&gt;Why dig up our own grave six months later&lt;/h3&gt;
&lt;p&gt;Two reasons, one of them not flattering.&lt;/p&gt;
&lt;p&gt;The honorable one: by 2026 we had built executable verification, reproducibility surfaces, hash-based provenance, and a public ledger. The old artifact stopped feeling like an embarrassment and started feeling like an &lt;strong&gt;obligation&lt;/strong&gt; — we made the mess, we finally had the tools to understand it, so cleaning it was our job.&lt;/p&gt;
&lt;p&gt;The other: curiosity. Criticising a bad artifact after the fact is easy. Taking the same domain and producing something tighter, smaller, and able to survive its own tooling is not. We wanted to know whether the newer skill was real. QSOT2 was the test.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-qsot2-changed-and-it-was-not-a-new-theorem&quot;&gt;What QSOT2 changed — and it was not a new theorem&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=6710970676358702437&quot; alt=&quot;3&quot;&gt;&lt;/p&gt;
&lt;p&gt;The most important change in QSOT2 is not a result. It is a &lt;strong&gt;boundary&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Boundary first.&lt;/strong&gt; QSOT2 is not a quantum-gravity result. It is not a first-principles derivation. It is a bounded mathematical-consistency verifier for one implemented phenomenological model.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;QSOT v1 tried to be a new-physics paper, a quantum-gravity gesture, a governance platform, and a math verifier at once. QSOT2 refuses all of that and asks one question:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Does the implemented model stay internally consistent — as quantum mechanics and as software — and are its numbers honest about what they are?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Smaller question. Much better question.&lt;/p&gt;
&lt;h4 id=&quot;1-the-math-matured-by-subtraction-not-ambition&quot;&gt;1. The math matured by subtraction, not ambition&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=12355222444266379742&quot; alt=&quot;4&quot;&gt;&lt;/p&gt;
&lt;p&gt;QSOT2 did not make the model bolder. It made its mathematical &lt;em&gt;status&lt;/em&gt; clean, by removing every place the old version could pretend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the curvature-to-noise map is stated plainly — &lt;code&gt;p = 1 - exp(-alpha * ||Riemann||_F)&lt;/code&gt;, with &lt;code&gt;alpha&lt;/code&gt; a free, dimensionless calibration parameter, &lt;strong&gt;not&lt;/strong&gt; a derived constant;&lt;/li&gt;
&lt;li&gt;the curvature inputs are disclosed as non-derived toy proxies, so the product &lt;code&gt;alpha * ||Riemann||_F&lt;/code&gt; carries no hidden physical-unit claim;&lt;/li&gt;
&lt;li&gt;Kirkwood-Dirac is demoted from &quot;contextuality witness&quot; to a bounded, flat-relative diagnostic;&lt;/li&gt;
&lt;li&gt;the memory proxy is demoted from &quot;full reconstruction&quot; to a self-tested one.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The curvature tensors are not smuggled in as derived physics: they are explicitly labelled toy proxies in the artifact (a per-background &lt;code&gt;riemann_is_toy&lt;/code&gt; flag), so the model cannot silently upgrade itself into a physical claim.&lt;/p&gt;
&lt;p&gt;This is what strengthening looks like when the problem was epistemic inflation, not numerical instability. You do not fix inflation by computing harder. You fix it by removing the claims the math could never support.&lt;/p&gt;
&lt;h4 id=&quot;2-the-code-stopped-being-simulation-and-became-the-witness&quot;&gt;2. The code stopped being &quot;simulation&quot; and became the witness&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=17097101516414711938&quot; alt=&quot;5&quot;&gt;&lt;/p&gt;
&lt;p&gt;In QSOT2 the code's job is not to simulate. It is &lt;strong&gt;constraint enforcement&lt;/strong&gt; — it fixes what may be claimed, what must be measured, what can be re-run, what gets hashed, and what is allowed to fail.&lt;/p&gt;
&lt;p&gt;A paper can write &quot;the axioms hold&quot; for free. QSOT2 instead emits, per run: linearity deviation &lt;code&gt;1.1e-16&lt;/code&gt;, CPTP completeness &lt;code&gt;1.6e-16&lt;/code&gt;, trace preservation &lt;code&gt;4.4e-16&lt;/code&gt; — all at machine epsilon — across &lt;code&gt;35&lt;/code&gt; deterministic checks (&lt;strong&gt;34 pass / 1 degraded / 0 fail&lt;/strong&gt;). The rule behind it:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Do not let prose carry a claim that the code cannot witness.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There is an architectural version too: the math layer is &lt;em&gt;forbidden from importing&lt;/em&gt; the reporting layer — the separation that was missing in v1 is now enforced by the code, not promised by prose.&lt;/p&gt;
&lt;h4 id=&quot;3-the-negative-result-is-advertised-not-hidden&quot;&gt;3. The negative result is advertised, not hidden&lt;/h4&gt;
&lt;p&gt;!6.png&lt;/p&gt;
&lt;p&gt;The overall verdict is &lt;code&gt;DEGRADED_PASS&lt;/code&gt;, on purpose: the flat-baseline KD optimizer does not converge inside its fixed 50-step budget — meaning it was still improving when the budget ran out, not that it diverged, so the reported value remains interpretable within the fixed-budget run.&lt;/p&gt;
&lt;p&gt; Instead of rounding up, the run says so — in the verdict, the schema, the README, and the paper. The difference between an artifact that wants to impress and one that wants to be trusted often lives in exactly this footnote.&lt;/p&gt;
&lt;h4 id=&quot;4-the-workflow-became-a-claim-custody-pipeline&quot;&gt;4. The workflow became a claim-custody pipeline&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=1658693058985950238&quot; alt=&quot;7&quot;&gt;&lt;/p&gt;
&lt;p&gt;The workflow ties it together: every claim travels a gated path —&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;claim → code check → artifact → canonical-LF hash → paper line → DOI.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One command runs the experiment and emits one machine-readable result under a fixed schema with a four-field claim boundary; one command runs 50 tests behind a ≥ 90% coverage gate (currently ~96%); the line is DOI-archived on Zenodo (QSOT2 v0.1.2). None of this makes the model physically true — it makes the artifact &lt;strong&gt;auditable.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One detail matters here: the reproducibility claim is not hand-waved. The result is anchored to a canonical-LF SHA-256; the known non-byte-stable field is &lt;code&gt;generated_at&lt;/code&gt;, and that exception is disclosed rather than hidden. The sensitivity numbers live in a separate committed sweep artifact, and the paper maps each claim back to a named file and hash.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-paper-is-the-formal-boundary-record&quot;&gt;The paper is the formal boundary record&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=12804472793274855895&quot; alt=&quot;paper&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://zenodo.org/records/20764446&quot;&gt;The paper&lt;/a&gt;&lt;/strong&gt; is not decoration. In the original artifact, formal writing made the work look stronger than the evidence underneath. In QSOT2, the paper has the opposite job: it records the boundary of the claim.&lt;/p&gt;
&lt;p&gt;Its title says the scope plainly: &lt;strong&gt;A Mathematical-Consistency Verifier for a Phenomenological Curved-Spacetime Quantum-Channel Model.&lt;/strong&gt; The paper does not present QSOT2 as a quantum-gravity result, a first-principles derivation, or an externally validated physical model. It presents it as an executable internal-consistency check for one implemented ansatz.&lt;/p&gt;
&lt;p&gt;The structure follows that boundary. It starts with scope and background, then moves through temporal axiom checks, curvature-noise baselines, the flat-relative KD diagnostic, the TTM-inspired memory proxy, consolidated results, explicit non-claims, and reproducibility.&lt;/p&gt;
&lt;p&gt;That order matters. The paper does not ask the reader to trust a polished argument. It asks the reader to follow a constrained chain: what the model claims, what the code checks, what the result reports, what the artifact refuses to claim, and how the run can be reproduced.&lt;/p&gt;
&lt;p&gt;The abstract already carries the important limits: the curvature-to-channel mapping is a conceptual ansatz with a free calibration parameter; the curvature norms are non-derived toy proxies; the product &lt;code&gt;alpha * ||Riemann||_F&lt;/code&gt; carries no physical-unit claim; and the reference run ends in &lt;code&gt;DEGRADED_PASS&lt;/code&gt; for one documented reason, the flat-baseline KD optimizer’s fixed-budget non-convergence.&lt;/p&gt;
&lt;p&gt;So the paper is not where QSOT2 becomes more impressive. It is where QSOT2 becomes harder to overclaim.&lt;/p&gt;
&lt;p&gt;If the repository is the executable surface, and the public ledger is the receipt surface, the paper is the formal boundary surface: the place where the claim is written down in a form that can be checked against the code, the result artifact, and the hash trail.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-receipt-every-v1-failure-a-measurable&quot;&gt;The receipt: every v1 failure → a measurable&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=16355761790428363566&quot; alt=&quot;8&quot;&gt;&lt;/p&gt;
&lt;p&gt;The honest way to prove a repair is to put the old defect and the new measurement side by side. The three that mattered:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Placeholders → bounded diagnostics&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;v1: KD negativity and non-Markovianity were both exactly &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;QSOT2: &lt;code&gt;kd_delta = +0.1230&lt;/code&gt;; self-test &lt;code&gt;nm = 1.41e-4&lt;/code&gt; (must fire on injected backflow) vs. model &lt;code&gt;nm = 0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Means: reproducible, model-relative comparisons — &lt;em&gt;not&lt;/em&gt; proofs of contextuality or curvature-induced decoherence.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. Named spacetime labels → explicit model inputs&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;v1: the curved-spacetime metrics were named in the papers, absent from the run.&lt;/li&gt;
&lt;li&gt;QSOT2: curvature drives the channel across six backgrounds; purities verified — Schwarzschild &lt;code&gt;0.99943&lt;/code&gt;, de Sitter &lt;code&gt;0.63607&lt;/code&gt;, AdS5 &lt;code&gt;0.67764&lt;/code&gt;, Eguchi-Hanson &lt;code&gt;0.99887&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Means: the behaviour of a phenomenological ansatz — &lt;em&gt;not&lt;/em&gt; a derived spacetime result.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. Asserted axioms → verified axioms&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;v1: temporal and axiomatic properties were stated, not checked.&lt;/li&gt;
&lt;li&gt;QSOT2: five temporal-state axioms verified as algebraic invariants, deviations &lt;code&gt;≤ 4.4e-16&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Means: the model's quantum mechanics is internally consistent under its assumptions. That is the whole claim.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Read this section as the remediation map. The next question is where that map can be inspected outside this essay.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-public-ledger-is-the-receipt-surface&quot;&gt;The public ledger is the receipt surface&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=3160259026642644918&quot; alt=&quot;ledger&quot;&gt;&lt;/p&gt;
&lt;p&gt;The public &lt;a rel=&quot;nofollow&quot; href=&quot;https://flamehaven01.github.io/Flamehaven-Verification-Ledger/&quot;&gt;&lt;strong&gt;Flamehaven Verification Ledger&lt;/strong&gt;&lt;/a&gt; is where this repair becomes inspectable outside the essay.&lt;/p&gt;
&lt;p&gt;The QSOT2 entry is recorded as &lt;strong&gt;EQA-TEST-0058&lt;/strong&gt;, a verification run dated 2026-06-17: &lt;strong&gt;&quot;QSOT2: Mathematical-Consistency Verifier (re-scoped honest successor of the 0057 slop).&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That entry states the result directly: &lt;code&gt;DEGRADED_PASS (34 / 0 / 0 / 1)&lt;/code&gt;. It also states why: the KD flat-baseline optimizer did not converge within its fixed budget. The limitation is surfaced, not hidden.&lt;/p&gt;
&lt;p&gt;The ledger record makes the repair checkable in four directions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;JSON&lt;/strong&gt; — the raw machine-readable result;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Report&lt;/strong&gt; — the human-readable verification note;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Repo&lt;/strong&gt; — the source implementation;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Paper&lt;/strong&gt; — the formal boundary record.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In about three minutes, a reader can move from the ledger card to the raw JSON, the report, the repository, and the paper, and see the same claim boundary repeated across all of them: model-output consistency only, not external physical validity.&lt;/p&gt;
&lt;p&gt;That is the point of the ledger. It is not a marketing page. It is a public verification record for Flamehaven's governance reviews, physics verification runs, and biomedical audit scans. Each published run is meant to be deterministic, locally executed, and inspectable from repository state.&lt;/p&gt;
&lt;p&gt;The ledger answers one question: where can the evidence be inspected? The next question is narrower and more important: what exactly does that evidence support?&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-qsot2-can-verify-and-what-it-refuses-to-claim&quot;&gt;What QSOT2 can verify — and what it refuses to claim&lt;/h3&gt;
&lt;p&gt;Stated plainly, because vagueness is where slop hides.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;QSOT2 verifies, and proves per run:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the implemented single-qubit channels are CPTP (completeness error at machine epsilon);&lt;/li&gt;
&lt;li&gt;evolved states stay valid density matrices (Hermitian, unit-trace, positive semidefinite);&lt;/li&gt;
&lt;li&gt;five temporal-state axioms hold to &lt;code&gt;≤ 4.4e-16&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;the reported purities, entropies, and KD-delta are deterministic, reproducible, hash-anchored outputs of the implemented model;&lt;/li&gt;
&lt;li&gt;the non-Markovianity detector actually fires on injected backflow &lt;em&gt;before&lt;/em&gt; it is trusted to report the model's &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;QSOT2 does not claim, and says so in the artifact:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;that the curvature-to-channel map is physically real;&lt;/li&gt;
&lt;li&gt;any first-principles derivation;&lt;/li&gt;
&lt;li&gt;any quantum-gravity or external-physical result;&lt;/li&gt;
&lt;li&gt;that KD negativity is a contextuality proof.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those refusals are not a closing disclaimer. They are serialized as a &lt;code&gt;claim_boundary&lt;/code&gt; block in &lt;strong&gt;every&lt;/strong&gt; result file the system writes.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;why-this-is-not-just-nicer-slop-&quot;&gt;Why this is not just &quot;nicer slop&quot;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=4435827695161796512&quot; alt=&quot;9&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here is the test, and you can run it yourself.&lt;/p&gt;
&lt;p&gt;Slop is the condition where, &lt;strong&gt;if you delete the rhetoric, nothing load-bearing remains.&lt;/strong&gt; In QSOT v1, if you stripped the LaTeX and the project page, the core claim — KD negativity — collapsed to a placeholder. The formality was load-bearing for the deception.&lt;/p&gt;
&lt;p&gt;Apply the same deletion to QSOT2. Strip the prose, the README, this newsletter. What is left:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a machine-readable result with 35 named checks and their pass/degrade status,&lt;/li&gt;
&lt;li&gt;numerical deviations at machine epsilon you can recompute,&lt;/li&gt;
&lt;li&gt;a four-field boundary that states the scope in the data itself,&lt;/li&gt;
&lt;li&gt;byte-deterministic outputs with a SHA-256 you can regenerate,&lt;/li&gt;
&lt;li&gt;a DOI you can resolve,&lt;/li&gt;
&lt;li&gt;a test suite you can run,&lt;/li&gt;
&lt;li&gt;an import boundary the interpreter will enforce whether you read the docs or not.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In other words: &lt;strong&gt;remove the rhetoric and QSOT2 is still standing; remove the rhetoric and QSOT v1 was a placeholder.&lt;/strong&gt; That is the difference between persuasion and verification, and it is the only argument here I actually trust — because it does not depend on trusting me.&lt;/p&gt;
&lt;p&gt;The cleanest single proof is the one most products would bury: QSOT2 ships its own failing check in plain sight. Slop hides its failures behind formality. QSOT2 prints its one degraded result on the front of the box.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-this-actually-felt-like&quot;&gt;What this actually felt like&lt;/h3&gt;
&lt;p&gt;Unpleasant first, then clarifying. We had worked hard on QSOT v1 — that was never in question. The hard part was accepting that effort and legitimacy are not the same thing. You can write clean code around a weak claim and a polished paper around a boundary you never defended, and if AI is accelerating your workflow, it accelerates the self-deception too.&lt;/p&gt;
&lt;p&gt;That is why the confession had to be public — and why the confession was not enough on its own. Anyone can say &quot;we got this wrong.&quot; The harder move is to say: here is what was wrong, here is how we constrained it, here is the artifact that now withstands inspection. The repair matters more than the confession.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-broader-lesson&quot;&gt;The broader lesson&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=13325823392505022493&quot; alt=&quot;10&quot;&gt;&lt;/p&gt;
&lt;p&gt;The lesson is not &quot;don't use AI&quot; — we used it heavily for both artifacts. It is sharper:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;When AI lets you produce high-formality output in minutes, the scarce resource is no longer generation. It is &lt;strong&gt;claim custody.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What is being claimed? What file carries it? What check fails if it drifts? What survives when you delete the rhetoric? QSOT v1 had abundant generation and almost no custody. QSOT2 inverts that ratio in one narrow domain.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;closing&quot;&gt;Closing&lt;/h3&gt;
&lt;p&gt;Six months ago we had something that looked like a scientific success and wasn't. Today we have something smaller, less glamorous, and much harder to fool — including harder for us to fool ourselves with. We trust the second one more. That is the progress.&lt;/p&gt;
&lt;p&gt;QSOT v1 was the cautionary tale. QSOT2 is what happened when we treated that failure not as embarrassment, but as engineering input.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=11420615897934478403&quot; alt=&quot;repo&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/Flamehaven-Labs/QSOT2-Compiler&quot;&gt;&lt;strong&gt;QSOT2 — a mathematical-consistency verifier&lt;/strong&gt;&lt;/a&gt;, Open source under MIT (Flamehaven Labs). If you disagree with any of it, use the path the artifact was built to survive: clone it, re-run it, and check the hash.&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/21011/we-dug-up-our-own-fake-physics-artifact-and-rebuilt-it-into-something-you-can-check</guid>
<pubDate>Sat, 20 Jun 2026 05:12:06 +0000</pubDate>
</item>
<item>
<title>Physical Keyboard for Typing Math</title>
<link>https://coderlegion.com/19908/physical-keyboard-for-typing-math</link>
<description>&lt;p&gt;I built a compact physical keyboard for people who type mathematical and scientific symbols often.&lt;/p&gt;
&lt;p&gt;The idea came from a small but repeated frustration: writing math by hand is fast, but typing math on a computer usually means stopping to find the right symbol.&lt;/p&gt;
&lt;p&gt;If I need a scientific symbol while writing notes, slides, lab reports, or technical explanations, I do not always want to open a symbol menu, copy from an old document, or switch into a full equation editor.&lt;/p&gt;
&lt;p&gt;So I started working on the Nitrax Mathematical Keyboard.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=2261966274280168947&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It is a physical math keyboard, not a virtual keyboard, calculator, or generic keypad. The symbols are printed directly on the keys, with blue and gray symbol layers accessed through key combinations.&lt;/p&gt;
&lt;p&gt;On Windows, the companion app uses AutoHotkey to send Unicode characters into the active application when Math Mode is enabled. &lt;/p&gt;
&lt;p&gt;The goal is not to replace LaTeX or professional equation typesetting. It is for everyday math typing in normal writing workflows, where you just need the symbol now and want to keep writing.&lt;/p&gt;
&lt;p&gt;Project link: &lt;a rel=&quot;nofollow&quot; href=&quot;https://mathematicalkeyboard.com/&quot;&gt;https://mathematicalkeyboard.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I would be interested to hear how other developers would approach the layout problem: would you organize math symbols by category, frequency of use, or memory cues?&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/19908/physical-keyboard-for-typing-math</guid>
<pubDate>Sun, 07 Jun 2026 18:55:16 +0000</pubDate>
</item>
<item>
<title>Usman Zafar Researcher: Milton. Ontario, Canada</title>
<link>https://coderlegion.com/19117/usman-zafar-researcher-milton-ontario-canada</link>
<description>&lt;p&gt;Over the past several years, I have been building a unified research program focused on one central objective:&lt;/p&gt;
&lt;p&gt;creating engineering-grade foundations for governing, stabilizing, auditing, and understanding advanced AI systems.&lt;/p&gt;
&lt;p&gt;Today, I’m formally sharing the integrated research portfolio of the ZULFR Measurement Institute — spanning AI governance, humanoid robotics, hybrid human–AI systems, observability engineering, and mathematical architectures for reliable AI.&lt;/p&gt;
&lt;p&gt;This research ecosystem has been intentionally structured across archival, implementation, citation, and public research platforms to create a transparent, traceable, and engineering-oriented body of work.&lt;/p&gt;
&lt;p&gt; Official Research Identity&lt;br&gt;
Website: &lt;a rel=&quot;nofollow&quot; href=&quot;http://www.zulfr.com&quot;&gt;www.zulfr.com&lt;/a&gt;&lt;br&gt;
Email: (&lt;em&gt;Emails are not allowed&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt; Research Archives &amp;amp; Publications&lt;br&gt;
Zenodo Research Community:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://zenodo.org/communities/zulfr/records?q=&amp;amp;l=list&amp;amp;p=1&amp;amp;s=10&amp;amp;sort=newest&quot;&gt;https://zenodo.org/communities/zulfr/records?q=&amp;amp;l=list&amp;amp;p=1&amp;amp;s=10&amp;amp;sort=newest&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SSRN Research Papers:&lt;br&gt;
AI Observability &amp;amp; Hallucination Control Engineering&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://dx.doi.org/10.2139/ssrn.6740280&quot;&gt;https://dx.doi.org/10.2139/ssrn.6740280&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hybrid Human–AI Agent Organizations&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://ssrn.com/abstract=6650158&quot;&gt;https://ssrn.com/abstract=6650158&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;AI Governance &amp;amp; System Architecture Foundations&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://dx.doi.org/10.2139/ssrn.6630121&quot;&gt;https://dx.doi.org/10.2139/ssrn.6630121&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; Engineering &amp;amp; Prototyping Workspace&lt;br&gt;
GitHub Research Workshop:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/usman19zafar?tab=repositories&quot;&gt;https://github.com/usman19zafar?tab=repositories&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; Research Profiles&lt;br&gt;
Google Scholar:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://scholar.google.ca/citations?user=UU3lozkAAAAJ&amp;amp;hl=en&quot;&gt;https://scholar.google.ca/citations?user=UU3lozkAAAAJ&amp;amp;hl=en&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ResearchGate:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.researchgate.net/profile/Usman-Zafar-27&quot;&gt;https://www.researchgate.net/profile/Usman-Zafar-27&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; Core Research Themes&lt;/p&gt;
&lt;p&gt;• ZULFR Governance Framework — categorical governance for agentic and embodied AI&lt;/p&gt;
&lt;p&gt;• Humanoid Robotics Control Architectures — structural analysis of modern humanoid cognitive-control stacks&lt;/p&gt;
&lt;p&gt;• AI Observability &amp;amp; Hallucination Control — data-centric stabilization and interpretability engineering&lt;/p&gt;
&lt;p&gt;• Hybrid Human–AI Agent Organizations — mathematical models for future organizational dynamics&lt;/p&gt;
&lt;p&gt;• TRUE-100 / TRUE-10 Reliability Systems — auditable and trustworthy AI behavior architectures&lt;/p&gt;
&lt;p&gt;This portfolio represents a long-term effort to move AI research toward measurable reliability, structural interpretability, and engineering-grade governance.&lt;/p&gt;
&lt;p&gt;I’m especially interested in connecting with researchers, governance engineers, robotics architects, formal systems researchers, and organizations working on advanced AI safety and system reliability.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/19117/usman-zafar-researcher-milton-ontario-canada</guid>
<pubDate>Wed, 27 May 2026 19:29:23 +0000</pubDate>
</item>
<item>
<title>Key Math Concepts in Data Structures and Algorithms</title>
<link>https://coderlegion.com/12467/key-math-concepts-in-data-structures-and-algorithms</link>
<description>&lt;p&gt;At the core of data structures and algorithms are fundamental mathematical principles that guide their design and implementation. This article explores key math concepts essential for mastering data structures and algorithms, helping developers write optimized and effective code.&lt;/p&gt;
&lt;h3 id=&quot;number-systems&quot;&gt;Number Systems&lt;/h3&gt;
&lt;p&gt;A &lt;strong&gt;number system&lt;/strong&gt; is a structured way of representing numbers using specific symbols and rules. Different number systems are based on different &lt;strong&gt;base values&lt;/strong&gt; (also called the &lt;em&gt;radix&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;We are most familiar with the &lt;strong&gt;decimal number system&lt;/strong&gt;, which is used in everyday life. It uses ten digits (&lt;strong&gt;0 through 9&lt;/strong&gt;) to represent all numbers. Because it uses ten distinct digits, its base is &lt;strong&gt;10&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Computers, however, operate using only two digits: &lt;strong&gt;0&lt;/strong&gt; and &lt;strong&gt;1&lt;/strong&gt;. Therefore, they use the &lt;strong&gt;binary number system&lt;/strong&gt;, which has a base of &lt;strong&gt;2&lt;/strong&gt;. All data inside a computer is ultimately stored and processed in binary form.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;octal number system&lt;/strong&gt; uses eight digits (&lt;strong&gt;0 to 7&lt;/strong&gt;) so its base is &lt;strong&gt;8&lt;/strong&gt;. It is used as a more compact way to represent binary numbers, since each octal digit corresponds to a group of &lt;strong&gt;three binary digits (bits)&lt;/strong&gt;. Octal is still used in certain areas of computing, such as &lt;strong&gt;file permissions in Unix and Linux systems&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;hexadecimal number system&lt;/strong&gt; uses sixteen symbols: the digits &lt;strong&gt;0–9&lt;/strong&gt; and the letters &lt;strong&gt;A–F&lt;/strong&gt;. Because it has sixteen symbols, its base is &lt;strong&gt;16&lt;/strong&gt;. Each hexadecimal digit corresponds to a group of &lt;strong&gt;four binary digits&lt;/strong&gt;, making it a convenient way to represent memory addresses, machine code, and other low-level data in computers.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The &lt;strong&gt;octal number system&lt;/strong&gt; has a base of 8, which means it uses eight symbols: 0 to 7.&lt;br&gt;
Since &lt;strong&gt;8 = 2³&lt;/strong&gt;, each octal digit can represent exactly &lt;strong&gt;three binary digits (bits)&lt;/strong&gt;. Same goes for hexadecimal number system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can learn how to convert between these number systems from &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.geeksforgeeks.org/digital-logic/number-system-and-base-conversions/&quot;&gt;this detailed article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, let’s talk about the binary number system. We are familiar with representing positive numbers using unsigned binary. But how do we represent negative numbers? For this, we use the &lt;strong&gt;two’s complement method&lt;/strong&gt;, which is the standard way to represent signed binary numbers.&lt;/p&gt;
&lt;h4 id=&quot;two-s-complement-method&quot;&gt;Two's complement method&lt;/h4&gt;
&lt;p&gt;Negative of any decimal number is mathematically found by subtracting that number from 0. The same applies to the binary number system. In the signed binary number system, the &lt;strong&gt;most significant bit&lt;/strong&gt; (the leftmost bit) indicates the sign of the number.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;See the image below if you are not familiar with the most and least significant bits in the binary representation of a number:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1771301336808/840ccc91-fd56-4047-9041-e1c5f1ed2bab.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let’s take the example of decimal 7 whose binary representation is 0111. Its binary number system is stored in 4 bits. Zero can be represented as 0000 (in 4 bits). In 4-bit representation, if a fifth bit is present in the leftmost position, it is discarded due to lack of space. So, we can represent zero as &lt;strong&gt;1&lt;/strong&gt;&lt;em&gt;0000&lt;/em&gt; (the bit 1 will be discarded). Now, &lt;strong&gt;10000&lt;/strong&gt; can be written as the sum of &lt;strong&gt;1111&lt;/strong&gt; and &lt;strong&gt;1&lt;/strong&gt;. We can then proceed as follows:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1771291657535/9ea48090-ea1d-4a5b-9ff1-fb0d1c51638f.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Essentially, &lt;strong&gt;the negative of a binary number will be its complement added to 1&lt;/strong&gt;. This method is called as the &lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Two%27s_complement&quot;&gt;two’s complement method&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;bitwise-operators&quot;&gt;Bitwise Operators&lt;/h3&gt;
&lt;p&gt;In the decimal number system, we use arithmetic operators like +, -, *, and / to perform mathematical operations. In computing, numbers are represented in binary, and in addition to arithmetic operators, we also use bitwise operators like &amp;amp;, |, ^, ~, &amp;gt;&amp;gt;, and &amp;lt;&amp;lt; to manipulate individual bits. Let’s discuss each of these operators.&lt;/p&gt;
&lt;h4 id=&quot;and-operator-amp-&quot;&gt;AND Operator (&amp;amp;)&lt;/h4&gt;
&lt;p&gt;This operator performs bit-by-bit AND operation on two values. This means that for each bit in the operands, the resulting bit is set to 1 only if both corresponding bits in the operands are 1; otherwise, it is set to 0.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Observation:&lt;/strong&gt; The AND operation of any number with 1 gives the &lt;strong&gt;least significant bit&lt;/strong&gt; (LSB) of that number.&lt;br&gt;
&lt;em&gt;Example&lt;/em&gt;: 5 &amp;amp; 1 results in 1 because 101 &amp;amp; 001 gives its LSB, which is 1.&lt;/p&gt;
&lt;h4 id=&quot;or-operator-&quot;&gt;OR Operator (|)&lt;/h4&gt;
&lt;p&gt;This operator performs a bitwise OR operation between two operands, setting each resulting bit to 1 if at least one of the corresponding bits in the operands is 1; otherwise, it is set to 0.&lt;/p&gt;
&lt;h4 id=&quot;xor-operator-&quot;&gt;XOR Operator (^)&lt;/h4&gt;
&lt;p&gt;XOR stands for &lt;strong&gt;exclusive OR&lt;/strong&gt;. This operator performs a bitwise comparison between two operands, setting each resulting bit to 1 if the corresponding bits in the operands are different; otherwise, it is set to 0.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Observations:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The XOR operation on any number with 1, results in a number where the &lt;strong&gt;least significant bit&lt;/strong&gt; (LSB) is flipped.&lt;br&gt;
&lt;em&gt;Example&lt;/em&gt;: 3 ^ 1 results in 2 because 11 ^ 01 changes the LSB to 0 in this case.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The XOR operation on any number with 0 results in the same number.&lt;br&gt;
&lt;em&gt;Example&lt;/em&gt;: 4 ^ 0 results in 4 because 100 ^ 000 gives 100, which is 4.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The XOR operation on any number with itself results in 0 because there are no differing bits.&lt;br&gt;
&lt;em&gt;Example&lt;/em&gt;: 5 ^ 5 results in 0 because 101 ^ 101 gives 0 as there are no bits that differ.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;complement-operator-&quot;&gt;Complement Operator (~)&lt;/h4&gt;
&lt;p&gt;The complement operator gives the bitwise inverse of a number, flipping each bit from 0 to 1 and from 1 to 0.&lt;/p&gt;
&lt;h4 id=&quot;left-shift-operator-lt-lt-&quot;&gt;Left Shift Operator (&amp;lt;&amp;lt;)&lt;/h4&gt;
&lt;p&gt;The left shift operator is a bitwise operator that shifts the bits of a number to the left by a specified number of positions. &lt;em&gt;Example&lt;/em&gt;: 5 &amp;lt;&amp;lt; 1 gives 10 because shifting the bits of 5 (which is 101 in binary) one position to the left results in 1010, which is 10 in decimal. If we shift twice (5 &amp;lt;&amp;lt; 2), we will get 20 because shifting the bits of 5 (which is 101 in binary) two positions to the left results in 10100, which is 20 in decimal. Therefore, each left shift operation effectively multiplies the number by 2 for each position shifted. In general, if the number is shifted k times, it is multiplied by 2^k.&lt;/p&gt;
&lt;h4 id=&quot;right-shift-operator-gt-gt-&quot;&gt;Right Shift Operator (&amp;gt;&amp;gt;)&lt;/h4&gt;
&lt;p&gt;The right shift operator is a bitwise operator that shifts the bits of a number to the right by a specified number of positions. &lt;em&gt;Example&lt;/em&gt;: 8 &amp;gt;&amp;gt; 1 gives 4 because shifting the bits of 8 (which is 1000 in binary) one position to the right results in 0100, which is 4 in decimal. If we shift twice (8 &amp;gt;&amp;gt; 2), we would get 2 because shifting the bits of 8 (which is 1000 in binary) two positions to the right results in 0010, which is 2 in decimal. Therefore, each right shift operation effectively divides the number by 2 for each position shifted. In general, if the number is shifted k times, it is divided by 2^k.&lt;/p&gt;
&lt;h3 id=&quot;core-number-theory&quot;&gt;Core Number Theory&lt;/h3&gt;
&lt;h4 id=&quot;prime-number&quot;&gt;Prime Number&lt;/h4&gt;
&lt;p&gt;A prime number is a natural number greater than 1 with exactly two positive divisors: 1 and itself. To determine if a number is prime, we typically check divisibility from &lt;strong&gt;2&lt;/strong&gt; up to &lt;strong&gt;n−1&lt;/strong&gt; since it is always divisible by 1 and itself.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;int n = 24;
boolean isPrime = true;
for (int i = 2; i &amp;lt; n; i++) {
    if (n % i == 0) {
        isPrime = false;
        break;
    }
}
if (isPrime) {
    System.out.println(&quot;Prime&quot;);
} else {
    System.out.println(&quot;Not prime&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above algorithm makes a maximum of &lt;strong&gt;n - 2&lt;/strong&gt; (2 to n-1) checks. So, its time complexity is &lt;strong&gt;O(N)&lt;/strong&gt;. Let's see if we can optimise it. If we closely examine the factors of any number, they appear in pairs (one smaller and one larger). Mathematically, we can say that for every divisor d &amp;gt; √n (&lt;em&gt;like d = 6&lt;/em&gt;), there exists a corresponding divisor \(\frac {n} {d} &amp;lt; \sqrt n\) (&lt;em&gt;like 4&lt;/em&gt;). Therefore, checking beyond √n is redundant.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/628869289490454c4d8475de/ae7349e0-0bcf-4d9b-9578-24ffed628d95.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If we look into the above possible pairs of factors of 24, we can see that we're checking divisibility of each pair twice. It is sufficient to check divisibility only up to &lt;strong&gt;√n&lt;/strong&gt; since √24 ≈ 4.89, checking up to 4 is enough. Hence, we can reduce the number of computations from the order of &lt;strong&gt;N&lt;/strong&gt; to &lt;strong&gt;√N&lt;/strong&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;int n = 24;
boolean isPrime = true;
for (int i = 2; i * i &amp;lt;= n; i++) {
    if (n % i == 0) {
        isPrime = false;
        break;
    }
}
if (isPrime) {
    System.out.println(&quot;Prime&quot;);
} else {
    System.out.println(&quot;Not prime&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The time complexity of this algorithm is now &lt;strong&gt;O(√N)&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;prime-numbers-in-range&quot;&gt;Prime Numbers in Range&lt;/h4&gt;
&lt;p&gt;Let's say we need to find prime numbers between two certain numbers. The simplest idea would be to check if &lt;strong&gt;each of the numbers&lt;/strong&gt; between them is &lt;strong&gt;prime&lt;/strong&gt; or not.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class Main {
    public static void main(String[] args) {
        int n = 50;
        displayAllPrimes(n);
    }
    
    public static void displayAllPrimes(int n){
        for (int i = 2; i &amp;lt;= n; i++) {
            if (isPrime(i)) {
                System.out.print(i + &quot; &quot;);
            }
        }
    }
    
    public static boolean isPrime(int n){
        if (n &amp;lt;= 1) return false;
        for (int i = 2; i * i &amp;lt;= n; i++) {
            if (n % i == 0) return false;
        }
        return true;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above program, the &lt;code&gt;isPrime()&lt;/code&gt; method takes &lt;strong&gt;O(√N)&lt;/strong&gt; to check whether a certain number is prime. The &lt;code&gt;displayAllPrimes()&lt;/code&gt; method calls the &lt;code&gt;isPrime()&lt;/code&gt; method approximately &lt;strong&gt;N times&lt;/strong&gt;. So, the time complexity of the entire algorithm is &lt;strong&gt;O(N√N)&lt;/strong&gt;. If we carefully observe the numbers we're checking for prime, we'll notice that there are a number of redundant checks. For example, if we already know that 2 is a prime number then its multiples won't be prime.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/uploads/covers/628869289490454c4d8475de/f43c11cb-83c2-478f-b55b-3871011ccbd8.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Similarly for the rest of the numbers, the below image shows the multiples of smaller prime numbers we've checked earlier.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/uploads/covers/628869289490454c4d8475de/1b7fa69e-cee6-478c-9a2d-72a868e04a6d.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The unmarked numbers turn out to be the &lt;strong&gt;prime numbers&lt;/strong&gt; we're finding in that &lt;strong&gt;range of 2 to 50&lt;/strong&gt;. This is known as the &lt;strong&gt;Sieve of Eratosthenes&lt;/strong&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class Sieve {
    public static void main(String[] args) {
        int n = 50;
        boolean[] isComposites = new boolean[n+1]; // size is n+1 to include n 
        sieve(n, isComposites);
    }

    public static void sieve(int n, boolean[] isComposite){
        for (int i = 2; i * i &amp;lt;= n; i++) {
            if (!isComposite[i]) {
                for (int j = 2 * i; j &amp;lt;= n; j += i) {
                    isComposite[j] = true;
                }
            }
        }

        for (int i = 2; i &amp;lt;= n; i++) {
            if (!isComposite[i]) {
                System.out.print(i + &quot; &quot;);
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the program above, we check for multiples up to &lt;strong&gt;√N&lt;/strong&gt; because large numbers can be factored using smaller numbers' multiples. The number of times the inner loop (the loop responsible for marking the composite numbers) runs for each prime number &lt;strong&gt;P&lt;/strong&gt; is \(\frac {N} {P}\). Therefore, total number of times the inner loop runs will be:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/uploads/covers/628869289490454c4d8475de/3754f281-3094-4dc8-87e1-3ca516c17243.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Hence, the time complexity of this algorithm is &lt;strong&gt;O(N loglog(N))&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;newton-raphson-method&quot;&gt;Newton Raphson Method&lt;/h4&gt;
&lt;p&gt;The Newton Raphson method is an iterative method of finding better approximations to the roots of a real-valued function. The best linear approximation to any differential function near the point \(x = x_i\) will be its tangent with the equation:&lt;br&gt;
&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=14937683237160031269&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;where x_i is the ith iterative approximation of root&lt;/p&gt;
&lt;p&gt;The root of the tangent equation will be the next iterative approximation x_{i+1} when it intercepts the x-axis (y = 0).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/uploads/covers/628869289490454c4d8475de/4a8807a9-24dc-421e-807a-48137df931df.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now, if we want to find the square root of any number (say &lt;strong&gt;n&lt;/strong&gt;), we can take f(x) = x² - n. The root of that equation will give us the closest approximation of &lt;strong&gt;√n&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/uploads/covers/628869289490454c4d8475de/28ed9672-f7a3-4498-96c2-71be6864d2ec.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;You can view &lt;a rel=&quot;nofollow&quot; href=&quot;https://upload.wikimedia.org/wikipedia/commons/e/e0/NewtonIteration_Ani.gif&quot;&gt;this animated image from Wikipedia&lt;/a&gt;, which visually demonstrates all the iteration of approximated roots of f(x).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let's try to write a program for finding the approximate square root of any number.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class NewtonRaphsonSqrt {
    public static void main(String[] args) {
        System.out.println(sqrt(43));
    }

    public static double sqrt(double n) {
        double x = n;
        double root;
        while (true) {
            root = 0.5 * (x + (n/x));

            if (Math.abs(root - x) &amp;lt; 0.5) { // Error threshold, can be adjusted for more precision
                break;
            }
            x = root;
        }
        return root;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reducing the error threshold, currently set at 0.5, will result in a more accurate approximation of the square root.&lt;/p&gt;
&lt;h4 id=&quot;modular-arithmetic&quot;&gt;Modular Arithmetic&lt;/h4&gt;
&lt;p&gt;It is a system of arithmetic operations for integers where the numbers &quot;&lt;em&gt;wrap around&lt;/em&gt;&quot; when exceeding a certain number called as the &lt;strong&gt;modulus&lt;/strong&gt;. For a given integer m ≥ 1, it is called a modulus if the difference of two integers &lt;strong&gt;a&lt;/strong&gt; and &lt;strong&gt;b&lt;/strong&gt; (&lt;em&gt;a - b&lt;/em&gt;) is an integer multiple of &lt;strong&gt;m&lt;/strong&gt; i.e. a - b = k*m (where k is an integer). The integers &lt;strong&gt;a&lt;/strong&gt; and &lt;strong&gt;b&lt;/strong&gt; are said to be congruent modulo m and is mathematically denoted by &lt;strong&gt;a ≡ b (mod m)&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The parentheses mean that (mod &lt;em&gt;m&lt;/em&gt;) applies to the entire equation, not just to the right-hand side (here, &lt;em&gt;b&lt;/em&gt;). In particular, &lt;strong&gt;(&lt;em&gt;a&lt;/em&gt; mod &lt;em&gt;m&lt;/em&gt;) = (&lt;em&gt;b&lt;/em&gt; mod &lt;em&gt;m&lt;/em&gt;)&lt;/strong&gt; is equivalent to &lt;strong&gt;&lt;em&gt;a&lt;/em&gt; ≡ &lt;em&gt;b&lt;/em&gt; (mod &lt;em&gt;m&lt;/em&gt;)&lt;/strong&gt;, and this explains why &quot;=&quot; is often used instead of &quot;≡&quot; in this context.&lt;/p&gt;
&lt;p&gt;The congruence relation is written as *&lt;em&gt;a = b + k\&lt;/em&gt;m**.&lt;/p&gt;
&lt;p&gt;Source: &lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Modular_arithmetic#Congruence&quot;&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In programming, we don’t write congruences directly. Instead, we use the &lt;code&gt;%&lt;/code&gt; operator, which computes the remainder. The &lt;code&gt;%&lt;/code&gt; operator is the practical realization of the congruence relation. For example:  ≡  (mod m) ⇔ (a % m) == (b % m) in code.&lt;/p&gt;
&lt;p&gt;The range of (&lt;strong&gt;a % m&lt;/strong&gt;) is always in the range (&lt;strong&gt;\[0, m-1\]&lt;/strong&gt;) when (m &amp;gt; 0). This ensures the remainder is non-negative, which is crucial for consistent modular arithmetic in programming.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Properties:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Addition Property:&lt;/strong&gt; When adding two numbers, their remainders modulo (m) add up, but if the sum exceeds (m), subtracting (m) (i.e., taking modulo again) brings it back within the valid range.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Subtraction Property:&lt;/strong&gt; Subtraction can lead to negative results, so adding (m) before taking modulo ensures the result stays within (&lt;strong&gt;\[0, m-1\]&lt;/strong&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiplication Property:&lt;/strong&gt; Multiplying the remainders and then taking modulo keeps the product within the modular system, preserving equivalence.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Division Property:&lt;/strong&gt; Division is not straightforward in modular arithmetic. For division by (b) modulo (m) to be valid, (b) must have a modular inverse modulo (m), which exists only if gcd(b, m) = 1.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=16810238809413296304&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Modular multiplicative inverse of an integer b is the solution (which exists only when b and m are coprime) of the equation: ax ≡ 1 (mod m).&lt;/p&gt;
&lt;h4 id=&quot;b-zout-s-identity&quot;&gt;&lt;strong&gt;Bézout's Identity&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;It is a theorem which related two arbitrary integers with their greatest common divisor (GCD). Mathematically,&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/uploads/covers/628869289490454c4d8475de/cbd13049-1d9e-49c5-95be-ae193c53ec55.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;where, x and y are integers.&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;gcd(a, b) = d&lt;/code&gt;, then every integer linear combination &lt;code&gt;ax + by&lt;/code&gt; is a multiple of d.&lt;/p&gt;
&lt;p&gt;For example, if a = 3 and b = 16, then 3*(-5) + 16*1 = 1 = gcd(3, 16).&lt;br&gt;
Let's take another example: a = 8 and b = 18. Then, 8*(-2) + 18*1 = 2 = gcd(8, 18).&lt;/p&gt;
&lt;p&gt;The coefficients x and y can be found using the Extended Euclidean algorithm and the gcd can be calculated using the Euclidean algorithm.&lt;/p&gt;
&lt;h4 id=&quot;euclidean-algorithm&quot;&gt;Euclidean Algorithm&lt;/h4&gt;
&lt;p&gt;The Euclidean Algorithm is one of the oldest and most efficient methods to compute the greatest common divisor (GCD) of two integers. Since Bézout’s identity relies on the GCD, understanding this algorithm is essential. It's based on the principle that if&lt;/p&gt;
&lt;p&gt;Effectively, a is reduced by multiples of b until only the remainder is left. Therefore, gcd(a, b) = gcd(b, a % b).&lt;/p&gt;
&lt;p&gt;Let’s compute &lt;strong&gt;gcd(514, 106)&lt;/strong&gt; using the Euclidean Algorithm.&lt;/p&gt;
&lt;p&gt;We start by dividing the larger number by the smaller one and continue replacing the pair with (b, a % b) until the remainder becomes zero:&lt;/p&gt;
&lt;p&gt;514 = 106*4 + 90 → gcd(514, 106) = gcd(106, 90) &lt;br&gt;
106 = 90*1 + 16 → gcd(106, 90) = gcd(90, 16) &lt;br&gt;
90 = 16*5 + 10 → gcd(90, 16) = gcd(16, 10) &lt;br&gt;
16 = 10*1 + 6 → gcd(16,10) = gcd(10, 6) &lt;br&gt;
10 = 6*1 + 4 → gcd(10, 6) = gcd(6, 4) &lt;br&gt;
6 = 4*1 + 2 → gcd(6, 4) = gcd(4, 2) &lt;br&gt;
4 = 2*2 + 0 → gcd(4, 2) = 2 &lt;/p&gt;
&lt;p&gt;Therefore, gcd(514, 106) = 2.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public static int gcd(int a, int b) {
    if (a == 0) {
        return b;
    }
    return gcd(b % a, a);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also calculate the LCM of two numbers using their GCD with the formula:&lt;br&gt;
\[\text{LCM}(a, b) = \frac{|a \times b|}{\text{GCD}(a, b)}\]&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public static int lcm(int a, int b) {
    return a * b / gcd(a, b);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;extended-euclidean-algorithm&quot;&gt;Extended Euclidean Algorithm&lt;/h4&gt;
&lt;p&gt;This algorithm is an extension of the Euclidean Algorithm which computes the coefficients of the Bézout's identity. We start with the gcd of the two numbers and eventually represent that as a linear combination of those two numbers.&lt;/p&gt;
&lt;p&gt;For example, we have found &lt;strong&gt;gcd(514, 106) = 2&lt;/strong&gt;. We start with the last non-zero remainder step: 6 = 4 + 2 ⇒ 2 = 6 - 4.&lt;br&gt;
Then, from previous steps, we can write &lt;strong&gt;6 = 16 - 10&lt;/strong&gt; and &lt;strong&gt;4 = 10 - 6&lt;/strong&gt;. We'll back-substitute them in the above equation.&lt;br&gt;
∴ 2 = (16-10) - (10 - 6) = 16 - 2*10 + 6 = 16 - 2*10 + (16 - 10) = 2*16 - 3*10&lt;br&gt;
∴ 2 = 2*16 - 3*(90 - 16*5) = 17*16 - 3*90 &lt;br&gt;
∴ 2 = 17*(106 - 90) - 3*90 = 17*106 - 20*90  &lt;br&gt;
∴ 2 = 17*106 - 20*(514 - 4*106) = (-20)*514 + 97*106&lt;/p&gt;
&lt;p&gt;Hence, (-20)*514 + 97*106 = 2 = gcd(514, 106). So, the coefficients (&lt;strong&gt;Bézout's coefficients&lt;/strong&gt;) of Bézout's identity would be &lt;strong&gt;-20&lt;/strong&gt; and &lt;strong&gt;97&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We can utilise the recursion stack to keep track of the steps performed in Euclidean Algorithm. Below is the code for this algorithm:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;static int gcdExtended(int a, int b, int[] xy) {
    if (a == 0) {
        xy[0] = 0; // x
        xy[1] = 1; // y
        return b;
    }

    int[] temp = new int[2];
    int gcd = gcdExtended(b % a, a, temp);

    // Update x and y using results of recursion
    xy[0] = temp[1] - (b / a) * temp[0];
    xy[1] = temp[0];

    return gcd;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In this article, we explored fundamental mathematical concepts that are crucial for understanding and implementing data structures and algorithms. We delved into number systems, including binary, octal, and hexadecimal, and discussed how computers represent numbers using the two's complement method for signed integers. We also covered bitwise operators and their applications in manipulating individual bits of data.&lt;/p&gt;
&lt;p&gt;⭐ Check out the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/SaptarshiSarkar12/DSA&quot;&gt;DSA&lt;/a&gt; GitHub repo for more code examples.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/12467/key-math-concepts-in-data-structures-and-algorithms</guid>
<pubDate>Sat, 07 Mar 2026 23:13:34 +0000</pubDate>
</item>
<item>
<title>Copiloting with AI: Learning with Founderz and ChatGPT</title>
<link>https://coderlegion.com/10916/copiloting-with-ai-learning-with-founderz-and-chatgpt</link>
<description>&lt;p&gt;In our daily lives, we constantly face barriers when trying to implement good ideas, often due to a lack of technical knowledge and the time needed to figure out where to start. The AI models available today have brought about a revolution in this regard, accelerating timelines and removing learning obstacles. Thanks to these models, we can do more in less time and delve into highly complex fields like programming, allowing us to bring simple applications that implement good ideas to life.&lt;/p&gt;
&lt;p&gt;In this context, I recently completed the &lt;strong&gt;Introduction to AI and Prompt Engineering course by Founderz&lt;/strong&gt;, which is no longer available though you can find more similar courses in their website (&lt;a rel=&quot;nofollow&quot; href=&quot;https://founderz.com/&quot;&gt;https://founderz.com/&lt;/a&gt;), taught by Pau García-Millá (Founder and Co-CEO of Founderz), Anna Cejudo (Founder and Co-CEO of Founderz), and Magda Teruel (Client Account Manager at Microsoft). It was easy to follow, very educational, well-structured, and it truly made an impact, offering glimpses of what can be achieved with AI through brief and effective instructions.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://datalaria.com/en/posts/founderz-coding-chatgpt/Founderz_AI_Introduction.png&quot; alt=&quot;Imagen del curso de Introducción a la IA Founderz&quot;&gt;&lt;/p&gt;
&lt;p&gt;The course consisted of short videos, between 5 and 15 minutes long, that explained and developed the idea of AI models as &quot;Copilots&quot; in our daily lives. Pau, Anna, and Magda presented examples of how to &quot;talk&quot; to these &quot;Copilots&quot; and how to use them in our day-to-day tasks, showing some advanced use cases and practical examples of how to turn our project ideas into web applications without knowing how to program, thanks to the good work of our &quot;Copilots.&quot; To finish, they proposed that you try creating a basic project yourself with these models based on what you've learned, providing a very interesting feedback mechanism from both themselves and other students.&lt;/p&gt;
&lt;p&gt;Besides recommending this kind of courses to anyone who wants to get started with AI models and learn more about having these &quot;Copilots,&quot; I'm going to use this post to illustrate one of the key takeaways from the course, focusing on how to create a functional application through a simple conversation with ChatGPT and the right instructions.&lt;/p&gt;
&lt;h4 id=&quot;the-aha-moment-of-the-founderz-course&quot;&gt;The &quot;Aha!&quot; Moment of the Founderz Course&lt;/h4&gt;
&lt;p&gt;The Founderz course was tremendously educational, and its greatest lesson was presenting AI (in this case, Copilot and ChatGPT) not just as a simple search assistant but as a &lt;strong&gt;creation partner (a copilot)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The clearest example of this copilotage is how a language model can help us create structured and functional code from an initial idea through a series of simple instructions. Through several practical cases, it teaches how to create self-contained web applications in a single HTML file, unleashing our ideas to improve our daily lives.&lt;/p&gt;
&lt;h4 id=&quot;the-challenge-creating-a-useful-tool-from-scratch-with-chatgpt&quot;&gt;The Challenge: Creating a Useful Tool from Scratch with ChatGPT&lt;/h4&gt;
&lt;p&gt;To put this skill to the test, we're going to create a &lt;strong&gt;learning game for basic math operations aimed at preschool and elementary school children between 5 and 7 years old&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The goal was simple: a webpage that would teach and allow practice of basic mathematical operations (addition, subtraction, multiplication, and division) by learning levels, making it engaging for users.&lt;/p&gt;
&lt;h4 id=&quot;the-recipe-the-detailed-prompt-and-its-refinement-is-key&quot;&gt;The Recipe: The Detailed Prompt (and its Refinement) is Key&lt;/h4&gt;
&lt;p&gt;This is where &lt;em&gt;Prompt Engineering&lt;/em&gt; comes into play. It's not about asking ChatGPT to &quot;make me an app,&quot; but about acting as a product manager who gives the development team (the AI) clear and detailed specifications.&lt;/p&gt;
&lt;h5 id=&quot;the-initial-prompt&quot;&gt;The Initial Prompt&lt;/h5&gt;
&lt;p&gt;This was the first prompt I used, inspired by the course's methodology, where I defined the entire structure and functionality I wanted (I encourage anyone to experiment and reproduce it themselves on ChatGPT):&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Create a simple web application to practice basic math functions: addition, subtraction, multiplication, and division. The goal is to create a simple application that makes it easier for preschool and elementary school children (between 5 and 7 years old) to learn these operations. The application must:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start with a learning page that explains the 4 mathematical operations.&lt;/li&gt;
&lt;li&gt;Allow the selection of a learning level from 4 levels (preschool 1 &amp;amp; 2, elementary 1 &amp;amp; 2).&lt;/li&gt;
&lt;li&gt;Allow the selection of a difficulty level (easy with 1 digit, hard with 2).&lt;/li&gt;
&lt;li&gt;Have a &quot;Start Game&quot; button that leads to a screen with operations.&lt;/li&gt;
&lt;li&gt;Check if the answer is correct and display a motivating message and an emoticon.&lt;/li&gt;
&lt;li&gt;Keep track of correct and incorrect answers.&lt;/li&gt;
&lt;li&gt;Have an attractive and responsive design using Tailwind CSS.&lt;/li&gt;
&lt;li&gt;Include all HTML, CSS, and JavaScript code in a single file.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;ChatGPT processed the request and, in seconds, returned a single block of code containing a fully functional application.&lt;/p&gt;
&lt;h5 id=&quot;the-refinement-the-conversation-continues&quot;&gt;The Refinement: The Conversation Continues&lt;/h5&gt;
&lt;p&gt;The first result worked quite well, but there's always room for improvement . This is where the true power of conversational AI lies: the ability to iterate and improve thanks to the coherence it can maintain in its results. As a test, I asked for a series of changes to make the application more dynamic and attractive:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;It works! Now I want you to make the following changes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Edit the design to be more attractive with gradient colors and nicer fonts.&lt;/li&gt;
&lt;li&gt;Add a 10-second countdown for each operation and a scoring system.&lt;/li&gt;
&lt;li&gt;Once the answer is submitted, show the correct/incorrect message for 3 seconds and then move to the next operation.&lt;/li&gt;
&lt;li&gt;Display the total score at all times.&lt;/li&gt;
&lt;li&gt;After 10 operations, show the final result.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Write the complete code again.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And as if by magic, the AI integrated all the improvements and provided me with the final, polished code. You can see the full conversation and the result here: &lt;strong&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chatgpt.com/share/68b5fa88-be78-8004-8d93-612409d559f5&quot;&gt;Math App Prompt on ChatGPT&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;the-magic-your-app-running-in-30-seconds&quot;&gt;The &quot;Magic&quot;: Your App Running in 30 Seconds&lt;/h4&gt;
&lt;p&gt;This is the most rewarding part. To run the application we just created, just follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Open a plain text editor&lt;/strong&gt; (like Notepad on Windows or TextEdit on Mac).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Paste the complete code&lt;/strong&gt; provided by ChatGPT.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Save the file&lt;/strong&gt; with any name you like, but make sure the extension is &lt;code&gt;.html&lt;/code&gt; (for example: &lt;code&gt;math-game.html&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Double-click the saved file.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And that's it! The file will open in your web browser, and you'll have a fully functional educational application, created by you and your AI copilot.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://datalaria.com/en/posts/founderz-coding-chatgpt/app_maths_chatgpt.png&quot; alt=&quot;App screenshot showing math game&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;conclusion-and-next-steps&quot;&gt;Conclusion and Next Steps&lt;/h4&gt;
&lt;p&gt;This experience demonstrates the incredible democratization that AI is bringing to the world of digital creation. It is no longer essential to be an expert programmer to build simple and useful tools. What is now crucial is the ability to &lt;strong&gt;think in a structured way and give clear instructions&lt;/strong&gt;, the essence of &lt;em&gt;Prompt Engineering&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This method is incredibly fast for creating and testing tools. But how can we take it a step further and publish this application so that anyone in the world can use it?&lt;/p&gt;
&lt;p&gt;We'll talk about that in one of our next posts, where we'll explore the creation process with &lt;strong&gt;Gemini's Code Canvas&lt;/strong&gt; and its public deployment using &lt;strong&gt;GitHub Pages&lt;/strong&gt;. In the meantime, for those who haven't been trying it out in parallel, you can see the result created here: &lt;a rel=&quot;nofollow&quot; href=&quot;https://datalaria.com/apps/maths/&quot;&gt;My math app for kids created with ChatGPT&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h5 id=&quot;sources-and-resources-&quot;&gt;Sources and Resources:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Founderz&lt;/strong&gt;: &lt;a rel=&quot;nofollow&quot; href=&quot;https://founderz.com/&quot;&gt;Official site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenAI&lt;/strong&gt;: &lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/&quot;&gt;ChatGPT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;App's Page&lt;/strong&gt;: &lt;a rel=&quot;nofollow&quot; href=&quot;https://datalaria.com/apps/maths&quot;&gt;My math app for kids created with ChatGPT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/10916/copiloting-with-ai-learning-with-founderz-and-chatgpt</guid>
<pubDate>Mon, 02 Feb 2026 06:49:51 +0000</pubDate>
</item>
<item>
<title>Inside Netflix’s $1 Billion Algorithm - How Recommendations Predict Your Next Binge</title>
<link>https://coderlegion.com/4669/inside-netflixs-1-billion-algorithm-how-recommendations-predict-your-next-binge</link>
<description>&lt;h3 id=&quot;ever-wonder-how-netflix-reads-your-mind-the-secret-is-out-&quot;&gt;Ever Wonder How Netflix Reads Your Mind? The Secret is Out.&lt;/h3&gt;
&lt;p&gt;Imagine finishing a show, and Netflix instantly suggests your next obsession. Magic? Coincidence? Neither. It's the silent symphony of algorithms, orchestrated to understand your viewing DNA. At its heart: &lt;strong&gt;Matrix Factorization&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This isn't just tech talk. It's your invitation to demystify the system that saves Netflix over a billion dollars annually and shapes entertainment. We'll simplify complex ideas, revealing the 'how' and 'why' behind this multi-billion dollar engine. Get ready to discover the secrets that make Netflix feel like it knows you better than you know yourself. Your mind-reading journey begins now.&lt;/p&gt;
&lt;p&gt;Netflix's algorithms analyze every click, pause, and genre to build your unique profile. This deep understanding transforms a vast library into a bespoke storefront, preventing 'analysis paralysis' and guiding you effortlessly through cinematic choices.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=18113584764523519932&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/codeverseproo/Demo-Codes/tree/master/netflix&quot;&gt;Clone the repository with all working codes and demonstration for preacticle overview&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;part-i-the-netflix-revolution---from-dvds-to-data-dominance&quot;&gt;Part I: The Netflix Revolution - From DVDs to Data Dominance&lt;/h3&gt;
&lt;h4 id=&quot;1-the-billion-dollar-algorithm-that-reads-your-mind&quot;&gt;1. The Billion-Dollar Algorithm That Reads Your Mind&lt;/h4&gt;
&lt;p&gt;Netflix's journey from DVD rentals to streaming giant is a testament to data leverage. Their recommendation system saves over &lt;strong&gt;$1 billion annually&lt;/strong&gt; by reducing churn and boosting engagement. This highlights the immense business value of algorithmic prowess.&lt;/p&gt;
&lt;h5 id=&quot;the-1-million-prize-that-changed-everything&quot;&gt;The $1 Million Prize That Changed Everything&lt;/h5&gt;
&lt;p&gt;In 2006, Netflix launched the &lt;strong&gt;Netflix Prize&lt;/strong&gt;, offering &lt;strong&gt;$1 million&lt;/strong&gt; to improve their Cinematch system by 10% . This sparked a global research frenzy, popularizing &lt;strong&gt;Matrix Factorization&lt;/strong&gt; and reshaping data science. It proved the power of collective intelligence in solving complex problems.&lt;/p&gt;
&lt;h5 id=&quot;why-15-000-movies-analysis-paralysis&quot;&gt;Why 15,000+ Movies = Analysis Paralysis&lt;/h5&gt;
&lt;p&gt;With tens of thousands of titles, Netflix needs to guide users. Without algorithms, the sheer volume leads to 'analysis paralysis.' The recommendation system acts as an intelligent filter, curating a personalized, relevant, and effortlessly discoverable experience.&lt;/p&gt;
&lt;h3 id=&quot;part-ii-matrix-math-made-visual---the-language-of-recommendations&quot;&gt;Part II: Matrix Math Made Visual - The Language of Recommendations&lt;/h3&gt;
&lt;h4 id=&quot;4-matrices-the-fundamental-language-of-netflix&quot;&gt;4. Matrices: The Fundamental Language of Netflix&lt;/h4&gt;
&lt;p&gt;At the heart of Netflix’s recommendations is the &lt;strong&gt;matrix&lt;/strong&gt;: a structured grid of numbers. In Netflix, matrices paint a picture of user preferences and movie attributes, forming the data foundation for predicting tastes.&lt;/p&gt;
&lt;h5 id=&quot;the-user-item-matrix-your-viewing-fingerprint&quot;&gt;The User-Item Matrix: Your Viewing Fingerprint&lt;/h5&gt;
&lt;p&gt;Imagine a giant spreadsheet: rows are users, columns are movies. Cells contain your rating. Empty cells mean you haven't watched it. This is the &lt;strong&gt;User-Item Matrix&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=1110183521069125168&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h5 id=&quot;the-sparsity-problem-the-vast-emptiness&quot;&gt;The Sparsity Problem: The Vast Emptiness&lt;/h5&gt;
&lt;p&gt;Netflix has millions of users and thousands of titles. Most cells in the User-Item Matrix are empty – this is the &lt;strong&gt;sparsity problem&lt;/strong&gt;. It's hard to recommend when data is missing. Matrix Factorization solves this by finding hidden patterns.&lt;/p&gt;
&lt;h4 id=&quot;5-the-hidden-factors-revolution-unveiling-latent-desires&quot;&gt;5. The Hidden Factors Revolution: Unveiling Latent Desires&lt;/h4&gt;
&lt;p&gt;To beat sparsity, recommendation systems uncover &lt;strong&gt;hidden factors&lt;/strong&gt; or &lt;strong&gt;latent features&lt;/strong&gt;. These aren't obvious categories, but abstract dimensions of taste learned from data. For you, a factor might be 'love for dark humor.' For a movie, it's how much it embodies that. By mapping users and movies to these factors, Netflix finds deep similarities, even with scarce ratings. It's like understanding your cinematic soul.&lt;/p&gt;
&lt;h4 id=&quot;6-matrix-factorization-the-algorithmic-engine-of-prediction&quot;&gt;6. Matrix Factorization: The Algorithmic Engine of Prediction&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Matrix Factorization&lt;/strong&gt; breaks the huge, sparse User-Item Matrix (R) into two smaller, dense matrices:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;User-Feature Matrix (P):&lt;/strong&gt; Your personal taste profile across hidden factors.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Movie-Feature Matrix (Q):&lt;/strong&gt; The movie's 'DNA' in terms of hidden factors.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://ucarecdn.com/2fdd1293-6784-42ae-8ed7-2f810ee0e1b6/-/preview/1000x666/&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Multiplying your row from P by a movie's column from Q gives a predicted rating, even if you haven't seen it! We find the best P and Q using &lt;strong&gt;Stochastic Gradient Descent (SGD)&lt;/strong&gt;. We start with random numbers, predict, calculate error, and nudge P and Q to reduce that error. Millions of repetitions later, our matrices accurately predict your next favorite show. It's a continuous learning loop.&lt;/p&gt;
&lt;h3 id=&quot;part-iii-code-your-own-netflix---from-theory-to-your-screen&quot;&gt;Part III: Code Your Own Netflix - From Theory to Your Screen&lt;/h3&gt;
&lt;p&gt;Let's build a simplified Netflix recommender in Python. Our goal: make the algorithm &lt;em&gt;click&lt;/em&gt; for you.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/codeverseproo/Demo-Codes/tree/master/netflix&quot;&gt;Clone the repository with all working codes and demonstration for preacticle overview&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;7-building-the-foundation-data-representation-and-initialization&quot;&gt;7. Building the Foundation: Data Representation and Initialization&lt;/h4&gt;
&lt;p&gt;We'll use a small dataset of user ratings. Our &lt;code&gt;ratings&lt;/code&gt; dictionary captures the sparsity:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Our simplified user-movie rating data: {user_id: {movie_id: rating}}
ratings = {
    0: {0: 5, 1: 3, 2: 4},          # Alice hasn't rated movie 3
    1: {0: 4, 1: 2, 2: 5},          # Bob hasn't rated movie 3
    2: {1: 4, 2: 2, 3: 5},          # Charlie hasn't rated movie 0
    3: {0: 2, 1: 5, 3: 4},          # David hasn't rated movie 2
    4: {0: 3, 2: 3}                 # Eve hasn't rated movies 1 &amp;amp; 3
}

movies = {
    0: &quot;The Action Hero&quot;,
    1: &quot;Romantic Comedy&quot;,
    2: &quot;Sci-Fi Epic&quot;,
    3: &quot;Drama Thriller&quot;,
}

users = {
    0: &quot;Alice&quot;,
    1: &quot;Bob&quot;,
    2: &quot;Charlie&quot;,
    3: &quot;David&quot;,
    4: &quot;Eve&quot;,
}

print(&quot;--- Our Sample Ratings Data ---&quot;)
for user_id, user_ratings in ratings.items():
    user_name = users[user_id]
    print(f&quot;User {user_name} (ID: {user_id}):&quot;)
    for movie_id, rating in user_ratings.items():
        movie_title = movies[movie_id]
        print(f&quot;  - {movie_title}: {rating} stars&quot;)
print(&quot;-------------------------------&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we initialize our User-Feature (P) and Movie-Feature (Q) matrices with random numbers. &lt;code&gt;num_factors&lt;/code&gt; defines how many hidden dimensions we'll discover.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import numpy as np

num_factors = 2 # How many 'hidden' characteristics to discover
num_users = len(ratings)
num_movies = len(movies)

P = np.random.rand(num_users, num_factors) # User-Feature Matrix
Q = np.random.rand(num_movies, num_factors) # Movie-Feature Matrix

print(f&quot;\n--- Initialized Matrices (Our Blank Slate) ---&quot;)
print(f&quot;User-Feature Matrix (P) shape: {P.shape}\n{P}&quot;)
print(f&quot;\nMovie-Feature Matrix (Q) shape: {Q.shape}\n{Q}&quot;)
print(&quot;--------------------------&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;8-the-training-pipeline-teaching-the-algorithm-to-predict&quot;&gt;8. The Training Pipeline: Teaching the Algorithm to Predict&lt;/h4&gt;
&lt;p&gt;We train our model using &lt;strong&gt;Stochastic Gradient Descent (SGD)&lt;/strong&gt;. For each known rating, we predict, calculate the error, and nudge P and Q to reduce that error. This iterative process, repeated over many 'epochs,' optimizes our matrices.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;learning_rate = 0.01 # How big of a 'nudge'
num_epochs = 50      # How many times to go through the dataset

print(&quot;\n--- Starting Training (Teaching the Algorithm) ---&quot;)

for epoch in range(num_epochs):
    total_absolute_error = 0
    for user_id, user_ratings in ratings.items():
        for movie_id, actual_rating in user_ratings.items():
            predicted_rating = np.dot(P[user_id, :], Q[movie_id, :])
            error = actual_rating - predicted_rating
            total_absolute_error += abs(error)

            P[user_id, :] += learning_rate * error * Q[movie_id, :]
            Q[movie_id, :] += learning_rate * error * P[user_id, :]

    if (epoch + 1) % 10 == 0:
        print(f&quot;Epoch {epoch + 1}/{num_epochs}, Total Absolute Error: {total_absolute_error:.4f}&quot;)

print(&quot;\n--- Training Complete! Our Algorithm Has Learned! ---&quot;)

print(f&quot;\nRefined User-Feature Matrix (P):\n{P}&quot;)
print(f&quot;\nRefined Movie-Feature Matrix (Q):\n{Q}&quot;)
print(&quot;--------------------------&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After training, &lt;code&gt;P&lt;/code&gt; and &lt;code&gt;Q&lt;/code&gt; capture your viewing patterns. The &lt;code&gt;total_absolute_error&lt;/code&gt; shrinks, showing our model getting smarter.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ucarecdn.com/395c6ab2-f531-4007-8db6-16a452748d68/-/preview/805x982/&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;9-advanced-implementation-patterns-bias-terms-and-regularization&quot;&gt;9. Advanced Implementation Patterns: Bias Terms and Regularization&lt;/h4&gt;
&lt;p&gt;Real-world systems add &lt;strong&gt;Bias Terms&lt;/strong&gt; and &lt;strong&gt;Regularization&lt;/strong&gt; for smarter, more robust models.&lt;/p&gt;
&lt;h5 id=&quot;bias-terms-accounting-for-your-quirks-and-a-movie-s-appeal&quot;&gt;Bias Terms: Accounting for Your Quirks and a Movie’s Appeal&lt;/h5&gt;
&lt;p&gt;Some users rate higher, some lower. Some movies are universally loved. &lt;strong&gt;Bias terms&lt;/strong&gt; account for these tendencies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Global Mean :&lt;/strong&gt; Average rating of all movies by all users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User Bias :&lt;/strong&gt; How much &lt;em&gt;you&lt;/em&gt; rate above/below average.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Movie Bias :&lt;/strong&gt; How much a &lt;em&gt;movie&lt;/em&gt; is rated above/below average.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These biases are learned during training, significantly improving accuracy.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;global_mean = np.mean([rating for user_ratings in ratings.values() for rating in user_ratings.values()])
user_biases = np.zeros(num_users)
movie_biases = np.zeros(num_movies)

learning_rate_bias = 0.005
num_epochs_bias = 100

P_biased = P.copy()
Q_biased = Q.copy()

print(&quot;\n--- Starting Training with Bias Terms (Getting Even Smarter!) ---&quot;)

for epoch in range(num_epochs_bias):
    total_absolute_error_biased = 0
    for user_id, user_ratings in ratings.items():
        for movie_id, actual_rating in user_ratings.items():
            predicted_rating_biased = global_mean + user_biases[user_id] + movie_biases[movie_id] + \
                                      np.dot(P_biased[user_id, :], Q_biased[movie_id, :])

            error_biased = actual_rating - predicted_rating_biased
            total_absolute_error_biased += abs(error_biased)

            P_biased[user_id, :] += learning_rate * error_biased * Q_biased[movie_id, :]
            Q_biased[movie_id, :] += learning_rate * error_biased * P_biased[movie_id, :]
            user_biases[user_id] += learning_rate_bias * error_biased
            movie_biases[movie_id] += learning_rate_bias * error_biased

    if (epoch + 1) % 20 == 0:
        print(f&quot;Epoch {epoch + 1}/{num_epochs_bias}, Total Absolute Error (with biases): {total_absolute_error_biased:.4f}&quot;)

print(&quot;\n--- Training with Bias Terms Complete! ---&quot;)

print(f&quot;\nRefined User-Feature Matrix (P) with Biases:\n{P_biased}&quot;)
print(f&quot;\nRefined Movie-Feature Matrix (Q) with Biases:\n{Q_biased}&quot;)
print(f&quot;\nUser Biases:\n{user_biases}&quot;)
print(f&quot;\nMovie Biases:\n{movie_biases}&quot;)
print(&quot;--------------------------&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://ucarecdn.com/86f4da31-9843-4ad5-9212-75cb0fe88879/-/preview/1000x858/&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h5 id=&quot;regularization-preventing-over-memorizing&quot;&gt;Regularization: Preventing Over-Memorizing&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;Regularization&lt;/strong&gt; prevents &lt;strong&gt;overfitting&lt;/strong&gt; (memorizing data instead of learning patterns). It adds a penalty during training, keeping &lt;code&gt;P&lt;/code&gt; and &lt;code&gt;Q&lt;/code&gt; values small. This forces the model to find simpler, more general patterns, improving predictions on new data.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;reg_lambda = 0.1 # Strength of the penalty

P_reg = np.random.rand(num_users, num_factors)
Q_reg = np.random.rand(num_movies, num_factors)
user_biases_reg = np.zeros(num_users)
movie_biases_reg = np.zeros(num_movies)

print(&quot;\n--- Starting Training with Bias Terms and Regularization (The Final Polish!) ---&quot;)

for epoch in range(num_epochs_bias):
    total_absolute_error_reg = 0
    for user_id, user_ratings in ratings.items():
        for movie_id, actual_rating in user_ratings.items():
            predicted_rating_reg = global_mean + user_biases_reg[user_id] + movie_biases_reg[movie_id] + \
                                   np.dot(P_reg[user_id, :], Q_reg[movie_id, :])

            error_reg = actual_rating - predicted_rating_reg
            total_absolute_error_reg += abs(error_reg)

            P_reg[user_id, :] += learning_rate * (error_reg * Q_reg[movie_id, :] - reg_lambda * P_reg[user_id, :])
            Q_reg[movie_id, :] += learning_rate * (error_reg * P_reg[movie_id, :] - reg_lambda * Q_reg[movie_id, :])
            user_biases_reg[user_id] += learning_rate_bias * (error_reg - reg_lambda * user_biases_reg[user_id])
            movie_biases_reg[movie_id] += learning_rate_bias * (error_reg - reg_lambda * movie_biases_reg[movie_id])

    if (epoch + 1) % 20 == 0:
        print(f&quot;Epoch {epoch + 1}/{num_epochs_bias}, Total Absolute Error (with biases &amp;amp; reg): {total_absolute_error_reg:.4f}&quot;)

print(&quot;\n--- Training with Bias Terms and Regularization Complete! ---&quot;)

print(f&quot;\nRefined User-Feature Matrix (P) with Biases &amp;amp; Reg:\n{P_reg}&quot;)
print(f&quot;\nRefined Movie-Feature Matrix (Q) with Biases &amp;amp; Reg:\n{Q_reg}&quot;)
print(f&quot;\nUser Biases (Regularized):\n{user_biases_reg}&quot;)
print(f&quot;\nMovie Biases (Regularized):\n{movie_biases_reg}&quot;)
print(&quot;--------------------------&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://ucarecdn.com/16389047-1188-4c0a-bd3d-c8b2f3eefd7a/-/preview/1000x715/&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Regularization ensures our model learns general patterns, performing better on new movies.&lt;/p&gt;
&lt;h3 id=&quot;sidebar-hash-tables---the-unsung-hero-of-millisecond-scale&quot;&gt;Sidebar: Hash Tables - The Unsung Hero of Millisecond Scale&lt;/h3&gt;
&lt;p&gt;While Matrix Factorization is the brain, &lt;strong&gt;Hash Tables&lt;/strong&gt; are the unsung heroes ensuring predictions reach 230 million users in milliseconds. They're fundamental data structures for lightning-fast data storage and retrieval.&lt;/p&gt;
&lt;h4 id=&quot;what-is-a-hash-table-&quot;&gt;What is a Hash Table?&lt;/h4&gt;
&lt;p&gt;A hash table maps keys to values using a &lt;strong&gt;hash function&lt;/strong&gt; to generate an index for direct, quick access. Imagine a magical librarian instantly telling you the exact shelf number for any book.&lt;/p&gt;
&lt;h4 id=&quot;why-are-hash-tables-crucial-for-netflix-&quot;&gt;Why are Hash Tables Crucial for Netflix?&lt;/h4&gt;
&lt;p&gt;Netflix needs extreme speed for user profiles, movie data, and recommendations. Hash tables provide:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Blazing Fast Lookups (O(1) Average):&lt;/strong&gt; Instant retrieval regardless of data size. Critical for real-time recommendations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Efficient Caching:&lt;/strong&gt; Backbone of caching, allowing instant fetching of pre-computed recommendations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Session Management:&lt;/strong&gt; Quick access to user session info for seamless experience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Distributed Systems:&lt;/strong&gt; Efficiently distribute data across servers, minimizing latency.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;interactive-performance-comparison-hash-table-vs-list-search&quot;&gt;Interactive Performance Comparison: Hash Table vs. List Search&lt;/h4&gt;
&lt;p&gt;Compare the speed of a Python dictionary (hash table) vs. a list search:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import time
import random

print(&quot;\n--- List Search Performance ---&quot;)
large_list = list(range(1_000_000))
search_item_list = random.choice(large_list)

start_time = time.time()
found_list = search_item_list in large_list
end_time = time.time()
print(f&quot;Searching for {search_item_list} in a list of {len(large_list)} items:&quot;)
print(f&quot;Found: {found_list}, Time taken: {(end_time - start_time):.6f} seconds&quot;)

print(&quot;\n--- Dictionary (Hash Table) Lookup Performance ---&quot;)
large_dict = {i: f&quot;Value_{i}&quot; for i in range(1_000_000)}
search_key_dict = random.choice(list(large_dict.keys()))

start_time = time.time()
found_dict = search_key_dict in large_dict
end_time = time.time()
print(f&quot;Looking up key {search_key_dict} in a dictionary of {len(large_dict)} items:&quot;)
print(f&quot;Found: {found_dict}, Time taken: {(end_time - start_time):.6f} seconds&quot;)
print(&quot;--------------------------------------------------&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://ucarecdn.com/c90bbf61-ef65-4633-b7fa-d34ad67a6a44/-/preview/1000x530/&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Running this shows dictionary lookups are orders of magnitude faster. This speed is why hash tables are vital for Netflix's scale.&lt;/p&gt;
</description>
<category>Python</category>
<guid isPermaLink="true">https://coderlegion.com/4669/inside-netflixs-1-billion-algorithm-how-recommendations-predict-your-next-binge</guid>
<pubDate>Wed, 13 Aug 2025 04:04:35 +0000</pubDate>
</item>
<item>
<title>⚽ Can We Predict the Next Premier League Champion with Binomial Probability?</title>
<link>https://coderlegion.com/4490/can-we-predict-the-next-premier-league-champion-with-binomial-probability</link>
<description>&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;What are the chances your favorite EPL team wins the league next season? Time to let math do the talking!&lt;/em&gt; &lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;idea-behind-the-madness&quot;&gt;Idea Behind the Madness&lt;/h3&gt;
&lt;p&gt;Every football fan has asked it:&lt;br&gt;
&lt;strong&gt;&quot;Can my team win the league next season?&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Instead of relying on blind hope, I decided to use &lt;strong&gt;binomial probability&lt;/strong&gt; to calculate each team's chances of taking the crown in the next Premier League season, based entirely on how they performed last time.&lt;/p&gt;
&lt;p&gt;We’ll:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fetch last season’s final standings from an API.&lt;/li&gt;
&lt;li&gt;Use binomial distribution to simulate two things:&lt;ul&gt;
&lt;li&gt;The probability of a team repeating its exact win total.&lt;/li&gt;
&lt;li&gt;The probability of a team reaching the typical &lt;strong&gt;championship threshold&lt;/strong&gt; which is ≈27.6 so &lt;strong&gt;28 wins&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Rank them accordingly.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;-step-1-fetching-epl-data-using-an-api&quot;&gt;️ Step 1: Fetching EPL Data Using an API&lt;/h3&gt;
&lt;p&gt;I used the &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.football-data.org/&quot;&gt;football-data.org&lt;/a&gt; API to pull the standings. You’ll need a free API token, save it in a &lt;code&gt;.env&lt;/code&gt; file like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;API_TOKEN=your_football_data_token
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now fetch the standings:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import requests
import os
from dotenv import load_dotenv

load_dotenv()

def fetch_epl_standings():
    token = os.getenv(&quot;API_TOKEN&quot;)
    if not token:
        raise ValueError(&quot;API_TOKEN not found in env&quot;)
    
    uri = &quot;http://api.football-data.org/v4/competitions/PL/standings?season=2024&quot;
    headers = { 'X-Auth-Token': token }

    response = requests.get(uri, headers=headers)

    if response.status_code != 200:
        raise Exception(f&quot;API request failed with status code {response.status_code}: {response.text}&quot;)

    data = response.json()
    return data[&quot;standings&quot;][0][&quot;table&quot;]

standings = fetch_epl_standings()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Convert to DataFrame:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import pandas as pd

data_rows = []
for team in standings:
    data_rows.append({
        &quot;Pos&quot;: team[&quot;position&quot;],
        &quot;Team&quot;: team[&quot;team&quot;][&quot;name&quot;],
        &quot;Matches&quot;: team[&quot;playedGames&quot;],
        &quot;Wins&quot;: team[&quot;won&quot;],
        &quot;Draws&quot;: team[&quot;draw&quot;],
        &quot;Losses&quot;: team[&quot;lost&quot;],
        &quot;Points&quot;: team[&quot;points&quot;],
        &quot;+/-&quot;: team[&quot;goalDifference&quot;],
        &quot;Goals&quot;: f'{team[&quot;goalsFor&quot;]}:{team[&quot;goalsAgainst&quot;]}'
    })

df = pd.DataFrame(data_rows)
df.to_csv('epl_standings.csv', index=False)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;step-2-binomial-probability-of-exact-win-count&quot;&gt;Step 2: Binomial Probability of Exact Win Count&lt;/h3&gt;
&lt;p&gt;Now let's calculate the probability of each team repeating the exact number of wins they had last season.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import math

# Loop through each row and calculate binomial probability
for index, row in df.iterrows():
    team = row['Team']
    n = int(row['Matches'])  # total games
    k = int(row['Wins'])     # wins
    p = k / n                # estimated win probability

    try:
        binom_prob = math.comb(n, k) * (p**k) * ((1 - p)**(n - k))
    except OverflowError:
        binom_prob = 0.0

    print(f&quot;{team}: P( {k} wins)  = {binom_prob:.6f}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sample Output:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Liverpool FC: P( 25 wins)  = 0.135388
Arsenal FC: P( 20 wins)  = 0.128761
Ipswich Town FC: P( 4 wins)  = 0.206486
Southampton FC: P( 2 wins)  = 0.278054
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;strong&gt;What These Results Tell Us&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Top teams like Liverpool have lower exact probabilities, there's more room for variation when you're near the top.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lower-table teams tend to have higher repeat chances, but don't celebrate just yet...&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;step-3-probability-of-title-winning-season-28-wins-&quot;&gt;Step 3: Probability of Title-Winning Season (≥ 28 Wins)&lt;/h3&gt;
&lt;p&gt;Next, we model the probability of each team reaching 28 or more wins, a common threshold to win the league.&lt;/p&gt;
&lt;p&gt;We'll use the cumulative binomial distribution:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from scipy.stats import binom

def title_probability(wins, matches=38, threshold=28):
    p = wins / matches
    return 1 - binom.cdf(threshold - 1, matches, p)

for index, row in df.iterrows():
    team = row['Team']
    wins = int(row['Wins'])
    prob = title_probability(wins, threshold=28)
    print(f&quot;{team}: P(Wins ≥ 28) = {prob:.6f}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sample Output:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Team                     &lt;/th&gt;&lt;th&gt;P(Wins ≥ 28)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Liverpool FC             &lt;/td&gt;&lt;td&gt;19.78%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Manchester City FC       &lt;/td&gt;&lt;td&gt;1.54%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Arsenal FC               &lt;/td&gt;&lt;td&gt;0.66%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Chelsea FC               &lt;/td&gt;&lt;td&gt;0.66%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Newcastle United         &lt;/td&gt;&lt;td&gt;0.66%&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Manchester United FC&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;&lt;strong&gt;0.00%&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;interpretation&quot;&gt;Interpretation&lt;/h3&gt;
&lt;p&gt;Liverpool is most likely to hit 28+ wins based on current form.&lt;/p&gt;
&lt;p&gt;City, Chelsea and the others trail behind, possibly due to more draws or inconsistent performances.&lt;/p&gt;
&lt;p&gt;Man United? Their chance rounds to zero. Ouch .&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt; United fans, this model says your 11-win season gives you a statistically negligible shot at the title. You might want to pray harder than you code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;-limitations&quot;&gt;⚠️ Limitations&lt;/h3&gt;
&lt;p&gt;Let’s be honest, binomial probability isn’t a crystal ball. Here's why:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It ignores real-world dynamics: transfers, injuries, managerial changes.&lt;/li&gt;
&lt;li&gt;It assumes independent, identically distributed matches (which football is not).&lt;/li&gt;
&lt;li&gt;Based on one season, not a large enough sample for deep insight.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But hey, it’s fun and statistically grounded!&lt;/p&gt;
&lt;h3 id=&quot;want-to-take-this-further-&quot;&gt;Want to Take This Further?&lt;/h3&gt;
&lt;p&gt;Here’s how you can level up the model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use Poisson regression to simulate goals per match.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrate Elo ratings or other power metrics.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run full Monte Carlo simulations of future fixtures.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Track the model live across the season for dynamic probabilities.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h3&gt;
&lt;p&gt;While this model won’t help you win your fantasy league, it does give a math-driven glimpse into who’s statistically positioned to succeed. Liverpool fans? You have reason to dream. Southampton? Maybe next year...&lt;/p&gt;
&lt;p&gt;Football is unpredictable, and that's what makes it beautiful. But every now and then, it's fun to let the math have a shot at calling the game. ⚽&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/4490/can-we-predict-the-next-premier-league-champion-with-binomial-probability</guid>
<pubDate>Thu, 07 Aug 2025 17:23:46 +0000</pubDate>
</item>
</channel>
</rss>