<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Rupert Foggo McKay</title>
  <subtitle>Technical blog exploring TypeScript, React, JavaScript, and computer science fundamentals. In-depth articles on software development, testing, and mathematical concepts.</subtitle>
  <link href="https://rupertmckay.com/feed.xml" rel="self"/>
  <link href="https://rupertmckay.com/"/>
  <updated>2026-05-29T00:00:00Z</updated>
  <id>https://rupertmckay.com/</id>
  <author>
    <name>Rupert Foggo McKay</name>
    <email>rupert@rupertmckay.com</email>
  </author>
  
  <entry>
    <title>The Hidden Complexity of Barcodes</title>
    <link href="https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/"/>
    <updated>2026-05-29T00:00:00Z</updated>
    <id>https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/</id>
    <content type="html">&lt;h2 id=&quot;what-is-a-barcode-encoding&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/#what-is-a-barcode-encoding&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; What is a barcode encoding?&lt;/h2&gt;
&lt;p&gt;The black and white stripes are an optical encoding of a decimal number. A scanner reads the pattern of bars and recovers the digits.&lt;/p&gt;
&lt;p&gt;For retail products, the dominant formats are UPC-A (12 digits, common in the US) and EAN-13 (13 digits, common everywhere else). Every product you buy in a supermarket has one of these.&lt;/p&gt;
&lt;h2 id=&quot;a-brief-history&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/#a-brief-history&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; A brief history&lt;/h2&gt;
&lt;p&gt;A corner shop with a few hundred products can function with a cashier who knows the prices. A suburban supermarket in 1970 might stock 10,000 SKUs and serve hundreds of customers a day. At that scale, manual price-keying at checkout wasn&#39;t just slow — the error rate across millions of daily transactions became a real cost.&lt;/p&gt;
&lt;p&gt;The inventory side was arguably more significant. Without item-level sales data, replenishment relied on periodic physical counts and buyer intuition. The barcode promised to turn the checkout lane into a data collection point: every sale automatically recorded, stock levels updated in real time.&lt;/p&gt;
&lt;p&gt;The timing was right. IBM had been building mainframes for large retailers through the 1960s, so the back-end infrastructure existed in prototype form. The missing piece was a reliable way to get an identifier off a tin of beans and into a database without a human in the loop.&lt;/p&gt;
&lt;p&gt;In 1970, US grocery trade associations formed the Ad Hoc Committee on a Uniform Grocery Product Code — a voluntary industry body with no regulatory authority — and invited technology companies to submit proposals.&lt;/p&gt;
&lt;p&gt;After evaluating submissions from IBM, RCA, Litton and others, they chose the IBM proposal, designed primarily by &lt;a href=&quot;https://www.ibm.com/history/george-laurer&quot;&gt;George Laurer&lt;/a&gt;, in 1973. This became UPC. &lt;a href=&quot;https://www.history.com/this-day-in-history/june-26/barcode-scanner-invention-first-use&quot;&gt;The first product ever scanned&lt;/a&gt; was a pack of Wrigley&#39;s chewing gum, at a Marsh supermarket in Troy, Ohio, on 26 June 1974.&lt;/p&gt;
&lt;p&gt;RCA had pushed a competing &lt;a href=&quot;https://www.ibm.com/history/upc&quot;&gt;bull&#39;s-eye circular barcode&lt;/a&gt; that could be scanned from any angle. It lost out partly because it was harder to print reliably on packaging of the era.&lt;/p&gt;
&lt;p&gt;In the US, UPC was administered by the Uniform Code Council. Europe responded with EAN in 1976, administered by the International Article Numbering Association. The two organisations coexisted for decades.&lt;/p&gt;
&lt;h2 id=&quot;upc-a-and-ean-13&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/#upc-a-and-ean-13&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; UPC-A and EAN-13&lt;/h2&gt;
&lt;p&gt;When EAN was designed in Europe in 1976, there was already a large installed base of US UPC scanners. The designers needed EAN to be backward compatible.&lt;/p&gt;
&lt;p&gt;Their solution: &lt;a href=&quot;https://en.wikipedia.org/wiki/International_Article_Number&quot;&gt;EAN-13 is a 13-digit superset of the 12-digit UPC-A&lt;/a&gt;, with one extra leading digit. European codes use non-zero values for that digit — the Netherlands prefix &lt;code&gt;870&lt;/code&gt;, for instance, starts with &lt;code&gt;8&lt;/code&gt;. For US products, the leading digit is &lt;code&gt;0&lt;/code&gt;, which means a UPC-A code becomes a valid EAN-13 simply by prepending a &lt;code&gt;0&lt;/code&gt;. An EAN scanner seeing a code that starts with &lt;code&gt;0&lt;/code&gt; can drop that digit and treat the remaining 12 as UPC-A — the mapping is bijective.&lt;/p&gt;
&lt;p&gt;This meant European scanners could read American barcodes from day one.&lt;/p&gt;
&lt;h2 id=&quot;gs1&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/#gs1&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; GS1&lt;/h2&gt;
&lt;p&gt;In 2005, the two organisations &lt;a href=&quot;https://en.wikipedia.org/wiki/GS1&quot;&gt;merged to form GS1&lt;/a&gt;, a non-profit that now serves as the global authority. The system works hierarchically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GS1 allocates 3-digit prefixes to national member organisations (GS1 UK, GS1 Netherlands, etc.)&lt;/li&gt;
&lt;li&gt;Each national body allocates company prefixes to businesses that pay to join&lt;/li&gt;
&lt;li&gt;Each company then assigns the remaining digits to their own products&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So an EAN-13 code like &lt;code&gt;0 01234 56789 X&lt;/code&gt; breaks down roughly as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;001&lt;/code&gt; → GS1 US prefix (starting with &lt;code&gt;0&lt;/code&gt;, as established above)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;234&lt;/code&gt; → company prefix (assigned to a specific business)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;5678&lt;/code&gt; → product reference (assigned by that company)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X&lt;/code&gt; → check digit&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This federated design means no central body needs to know every product in the world. They just carve up the number space and delegate.&lt;/p&gt;
&lt;h2 id=&quot;prefix-allocation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/#prefix-allocation&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Prefix allocation&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_GS1_country_codes&quot;&gt;GS1 prefixes&lt;/a&gt; are 3 digits, ranging from 000 to 999, giving 1,000 possible values. Not all are assigned — large portions are reserved for future use. In practice there are around 120 active member organisations.&lt;/p&gt;
&lt;p&gt;The US alone occupies a huge chunk: 000–139. The Netherlands gets 870–879, a block of 10 prefixes. Smaller countries often get just one or two.&lt;/p&gt;
&lt;h2 id=&quot;the-structure-within-a-prefix&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/#the-structure-within-a-prefix&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; The structure within a prefix&lt;/h2&gt;
&lt;p&gt;Once you&#39;re past the 3-digit GS1 prefix, the remaining 9 digits (before the check digit) are split between a &lt;a href=&quot;https://www.gs1.org/standards/id-keys/company-prefix&quot;&gt;company prefix and a product reference&lt;/a&gt;. Crucially, this split is not fixed.&lt;/p&gt;
&lt;p&gt;GS1 allocates company prefixes of varying lengths depending on how many products you need:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Company prefix length&lt;/th&gt;
&lt;th&gt;Product reference digits&lt;/th&gt;
&lt;th&gt;Max distinct products&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;7 digits&lt;/td&gt;
&lt;td&gt;5 digits&lt;/td&gt;
&lt;td&gt;100,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8 digits&lt;/td&gt;
&lt;td&gt;4 digits&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9 digits&lt;/td&gt;
&lt;td&gt;3 digits&lt;/td&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 digits&lt;/td&gt;
&lt;td&gt;2 digits&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11 digits&lt;/td&gt;
&lt;td&gt;1 digit&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Larger companies with more products get shorter prefixes, leaving more room for product references. Smaller companies get longer prefixes and can identify fewer products.&lt;/p&gt;
&lt;p&gt;The 12-digit code space gives 10¹² = 1 trillion possible identifiers. That sounds like a lot, but every digit is decimal — 0–9 only, no hex, no alphanumeric encoding — which makes the space around 4,700 times smaller than it would be with base-36 characters. The constraint was baked in during the early 1970s, when systems needed to be operable by humans reading and typing numbers.&lt;/p&gt;
&lt;h2 id=&quot;the-check-digit&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/#the-check-digit&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; The check digit&lt;/h2&gt;
&lt;p&gt;The final digit is a checksum &lt;a href=&quot;https://www.activebarcode.com/codes/checkdigit/modulo10&quot;&gt;mathematically derived from the preceding ones&lt;/a&gt; — alternating multiply-by-1 and multiply-by-3, sum the results, modulo 10. This catches most scanning errors and accidental transpositions. A misread digit almost always produces an invalid check digit.&lt;/p&gt;
&lt;h2 id=&quot;collisions&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/#collisions&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Collisions&lt;/h2&gt;
&lt;p&gt;In theory, the namespace partitioning guarantees uniqueness — if everyone follows the rules. In practice, a few things go wrong:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fraud&lt;/strong&gt; — counterfeit goods sometimes copy a legitimate barcode from a real product.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Recycling&lt;/strong&gt; — GTINs (the formal term for barcode numbers) were historically permitted for reuse after a 48-month window. &lt;a href=&quot;https://www.gs1uk.org/insights/news/from-january-2019-gtins-should-never-be-reused-again&quot;&gt;GS1 prohibited reuse entirely in 2019&lt;/a&gt;, but old assignments still circulate in legacy systems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unofficial barcodes&lt;/strong&gt; — small sellers sometimes generate barcodes without a GS1 prefix, using randomly chosen numbers that may clash with real products.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In-store barcodes&lt;/strong&gt; — &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_GS1_country_codes&quot;&gt;codes starting with &lt;code&gt;2&lt;/code&gt;&lt;/a&gt; are explicitly designated for internal store use (loose produce, deli counter items). These are not globally unique and only mean something within that store&#39;s system.&lt;/p&gt;
&lt;h2 id=&quot;shortcomings&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/#shortcomings&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Shortcomings&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;No GTIN history&lt;/strong&gt; — GS1&#39;s registries reflect current assignments only. Historical data exists only as a byproduct of services that happened to cache it — crowd-sourced databases like Open Food Facts, web archives, commercial lookup tools. No one designed a system to track reassignment history; the assumption was that reassignment would be rare enough not to matter.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prefix exhaustion&lt;/strong&gt; — If a company exhausts its product reference space, it can&#39;t get its prefix shortened — that would renumber all existing products, cascading through every retailer and system that holds those GTINs. So they acquire a second prefix and assign new products from there.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mergers&lt;/strong&gt; — Two companies bring two prefixes. There&#39;s no clean way to consolidate, because renumbering would require updating every downstream system. Merged companies typically carry both prefixes indefinitely, which is why products from the same brand sometimes look like they come from different companies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Corporate identity coupled to product identity&lt;/strong&gt; — the constraint underlying all of this. The GTIN system ties product identification to corporate structure, which causes pain whenever corporate structures change — and they change constantly.&lt;/p&gt;
&lt;h2 id=&quot;digital-link&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/the-hidden-complexity-of-barcodes/#digital-link&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Digital Link&lt;/h2&gt;
&lt;p&gt;The 1D barcode is showing its age. It encodes only the GTIN. Modern supply chains also want to encode expiry dates, batch numbers, serial numbers, and sustainability data on the same label. Right now that typically means printing multiple barcodes on the same packaging.&lt;/p&gt;
&lt;p&gt;GS1&#39;s answer is &lt;a href=&quot;https://www.gs1.org/standards/gs1-digital-link&quot;&gt;Digital Link&lt;/a&gt; — a QR code that encodes a URL, pointing to a rich product data page. The URL structure embeds the GTIN, so existing systems can still extract the product identifier, but the code can carry much more.&lt;/p&gt;
&lt;p&gt;GS1 has been pushing a target called &lt;a href=&quot;https://www.gs1us.org/industries-and-insights/by-topic/sunrise-2027&quot;&gt;Sunrise 2027&lt;/a&gt;: by that point, major retailers&#39; point-of-sale systems should be capable of scanning 2D codes at checkout. &lt;a href=&quot;https://www.gs1.org/sites/gs1/files/2024-06/global-industry-endorsement-statement-qr-codes-with-gs1-standards.pdf&quot;&gt;Walmart, Carrefour and others&lt;/a&gt; are publicly committed to this.&lt;/p&gt;
&lt;p&gt;The transition strategy for suppliers is straightforward: print both. Legacy 1D barcode for scanners that aren&#39;t yet 2D-capable, Digital Link QR code alongside it for those that are. Suppliers can adopt now without waiting for universal retailer readiness.&lt;/p&gt;
&lt;p&gt;The 1D barcode won&#39;t disappear in 2027. Vending machines, self-checkout kiosks, and embedded scanners in smaller retailers have long replacement cycles. The magnetic stripe on payment cards was superseded by the chip in the 1990s and lingered for decades. Expect something similar here.&lt;/p&gt;
&lt;p&gt;Take care,&lt;/p&gt;
&lt;p&gt;Rupert&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Death</title>
    <link href="https://rupertmckay.com/blog/death/"/>
    <updated>2024-03-24T00:00:00Z</updated>
    <id>https://rupertmckay.com/blog/death/</id>
    <content type="html">&lt;p&gt;My mum was born 22nd November 1946. In 2005 she died of cancer.&lt;/p&gt;
&lt;p&gt;As of January 2023, she died more than half my life ago.&lt;/p&gt;
&lt;p&gt;We were in New Zealand in 2003. One day she began to bleed from the vagina. I remember her on the toilet with the door open, crying: &amp;quot;I just want to stop bleeding&amp;quot;. The doctors diagnosed her with uterine cancer. She had a hysterectomy not much later. But later still when she had trouble breathing, the doctors found cancer in her lungs. You can remove a uterus, but you can&#39;t remove the lungs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;12th of May 2004 21:55 Wednesday&lt;/p&gt;
&lt;p&gt;Hello today. Did I tell you mum’s got cancer? Well she has. She seems to be responding well the to chemo and is likely to survive. She takes it on the chin. I try harder to help around the house for my some what incapacitated mother. Life goes on. Good night.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;She was put on a course of chemotherapy. They put poison into her blood. It is a treatment which attacks all the cells in the body. The theory goes that if you do it for long enough the cancerous cells will die, at which point you stop putting poison in the blood, and hope the other cells will recover. Hair falls out as the follicle cells die. The stomach lining also suffers especially. Usually patients on chemotherapy lose a lot of weight. If any other medical treatment had even a half the side-effects, it would not be allowed on humans. But chemotherapy is reserved for cases of desperation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;10th of April 2005 Sunday 23:51&lt;/p&gt;
&lt;p&gt;Mum came back from London weeping, she could be dying soon but is not afraid of that but is sorry that she never got further in life and afraid that she’ll never see me and felix grow up.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One day after school my mother texted me to come home. Her hair was coming out. We sat together on the couch, gently pulling it out in clumps. It felt like peeling velcro.&lt;/p&gt;
&lt;p&gt;My mother didn&#39;t like being bald. She was self-conscious in public about it. She tried wearing wigs for a while, but felt self-conscious about wearing a wig too. Eventually she would become adept at styling her outfit with a hat or headwrap.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;19th of August 2005 Friday 23:25&lt;/p&gt;
&lt;p&gt;I’m back from a ten day holiday in Holland and mum has begun another course of chemo-therapy. This has put her in an ill state.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;She was so tired all the time. The chemotherapy puts the body in a constant state of fighting to recover from the damage it does. We were on the train one time; I had to help her walk. She needed to sit down to rest. We found a little nook near the kitchen carriage. It was quiet there and she fell asleep sitting beside me. But soon a group of five lads came and sat nearby. They were drinking and joking and laughing. Loudly. I could tell my mother couldn&#39;t sleep &lt;em&gt;but she needed to&lt;/em&gt;. I wanted so desperately to tell the men to shut up and let my dying mother rest for just one little moment. But I was afraid of them. They were loud adult men. I was just a scared little boy, and I didn&#39;t know how to protect my mother.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1st of November 2005 Tuesday 23:06&lt;/p&gt;
&lt;p&gt;Mum had problems with breathing this morning and I was pulled out at lunch to drive her to the hospital, she’s now staying there for a couple of days on a ventilator. She’s caught a chest infection.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The cancer in her lungs caused the tissue to become useless. As her lung capacity melted, she had to be put on an oxygen mask. As her lung capacity went further down, so the oxygen concentration had to go up. The high oxygen concentration dries out the lungs. Periodically they had to remove the oxygen mask, and use a different tool. Something like an inhaler but specifically for spreading moisture in the lungs. She had to inhale and exhale through this thing for a minute. The doctor would stand there and time every second. She cried the whole time, every time, because she couldn&#39;t breathe. She felt that she was suffocating every time. We couldn&#39;t do anything.&lt;/p&gt;
&lt;p&gt;My brother Felix didn&#39;t live with us during this time. He had been studying in Coventry, and then after graduation, moved to London. I remember the first time he saw this process of suffocating my mother for 60 seconds. He cried in the chair beside her bed. I watched him cry, and in that moment I realised how numb I was to all this. I had gotten used to it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;3rd of November 2005 &lt;s&gt;Wednesday&lt;/s&gt; Thursday 00:35&lt;/p&gt;
&lt;p&gt;Visited mum in hospital, she says it’ll be better for me if she dies sooner so that I can get over it before my A2level final exams.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&#39;m not &amp;quot;over it&amp;quot;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;4th of November 2005 Friday 00:01&lt;/p&gt;
&lt;p&gt;Mum’s on a nebuliser, she doesn’t have a chest infection, she doesn’t have a clot in her lung, she doesn’t etc. etc. but still she can only barely breath without aid.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was given &amp;quot;power of attorney&amp;quot;. If my mother became a vegetable, I had the legal power to decide whether to pull the plug. I didn&#39;t want that power. But they had to give it to someone.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;6th of November 2005 23:52 Sunday&lt;/p&gt;
&lt;p&gt;So Mum’s now on 15 litres of oxygen an hour (the maximum) and a constant morphine drip.&lt;/p&gt;
&lt;p&gt;Mum could die any time now. She&#39;s just not breathing right.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Every week or so the doctor would tell us that they had increased the oxygen concentration she was receiving. Pure oxygen is not fit for humans however. There is a maximum limit that is safe. So it was that one day the doctor said: &amp;quot;We have reached the maximum oxygen concentration we can administer&amp;quot;. He didn&#39;t say more than that. What he didn&#39;t say was &amp;quot;Whatever hope you had up until now, forget about it. Her death is now guaranteed&amp;quot;. I looked around the room at the other adults. I wanted to understand if they had heard the thing the doctor hadn&#39;t said. But they didn&#39;t say anything either.&lt;/p&gt;
&lt;p&gt;With the maximum oxygen limit and the lung capacity decreasing bit by bit each day, my mother died of an excruciatingly gradual suffocation. In the last two days of her life, she was largely unconscious the whole time.&lt;/p&gt;
&lt;p&gt;The call was put out to all friends and family, &lt;em&gt;this is it, come say your goodbyes now.&lt;/em&gt; They flocked to us. They flocked to her. Some 20 or so people seemed camped out in our home, and in the hospital ward. Some came all the way from New Zealand.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;7th of November 2005 Monday 22:18&lt;/p&gt;
&lt;p&gt;Got pulled out of school at 10 o’clock cos mum’s going comatose.&lt;/p&gt;
&lt;p&gt;Spoke to mum in private on one occasion (you cant speak with, only to) and cried alot. Becky came back down late in the day and Dad came.
I’ve been at the hospital since 10 and up til now. (12 hours) Toni and Simon are staying the night with mum.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I remember speaking to her that day. I was left alone in the room with her. I told her about school, and my saxophone lessons. I tried to keep talking, because I was afraid of what would happen when I ran out of things to say. But I didn&#39;t know what to say. I couldn&#39;t bare my own silence. But I couldn&#39;t bare to leave the room either. I needed someone to come in and relieve me from having to confront this reality. Eventually, with great guilt I left the room, just briefly to tell the others in the waiting room, that someone else should go be with her now. Immediately afterwards I stepped to one side in the corridor, and wept facing the wall. I couldn&#39;t see through my own hands and tears. But an anonymous nurse slipped in to hug me. I never saw their face. In that moment they were literally just a shoulder that I cried into. I owe them so much for that moment in which I was able to sob. Neither of us said a word during. I hope I at least mumbled a &amp;quot;thank you&amp;quot; afterwards, but I don&#39;t remember.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;9th of November 2005 Wednesday 03:03&lt;/p&gt;
&lt;p&gt;Got a call from simon at 7 last morning saying mum odd only had a few hours left. We got their and she was weaker than ever. Its been a fucking long day. Linda met us at the hospital and brought a tiny little locket of Manley beach. She’s hanging in though. We all know its time for her to go soon but she’s clinging to something.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We had been staying more or less non-stop in the hospital ward. Watching her die. That evening someone recommended that Felix and I go home and sleep just one night in our own beds to recover. So we did.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;9th of November 2005 Wednesday 23:38&lt;/p&gt;
&lt;p&gt;Got a call from Simon at 10 in the morning saying that mum’s breathing had become distressed and as we prepared to set out he called us again to say that she had died. We all still went to see her&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neither Felix nor I were surprised. But I felt guilty. Later I would lie to people that asked &amp;quot;of course I was there when she died&amp;quot;. I would feel guilty about the lie too.&lt;/p&gt;
&lt;p&gt;We travelled to the hospital to visit her. I had expected to see my mum in a hospital bed, just the same as yesterday. But her limp jaw was so twisted to the side. This was not my mother. This was a corpse.&lt;/p&gt;
&lt;p&gt;Just as fast as the swarm of well wishers arrived, so too did they leave. Even Richard and Felix returned to London. Felix encouraged me to visit often, but I didn&#39;t like to leave home. So it was that I came to living alone in a three bedroom house. I don&#39;t know how I survived that time. I was not ready to live alone. I was not ready for the world.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>The Skull</title>
    <link href="https://rupertmckay.com/blog/the-skull/"/>
    <updated>2023-09-23T00:00:00Z</updated>
    <id>https://rupertmckay.com/blog/the-skull/</id>
    <content type="html">&lt;p&gt;There&#39;s a skull on my shelf. I&#39;m not kidding. It&#39;s a real human skull.&lt;/p&gt;
&lt;p&gt;I used to spend every summer with a family in Holland. The grandfather of the family was called Henk Pelser. He was a medical student in Amsterdam when World War II broke out. To the Nazis he was an Aryan, and he could simply have kept out of trouble in occupied Netherlands. But he saw Nazism for the evil it was and spent all his time being a thorn in their side, at great personal risk.&lt;/p&gt;
&lt;p&gt;There&#39;s an organisation in Israel called Yad Vashem, who are dedicated to the remembrance of the holocaust and those who resisted. Here is their page on &lt;a href=&quot;https://collections.yadvashem.org/en/righteous/4043444&quot;&gt;Henk Pelser&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Henk died in 2007. He seemed to die by choice. His wife Sara had died of throat cancer shortly before. Around the time she died, Henk had been recovering from a hip replacement. He was doing simple exercises everyday to get used to walking again. But when Sara died, he just stopped trying. I remember him staying in that chair. His daughter, Simcha, would speak quietly to him, but he was adamant, there was nothing left for him without Sara.&lt;/p&gt;
&lt;p&gt;At his funeral they played a piece of music from a dutch nursery rhyme. It was the tune he would whistle outside Sara&#39;s window when they were just teenagers in Amsterdam. She would come to the window even when her parents wouldn&#39;t let her out, just so that they could see each other every day.&lt;/p&gt;
&lt;p&gt;After his death, we had to go through the sombre process of looking through all his things and seeing what ought to be kept. It was then that we found the skull. No one knows how or when he got it. But it had a pair of pins embedded on either side, which hinted at our best guess: it may have originally been part of a complete preserved skeleton arranged on a scaffold and used as a teaching aid for medical students. You don&#39;t often see these around anymore, and even when you do, they tend to be made of something synthetic. Originally however these were made from the remains of a real human.&lt;/p&gt;
&lt;p&gt;So there it was. A skull.&lt;/p&gt;
&lt;p&gt;No one else wanted it. They ummed and ahhed. It couldn&#39;t possibly be thrown away, but no one had the stomach to keep it. I had been respectfully silent all day. I&#39;m not a blood relative after all, and was only there as a spare pair of hands. But finally I suggested that I could take it. To my surprise no one disagreed.&lt;/p&gt;
&lt;p&gt;Since then the skull has stayed with me. First I had I took it in hand luggage to England, and then it travelled with me again when I moved to the Netherlands permanently. On both occasions I did not declare it and security never seemed to notice it.&lt;/p&gt;
&lt;p&gt;The skull still sits on my shelf. Some nights before I go to bed, I&#39;ll rest my hand on the crown. I&#39;m not sure what I intend by this. But I have this almost desperate sense of wanting to understand what it means for this artefact to represent the remains of a human story. I know nothing about this story. I do not know the skull&#39;s age, gender or origin. But as I rest my hand on the crown, I will sometimes rest my other hand on my own head. In that moment I try to capture the feeling that I&#39;m just a big bag of bones. That my two hands contain only superficially different contents. Somehow this calms me. I sleep easier when I can clear my mind of the day to day.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>How Phi and Fibonacci are connected</title>
    <link href="https://rupertmckay.com/blog/how-phi-and-fibonacci-are-connected/"/>
    <updated>2023-07-09T00:00:00Z</updated>
    <id>https://rupertmckay.com/blog/how-phi-and-fibonacci-are-connected/</id>
    <content type="html">&lt;h2 id=&quot;definition-fibonacci-sequence&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/how-phi-and-fibonacci-are-connected/#definition-fibonacci-sequence&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Definition: Fibonacci Sequence&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Fibonacci_number&quot;&gt;Fibonacci Sequence&lt;/a&gt; is a sequence starting, &lt;code&gt;0, 1, 1, 2, 3, 5, 8, 13...&lt;/code&gt;, and each subsequent number is the sum of the previous two.&lt;/p&gt;
&lt;p&gt;We can define the Fibonacci numbers recursively as:&lt;/p&gt;
&lt;math display=&quot;block&quot;&gt;
  &lt;msub&gt;
    &lt;mi&gt;F&lt;/mi&gt;
    &lt;mn&gt;0&lt;/mn&gt;
  &lt;/msub&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;mn&gt;0&lt;/mn&gt;
&lt;/math&gt;
&lt;math display=&quot;block&quot;&gt;
  &lt;msub&gt;
    &lt;mi&gt;F&lt;/mi&gt;
    &lt;mn&gt;1&lt;/mn&gt;
  &lt;/msub&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;mn&gt;1&lt;/mn&gt;
&lt;/math&gt;
&lt;math display=&quot;block&quot;&gt;
  &lt;msub&gt;
    &lt;mi&gt;F&lt;/mi&gt;
    &lt;mi&gt;n&lt;/mi&gt;
  &lt;/msub&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;msub&gt;
    &lt;mi&gt;F&lt;/mi&gt;
    &lt;mrow&gt;
      &lt;mi&gt;n&lt;/mi&gt;
      &lt;mo&gt;-&lt;/mo&gt;
      &lt;mn&gt;1&lt;/mn&gt;
    &lt;/mrow&gt;
  &lt;/msub&gt;
  &lt;mo&gt;+&lt;/mo&gt;
    &lt;msub&gt;
    &lt;mi&gt;F&lt;/mi&gt;
    &lt;mrow&gt;
      &lt;mi&gt;n&lt;/mi&gt;
      &lt;mo&gt;-&lt;/mo&gt;
      &lt;mn&gt;2&lt;/mn&gt;
    &lt;/mrow&gt;
  &lt;/msub&gt;
&lt;/math&gt;
&lt;h2 id=&quot;definition-phi&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/how-phi-and-fibonacci-are-connected/#definition-phi&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Definition: Phi&lt;/h2&gt;
&lt;p&gt;Phi is the &amp;quot;Golden Ratio&amp;quot;. Two quantities
&lt;math&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/math&gt;
and
&lt;math&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;/math&gt;
are in the &lt;em&gt;golden ratio&lt;/em&gt;
&lt;math&gt;&lt;mi&gt;φ&lt;/mi&gt;&lt;/math&gt;
if:&lt;/p&gt;
&lt;math display=&quot;block&quot;&gt;
  &lt;mfrac&gt;
    &lt;mrow&gt;
      &lt;mi&gt;a&lt;/mi&gt;
      &lt;mo&gt;+&lt;/mo&gt;
      &lt;mi&gt;b&lt;/mi&gt;
    &lt;/mrow&gt;
    &lt;mi&gt;a&lt;/mi&gt;
  &lt;/mfrac&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;mfrac&gt;
    &lt;mi&gt;a&lt;/mi&gt;
    &lt;mi&gt;b&lt;/mi&gt;
  &lt;/mfrac&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;mi&gt;φ&lt;/mi&gt;
&lt;/math&gt;
&lt;p&gt;Given this definition, we can derive the following additional relationships:&lt;/p&gt;
&lt;math display=&quot;block&quot;&gt;
  &lt;mn&gt;1&lt;/mn&gt;
  &lt;mo&gt;+&lt;/mo&gt;
  &lt;mfrac&gt;
    &lt;mn&gt;1&lt;/mn&gt;
    &lt;mi&gt;φ&lt;/mi&gt;
  &lt;/mfrac&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;mi&gt;φ&lt;/mi&gt;
&lt;/math&gt;
&lt;math display=&quot;block&quot;&gt;
  &lt;msup&gt;
    &lt;mi&gt;φ&lt;/mi&gt;
    &lt;mn&gt;2&lt;/mn&gt;
  &lt;/msup&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;mi&gt;φ&lt;/mi&gt;
  &lt;mo&gt;+&lt;/mo&gt;
  &lt;mn&gt;1&lt;/mn&gt;
&lt;/math&gt;
&lt;h2 id=&quot;connecting-the-two-together&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/how-phi-and-fibonacci-are-connected/#connecting-the-two-together&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Connecting the two together&lt;/h2&gt;
&lt;p&gt;The values of the Fibonacci sequence increase in size very quickly. But how fast exactly?&lt;/p&gt;
&lt;p&gt;Lets assume it can be approximated by some exponential curve of the form:&lt;/p&gt;
&lt;math display=&quot;block&quot;&gt;
  &lt;msub&gt;
    &lt;mi&gt;F&lt;/mi&gt;
    &lt;mi&gt;n
  &lt;/mi&gt;&lt;/msub&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;msup&gt;
    &lt;mi&gt;x&lt;/mi&gt;
    &lt;mi&gt;n&lt;/mi&gt;
  &lt;/msup&gt;
&lt;/math&gt;
&lt;p&gt;Where &lt;math&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;/math&gt; is some constant.&lt;/p&gt;
&lt;p&gt;If so, then from the recursive definition of the Fibonacci numbers:&lt;/p&gt;
&lt;math display=&quot;block&quot;&gt;
  &lt;msub&gt;
    &lt;mi&gt;F&lt;/mi&gt;
    &lt;mi&gt;n
  &lt;/mi&gt;&lt;/msub&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;msup&gt;
    &lt;mi&gt;x&lt;/mi&gt;
    &lt;mi&gt;n&lt;/mi&gt;
  &lt;/msup&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;msub&gt;
    &lt;mi&gt;F&lt;/mi&gt;
    &lt;mrow&gt;
      &lt;mi&gt;n&lt;/mi&gt;
      &lt;mo&gt;-&lt;/mo&gt;
      &lt;mn&gt;1&lt;/mn&gt;
    &lt;/mrow&gt;
  &lt;/msub&gt;
  &lt;mo&gt;+&lt;/mo&gt;
    &lt;msub&gt;
    &lt;mi&gt;F&lt;/mi&gt;
    &lt;mrow&gt;
      &lt;mi&gt;n
      &lt;mo&gt;-&lt;/mo&gt;
      &lt;mn&gt;2&lt;/mn&gt;
    &lt;/mi&gt;&lt;/mrow&gt;
  &lt;/msub&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;msup&gt;
    &lt;mi&gt;x&lt;/mi&gt;
    &lt;mrow&gt;
      &lt;mi&gt;n&lt;/mi&gt;
      &lt;mo&gt;-&lt;/mo&gt;
      &lt;mn&gt;1&lt;/mn&gt;
    &lt;/mrow&gt;
  &lt;/msup&gt;
  &lt;mo&gt;+&lt;/mo&gt;
  &lt;msup&gt;
    &lt;mi&gt;x&lt;/mi&gt;
    &lt;mrow&gt;
      &lt;mi&gt;n&lt;/mi&gt;
      &lt;mo&gt;-&lt;/mo&gt;
      &lt;mn&gt;2&lt;/mn&gt;
    &lt;/mrow&gt;
  &lt;/msup&gt;
&lt;/math&gt;
&lt;math display=&quot;block&quot;&gt;
  &lt;msup&gt;
    &lt;mi&gt;x&lt;/mi&gt;
    &lt;mi&gt;n&lt;/mi&gt;
  &lt;/msup&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;msup&gt;
    &lt;mi&gt;x&lt;/mi&gt;
    &lt;mrow&gt;
      &lt;mi&gt;n&lt;/mi&gt;
      &lt;mo&gt;-&lt;/mo&gt;
      &lt;mn&gt;1&lt;/mn&gt;
    &lt;/mrow&gt;
  &lt;/msup&gt;
  &lt;mo&gt;+&lt;/mo&gt;
  &lt;msup&gt;
    &lt;mi&gt;x&lt;/mi&gt;
    &lt;mrow&gt;
      &lt;mi&gt;n&lt;/mi&gt;
      &lt;mo&gt;-&lt;/mo&gt;
      &lt;mn&gt;2&lt;/mn&gt;
    &lt;/mrow&gt;
  &lt;/msup&gt;
&lt;/math&gt;
&lt;p&gt;And if we divide through by:
&lt;math display=&quot;block&quot;&gt;
&lt;msup&gt;
&lt;mi&gt;x&lt;/mi&gt;
&lt;mrow&gt;
&lt;mi&gt;n&lt;/mi&gt;
&lt;mo&gt;-&lt;/mo&gt;
&lt;mn&gt;2&lt;/mn&gt;
&lt;/mrow&gt;
&lt;/msup&gt;
&lt;/math&gt;&lt;/p&gt;
&lt;p&gt;Then we get:&lt;/p&gt;
&lt;math display=&quot;block&quot;&gt;
  &lt;msup&gt;
    &lt;mi&gt;x&lt;/mi&gt;
    &lt;mn&gt;2&lt;/mn&gt;
  &lt;/msup&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;mi&gt;x&lt;/mi&gt;
  &lt;mo&gt;+&lt;/mo&gt;
  &lt;mn&gt;1&lt;/mn&gt;
&lt;/math&gt;
&lt;p&gt;This last relationship is &lt;em&gt;exactly&lt;/em&gt; the relationship we identified earlier in the definition of φ. And so we can conclude:
&lt;math display=&quot;block&quot;&gt;
&lt;mi&gt;x&lt;/mi&gt;
&lt;mo&gt;=&lt;/mo&gt;
&lt;mi&gt;φ&lt;/mi&gt;
&lt;/math&gt;&lt;/p&gt;
&lt;p&gt;But wait! We aren&#39;t done. This conclusion was predicated on a very shaky assumption &amp;quot;lets assume the Fibonacci sequence can be approximated by some exponential curve&amp;quot;.&lt;/p&gt;
&lt;p&gt;Despite this assumption we can conclude rigorously that &lt;em&gt;if&lt;/em&gt; any consecutive pair of Fibonacci numbers were exactly in the Golden Ratio, then all subsequent pairs would also be.&lt;/p&gt;
&lt;p&gt;So we&#39;ve identified that the Golden Ratio is &amp;quot;stable&amp;quot; with respect to the recursive property of Fibonacci numbers.&lt;/p&gt;
&lt;p&gt;But that&#39;s not useful if we never happen to hit the Golden Ratio in the course of the Fibonacci pairs.&lt;/p&gt;
&lt;p&gt;Lets consider what happens when the current ratio is not &lt;math&gt;&lt;mi&gt;φ&lt;/mi&gt;&lt;/math&gt;.
Lets model it as having a ratio of
&lt;math&gt;
&lt;mi&gt;φ&lt;/mi&gt;
&lt;mo&gt;+&lt;/mo&gt;
&lt;mi&gt;δ&lt;/mi&gt;
&lt;/math&gt;, for some non-zero &lt;math&gt;&lt;mi&gt;δ&lt;/mi&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;p&gt;Then the next ratio will be:&lt;/p&gt;
&lt;math display=&quot;block&quot;&gt;
  &lt;mfrac&gt;
    &lt;mrow&gt;
      &lt;mn&gt;1&lt;/mn&gt;
      &lt;mo&gt;+&lt;/mo&gt;
      &lt;mi&gt;φ&lt;/mi&gt;
      &lt;mo&gt;+&lt;/mo&gt;
      &lt;mi&gt;δ&lt;/mi&gt;
    &lt;/mrow&gt;
    &lt;mrow&gt;
      &lt;mi&gt;φ&lt;/mi&gt;
      &lt;mo&gt;+&lt;/mo&gt;
      &lt;mi&gt;δ&lt;/mi&gt;
    &lt;/mrow&gt;
  &lt;/mfrac&gt;
  &lt;mo&gt;=&lt;/mo&gt;
  &lt;mfrac&gt;
    &lt;mn&gt;1&lt;/mn&gt;
    &lt;mrow&gt;
      &lt;mi&gt;φ&lt;/mi&gt;
      &lt;mo&gt;+&lt;/mo&gt;
      &lt;mi&gt;δ&lt;/mi&gt;
    &lt;/mrow&gt;
  &lt;/mfrac&gt;
  &lt;mo&gt;+&lt;/mo&gt;
  &lt;mn&gt;1&lt;/mn&gt;
&lt;/math&gt;
&lt;p&gt;This last term is similar to
&lt;math&gt;
&lt;mn&gt;1&lt;/mn&gt;
&lt;mo&gt;+&lt;/mo&gt;
&lt;mfrac&gt;
&lt;mn&gt;1&lt;/mn&gt;
&lt;mi&gt;φ&lt;/mi&gt;
&lt;/mfrac&gt;
&lt;mo&gt;=&lt;/mo&gt;
&lt;mi&gt;φ&lt;/mi&gt;
&lt;/math&gt;
but with the added &lt;math&gt;&lt;mi&gt;δ&lt;/mi&gt;&lt;/math&gt; term.
As such if &lt;math&gt;&lt;mi&gt;δ&lt;/mi&gt;&lt;mo&gt;&amp;gt;&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/math&gt;,
then our first ratio was greater than &lt;math&gt;&lt;mi&gt;φ&lt;/mi&gt;&lt;/math&gt;,
but our second ratio will be less than &lt;math&gt;&lt;mi&gt;φ&lt;/mi&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;p&gt;On the other hand if &lt;math&gt;&lt;mi&gt;δ&lt;/mi&gt;&lt;mo&gt;&amp;lt;&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/math&gt;,
then our first ratio was less than &lt;math&gt;&lt;mi&gt;φ&lt;/mi&gt;&lt;/math&gt;,
but our second ratio will be greater than &lt;math&gt;&lt;mi&gt;φ&lt;/mi&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;p&gt;From this we can conclude that ratios of Fibonacci pairs will &amp;quot;oscillate&amp;quot; either side of &lt;math&gt;&lt;mi&gt;φ&lt;/mi&gt;&lt;/math&gt;. But you may also note that because of the position of the &lt;math&gt;&lt;mi&gt;δ&lt;/mi&gt;&lt;/math&gt; term in the denominator the absolute distance from &lt;math&gt;&lt;mi&gt;φ&lt;/mi&gt;&lt;/math&gt; reduces from every ratio to the next.&lt;/p&gt;
&lt;p&gt;We have therefore concluded two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fibonacci pair ratios will &amp;quot;oscillate&amp;quot; either side of &lt;math&gt;&lt;mi&gt;φ&lt;/mi&gt;&lt;/math&gt;.&lt;/li&gt;
&lt;li&gt;Fibonacci pair ratios will converge on &lt;math&gt;&lt;mi&gt;φ&lt;/mi&gt;&lt;/math&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notice also that these two conclusions did not depend on the starting values chosen for the Fibonacci sequence. They follow solely from the recursive property of the Fibonacci numbers and the definition of &lt;math&gt;&lt;mi&gt;φ&lt;/mi&gt;&lt;/math&gt;. As such these conclusions would still hold no matter what starting values are chosen.&lt;/p&gt;
&lt;p&gt;Take care,&lt;/p&gt;
&lt;p&gt;Rupert&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Counting the Hard Way</title>
    <link href="https://rupertmckay.com/blog/counting-the-hard-way/"/>
    <updated>2023-06-25T00:00:00Z</updated>
    <id>https://rupertmckay.com/blog/counting-the-hard-way/</id>
    <content type="html">&lt;p&gt;In this post we&#39;ll explore the weird world of alternative base number systems.&lt;/p&gt;
&lt;p&gt;Let&#39;s start by counting to ten:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Congratulations.&lt;/p&gt;
&lt;p&gt;But let&#39;s look at that sequence of symbols above. Isn&#39;t it weird that for most of the numbers I used just a single symbol, but for the last one I used two symbols (&lt;code&gt;1&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt;)?&lt;/p&gt;
&lt;p&gt;In base 10 we have 10 distinct symbols from 0-9, but we have to break out into multiple symbols for numeric values larger than 9. Let&#39;s hold that thought and move onto a different base number system.&lt;/p&gt;
&lt;h2 id=&quot;binary-base-2&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/counting-the-hard-way/#binary-base-2&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Binary Base 2&lt;/h2&gt;
&lt;p&gt;Binary is a numeral system using just the digits &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt;. It is used extensively in computing and digital technology.&lt;/p&gt;
&lt;p&gt;In binary, counting to ten looks like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, ...&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;general-rules-of-positional-notation-systems&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/counting-the-hard-way/#general-rules-of-positional-notation-systems&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; General Rules of Positional Notation Systems&lt;/h2&gt;
&lt;p&gt;Now that we&#39;ve seen two examples, lets consider the general properties of Positional Notation Systems.&lt;/p&gt;
&lt;p&gt;When we read a number like &lt;code&gt;423&lt;/code&gt;. We interpret this as three separate values added together:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;4 * 100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2 * 10&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3 * 1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We could also write this as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;4 * 10^2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2 * 10^1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3 * 10^0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We do almost exactly the same in binary. Consider &lt;code&gt;1011&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1 * 8 = 1 * 2^3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0 * 4 = 0 * 2^2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1 * 2 = 1 * 2^1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1 * 1 = 1 * 2^0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In both cases the individual digit values are multiplied by some power of the base value.&lt;/p&gt;
&lt;p&gt;With this understanding it should be possible to understand how any &lt;em&gt;integer greater than 1&lt;/em&gt; can be used as a base, and what counting in such a system would look like.&lt;/p&gt;
&lt;p&gt;But now that we know the rules... what if we start to break them?&lt;/p&gt;
&lt;p&gt;First up: what if the base was negative?&lt;/p&gt;
&lt;h2 id=&quot;negabinary-base-2&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/counting-the-hard-way/#negabinary-base-2&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Negabinary Base -2&lt;/h2&gt;
&lt;p&gt;Suppose we have a base of -2. The powers of -2 are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-2^5 = -32&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-2^4 = 16&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-2^3 = -8&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-2^2 = 4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-2^1 = -2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-2^0 = 1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So how can we use this to count to ten?&lt;/p&gt;
&lt;p&gt;The first two numbers are easy: &lt;code&gt;0, 1&lt;/code&gt;. But already the next number presents a problem. Using just the powers available to us above how can we represent two?&lt;/p&gt;
&lt;p&gt;The trick here is to notice that we can use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-2^2 = 4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-2^1 = -2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;i.e. &lt;code&gt;110&lt;/code&gt; is two in Negabinary.&lt;/p&gt;
&lt;p&gt;We make three by simply adding one to two.&lt;/p&gt;
&lt;p&gt;i.e. &lt;code&gt;111&lt;/code&gt; is three in Negabinary.&lt;/p&gt;
&lt;p&gt;Then the whole sequence to ten is:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0, 1, 110, 111, 100, 101, 11010, 11011, 11000, 11001, 11110, ...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;But what if we now also decide to count down?&lt;/p&gt;
&lt;p&gt;Counting negatively:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0, 11, 10, 1101, 1100, 1111, 1110, 1001, 1000, 1011, 1010, ...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Notice an interesting property here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All the positive values have an odd number of digits&lt;/li&gt;
&lt;li&gt;All the negative values have an even number of digits&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At no point did we need a minus sign to represent negative values!&lt;/p&gt;
&lt;p&gt;We can intuitively understand this interesting property by recognising that the minus symbol has become redundant since it is &amp;quot;prebaked&amp;quot; into the base itself. Our &amp;quot;menu&amp;quot; of powers of -2 offers us both negative and positive values to choose from.&lt;/p&gt;
&lt;p&gt;But we aren&#39;t done yet! What if our base was a complex number?&lt;/p&gt;
&lt;h2 id=&quot;quarter-imaginary-base-2i&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/counting-the-hard-way/#quarter-imaginary-base-2i&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Quarter-Imaginary Base 2i&lt;/h2&gt;
&lt;p&gt;The Quarter-Imaginary numeral system was first proposed by Donald Knuth in 1960. The trick with this base is recognising that powers of &lt;code&gt;2i&lt;/code&gt; &amp;quot;rotate&amp;quot; through the Gaussian plane.&lt;/p&gt;
&lt;p&gt;Powers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-1: -(1/2)i&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0: 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1: 2i&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2: -4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3: -8i&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;4: 16&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;5: 32i&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;6: -64&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;7: -128i&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;8: 256&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;9: 512i&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this base we need four symbols: &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;3&lt;/code&gt; to represent all values.&lt;/p&gt;
&lt;p&gt;Positive real integers:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0, 1, 2, 3, 10300, 10301, 10302, 10303, 10200, 10201, 10202, ...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Negative real integers:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0, 103, 102, 101, 100, 203, 202, 201, 200, 303, 302, ...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Positive imaginaries:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0, 10.2, 10, 20.2, 20, 30.2, 30, 103000.2, 103000, 103010.2, 103010, ...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Negative imaginaries:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0, 0.2, 1030, 1030.2, 1020, 1020.2, 1010, 1010.2, 1000, 1000.2, 2030, ...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Some other examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1+i = 11.2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-1+i = 113.2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-1-i = 103.2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1-i = 1.2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this way we can represent all complex numbers without needing a minus sign, nor a sign for &lt;code&gt;i&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As before you&#39;ll notice that the modulo of the length of a number tells us something about where on the Gaussian plane our value is. Another interesting feature is the use of &lt;code&gt;0.2&lt;/code&gt; to give us &lt;code&gt;-i&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That&#39;s all for today.&lt;/p&gt;
&lt;p&gt;Take care,&lt;/p&gt;
&lt;p&gt;Rupert&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Loose Equality violates Transitivity</title>
    <link href="https://rupertmckay.com/blog/loose-equality-violates-transitivity/"/>
    <updated>2023-03-09T00:00:00Z</updated>
    <id>https://rupertmckay.com/blog/loose-equality-violates-transitivity/</id>
    <content type="html">&lt;p&gt;In JavaScript:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;0&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;0&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These three statements demonstrate that loose equality in JavaScript is not &lt;em&gt;transitive&lt;/em&gt; and therefore is not a valid &lt;em&gt;equivalence relation&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Despite this, the above is not a bug. It conforms exactly to &lt;a href=&quot;https://262.ecma-international.org/#sec-islooselyequal&quot;&gt;ECMAScript: IsLooselyEqual&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;equivalence-relations&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/loose-equality-violates-transitivity/#equivalence-relations&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Equivalence Relations&lt;/h2&gt;
&lt;p&gt;An &lt;a href=&quot;https://en.wikipedia.org/wiki/Equivalence_relation&quot;&gt;Equivalence Relation&lt;/a&gt; is the mathematically formal term for what we intuitively understand as &amp;quot;equals&amp;quot;. In order for a relation to be a valid &lt;code&gt;Equivalence Relation&lt;/code&gt;, it must satisfy the following three properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Reflexive_relation&quot;&gt;Reflexivity&lt;/a&gt;: &lt;code&gt;a == a&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Symmetric_relation&quot;&gt;Symmetry&lt;/a&gt;: &amp;quot;If &lt;code&gt;a == b&lt;/code&gt; then &lt;code&gt;b == a&lt;/code&gt;&amp;quot;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Transitive_relation&quot;&gt;Transitivity&lt;/a&gt;: &amp;quot;If &lt;code&gt;a == b&lt;/code&gt; and &lt;code&gt;b == c&lt;/code&gt;, then &lt;code&gt;a == c&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By the way, &lt;code&gt;NaN == NaN; // false&lt;/code&gt; violates reflexivity. But there are reasons for that decision, which I will not get into in this post. If you are especially interested, I recommend: &lt;a href=&quot;https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN&quot;&gt;Wikipedia | Comparison with NaN&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-easy-fix&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/loose-equality-violates-transitivity/#the-easy-fix&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; The Easy Fix&lt;/h2&gt;
&lt;p&gt;The easiest way to alter loose equality (&lt;code&gt;==&lt;/code&gt;) to fix transitivity would be to treat all cross-type comparisons as false. This is exactly what the strict equality (&lt;code&gt;===&lt;/code&gt;) operator in JavaScript does. Reference: &lt;a href=&quot;https://262.ecma-international.org/#sec-isstrictlyequal&quot;&gt;ECMAScript: IsStrictlyEqual&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But that&#39;s boring. Let&#39;s entertain the question: are there ways we can preserve at least cross-type equalities, while also preserving transitivity?&lt;/p&gt;
&lt;h2 id=&quot;the-pitfalls&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/loose-equality-violates-transitivity/#the-pitfalls&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; The Pitfalls&lt;/h2&gt;
&lt;p&gt;As soon as we allow even one equality across types we create a cross-type equivalence class.&lt;/p&gt;
&lt;p&gt;An &lt;code&gt;Equivalence Class&lt;/code&gt; is the set of all elements which are equivalent to one another.&lt;/p&gt;
&lt;p&gt;Once you have a cross-type equivalence class, you have to be very careful when considering new members of that class. It is not sufficient to check our intuition against just one member of the equivalence class, since equivalence with any member, implies equivalence to all members (via transitivity).&lt;/p&gt;
&lt;p&gt;The above implies two statements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Distinct values of the same type &lt;em&gt;must never be members of the same equivalence class&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;A maximal equivalence class has exactly one value from each type.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;a-silly-proposal&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/loose-equality-violates-transitivity/#a-silly-proposal&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; A Silly Proposal&lt;/h2&gt;
&lt;p&gt;Given the boolean type has only two values, there can exist only two distinct equivalence classes including booleans. We can use this as the basis for a set of maximal equivalence classes.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;false&lt;/code&gt; equivalence class:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;String: &lt;code&gt;&#39;&#39;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Number: &lt;code&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;BigInt: &lt;code&gt;BigInt(0)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Boolean: &lt;code&gt;false&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Undefined: &lt;code&gt;undefined&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Symbol: &lt;code&gt;Symbol.for(&#39;&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Null: &lt;code&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;true&lt;/code&gt; equivalence class:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;String: &lt;code&gt;&#39;true&#39;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Number: &lt;code&gt;1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;BigInt: &lt;code&gt;BigInt(1)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Boolean: &lt;code&gt;true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Symbol: &lt;code&gt;Symbol.for(&#39;true&#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;false&lt;/code&gt; class includes seven values, exactly one value from each primitive type.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;true&lt;/code&gt; class has five values. The only missing types are &lt;code&gt;undefined&lt;/code&gt; and &lt;code&gt;null&lt;/code&gt;, which cannot be included without merging the two equivalence classes. I &lt;em&gt;really&lt;/em&gt; don&#39;t like the use of &lt;code&gt;&#39;true&#39;&lt;/code&gt; as the canonically true string, but this is what we get for pushing an idea to its limit.&lt;/p&gt;
&lt;p&gt;In reality prohibiting cross-type equality is a perfectly sensible decision and very easy to reason about. It&#39;s no wonder that &lt;code&gt;===&lt;/code&gt; is greatly preferred to &lt;code&gt;==&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Take care,&lt;/p&gt;
&lt;p&gt;Rupert&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Langton&#39;s Ant and Unanswerable Questions</title>
    <link href="https://rupertmckay.com/blog/langtons-ant-and-unanswerable-questions/"/>
    <updated>2022-11-21T00:00:00Z</updated>
    <id>https://rupertmckay.com/blog/langtons-ant-and-unanswerable-questions/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Langton%27s_ant&quot;&gt;Langton&#39;s Ant&lt;/a&gt; is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Cellular_automaton&quot;&gt;cellular automaton&lt;/a&gt; first described by &lt;a href=&quot;https://en.wikipedia.org/wiki/Christopher_Langton&quot;&gt;Christopher Gale Langton&lt;/a&gt; in 1986. It looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rupertmckay.com/blog/langtons-ant-and-unanswerable-questions/LangtonsAntAnimated.gif&quot; alt=&quot;Animation of first 200 steps of Langton&#39;s ant&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The &amp;quot;Ant&amp;quot; exists on an infinite grid. Each cell of the grid can be either white or black, but initially all are white. Each &amp;quot;generation&amp;quot; the Ant moves according to the following rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Turn left if the current cell is white, else turn right&lt;/li&gt;
&lt;li&gt;Change the colour of the current cell&lt;/li&gt;
&lt;li&gt;Step forwards&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we allow the ant to run for some time, it initially produces some very beautiful symmetries. For example:&lt;/p&gt;
&lt;p&gt;Generation 96 displays an &amp;quot;S&amp;quot;-like pattern:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://rupertmckay.com/langton/?generation=96&quot;&gt;&lt;img src=&quot;https://rupertmckay.com/blog/langtons-ant-and-unanswerable-questions/langton96.png&quot; alt=&quot;Langton&#39;s Ant at generation 96&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Generation 184 looks like a pokeball about to open:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://rupertmckay.com/langton/?generation=184&quot;&gt;&lt;img src=&quot;https://rupertmckay.com/blog/langtons-ant-and-unanswerable-questions/langton184.png&quot; alt=&quot;Langton&#39;s Ant at generation 184&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Generation 368 is like a four tentacled monster:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://rupertmckay.com/langton/?generation=368&quot;&gt;&lt;img src=&quot;https://rupertmckay.com/blog/langtons-ant-and-unanswerable-questions/langton368.png&quot; alt=&quot;Langton&#39;s Ant at generation 368&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But then it produces chaotic patterns for many thousands of steps.&lt;/p&gt;
&lt;p&gt;We might have guessed that this chaos would proceed forever. But then at around 10,000 steps, something magical emerges:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://rupertmckay.com/langton/?generation=10500&quot;&gt;&lt;img src=&quot;https://rupertmckay.com/blog/langtons-ant-and-unanswerable-questions/langton10500.png&quot; alt=&quot;Langton&#39;s Ant at generation 10500&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Ant has begun to build a structure known as the highway. The highway is an infinitely repeating pattern. It takes the ant 104 steps for each iteration of the highway, and each iteration extends the pattern along a diagonal trajectory.&lt;/p&gt;
&lt;p&gt;But we can change things. Instead of starting with a blank grid, we could set some cells to black at the beginning. If we then run the Ant it will generate different patterns. When people try this, they find that the highway &lt;em&gt;always seems to emerge sooner or later&lt;/em&gt;. It is widely believed that the highway is inevitable, and yet this conjecture has never been proven nor disproven, despite many years of effort.&lt;/p&gt;
&lt;p&gt;Such a simple system to define, and yet we are unable to answer the question &amp;quot;Does the highway always appear, no matter the starting state?&amp;quot;&lt;/p&gt;
&lt;h2 id=&quot;rices-theorem&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/langtons-ant-and-unanswerable-questions/#rices-theorem&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Rice&#39;s Theorem&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Henry_Gordon_Rice&quot;&gt;Henry Gordon Rice&lt;/a&gt; proved the following theorem in 1951:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;All non-trivial semantic properties of programs are undecidable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A &lt;em&gt;trivial&lt;/em&gt; property of a program is one which is either always true or always false for every possible program.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Semantic&lt;/em&gt; properties are about the behaviour of the program, rather than &lt;em&gt;syntactic&lt;/em&gt; properties which are about the source code.&lt;/p&gt;
&lt;p&gt;A property is &lt;em&gt;undecidable&lt;/em&gt; if it is not possible for there to exist an algorithm which correctly identifies the property for all possible inputs.&lt;/p&gt;
&lt;p&gt;A famous example of such a non-trivial semantic property is: &amp;quot;Does this program halt?&amp;quot;. We know from the &lt;a href=&quot;https://en.wikipedia.org/wiki/Halting_problem&quot;&gt;Halting Problem&lt;/a&gt; that there can never exist a systematic way to identify whether any program halts or not.&lt;/p&gt;
&lt;p&gt;Once again, we find that such a simple question cannot be answered.&lt;/p&gt;
&lt;h2 id=&quot;rationalism-and-empiricism&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/langtons-ant-and-unanswerable-questions/#rationalism-and-empiricism&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Rationalism and Empiricism&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Rationalism&lt;/em&gt; and &lt;em&gt;Empiricism&lt;/em&gt; are two different philosophical stances on how best to pursue knowledge.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;em&gt;Rationalist&lt;/em&gt; believes that &lt;em&gt;reason&lt;/em&gt; is the primary way to gain knowledge. Truth is found by reasoning from first principles.&lt;/li&gt;
&lt;li&gt;An &lt;em&gt;Empiricist&lt;/em&gt; believes that &lt;em&gt;experience&lt;/em&gt; is the primary way to gain knowledge. Truth is found from direct observation and experimentation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Neither view is always correct. Different fields of knowledge lend themselves more to rationalism while others to empiricism. Mathematics for example is exceedingly rational, whereas Biology is exceedingly empirical.&lt;/p&gt;
&lt;p&gt;Computer Science is founded upon Mathematics, with the aim to &lt;em&gt;reason&lt;/em&gt; about computation and in so doing to derive concrete proofs. And yet examples like Langton&#39;s Ant and Rice&#39;s Theorem demonstrate that even very simple problems can elude solution.&lt;/p&gt;
&lt;p&gt;There is a tension between Computer Science as an academic pursuit vs Software Engineering as a professional discipline. At heart, I am a rationalist. I crave proof and certainty. But I am employed as a professional. When trying to find truth in any matter, think critically about what is provable from reason and what is not. For the unprovables, be humble and open minded. Observe, experiment and adapt to your circumstances.&lt;/p&gt;
&lt;p&gt;Take care,&lt;/p&gt;
&lt;p&gt;Rupert&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Default Options Pattern in TypeScript</title>
    <link href="https://rupertmckay.com/blog/default-options-pattern-in-typescript/"/>
    <updated>2022-10-24T00:00:00Z</updated>
    <id>https://rupertmckay.com/blog/default-options-pattern-in-typescript/</id>
    <content type="html">&lt;p&gt;Here&#39;s a pattern I find myself reusing in a lot of projects:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FormatOptions&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	color&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	fontWeight&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; color &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;black&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fontWeight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;medium&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Partial&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;FormatOptions&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// Implementation not important&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// for this blog post&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;explanation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/default-options-pattern-in-typescript/#explanation&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Explanation&lt;/h2&gt;
&lt;p&gt;Imagine you have a function which can display some text formatted in a particular colour:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; color&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Format the text red&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;My message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;red&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But most of the time you don&#39;t want to have to specify a color, so it would be nice if the color argument were optional:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; color &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;black&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// A red message&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;My red message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;red&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// A message using default color&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;My black message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But now suppose I also want to support a font-weight option. We could provide two optional arguments, one after the other:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; color &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;black&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fontWeight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;medium&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;My medium black message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// This works nicely!&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 🚨 I wanted bold fontWeight...&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 🚨 but this is read as a color&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;O no this won&#39;t work&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bold&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem is that we want a way to make &lt;code&gt;color&lt;/code&gt; and &lt;code&gt;fontWeight&lt;/code&gt; both optional, but if they are just optional parameters, then order matters. So we have to pick one to go before the other, and then we lose the ability to specify a later optional argument without also specifying an earlier one.&lt;/p&gt;
&lt;p&gt;Instead we should wrap them up in an options object:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		color &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;black&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		fontWeight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;medium&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		color&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		fontWeight&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// This works!&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;default formatted message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Also works!&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;A red message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	color&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;red&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// This works too!&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;A bold message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	fontWeight&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bold&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a perfectly good point to stop... however I don&#39;t entirely love having to pass an empty object in the case where we want all the defaults. What if instead the whole options object were itself optional?&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		color &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;black&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		fontWeight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;medium&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		color&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		fontWeight&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Now this is fine too!&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;A plain default message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Formatting still works too&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	color&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;blue&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	fontWeight&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;light&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perfect! We get support for sensible defaults, while also allowing users to provide specific options only for the bits they care about.&lt;/p&gt;
&lt;p&gt;The only thing I might do in this position is pull out the type of the options object for clarity:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FormatOptions&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	color&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	fontWeight&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; format &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
	message&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; color &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;black&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fontWeight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;medium&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Partial&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;FormatOptions&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which brings us to where we started 😀&lt;/p&gt;
&lt;p&gt;That&#39;s all for today&lt;/p&gt;
&lt;p&gt;Take care,&lt;/p&gt;
&lt;p&gt;Rupert&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Accessing Unknown Objects in TypeScript</title>
    <link href="https://rupertmckay.com/blog/accessing-unknown-objects-in-typescript/"/>
    <updated>2022-09-11T00:00:00Z</updated>
    <id>https://rupertmckay.com/blog/accessing-unknown-objects-in-typescript/</id>
    <content type="html">&lt;p&gt;There&#39;s a utility function I find myself adding to almost every TypeScript repo I work on.&lt;/p&gt;
&lt;p&gt;It goes like this:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; Record&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;PropertyKey&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;object&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;usecase-in-error-handling&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/accessing-unknown-objects-in-typescript/#usecase-in-error-handling&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Usecase in Error Handling&lt;/h2&gt;
&lt;p&gt;Occasionally we have to deal with &lt;code&gt;unknown&lt;/code&gt; values. The most common example of this is in &lt;code&gt;catch&lt;/code&gt; blocks. Often we want to assume that the caught error is some kind of native &lt;code&gt;Error&lt;/code&gt; object, which would have a &lt;code&gt;message&lt;/code&gt; property.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;somethingDangerous&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// `error` is of `unknown`&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// We get a type error on `error.message`&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// because `Object is of type &#39;unknown&#39;`&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Since &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html#using-unknown-in-catch-variables&quot;&gt;TypeScript 4.4&lt;/a&gt; caught errors are &lt;code&gt;unknown&lt;/code&gt; by default.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But by using our &lt;code&gt;isObject&lt;/code&gt; utility, we can narrow the &lt;code&gt;error&lt;/code&gt; to something which has keys or not:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;somethingDangerous&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;isObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message
    &lt;span class=&quot;token comment&quot;&gt;// 👆 safe access within this branch&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; error
    &lt;span class=&quot;token comment&quot;&gt;// In this case `error` is something different&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// So we&#39;ll just log it directly as is.&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;usecase-in-composing-type-predicates&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/accessing-unknown-objects-in-typescript/#usecase-in-composing-type-predicates&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Usecase in Composing Type Predicates&lt;/h2&gt;
&lt;p&gt;Learning to create your own type predicates is an important skill in TypeScript. There&#39;s a lot you can do by hand, but I will very often use &lt;code&gt;isObject&lt;/code&gt; as a starting point for more involved type predicates.&lt;/p&gt;
&lt;p&gt;Here&#39;s a very simple example:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserApiResponse&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isUserApiResponse &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  userResponse&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; userResponse &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; UserApiResponse &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;isObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userResponse&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; userResponse&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;string&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we need to go any deeper than one level, this approach becomes very cumbersome; at which point I recommend reaching for a schema validation library such as &lt;a href=&quot;https://github.com/colinhacks/zod&quot;&gt;Zod&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&#39;s how the same code above would look with Zod:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; z &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;zod&#39;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; UserApiResponse &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  userName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UserApiResponse&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; z&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;infer&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; UserApiResponse&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isUserApiResponse &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  userResponse&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;unknown&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserResponse &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; UserApiResponse &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; 
  UserApiResponse&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;safeParse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userResponse&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;success&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s all for today.&lt;/p&gt;
&lt;p&gt;Take care,&lt;/p&gt;
&lt;p&gt;Rupert&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Simulating Dice</title>
    <link href="https://rupertmckay.com/blog/simulating-dice/"/>
    <updated>2022-08-13T00:00:00Z</updated>
    <id>https://rupertmckay.com/blog/simulating-dice/</id>
    <content type="html">&lt;p&gt;In this post I will demonstrate two approaches for simulating rolls of a die of a given size, using only rolls of a die of a different size.&lt;/p&gt;
&lt;p&gt;Throughout this post I will use &lt;code&gt;dn&lt;/code&gt; terminology to refer to a die of size &lt;code&gt;n&lt;/code&gt;. For example a &lt;code&gt;d6&lt;/code&gt; refers to the classic six-sided die.&lt;/p&gt;
&lt;h2 id=&quot;using-base-number-conversion&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/simulating-dice/#using-base-number-conversion&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Using base number conversion&lt;/h2&gt;
&lt;p&gt;Given an input die of size &lt;code&gt;n&lt;/code&gt; and a target die of size &lt;code&gt;m&lt;/code&gt;, this approach works by expanding the output space of the &lt;code&gt;dn&lt;/code&gt; by rolling it repeated times, and interpreting the rolls in base &lt;code&gt;n&lt;/code&gt; mod &lt;code&gt;m&lt;/code&gt;. Some rolls however must be discarded to prevent bias in the outcomes.&lt;/p&gt;
&lt;p&gt;To present this approach, I will start with some small examples before building up to a fully generalized algorithm.&lt;/p&gt;
&lt;h3 id=&quot;simulating-a-d6-using-repeated-coin-flips&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/simulating-dice/#simulating-a-d6-using-repeated-coin-flips&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Simulating a d6 using repeated coin flips&lt;/h3&gt;
&lt;p&gt;Given a coin, we can flip it as many times as necessary for the number of outcomes to exceed the target number.&lt;/p&gt;
&lt;p&gt;For a d6, we would need to flip the coin at least 3 times to produce more than 6 outcomes. If we only flipped 2 times, we could only output 4 outcomes. At 3 flips we can output 8 outcomes. Given that we have 8 outcomes, we need to discard 2.&lt;/p&gt;
&lt;p&gt;Here is one scheme for doing that:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HHH&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HHT&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTH&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTT&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;THH&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;THT&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TTH&lt;/td&gt;
&lt;td&gt;DISCARD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TTT&lt;/td&gt;
&lt;td&gt;DISCARD&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Note that the ordering here is arbitrary, but I have used binary ordering, treating &lt;code&gt;H&lt;/code&gt; as &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;T&lt;/code&gt; as &lt;code&gt;1&lt;/code&gt;. Although arbitrary, this ordering will prove convenient for generalization to other die sizes.&lt;/p&gt;
&lt;p&gt;Additionally notice that in this case both of the discarded results start with &lt;code&gt;TT&lt;/code&gt;, so we can restart after only the second flip if we have seen &lt;code&gt;TT&lt;/code&gt; so far.&lt;/p&gt;
&lt;p&gt;We can combine the above two notes to produce a method of arriving at results without needing a lookup table:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flip a coin twice&lt;/li&gt;
&lt;li&gt;If the flips were &lt;code&gt;TT&lt;/code&gt;, discard and restart&lt;/li&gt;
&lt;li&gt;Otherwise flip a third time&lt;/li&gt;
&lt;li&gt;Treating &lt;code&gt;H&lt;/code&gt; as &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;T&lt;/code&gt; as &lt;code&gt;1&lt;/code&gt;, read the flip outcomes as a binary number and add 1.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;simulating-a-d6-with-a-d4&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/simulating-dice/#simulating-a-d6-with-a-d4&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Simulating a d6 with a d4&lt;/h3&gt;
&lt;p&gt;The above method of using a coin is equivalent to repeated use of a d2. &lt;em&gt;A coin is a d2&lt;/em&gt;. We can extend this method to any other die size.&lt;/p&gt;
&lt;p&gt;With a d4, we need two rolls to produce a large enough outcome space to simulate at least 6 results. The outcome space is much larger than we need though, having 16 outcomes.&lt;/p&gt;
&lt;p&gt;But we can map a given target result to multiple rows in our table, like so:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;First roll&lt;/th&gt;
&lt;th&gt;Second Roll&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&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;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;DISCARD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;DISCARD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;DISCARD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;DISCARD&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Note as before that we have an opportunity to terminate early. In this case when the first roll is a &lt;code&gt;4&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In order to produce a result without a lookup table we can use the same approach as before, but instead of interpreting &lt;code&gt;d2&lt;/code&gt; rolls in binary, we instead interpret &lt;code&gt;d4&lt;/code&gt; rolls in base 4, but also needing to take care to adjust for out by one errors caused by our base number system starting at 0, but the numbers on our dice conventionally starting at 1.&lt;/p&gt;
&lt;p&gt;Precisely, one must follow these steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Roll a d4.&lt;/li&gt;
&lt;li&gt;If the outcome was &lt;code&gt;4&lt;/code&gt;, discard and restart.&lt;/li&gt;
&lt;li&gt;Roll the d4 a second time.&lt;/li&gt;
&lt;li&gt;Subtract one from both outcomes.&lt;/li&gt;
&lt;li&gt;Concatenate the two results and read as a base-4 number.&lt;/li&gt;
&lt;li&gt;The computed value at this point will be between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;11&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add 1 to this value and then apply &lt;code&gt;mod 6&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can now extract from this a pattern to this process, in which any die can simulate any other die.&lt;/p&gt;
&lt;p&gt;Given some pair of naturals &lt;code&gt;n&lt;/code&gt; and &lt;code&gt;m&lt;/code&gt;, We can simulate a &lt;code&gt;dm&lt;/code&gt; using a &lt;code&gt;dn&lt;/code&gt; as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Find the smallest natural &lt;code&gt;k&lt;/code&gt; such that &lt;code&gt;n^k &amp;gt;= m&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Roll the &lt;code&gt;dn&lt;/code&gt; repeatedly, &lt;code&gt;k&lt;/code&gt; times.&lt;/li&gt;
&lt;li&gt;Read the rolls as digits of a base &lt;code&gt;n&lt;/code&gt; number.&lt;/li&gt;
&lt;li&gt;Discard values greater than the largest multiple of &lt;code&gt;n&lt;/code&gt; that is less than or equal to &lt;code&gt;m&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Mod the result by &lt;code&gt;m&lt;/code&gt; and add 1.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See below for an implementation of this process in TypeScript.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;[Click to expand]&lt;/strong&gt; Implementation&lt;/summary&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * Given `n`, simulate rolling a `dn` once.
 *
 * The possible outcomes are the set of naturals from 1 to n inclusive.
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;floor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;produceOneResult&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; repeatCount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rollResults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;Array&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;repeatCount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// This reads the results as a single number in base `n`&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; rollResults
		&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;roll&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;roll &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;repeatCount &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Given a `dn`, simulate the outcomes of a `dm`
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;simulateMwithN&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;/**
	 * `repeatCount` is the number of times we will need to roll the smaller die.
	 */&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; repeatCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ceil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;/**
	 * The maximum valid result is the largest multiple of n that is
	 * less than or equal to the size of our target space
	 */&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; maxValidResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;floor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt; repeatCount &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; m &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;produceOneResult&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; repeatCount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; maxValidResult&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;simulateMwithN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/play?ssl=30&amp;amp;ssc=9&amp;amp;pln=30&amp;amp;pc=23#code/PQKhCgAIUhxBLAbgUwHaQAaowGkgZ3gFsBXAGwEMAXZSAJwHsyz5UBzSCzAE20gdQBjZADooEaJAAqAC1oAHBvkIAjMrQYkqghkWT5OdWlTkFkVfgDNIqaiToUyBy4yKQAjJCoMbkVoLISQhQxaGBwHVR8C25IAF5IAApUAC4bEiIVZDoASniAPkgAWWoZEUsyBgY6ZMkSkxEHVG5dRJy8gGoPAG5wCIFoyHlGbhJhAHlUZAAlfXILBOS01AysujwjeWRqAGFNVCpl1ey8uMKAbyhISMHGZln8eYMEqYB3SABBOgcAT0TN7ZUPYkA45crwZiJAAMYKIFHkiTaBUg3GS7V6V2AwGkMngBiMFG4BhMtCMjzIVAMFCpBFYbHU6Uy2T86BU1NoWAwVxuFjJ83i9CYZAeTyukEgIjhCP+Qrw8FOhRlzEgAFoPHkYOgwEkAbt9hY1fBVeqcmKJUZRsJERQ8CoFZxIF0VHgYRjxUYqPZ0HyKb0AL4Y0ASGAIFDoLgYXi4WmkSg0LymTTaXT6KwOyNELlhfpRCyEWPUZBFV7wEwAOQFiSIRyZ6xsNbW9su4qDYpgGF1QP1GD8xNMK1raaoxFTr1oJeVU2QsW8guVJIIcOYzO48FEbfC4p59GQWz1IIWxVKImEEMS9TKlTYVby2IvIivaJyvRbYDbONocIAHsQMpBEI48CxD6Fh4gmtCUHQbD6BYsbDvIDIMNY6AmNQvaQOoygJhQ6DVJAyAAI4kI4Xg+EQG7cgMsEUF+ABqgHcCKFICveFRVDUWowJ2wIHJA2JEBqkBuGq7huhh5g7uShyMmsL4oj4zbipJ-IJMMDCWsgkwzHMFLJBsu6AjxVDPlcfqQK8uIMv8OkWIU370SwjE2SZVwel6Oo2ZAACkQmdD04ABn0raSB8XgwUOpirtEdDwCoWjwAIaZcPm5CFrEq7COI4TbjQgwvMg7xfL8iTuFCZUwuCkIVVKiL2ilcZFiW5aJAAbHgAAs7SNNOYzINagiCHggj2LkyKKfA1iJAAhAA2u4OAAEw4AAzDg7U4AArDgLUALoiP4gTcPoiTDd87SQIp4omIw7xvJAACi3zVIkGAAJKoABjlzmQykUmkAAk5ynXQfoYKa4p+n07rmO55wiPDFADXgM3AztaSI4IKMjZwBjuDtjoeJDfp4Ip7hpFCOBXAt5OU+Ky001c7UM+KG3M5ALXkwFpo5vgTCiI+uXGeAQA&quot;&gt;Try in the TypeScript Playground&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;using-recursive-unit-interval-segmentation&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/simulating-dice/#using-recursive-unit-interval-segmentation&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Using recursive unit interval segmentation&lt;/h2&gt;
&lt;p&gt;Given an input die of size &lt;code&gt;n&lt;/code&gt; and a target die of size &lt;code&gt;m&lt;/code&gt;, this approach works by mapping to and from the unit interval. First segment the unit interval by &lt;code&gt;m&lt;/code&gt;. Then treat rolls of the &lt;code&gt;dn&lt;/code&gt; as &amp;quot;narrowing in&amp;quot; on a range of the unit line segment. We start from a range inclusive of the whole unit line segment: &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;. Then for example we can treat a roll of a &lt;code&gt;1&lt;/code&gt; on a &lt;code&gt;d4&lt;/code&gt; as narrowing from the range &lt;code&gt;0-1&lt;/code&gt; to &lt;code&gt;0-1/4&lt;/code&gt;. If we rolled at again and it came up &lt;code&gt;2&lt;/code&gt; we would then narrow to the second quarter of the current range, i.e. &lt;code&gt;0-1/4&lt;/code&gt; to &lt;code&gt;1/16-2/16&lt;/code&gt;. At each stage we can check whether the current range fits entirely within a single &#39;segment&#39; of the output die. If so we output the value on the target die associated with the segment. Otherwise we continue narrowing.&lt;/p&gt;
&lt;p&gt;Let&#39;s show a complete example to demonstrate.&lt;/p&gt;
&lt;p&gt;Given an input &lt;code&gt;d4&lt;/code&gt; and target &lt;code&gt;d20&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The target segments are 20 equal sized segments on the unit interval.&lt;/p&gt;
&lt;p&gt;The current input range is the full &lt;code&gt;0-1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The first roll of the &lt;code&gt;d4&lt;/code&gt; yields a &lt;code&gt;3&lt;/code&gt;. The current input range is narrowed to &lt;code&gt;2/4-3/4&lt;/code&gt;. The current viable output values are &lt;code&gt;11-15&lt;/code&gt;. We need to narrow further.&lt;/p&gt;
&lt;p&gt;The second roll of the &lt;code&gt;d4&lt;/code&gt; yields a &lt;code&gt;1&lt;/code&gt;. The current input range is narrowed to &lt;code&gt;8/16-9/16&lt;/code&gt;. The current viable output values are &lt;code&gt;11-12&lt;/code&gt;. We need to narrow further.&lt;/p&gt;
&lt;p&gt;The third roll of the &lt;code&gt;d4&lt;/code&gt; yields a &lt;code&gt;4&lt;/code&gt;. The current input range is narrowed to &lt;code&gt;35/64-36/64&lt;/code&gt;. The current viable output values are &lt;code&gt;12&lt;/code&gt;. We halt with the output &lt;code&gt;12&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;See below for an implementation of this process in TypeScript:&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;[Click to expand]&lt;/strong&gt; Implementation&lt;/summary&gt;
&lt;pre class=&quot;language-ts&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * Represents a range on the unit interval
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Interval&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Given `n`, simulate rolling a `dn` once.
 *
 * The possible outcomes are the set of naturals from 1 to n inclusive.
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;floor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Let the unit interval be segmented into `m` segments of equal size,
 * label the segments from 1 to `m`.
 *
 * Then given some `n` on the unit interval, output which segment of `m` it belongs to.
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;fromUnitNtoSegmentsM&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ceil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Given a die, map a single result to the unit interval
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;fromDNtoInterval&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dieResult &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; lowerBound &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dieResult &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; upperBound &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lowerBound &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;lowerBound&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; upperBound&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Given an interval and a die size,
 * narrow the interval using a single role of the die
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;narrowIntervalWithDN&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;interval&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Interval&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Interval &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// This generates a new unit interval&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;innerLower&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; innerUpper&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fromDNtoInterval&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token comment&quot;&gt;// But we need to map it into our existing interval&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; currentIntervalSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; interval&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; interval&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newLowerBound &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; interval&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; innerLower &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; currentIntervalSize&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newUpperBound &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; interval&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; innerUpper &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; currentIntervalSize&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;newLowerBound&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; newUpperBound&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Given a `dn`, simulate the outcomes of a `dm`
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;simulateMwithN&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// We&#39;ll use a tuple to track a range on the unit interval&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; interval&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Interval &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mapToDM &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fromUnitNtoSegmentsM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mapFromDN &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;narrowIntervalWithDN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// In this loop we repeatedly narrow our output interval&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// Until its lower and upper bounds fit within the same segment of `dm`&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mapToDM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;interval&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mapToDM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;interval&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		interval &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mapFromDN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;interval&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mapToDM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;interval&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * A test of the distribution of a simulated dice
 *
 * Outputs a record where each key is a die result,
 * and each value is how often that result occurred
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; test &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;Array&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;simulateMwithN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-function&quot;&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Record&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; curr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;curr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;curr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * If the test is successful, each value should be roughly equal
 */&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/play?#code/PQKhCgAIUglBTADgJ3gZ3gOwC5sgQ0mX0wHN5IB7TSbACwoFdMBLbSFneZAN3wBsoIYOGwBPRBQCSXXgMgBeSAG1MjALYAjbgBpIardwC64cKAjRIAcRY8skAAaYHetC3WN++bBWSV+-JykBI4AJs5UmADG8AB0QkKQACoMkIiUaG6a-BSUjNhRlOroBKi0qRjslABm+t6MxPx41X7qkACMtJT6HNH8jG528dAihZho7KGKkAAUmABc+hrayACUigB8kACy3nSx1fyUlMhzlrv0scSYoUUzq+sA1B0A3KbmiQAy8Oz0TKzsTg+OT8SDaSAYUjFLhTIHdBzqBwQ+BQrC4Ki1eAAR0Y8jcAC94DpEl5tKC-sjUThmq0Ol1HIjhjBEil7KRbPY0EUKE4kdRyv82L1gXx+Ho8thEPlIAB3OgsKJ0SnQqq1BFIoVk6ikPDYShM0bUCaQFpFACqAIAcnqAMoolVobbTGbqRYGFbrBRbOZu5bcT1bADeUA4tTOCgjkAADOtUNgGjR2m9IEQfgmdntYjEWPwzjB1Ks3gBfd5gRI2Ow0QihFhEyDqfCIEJuMg5VNoTy-boU5hCoHcUVCQ3jdim9QAEWtlBkIvkSh9S0Ma02kGDKbGxpr8AQHf47CUoTmhdM66N7COMu4ACE8jdnVud53IABaDrrGAzTrAfTH08jyCMIgkjIDezBTEoF7XreUzPJ+kDfpgx4hnG6bKJBIHQXogHAaBNxGMWpYWDAFb2CQwoDvIJBTNWtYQiwhLEpYmD4MgfgygK5EggBLbBIQPFtn4bY1BxW5DuAG7sMxrGUDKM4UfwADqbB0JOzoLIuHorjM-YgosckgqsemyKKK5rvB34pCweDkJg3DeCUhC2exvaAsZAghhJKicLZyCfDJui9D5ZpAcY0xjpOer6aKR5vCGwDfle0qXvo8DwFMer1o2HCuRleTIJA8AAB5WdgQScYOf7GlEDSoDgUUCDa9EUEoOmiso7RGC+5UCMoUb4R5Z4pTKfmXhhYHTK1PV9ZAsHedwI3cJY1WsWi9X8I1hK-pAnlOcFOHQRNbn8L1nWzZgQUhflMDLbV2BrRt8BISmKHIDQqjwMN-ljTcei7ZduGhP1JZmGWlgkVWYTOK47iePZHESoUxR4MJhAOKEiJiZ5bgeF4PjbDKymWs6roaQF6nuv6plxd+CnwAA5AE3EUIQ8aIG2GXYMQUQANYhNc5CRBxLndYIKY5Dl8lGbOoJKL1egdbFlXsA2iBJJQ45OkoY4WmwU52lSuDbC6W2eSrABirSqUoUlsWtSn0JOMUnuZkAyOUVmQEclBNslqCSPZoT8GIdTSexeVUPkUoSyC1OQBapWgmweDoQQd7YYtmjQc0QoE-QnAcWg+DFMqaIYmEGMpnKOYUC6jZqxr2lHSd6wAISRir9dG5Nx0dQ8q4him3fTObluWo30tbcDz1pq9mWq+rXdN31x5FrFHyWAAgrQ6CqiJJXICwmj5Cw-Io3ROMB5ANYxIkiQAPKR-keCEKghTIFMcrcBQ8D4IqkDc-AYOHsaK+HQJ2RiMAqIFV-kqUUjAKAezoDJDEPgaD0G8O2J8lAojLTSpjQaPhjTWw+pADerF8BiE-FGahMYQwHBzLmWhKZYgqxmPcFc2NYZ41znQMeAA2PQAAWB4dDUChEYDEAAPAgN+oRJEU2QL9P0yANgbBmAPWYv8oh6BugGWYgZYiGK0XoZQN0jCLBmFo0xNVOoAH5bHRieB0IsqxGIplXCWFMSF14wCkLUCkhDAR4A7Dg9AaBqieD0D-P+cCKBoCQZ4KY4I-CMFIHQIOBUcTuRGOJI0-g4hHFIDMQJx4gA&quot;&gt;Try in the TypeScript Playground&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;comparisons&quot; tabindex=&quot;-1&quot;&gt;&lt;a class=&quot;direct-link&quot; href=&quot;https://rupertmckay.com/blog/simulating-dice/#comparisons&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt; Comparisons&lt;/h2&gt;
&lt;p&gt;Both approaches could theoretically &lt;em&gt;never halt&lt;/em&gt;. In the first approach, we might always hit a DISCARD result. In the second approach we might always narrow in on a segment that straddles the boundary between two possible output values. However in practice the probability of this happening for either approach tends to zero for sufficiently many rolls of the input die.&lt;/p&gt;
&lt;p&gt;One might also consider the practicality of either approach. In the presence of a computer there are much more convenient methods for simulating a die. However in the absence, the first approach can be somewhat pre-computed by drawing up lookup tables for a given input die (such as the ubiquitous d6) and a selection of output die.&lt;/p&gt;
&lt;p&gt;I can&#39;t find a comparative advantage to the second approach compared to the first... and yet I can&#39;t help but shake some gut feeling of preference for it. Something about &amp;quot;zooming in&amp;quot; on the unit segment appeals to me.&lt;/p&gt;
&lt;p&gt;That&#39;s all for this post.&lt;/p&gt;
&lt;p&gt;Take care,&lt;/p&gt;
&lt;p&gt;Rupert&lt;/p&gt;
</content>
  </entry>
</feed>
