|
| 1 | +^{:kindly/hide-code true |
| 2 | + :clay {:title "The Hidden Geometry of Dice" |
| 3 | + :quarto {:type :post |
| 4 | + :author [:timothypratley] |
| 5 | + :date "2025-06-05" |
| 6 | + :description "A simple probability puzzle turns into a journey through triangular numbers and tessellated hexagons." |
| 7 | + :category :math |
| 8 | + :tags [:probability :stats] |
| 9 | + :keywords [:quantquestions]}}} |
| 10 | +(ns math.stats.quantquestions.what-are-the-odds.the-hidden-geometry-of-dice |
| 11 | + (:require [civitas.explorer.geometry :as geom] |
| 12 | + [civitas.explorer.svg :as svg])) |
| 13 | + |
| 14 | +;; Welcome to What Are the Odds? |
| 15 | +;; The show where we answer life’s important questions, like can I outsmart a six-sided die? |
| 16 | +;; Today we’re starting small. |
| 17 | +;; Two rolls of the dice and one burning question. |
| 18 | +;; No magic formulas, just curiosity, some patient counting, and a faint hope that math is on our side. |
| 19 | +;; Let’s roll. |
| 20 | + |
| 21 | +;; > *Pop quiz:* |
| 22 | +;; > You roll a fair 6-sided die twice. |
| 23 | +;; > Calculate the probability that the value of the first roll is strictly less than the value of the second roll. |
| 24 | + |
| 25 | +;; As I always like to say to my niece, |
| 26 | +;; "the secret to answering any probability question is to enumerate the outcomes and count the ones we care about." |
| 27 | + |
| 28 | +;; $P(Interesting) = InterestingOutcomes / TotalOutcomes$ |
| 29 | + |
| 30 | +;; Rolling 1 die once has 6 outcomes: 1 2 3 4 5 6. |
| 31 | + |
| 32 | +;; Rolling 1 die twice gives us a combination of outcomes, let's write out a few. |
| 33 | + |
| 34 | +;; ``` |
| 35 | +;; [1 1] [1 2] '... [1 6] |
| 36 | +;; [2 1] [2 2] '... |
| 37 | +;; ``` |
| 38 | + |
| 39 | +;; Following this pattern would produce 6 rows of 6 columns, |
| 40 | +;; so there must be `36` outcomes. |
| 41 | +;; We write down just enough of the pattern to figure out the best way to count it. |
| 42 | +;; Now we count how many of those meet the criteria. |
| 43 | + |
| 44 | +;; ``` |
| 45 | +;; [1 1 :no] [1 2 :yes] '... |
| 46 | +;; [2 1 :no] [2 2 :no] [2 3 :yes] '... |
| 47 | +;; ``` |
| 48 | + |
| 49 | +;; Logically we should see 5 yeses on the first row, |
| 50 | +;; then 4, 3, 2, 1, and 0, which we can ignore. |
| 51 | +;; Add them all up and we get `15`. |
| 52 | + |
| 53 | +;; So the answer to the question is `15/36` which reduces to `5/12`, |
| 54 | +;; dividing top and bottom by the greatest common divisor 3. |
| 55 | + |
| 56 | +;; You might be thinking that it's not practical to enumerate everything all the time, |
| 57 | +;; I should use the formulas of probability. |
| 58 | +;; That's true, those are marvelous. |
| 59 | +;; However, in my experience it is also easy to go wrong reasoning from formulas. |
| 60 | +;; It's harder to go wrong starting with a counting problem, |
| 61 | +;; then improving your method of counting. |
| 62 | +;; You end up in the same place, but more confident in the answer. |
| 63 | + |
| 64 | +;; The full enumeration of our simple 2 roll question as a counting problem is just big enough to be too tedious to use only counting. |
| 65 | + |
| 66 | +(let [roll [1 2 3 4 5 6]] |
| 67 | + (for [i roll] |
| 68 | + (for [j roll] |
| 69 | + [i j]))) |
| 70 | + |
| 71 | +;; Identifying the pattern is enough to realize the answer |
| 72 | + |
| 73 | +(+ 5 4 3 2 1) |
| 74 | + |
| 75 | +;; What a marvelous pattern it is! |
| 76 | +;; Predictable, but not flat. |
| 77 | +;; Smooth, but not boring. |
| 78 | +;; Recursive, and not obvious. |
| 79 | + |
| 80 | +^:kindly/hide-code |
| 81 | +(into [] (map #(reduce + (range (inc %)))) (range 1 21)) |
| 82 | + |
| 83 | +;; There's something special about this sequence. |
| 84 | +;; Aren't those numbers just... pleasing in some way? |
| 85 | + |
| 86 | +;; This sequence is called the triangular numbers. |
| 87 | + |
| 88 | +;; ``` |
| 89 | +;; . |
| 90 | +;; . . |
| 91 | +;; . . . |
| 92 | +;; . . . . |
| 93 | +;; ``` |
| 94 | + |
| 95 | +;; You can find the first 10 or so numbers in your head, |
| 96 | +;; and with some paper many more quite quickly. |
| 97 | + |
| 98 | +;;  |
| 99 | + |
| 100 | +;; There is a formula for calculating the nth triangular number: |
| 101 | +;; $T_n = 1 + 2 + 3 + \dots + n = \frac{n(n + 1)}{2}$ |
| 102 | + |
| 103 | +;; The 20th triangular number is `(20x21)/2 = (400+20)/2 = 210`. |
| 104 | +;; Isn't it wonderful how there's so many different ways to find the same answer in math? |
| 105 | + |
| 106 | +;; There is something curious about the formula; it divides by 2 but only produces integers. |
| 107 | +;; How can we be certain we will only ever get an integer? |
| 108 | +;; So mysterious. |
| 109 | +;; `n(n+1)` is always even! |
| 110 | +;; Let's think about that a bit more, if n is odd, then n+1 is even. |
| 111 | +;; If n is even, then n+1 is odd. |
| 112 | +;; One of the multiples is always even, meaning that 2 is a factor, |
| 113 | +;; so the multiple must always have a factor 2, and be even. |
| 114 | + |
| 115 | +;; It's easy now to imagine if we had a 1000 sided dice what the answer would be. |
| 116 | +;; But be careful! For a 1000 side die, we want the 999nth triangular number: |
| 117 | +;; $(999 \times 1000)/2 = (1000000-1000)/2 = 500000-500 = 499500$ |
| 118 | +;; and the total outcomes would be `1000x1000`, so the answer would be `0.4995`. |
| 119 | +;; It's comforting to see that for a large range, we land closer to 50%. |
| 120 | + |
| 121 | +;; The point is that once we know what we are counting, |
| 122 | +;; it feels more obvious that we used the right formula to count it. |
| 123 | + |
| 124 | +;; Triangular numbers show up in many situations, |
| 125 | +;; my favorite is that they can be used to lay out hexagons. |
| 126 | +;; The [code that draws Clojure Civitas hexagons](https://github.com/ClojureCivitas/clojurecivitas.github.io/blob/main/src/civitas/explorer/geometry.clj) |
| 127 | +;; is based on the triangular number formula. |
| 128 | + |
| 129 | +^:kindly/hide-code |
| 130 | +(let [layers 4 |
| 131 | + r 80 |
| 132 | + vr (* layers r 2)] |
| 133 | + ^:kind/hiccup |
| 134 | + [:svg {:xmlns "http://www.w3.org/2000/svg" |
| 135 | + :viewBox [(- vr) (- vr) (* 2 vr) (* 2 vr)] |
| 136 | + :width "100%"} |
| 137 | + (for [[x y] (->> (geom/cube-spiral layers) |
| 138 | + (map geom/cube-to-cartesian-flat))] |
| 139 | + (let [x (* r x) |
| 140 | + y (* r y)] |
| 141 | + [:g {:transform (str "translate(" x "," y ")")} |
| 142 | + (svg/polygon {:fill "lightblue"} (geom/hex (* 0.9 r)))]))]) |
| 143 | + |
| 144 | +;; Triangular numbers also show up in the number of pairs, |
| 145 | +;; handshakes, edges in a complete graph, diagonals sum to triangular numbers, |
| 146 | +;; square numbers as sums of consecutive odd numbers, differences of triangulars, |
| 147 | +;; acceleration frames, smooth transitions, spacing. |
| 148 | +;; Such a beautiful pattern that can be found in so many situations! |
| 149 | + |
| 150 | +;; Until next time, may your dice be fair and your outcomes interesting. |
0 commit comments