[{"id":247395,"date":"2026-07-21T10:05:04","date_gmt":"2026-07-21T15:05:04","guid":{"rendered":"https:\/\/www.johndcook.com\/blog\/?p=247395"},"modified":"2026-07-21T17:18:37","modified_gmt":"2026-07-21T22:18:37","slug":"forensic-accounting-in-python","status":"publish","type":"post","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/forensic-accounting-in-python\/","title":{"rendered":"Forensic accounting in Python"},"content":{"rendered":"<p>I recently had a project in which I had to reverse engineer a data analysis. There was some ambiguity regarding which of several possibilities someone chose for several of the variables, something analogous to the following example.<\/p>\n<p>Suppose you have three numbers with uncertain values with a known, or at least purported, sum. The first number could be 31, 41, or 59; the second could be either 26 or 53; the last could be 58, 97, 93, or 23.<\/p>\n<p>The following code enumerates all 3 &times; 2 &times; 4 = 24 possibilities and prints their sums.<\/p>\n<pre>\r\nfrom itertools import product\r\n\r\n# Example input\r\npossibilities = [(31, 41, 59), (26, 53), (58, 97, 93, 23)]\r\n\r\nfor combo in product(*possibilities):\r\n    total = sum(combo) \r\n    print(f\"Combination {combo} sums to: {total}\")\r\n<\/pre>\n<p>In this example all the sums are unique, though of course that might not happen in practice. If, for example, you know the sum is 187, you know the three numbers were 41, 53, and 93. If the reported sum is 200, you know some assumption has been violated because none of the possible choices add up to 200.<\/p>\n<h2>More forensics posts<\/h2>\n<ul>\n<li class='link'><a href='https:\/\/www.johndcook.com\/blog\/2009\/09\/18\/make-up-your-own-rules-of-probability\/'>Make up your own rules of probability<\/a><\/li>\n<li class='link'><a href='https:\/\/www.johndcook.com\/blog\/2023\/04\/01\/identifiable-to-man-or-machine\/'>Identifiable to man or machine?<\/a><\/li>\n<li class='link'><a href='https:\/\/www.johndcook.com\/blog\/2024\/02\/13\/photo-metadata\/'>Metadata in photos<\/a><\/li>\n<li class='link'><a href='https:\/\/www.johndcook.com\/blog\/2026\/05\/05\/changing-one-character-in-a-pdf\/'>Changing one character in a PDF<\/a><\/li>\n<li class='link'><a href='https:\/\/www.johndcook.com\/blog\/2018\/03\/02\/bits-of-information-in-age-birthday-and-birthdate\/'>Bits of information in age or birthday<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>I recently had a project in which I had to reverse engineer a data analysis. There was some ambiguity regarding which of several possibilities someone chose for several of the variables, something analogous to the following example. Suppose you have three numbers with uncertain values with a known, or at least purported, sum. The first [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[17],"tags":[],"class_list":["post-247395","post","type-post","status-publish","format-standard","hentry","category-statistics"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"Writing Python code to reverse engineer a data analysis, iterating over possibilities to try to make the numbers add up.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"John\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/forensic-accounting-in-python\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"John D. Cook | Applied Mathematics Consulting\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Forensic statistics in Python\" \/>\n\t\t<meta property=\"og:description\" content=\"Writing Python code to reverse engineer a data analysis, iterating over possibilities to try to make the numbers add up.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/forensic-accounting-in-python\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-07-21T15:05:04+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-07-21T22:18:37+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Forensic statistics in Python\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Writing Python code to reverse engineer a data analysis, iterating over possibilities to try to make the numbers add up.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Forensic statistics in Python","description":"Writing Python code to reverse engineer a data analysis, iterating over possibilities to try to make the numbers add up.","canonical_url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/forensic-accounting-in-python\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"John D. Cook | Applied Mathematics Consulting","og:type":"article","og:title":"Forensic statistics in Python","og:description":"Writing Python code to reverse engineer a data analysis, iterating over possibilities to try to make the numbers add up.","og:url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/forensic-accounting-in-python\/","article:published_time":"2026-07-21T15:05:04+00:00","article:modified_time":"2026-07-21T22:18:37+00:00","twitter:card":"summary","twitter:title":"Forensic statistics in Python","twitter:description":"Writing Python code to reverse engineer a data analysis, iterating over possibilities to try to make the numbers add up.","twitter:image":"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png"},"aioseo_meta_data":{"post_id":"247395","title":"Forensic statistics in Python","description":"Writing Python code to reverse engineer a data analysis, iterating over possibilities to try to make the numbers add up.","keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"created":"2026-07-21 02:37:46","updated":"2026-07-21 22:18:58","ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\/category\/statistics\/\" title=\"Statistics\">Statistics<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tForensic accounting in Python\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.johndcook.com\/blog"},{"label":"Statistics","link":"https:\/\/www.johndcook.com\/blog\/category\/statistics\/"},{"label":"Forensic accounting in Python","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/forensic-accounting-in-python\/"}],"_links":{"self":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247395","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/comments?post=247395"}],"version-history":[{"count":6,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247395\/revisions"}],"predecessor-version":[{"id":247406,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247395\/revisions\/247406"}],"wp:attachment":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/media?parent=247395"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/categories?post=247395"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/tags?post=247395"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}},{"id":247398,"date":"2026-07-21T07:14:03","date_gmt":"2026-07-21T12:14:03","guid":{"rendered":"https:\/\/www.johndcook.com\/blog\/?p=247398"},"modified":"2026-07-21T10:18:24","modified_gmt":"2026-07-21T15:18:24","slug":"jacobian-conjecture","status":"publish","type":"post","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/jacobian-conjecture\/","title":{"rendered":"Locally everywhere does not imply everywhere"},"content":{"rendered":"<p>A couple days ago, Levent Alp\u00f6ge, a mathematician working at Anthropic, discovered a counterexample to the Jacobian conjecture using Claude Fable 5.<\/p>\n<p>I was curious whether most mathematicians were trying to prove or disprove the conjecture, so I asked Claude.<\/p>\n<blockquote><p>Before a counterexample to the Jacobian conjecture was found, did most mathematicians believe it was true or false?<\/p><\/blockquote>\n<p>Claude&#8217;s response was<\/p>\n<blockquote><p>The premise of this question isn&#8217;t quite right \u2014 no counterexample to the Jacobian conjecture has been found. It remains an open problem in mathematics: no one has proven it true, and no one has found a counterexample disproving it. \u2026 If you encountered a claim that a counterexample was found, do you have a source for that? I&#8217;d be happy to look into it, since that would actually be a major result in algebraic geometry if true.<\/p><\/blockquote>\n<p>Of course Claude doesn&#8217;t <em>know<\/em> that it solved the conjecture. It didn&#8217;t even solve the conjecture. It was an inanimate tool in the hand of a mathematician, just like a piece of chalk or a dry erase marker.<\/p>\n<p>The middle part of Claude&#8217;s response was that mathematicians are (were) divided on whether the conjecture is true. So it was not like the Riemann hypothesis, which most people believe to be true, or the P = NP conjecture, which most people believe to be false.<\/p>\n<p>Now what is the Jacobian conjecture? It says that a polynomial function from \u211d<sup><em>n<\/em><\/sup> to \u211d<sup><em>n<\/em><\/sup> with constant, non-zero Jacobian has a polynomial inverse. (The conjecture was stated more generally for fields of characteristic 0, in which the derivatives defining the Jacobian would have to be defined algebraically, not in terms of limits.)<\/p>\n<p>Alp\u00f6ge came up with a counterexample, a polynomial function from \u211d\u00b3 to \u211d\u00b3 with constant Jacobian determinant \u22122. The function is<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" style=\"background-color: white;\" src=\"https:\/\/www.johndcook.com\/jacobian_conjecture.svg\" alt=\"\\begin{align*}F(x,y,z)={}\\bigl(~\\!&amp; z (1+xy)^3 + y^2 (1+xy) (4+3xy),\\\\ &amp;y + 3x(1+xy)^2 z + 3xy^2 (4+3xy), \\\\ &amp;2x - 3x^2 y - x^3 z ~\\!\\bigr).\\end{align*}\" width=\"385\" height=\"88\" \/><\/p>\n<p>It&#8217;s a tedious but simple calculus exercise to show that the determinant equals \u22122 everywhere. The inverse function theorem says that a function is locally invertible at any point where the Jacobian determinant is non-zero, so Alp\u00f6ge&#8217;s function is locally invertible everywhere.<\/p>\n<p>However, the function takes on some values more than once. For example, (0, 0, &minus;1\/4) and (1, &minus;3\/2, 13\/2) both map to (&minus;1\/4, 0, 0). Therefore the function is not invertible globally. So not only does the function not have a polynomial inverse, it doesn&#8217;t have an inverse even if you allow non-polynomial functions.<\/p>\n<p>Alp\u00f6ge&#8217;s counterexample disproves the Jacobian conjecture for <em>n<\/em> = 3. It can trivially be extended to all <em>n<\/em> &gt; 3 by defining the function to be Alp\u00f6ge&#8217;s function for three variables and the identity for the rest. The conjecture remains open for <em>n<\/em> = 2.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A couple days ago, Levent Alp\u00f6ge, a mathematician working at Anthropic, discovered a counterexample to the Jacobian conjecture using Claude Fable 5. I was curious whether most mathematicians were trying to prove or disprove the conjecture, so I asked Claude. Before a counterexample to the Jacobian conjecture was found, did most mathematicians believe it was [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[9],"tags":[154],"class_list":["post-247398","post","type-post","status-publish","format-standard","hentry","category-math","tag-algebraic-geometry"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"Expanding on the recent counterexample to the Jacobian conjecture.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"John\"\/>\n\t<meta name=\"keywords\" content=\"algebraic geometry\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/jacobian-conjecture\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"John D. Cook | Applied Mathematics Consulting\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Locally everywhere does not imply everywhere\" \/>\n\t\t<meta property=\"og:description\" content=\"Expanding on the recent counterexample to the Jacobian conjecture.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/jacobian-conjecture\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-07-21T12:14:03+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-07-21T15:18:24+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Locally everywhere does not imply everywhere\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Expanding on the recent counterexample to the Jacobian conjecture.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Locally everywhere does not imply everywhere","description":"Expanding on the recent counterexample to the Jacobian conjecture.","canonical_url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/jacobian-conjecture\/","robots":"max-image-preview:large","keywords":"algebraic geometry","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"John D. Cook | Applied Mathematics Consulting","og:type":"article","og:title":"Locally everywhere does not imply everywhere","og:description":"Expanding on the recent counterexample to the Jacobian conjecture.","og:url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/jacobian-conjecture\/","article:published_time":"2026-07-21T12:14:03+00:00","article:modified_time":"2026-07-21T15:18:24+00:00","twitter:card":"summary","twitter:title":"Locally everywhere does not imply everywhere","twitter:description":"Expanding on the recent counterexample to the Jacobian conjecture.","twitter:image":"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png"},"aioseo_meta_data":{"post_id":"247398","title":null,"description":"Expanding on the recent counterexample to the Jacobian conjecture.","keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"created":"2026-07-21 11:46:59","updated":"2026-07-21 17:02:27","ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\/category\/math\/\" title=\"Math\">Math<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tLocally everywhere does not imply everywhere\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.johndcook.com\/blog"},{"label":"Math","link":"https:\/\/www.johndcook.com\/blog\/category\/math\/"},{"label":"Locally everywhere does not imply everywhere","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/21\/jacobian-conjecture\/"}],"_links":{"self":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247398","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/comments?post=247398"}],"version-history":[{"count":4,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247398\/revisions"}],"predecessor-version":[{"id":247405,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247398\/revisions\/247405"}],"wp:attachment":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/media?parent=247398"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/categories?post=247398"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/tags?post=247398"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}},{"id":247378,"date":"2026-07-20T09:35:21","date_gmt":"2026-07-20T14:35:21","guid":{"rendered":"https:\/\/www.johndcook.com\/blog\/?p=247378"},"modified":"2026-07-20T09:35:21","modified_gmt":"2026-07-20T14:35:21","slug":"volume-area-regular-solids","status":"publish","type":"post","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/volume-area-regular-solids\/","title":{"rendered":"Volume to Area ratio for Regular Solids"},"content":{"rendered":"<p>The volume of a sphere of radius <em>r<\/em> is<\/p>\n<p style=\"padding-left: 40px;\"><em>V<\/em> = 4\u03c0<em>r<\/em>\u00b3 \/ 3<\/p>\n<p>and the surface area is<\/p>\n<p style=\"padding-left: 40px;\"><em>A<\/em> = 4\u03c0<em>r<\/em>\u00b2<\/p>\n<p>and so the ratio of volume to area is<\/p>\n<p style=\"padding-left: 40px;\"><em>V<\/em> \/ <em>A<\/em> = <em>r<\/em> \/ 3.<\/p>\n<p>Surprisingly, the same ratio holds for all regular solids if\u00a0<em>r<\/em> is the radius of the largest sphere that can be inscribed inside the regular solid.<\/p>\n<p>For example, if the edge of a cube is\u00a0<em>a<\/em>, then\u00a0<em>r<\/em> =\u00a0<em>a<\/em>\/2. The volume is 8<em>r<\/em>\u00b3, the area is 24<em>r<\/em>\u00b2, and the ratio is\u00a0<em>r<\/em>\/3.<\/p>\n<p>The relationship between edge length and radius, and between radius and volume, is more complicated for the four other regular solids (tetrahedron, octahedron, dodecahedron, and icosahedron). However, in each case the ratio of volume to area is\u00a0<em>r<\/em>\/3.<\/p>\n<p>The proof is surprisingly simple. Pick a face and form a pyramid by connecting each face vertex to the center of the inscribed sphere. The pyramid has height <em>r<\/em> and volume equal to\u00a0<em>B<\/em>\/3 where\u00a0<em>B<\/em> is the area of the base. If the regular solid has\u00a0<em>f<\/em> faces, the volume of the solid is\u00a0<em>fBr<\/em> \/ 3 and the area is\u00a0<em>fB<\/em>. So the ratio of volume to area is\u00a0<em>r<\/em>\/3.<\/p>\n<p>The theorem generalizes to <em>n<\/em> &gt; 3 dimensions. The formula for the volume of a pyramid in <em>n<\/em> dimensions is\u00a0<em>Bh<\/em>\/<em>n<\/em> where\u00a0<em>B<\/em> is the (<em>n<\/em> \u2212 1)-dimensional volume of the base, and so the ratio of <em>n<\/em>-dimensional volume of a regular solid to (<em>n<\/em> \u2212 1)-dimensional volume of its boundary is <em>r<\/em>\/<em>n<\/em>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The volume of a sphere of radius r is V = 4\u03c0r\u00b3 \/ 3 and the surface area is A = 4\u03c0r\u00b2 and so the ratio of volume to area is V \/ A = r \/ 3. Surprisingly, the same ratio holds for all regular solids if\u00a0r is the radius of the largest sphere [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[9],"tags":[224],"class_list":["post-247378","post","type-post","status-publish","format-standard","hentry","category-math","tag-geometry"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"The ratio of the volume to surface area of a regular solid is r\/3 where r is the radius of the inscribed sphere.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"John\"\/>\n\t<meta name=\"keywords\" content=\"geometry\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/volume-area-regular-solids\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"John D. Cook | Applied Mathematics Consulting\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Volume to Area ratio for Regular Solids\" \/>\n\t\t<meta property=\"og:description\" content=\"The ratio of the volume to surface area of a regular solid is r\/3 where r is the radius of the inscribed sphere.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/volume-area-regular-solids\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-07-20T14:35:21+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-07-20T14:35:21+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Volume to Area ratio for Regular Solids\" \/>\n\t\t<meta name=\"twitter:description\" content=\"The ratio of the volume to surface area of a regular solid is r\/3 where r is the radius of the inscribed sphere.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Volume to Area ratio for Regular Solids","description":"The ratio of the volume to surface area of a regular solid is r\/3 where r is the radius of the inscribed sphere.","canonical_url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/volume-area-regular-solids\/","robots":"max-image-preview:large","keywords":"geometry","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"John D. Cook | Applied Mathematics Consulting","og:type":"article","og:title":"Volume to Area ratio for Regular Solids","og:description":"The ratio of the volume to surface area of a regular solid is r\/3 where r is the radius of the inscribed sphere.","og:url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/volume-area-regular-solids\/","article:published_time":"2026-07-20T14:35:21+00:00","article:modified_time":"2026-07-20T14:35:21+00:00","twitter:card":"summary","twitter:title":"Volume to Area ratio for Regular Solids","twitter:description":"The ratio of the volume to surface area of a regular solid is r\/3 where r is the radius of the inscribed sphere.","twitter:image":"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png"},"aioseo_meta_data":{"post_id":"247378","title":null,"description":"The ratio of the volume to surface area of a regular solid is r\/3 where r is the radius of the inscribed sphere.","keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"created":"2026-07-19 17:32:21","updated":"2026-07-20 16:38:00","ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\/category\/math\/\" title=\"Math\">Math<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tVolume to Area ratio for Regular Solids\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.johndcook.com\/blog"},{"label":"Math","link":"https:\/\/www.johndcook.com\/blog\/category\/math\/"},{"label":"Volume to Area ratio for Regular Solids","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/volume-area-regular-solids\/"}],"_links":{"self":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247378","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/comments?post=247378"}],"version-history":[{"count":3,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247378\/revisions"}],"predecessor-version":[{"id":247394,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247378\/revisions\/247394"}],"wp:attachment":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/media?parent=247378"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/categories?post=247378"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/tags?post=247378"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}},{"id":247386,"date":"2026-07-20T09:33:31","date_gmt":"2026-07-20T14:33:31","guid":{"rendered":"https:\/\/www.johndcook.com\/blog\/?p=247386"},"modified":"2026-07-20T09:33:31","modified_gmt":"2026-07-20T14:33:31","slug":"grok-chess","status":"publish","type":"post","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/grok-chess\/","title":{"rendered":"Solving a chess puzzle with Grok 4.5"},"content":{"rendered":"<p>I&#8217;ve written several posts about using Claude or ChatGPT to generate Prolog or Lean code to solve a chess puzzle. I didn&#8217;t think Grok would be up to the task, though I didn&#8217;t try it. I&#8217;ve heard good things about Grok 4.5, so I gave it a shot. It did great.<\/p>\n<p>Here&#8217;s the problem, a variation on the\u00a0<em>n<\/em>-queens problem formulated by Martin Gardner.<\/p>\n<blockquote><p>Can you place five white queens and three black queens on a 5 \u00d7 5 board so that no queen of one color attacks a queen of another color?<\/p><\/blockquote>\n<p>Here&#8217;s the prompt I have Grok 4.5.<\/p>\n<blockquote><p>Generate SWI Prolog code to solve the following chess puzzle. On a 5 by 5 chessboard, place 5 white queens and 3 black queens so that no queen is attacking a queen of the other color. Have the code enumerate all solutions.<\/p><\/blockquote>\n<p>The code ran correctly, giving all eight solutions.<\/p>\n<p>I then asked Grok<\/p>\n<blockquote><p>Now generate Lean 4 code to solve the same puzzle.<\/p><\/blockquote>\n<p>The code did not run on the first or second attempts but ran correctly on the third iteration. That&#8217;s better than I&#8217;ve seen before. It&#8217;s not an apples-to-apples comparison, but it has usually taken many iterations with Claude before Lean code would run.<\/p>\n<h2>Solutions<\/h2>\n<p>There are eight solutions, each being a flip or a rotation of one fundamental solution. Here&#8217;s a representative.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium\" src=\"https:\/\/www.johndcook.com\/black_white_queens.png\" width=\"400\" height=\"400\" \/><\/p>\n<h2>SWI Prolog code<\/h2>\n<pre>:- use_module(library(clpfd)).\r\n\r\n%% Enumerate all ways to place 5 white queens and 3 black queens\r\n%% on a 5x5 board so that no queen attacks a queen of the opposite colour.\r\n%% Same-colour queens are allowed to attack each other.\r\n%%\r\n%% Positions are numbered 1..25 in row-major order:\r\n%%   1  2  3  4  5\r\n%%   6  7  8  9 10\r\n%%  11 12 13 14 15\r\n%%  16 17 18 19 20\r\n%%  21 22 23 24 25\r\n\r\nsolve :-\r\n    solution(Whites, Blacks),\r\n    print_solution(Whites, Blacks),\r\n    fail.\r\nsolve :-\r\n    writeln('No more solutions.').\r\n\r\nsolution(Whites, Blacks) :-\r\n    length(Whites, 5),\r\n    length(Blacks, 3),\r\n    append(Whites, Blacks, All),\r\n    All ins 1..25,\r\n    all_distinct(All),\r\n    % canonical order so each set of positions is generated once\r\n    Whites = [W1,W2,W3,W4,W5],\r\n    W1 #&lt; W2, W2 #&lt; W3, W3 #&lt; W4, W4 #&lt; W5,\r\n    Blacks = [B1,B2,B3],\r\n    B1 #&lt; B2, B2 #&lt; B3, % every black is safe from every white maplist(safe_from_all(Whites), Blacks), label(All). safe_from_all(Whites, Black) :- maplist(no_attack(Black), Whites). %% Two queens do *not* attack each other. no_attack(P, Q) :- R1 #= (P-1) div 5 + 1, C1 #= (P-1) mod 5 + 1, R2 #= (Q-1) div 5 + 1, C2 #= (Q-1) mod 5 + 1, R1 #\\= R2, % different row C1 #\\= C2, % different column abs(R1-R2) #\\= abs(C1-C2). % different diagonal print_solution(Whites, Blacks) :- format('Whites: ~w~n', [Whites]), format('Blacks: ~w~n', [Blacks]), forall(between(1, 5, R), ( forall(between(1, 5, C), ( Pos is (R-1)*5 + C, ( memberchk(Pos, Whites) -&gt; write('W ')\r\n                      ; memberchk(Pos, Blacks) -&gt; write('B ')\r\n                      ; write('. ')\r\n                      )\r\n                    )),\r\n             nl )),\r\n    nl.\r\n<\/pre>\n<h2>Lean 4 code<\/h2>\n<pre>-- Lean 4 solution for the 5\u00d75 black-and-white queens puzzle.\r\n-- 5 white queens + 3 black queens; no opposite-colour attacks.\r\n\r\ndef absDiff (a b : Nat) : Nat :=\r\n  if a \u2265 b then a - b else b - a\r\n\r\ndef attacks (p q : Nat \u00d7 Nat) : Bool :=\r\n  p.1 == q.1 || p.2 == q.2 || absDiff p.1 q.1 == absDiff p.2 q.2\r\n\r\n\/-- All 25 squares (0-based, row-major). -\/\r\ndef allPositions : List (Nat \u00d7 Nat) :=\r\n  (List.range 5).flatMap fun r =&gt;\r\n    (List.range 5).map fun c =&gt; (r, c)\r\n\r\n\/-- Combinations of length exactly `k` (order-preserving). -\/\r\ndef combinations {\u03b1 : Type} : Nat \u2192 List \u03b1 \u2192 List (List \u03b1)\r\n  | 0,     _      =&gt; [[]]\r\n  | _,     []     =&gt; []\r\n  | k + 1, x::ys  =&gt;\r\n      (combinations k ys).map (fun zs =&gt; x :: zs) ++\r\n      combinations (k + 1) ys\r\n\r\ndef isAttackedBy (pos : Nat \u00d7 Nat) (queens : List (Nat \u00d7 Nat)) : Bool :=\r\n  queens.any (fun q =&gt; attacks q pos)\r\n\r\n\/-- Every solution as a pair (white squares, black squares). -\/\r\ndef solve : List (List (Nat \u00d7 Nat) \u00d7 List (Nat \u00d7 Nat)) :=\r\n  (combinations 3 allPositions).foldl (fun acc blacks =&gt;\r\n    let forbidden := allPositions.filter fun p =&gt;\r\n      blacks.contains p || isAttackedBy p blacks\r\n    let available := allPositions.filter fun p =&gt;\r\n      !(forbidden.contains p)\r\n    acc ++ (combinations 5 available).map fun whites =&gt; (whites, blacks)\r\n  ) []\r\n\r\n\/-- Pretty-print one board. -\/\r\ndef printBoard (whites blacks : List (Nat \u00d7 Nat)) : IO Unit := do\r\n  for r in List.range 5 do\r\n    let mut row := \"\"\r\n    for c in List.range 5 do\r\n      let p := (r, c)\r\n      row := row ++\r\n        (if whites.contains p then \"W \"\r\n         else if blacks.contains p then \"B \"\r\n         else \". \")\r\n    IO.println row\r\n  IO.println \"\"\r\n\r\n\/-- Enumerate and display every solution. -\/\r\ndef main : IO Unit := do\r\n  let sols := solve\r\n  IO.println s!\"Found {sols.length} solutions.\\n\"\r\n  for p in (List.range sols.length).zip sols do\r\n    let i := p.1\r\n    let (whites, blacks) := p.2\r\n    IO.println s!\"Solution {i + 1}:\"\r\n    printBoard whites blacks\r\n\r\n#eval main\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve written several posts about using Claude or ChatGPT to generate Prolog or Lean code to solve a chess puzzle. I didn&#8217;t think Grok would be up to the task, though I didn&#8217;t try it. I&#8217;ve heard good things about Grok 4.5, so I gave it a shot. It did great. Here&#8217;s the problem, a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-247386","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"I&#039;ve written several posts about using Claude or ChatGPT to generate Prolog or Lean code to solve a chess puzzle. I didn&#039;t think Grok would be up to the task, though I didn&#039;t try it. I&#039;ve heard good things about Grok 4.5, so I gave it a shot. It did great. Here&#039;s the problem, a\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"John\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/grok-chess\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"John D. Cook | Applied Mathematics Consulting\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Generating Lean 4 and SWI Prolog code with Grok 4.5\" \/>\n\t\t<meta property=\"og:description\" content=\"I&#039;ve written several posts about using Claude or ChatGPT to generate Prolog or Lean code to solve a chess puzzle. I didn&#039;t think Grok would be up to the task, though I didn&#039;t try it. I&#039;ve heard good things about Grok 4.5, so I gave it a shot. It did great. Here&#039;s the problem, a\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/grok-chess\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-07-20T14:33:31+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-07-20T14:33:31+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Generating Lean 4 and SWI Prolog code with Grok 4.5\" \/>\n\t\t<meta name=\"twitter:description\" content=\"I&#039;ve written several posts about using Claude or ChatGPT to generate Prolog or Lean code to solve a chess puzzle. I didn&#039;t think Grok would be up to the task, though I didn&#039;t try it. I&#039;ve heard good things about Grok 4.5, so I gave it a shot. It did great. Here&#039;s the problem, a\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Generating Lean 4 and SWI Prolog code with Grok 4.5","description":"I've written several posts about using Claude or ChatGPT to generate Prolog or Lean code to solve a chess puzzle. I didn't think Grok would be up to the task, though I didn't try it. I've heard good things about Grok 4.5, so I gave it a shot. It did great. Here's the problem, a","canonical_url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/grok-chess\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"John D. Cook | Applied Mathematics Consulting","og:type":"article","og:title":"Generating Lean 4 and SWI Prolog code with Grok 4.5","og:description":"I've written several posts about using Claude or ChatGPT to generate Prolog or Lean code to solve a chess puzzle. I didn't think Grok would be up to the task, though I didn't try it. I've heard good things about Grok 4.5, so I gave it a shot. It did great. Here's the problem, a","og:url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/grok-chess\/","article:published_time":"2026-07-20T14:33:31+00:00","article:modified_time":"2026-07-20T14:33:31+00:00","twitter:card":"summary","twitter:title":"Generating Lean 4 and SWI Prolog code with Grok 4.5","twitter:description":"I've written several posts about using Claude or ChatGPT to generate Prolog or Lean code to solve a chess puzzle. I didn't think Grok would be up to the task, though I didn't try it. I've heard good things about Grok 4.5, so I gave it a shot. It did great. Here's the problem, a","twitter:image":"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png"},"aioseo_meta_data":{"post_id":"247386","title":"Generating Lean 4 and SWI Prolog code with Grok 4.5","description":null,"keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"created":"2026-07-19 21:02:18","updated":"2026-07-20 16:38:00","ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\/category\/uncategorized\/\" title=\"Uncategorized\">Uncategorized<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tSolving a chess puzzle with Grok 4.5\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.johndcook.com\/blog"},{"label":"Uncategorized","link":"https:\/\/www.johndcook.com\/blog\/category\/uncategorized\/"},{"label":"Solving a chess puzzle with Grok 4.5","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/20\/grok-chess\/"}],"_links":{"self":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247386","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/comments?post=247386"}],"version-history":[{"count":4,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247386\/revisions"}],"predecessor-version":[{"id":247393,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247386\/revisions\/247393"}],"wp:attachment":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/media?parent=247386"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/categories?post=247386"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/tags?post=247386"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}},{"id":247380,"date":"2026-07-19T14:30:17","date_gmt":"2026-07-19T19:30:17","guid":{"rendered":"https:\/\/www.johndcook.com\/blog\/?p=247380"},"modified":"2026-07-20T06:32:14","modified_gmt":"2026-07-20T11:32:14","slug":"fitting-a-regex","status":"publish","type":"post","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/fitting-a-regex\/","title":{"rendered":"Fitting a regular expression to a list of words"},"content":{"rendered":"<p>Suppose you want to search for a list of words. If you&#8217;re using grep, you can add the <code>-f<\/code> flag provide a file of regular expressions, and you can add the <code>-F<\/code> to tell it that the regular expressions are in fact just words. I did something like this <a href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regex-speed-error\/\">a couple days ago<\/a> when searching for diagnosis codes.<\/p>\n<pre>grep -w -F -o -f icd10codes.txt notes.txt<\/pre>\n<p>Now you might want to combine your list of words into a singular regular expression, for efficiency or possibly for some other reason. Apparently ripgrep does this because when I tried replacing grep with ripgrep in the command above I got an error saying &#8220;Compiled regex exceeds size limit of 104857600 bytes.&#8221;<\/p>\n<h2>Beating brute force<\/h2>\n<p>Say you wanted to search for the strings &#8220;bluecross&#8221;, &#8220;blueshield&#8221;, and &#8220;bluey&#8221;. You could simply form the brute force regular expression<\/p>\n<pre>bluecross|blueshied|bluey<\/pre>\n<p>but that doesn&#8217;t take advantage of the fact that all three strings begin with &#8220;blue.&#8221; A smaller regular expression would be<\/p>\n<pre>blue(shield|cross|y)<\/pre>\n<p>Finding the shortest regular expression that matches a list of words is a hard problem, but finding a regular expression that&#8217;s shorter than brute force is not. The Python package <a href=\"https:\/\/github.com\/ermanh\/trieregex\">trieregex<\/a> will do this. According to the documentation,<\/p>\n<blockquote><p>trieregex creates efficient regular expressions (regexes) by storing a list of words in a trie structure, and translating the trie into a more compact pattern.<\/p><\/blockquote>\n<p>Let&#8217;s try our blue example with trieregex.<\/p>\n<pre>import re\r\nfrom trieregex import TrieRegEx as TRE\r\n\r\nwords = ['bluecross', 'blueshield', 'bluey']\r\ntre = TRE(*words) \r\nprint(tre.regex())\r\n<\/pre>\n<p>This produces the same regular expression as above, except it adds <code>?:<\/code> to make the parentheses non-capturing.<\/p>\n<pre>blue(?:shield|cross|y)<\/pre>\n<h2>Prefixes versus suffixes<\/h2>\n<p>The library builds a trie data structure using common prefixes. That works well in the example above, but the result is disappointing when we have common suffixes rather than common prefixes. The following code<\/p>\n<pre>words = ['javascript', 'typescript']\r\ntre = TRE(*words) \r\nprint(tre.regex())\r\n<\/pre>\n<p>produces the regular expression<\/p>\n<pre>(?:javascript|typescript)<\/pre>\n<p>which is no better than brute force, whereas we might have hoped for<\/p>\n<pre>(?:java|type)script<\/pre>\n<h2>HCPCS examples<\/h2>\n<p>As mentioned at the top of the post, ripgrep failed to search on a list of ICD-10 codes. The list of HCPCS codes is about 10x smaller, and more compressible. Ripgrep was able to fit all HCPCS codes into a single regex and was able to search the test file much faster than grep. The command<\/p>\n<pre>grep -w -F -o -f hcpcs.txt notes.txt<\/pre>\n<p>took 73.426 seconds to execute, while the command<\/p>\n<pre>rg -w -F -o -f hcpsc.txt notes.txt<\/pre>\n<p>took 0.078 seconds, three orders of magnitude faster.<\/p>\n<p>The following code will read a list of HCPCS codes from a file and create a regular expression.<\/p>\n<pre>tre = TRE()\r\nwith open('hcpcs.txt', 'r') as file:\r\n    for line in file:\r\n        tre.add(line.strip())\r\nprint(len(tre.regex()))\r\n<\/pre>\n<p>This shows that the resulting regular expression has 17,198 characters. The file of codes has 8725 five-character codes, so the regex compresses the code characters by roughly a ratio of 5 to 2.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Suppose you want to search for a list of words. If you&#8217;re using grep, you can add the -f flag provide a file of regular expressions, and you can add the -F to tell it that the regular expressions are in fact just words. I did something like this a couple days ago when searching [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[5],"tags":[116],"class_list":["post-247380","post","type-post","status-publish","format-standard","hentry","category-computing","tag-regular-expressions"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"Creating a regular expression that matches a given list of words. Improving on brute force. Example compressing all HCPCS codes to a regex.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"John\"\/>\n\t<meta name=\"keywords\" content=\"regular expressions\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/fitting-a-regex\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"John D. Cook | Applied Mathematics Consulting\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Fitting a regular expression to a list of words\" \/>\n\t\t<meta property=\"og:description\" content=\"Creating a regular expression that matches a given list of words. Improving on brute force. Example compressing all HCPCS codes to a regex.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/fitting-a-regex\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-07-19T19:30:17+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-07-20T11:32:14+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Fitting a regular expression to a list of words\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Creating a regular expression that matches a given list of words. Improving on brute force. Example compressing all HCPCS codes to a regex.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Fitting a regular expression to a list of words","description":"Creating a regular expression that matches a given list of words. Improving on brute force. Example compressing all HCPCS codes to a regex.","canonical_url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/fitting-a-regex\/","robots":"max-image-preview:large","keywords":"regular expressions","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"John D. Cook | Applied Mathematics Consulting","og:type":"article","og:title":"Fitting a regular expression to a list of words","og:description":"Creating a regular expression that matches a given list of words. Improving on brute force. Example compressing all HCPCS codes to a regex.","og:url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/fitting-a-regex\/","article:published_time":"2026-07-19T19:30:17+00:00","article:modified_time":"2026-07-20T11:32:14+00:00","twitter:card":"summary","twitter:title":"Fitting a regular expression to a list of words","twitter:description":"Creating a regular expression that matches a given list of words. Improving on brute force. Example compressing all HCPCS codes to a regex.","twitter:image":"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png"},"aioseo_meta_data":{"post_id":"247380","title":null,"description":"Creating a regular expression that matches a given list of words. Improving on brute force. Example compressing all HCPCS codes to a regex.","keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"created":"2026-07-19 18:13:47","updated":"2026-07-20 13:01:30","ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\/category\/computing\/\" title=\"Computing\">Computing<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tFitting a regular expression to a list of words\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.johndcook.com\/blog"},{"label":"Computing","link":"https:\/\/www.johndcook.com\/blog\/category\/computing\/"},{"label":"Fitting a regular expression to a list of words","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/fitting-a-regex\/"}],"_links":{"self":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247380","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/comments?post=247380"}],"version-history":[{"count":5,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247380\/revisions"}],"predecessor-version":[{"id":247390,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247380\/revisions\/247390"}],"wp:attachment":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/media?parent=247380"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/categories?post=247380"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/tags?post=247380"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}},{"id":247374,"date":"2026-07-19T11:41:48","date_gmt":"2026-07-19T16:41:48","guid":{"rendered":"https:\/\/www.johndcook.com\/blog\/?p=247374"},"modified":"2026-07-20T07:11:34","modified_gmt":"2026-07-20T12:11:34","slug":"sum-of-low-squares","status":"publish","type":"post","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/sum-of-low-squares\/","title":{"rendered":"Sum of low squares"},"content":{"rendered":"<h2>Squares, high and low<\/h2>\n<p>Let <em>p<\/em> be an odd prime number. Then half the numbers from 1 through <em>p<\/em> \u2212 1 are squares and half are not. That is, for half of numbers 1 \u2264 <em>k<\/em> &lt; <em>p<\/em>, the equation<\/p>\n<p style=\"padding-left: 40px;\"><em>x<\/em>\u00b2 = <em>k<\/em> mod <em>p<\/em><\/p>\n<p>has a solution. The traditional name for these numbers is &#8220;quadratic residues&#8221; but we can just say &#8220;squares&#8221; if the context is clear. So, for example, the numbers 1, 2, and 4 are squares mod 7, and the numbers 3, 5, and 6 are not.<\/p>\n<p>If <em>k<\/em> is a square mod <em>p<\/em> we will call is a <strong>low square<\/strong> if 0 \u2264\u00a0<em>k<\/em> &lt;\u00a0<em>p<\/em>\/2 and a <strong>high square<\/strong> if\u00a0<em>p<\/em>\/2 &lt;\u00a0<em>k<\/em> &lt;\u00a0<em>p<\/em>.<\/p>\n<h2>Signatures<\/h2>\n<p>Now let\u00a0<em>p<\/em> &gt; 3 be a prime congruent to 3 mod 4. Add up all the low squares mod <em>p<\/em> and take the remainder mod\u00a0<em>p<\/em>. Call this the signature of\u00a0<em>p<\/em>. Here&#8217;s Python code to make this explicit.<\/p>\n<pre>from sympy import isprime, factorint, is_quad_residue\r\n\r\ndef signature(p):\r\n    assert(p &gt; 3)\r\n    assert(isprime(p))\r\n    assert(p % 4 == 3)\r\n    s = 0\r\n    for k in range(1, 1 + p\/\/2):\r\n        if is_quad_residue(k, p):\r\n            s += k\r\n    return s % p\r\n<\/pre>\n<h2>Inverse signatures<\/h2>\n<p>Surprisingly, the signature of each <em>p<\/em> is unique. Given the signature of <em>p<\/em>, you can uniquely determine <em>p<\/em>, and in fact you can do so easily. I ran across this in a paper [1] that presented the results in the form of a parlor trick: have someone pick a prime <em>p<\/em> such that <em>p<\/em> = 3 mod 4 and ask them to compute its signature, the sum of the low squares mod <em>p<\/em>. Then you can quickly tell them what their choice of <em>p<\/em> was.<\/p>\n<p>Given a signature <em>s<\/em>, the corresponding prime <em>p<\/em> is the largest prime factor of 16<em>s<\/em> + 1.<\/p>\n<p>Not only that,<\/p>\n<p style=\"padding-left: 40px;\"><em>p<\/em> = (16<em>s<\/em> + 1)\/<em>m<\/em><\/p>\n<p>where <em>m<\/em> is the smallest of the numbers {3, 7, 11, 15} such that the fraction above is a prime number. In term of Python code, both the following functions should invert the signature of\u00a0<em>p<\/em>.<\/p>\n<pre>def inverse_signature1(s):\r\n    n = 16*s + 1\r\n    return max(factorint(n).keys())\r\n\r\ndef inverse_signature2(s):\r\n    n = 16*s + 1\r\n    for m in [3, 7, 11, 15]:\r\n        if n % m == 0 and isprime(n \/\/ m):\r\n            return n \/\/ m\r\n<\/pre>\n<p>The following code demonstrates that this is the case for numbers less than 1,000.<\/p>\n<pre>for n in range(7, 1000, 4):\r\n    if isprime(n):\r\n        s = signature(n)\r\n        assert(n == inverse_signature1(s))\r\n        assert(n == inverse_signature2(s))        \r\n<\/pre>\n<p>[1] David M. Bloom. A Quadratic Residues Parlor Trick. Mathematics Magazine, Vol. 71, No. 3 (Jun., 1998), pp. 201\u2013203.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Squares, high and low Let p be an odd prime number. Then half the numbers from 1 through p \u2212 1 are squares and half are not. That is, for half of numbers 1 \u2264 k &lt; p, the equation x\u00b2 = k mod p has a solution. The traditional name for these numbers is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[9],"tags":[94,142],"class_list":["post-247374","post","type-post","status-publish","format-standard","hentry","category-math","tag-number-theory","tag-sympy"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"If p &gt; 3 is a prime number and p = 3 mod 4, then the sum of the low squares of p uniquely determines p.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"John\"\/>\n\t<meta name=\"keywords\" content=\"number theory,sympy\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/sum-of-low-squares\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"John D. Cook | Applied Mathematics Consulting\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Sum of low squares\" \/>\n\t\t<meta property=\"og:description\" content=\"If p &gt; 3 is a prime number and p = 3 mod 4, then the sum of the low squares of p uniquely determines p.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/sum-of-low-squares\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-07-19T16:41:48+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-07-20T12:11:34+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Sum of low squares\" \/>\n\t\t<meta name=\"twitter:description\" content=\"If p &gt; 3 is a prime number and p = 3 mod 4, then the sum of the low squares of p uniquely determines p.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Sum of low squares","description":"If p > 3 is a prime number and p = 3 mod 4, then the sum of the low squares of p uniquely determines p.","canonical_url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/sum-of-low-squares\/","robots":"max-image-preview:large","keywords":"number theory,sympy","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"John D. Cook | Applied Mathematics Consulting","og:type":"article","og:title":"Sum of low squares","og:description":"If p &gt; 3 is a prime number and p = 3 mod 4, then the sum of the low squares of p uniquely determines p.","og:url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/sum-of-low-squares\/","article:published_time":"2026-07-19T16:41:48+00:00","article:modified_time":"2026-07-20T12:11:34+00:00","twitter:card":"summary","twitter:title":"Sum of low squares","twitter:description":"If p &gt; 3 is a prime number and p = 3 mod 4, then the sum of the low squares of p uniquely determines p.","twitter:image":"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png"},"aioseo_meta_data":{"post_id":"247374","title":null,"description":"If p &gt; 3 is a prime number and p = 3 mod 4, then the sum of the low squares of p uniquely determines p.","keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"created":"2026-07-19 13:14:16","updated":"2026-07-20 13:01:30","ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\/category\/math\/\" title=\"Math\">Math<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tSum of low squares\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.johndcook.com\/blog"},{"label":"Math","link":"https:\/\/www.johndcook.com\/blog\/category\/math\/"},{"label":"Sum of low squares","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/19\/sum-of-low-squares\/"}],"_links":{"self":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247374","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/comments?post=247374"}],"version-history":[{"count":4,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247374\/revisions"}],"predecessor-version":[{"id":247392,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247374\/revisions\/247392"}],"wp:attachment":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/media?parent=247374"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/categories?post=247374"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/tags?post=247374"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}},{"id":247369,"date":"2026-07-17T11:12:31","date_gmt":"2026-07-17T16:12:31","guid":{"rendered":"https:\/\/www.johndcook.com\/blog\/?p=247369"},"modified":"2026-07-17T11:12:44","modified_gmt":"2026-07-17T16:12:44","slug":"visualizing-medical-code-hierarchy","status":"publish","type":"post","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/visualizing-medical-code-hierarchy\/","title":{"rendered":"Visualizing Medical Code Hierarchy"},"content":{"rendered":"<p>Quick follow up to the previous two posts on ICD-10 codes and HCPCS codes. This post uses Python&#8217;s squarify library to create treemaps visualizing how many codes begin with each letter.<\/p>\n<p>Here&#8217;s the treemap for HCPCS codes.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium\" src=\"https:\/\/www.johndcook.com\/HCPCS_treemap.png\" alt=\"HCPCS code treemap\" width=\"600\" height=\"400\" \/><\/p>\n<p>And here&#8217;s the treemap for ICD-10 codes.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium\" src=\"https:\/\/www.johndcook.com\/ICD10_treemap.png\" alt=\"HCPCS code treemap\" width=\"600\" height=\"400\" \/><\/p>\n<p>The sizes of the squares are proportional to the number of codes beginning with that letter. Note that they are not necessarily proportional to how often codes are used.<\/p>\n<p>The HCPCS map omits R and U because these are tiny relative to the rest. The ICD-10 map omits U for the same reason.<\/p>\n<p>Here&#8217;s the code that was used to create the HCPCS map.<\/p>\n<pre>\r\nimport matplotlib.pyplot as plt\r\nimport squarify\r\n\r\n# HCPCS\r\ndata = {\r\n    \"G\": 2010,\r\n    \"J\": 1232,\r\n    \"L\": 940,\r\n    \"A\": 862,\r\n    \"E\": 671,\r\n    \"Q\": 639,\r\n    \"C\": 619,\r\n    \"S\": 533,\r\n    \"M\": 506,\r\n    \"V\": 212,\r\n    \"K\": 175,\r\n    \"T\": 114,\r\n    \"H\": 94,\r\n    \"P\": 59,\r\n    \"B\": 51,\r\n  # \"U\": 5,\r\n  # \"R\": 3,\r\n}\r\n\r\nlabels = list(data.keys())\r\nsizes = list(data.values())\r\n\r\n# Labels are just the letters (no counts)\r\ndisplay_labels = labels\r\n\r\n# Color map \u2014 one distinct color per box\r\ncolors = plt.cm.tab20.colors[: len(labels)]\r\n\r\nfig, ax = plt.subplots(figsize=(12, 8))\r\nsquarify.plot(\r\n    sizes=sizes,\r\n    label=display_labels,\r\n    color=colors,\r\n    alpha=0.85,\r\n    ax=ax,\r\n    text_kwargs={\"fontsize\": 30, \"weight\": \"bold\"},\r\n    pad=True,\r\n)\r\nax.axis(\"off\")\r\n\r\nplt.tight_layout()\r\nplt.savefig(\"treemap.png\", dpi=72)\r\nplt.show()\r\n<\/pre>\n<p>The code to create the ICD-10 map differs only in its data.<\/p>\n<pre>\r\n# ICD-10\r\ndata = {\r\n    \"S\": 31052, \r\n    \"T\": 10090, \r\n    \"M\":  6665, \r\n    \"V\":  4086, \r\n    \"H\":  3330, \r\n    \"O\":  2437, \r\n    \"Y\":  1590, \r\n    \"I\":  1427, \r\n    \"Z\":  1411, \r\n    \"W\":  1290, \r\n    \"C\":  1226, \r\n    \"L\":  1000, \r\n    \"E\":   971, \r\n    \"Q\":   894, \r\n    \"F\":   871, \r\n    \"K\":   857, \r\n    \"N\":   836, \r\n    \"D\":   824, \r\n    \"R\":   773, \r\n    \"G\":   700, \r\n    \"A\":   573, \r\n    \"X\":   495, \r\n    \"B\":   495, \r\n    \"P\":   463, \r\n    \"J\":   360, \r\n  # \"U\":     3,\r\n}  \r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Quick follow up to the previous two posts on ICD-10 codes and HCPCS codes. This post uses Python&#8217;s squarify library to create treemaps visualizing how many codes begin with each letter. Here&#8217;s the treemap for HCPCS codes. And here&#8217;s the treemap for ICD-10 codes. The sizes of the squares are proportional to the number of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[327],"class_list":["post-247369","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-medical-codes"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"The first letters of ICD-10 codes and HCPCS codes are not evenly distributed. Many more codes start with some letters than others. Visualization using treeplots.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"John\"\/>\n\t<meta name=\"keywords\" content=\"medical codes\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/visualizing-medical-code-hierarchy\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"John D. Cook | Applied Mathematics Consulting\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Visualizing medical code hierarchy with treemaps\" \/>\n\t\t<meta property=\"og:description\" content=\"The first letters of ICD-10 codes and HCPCS codes are not evenly distributed. Many more codes start with some letters than others. Visualization using treeplots.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/visualizing-medical-code-hierarchy\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-07-17T16:12:31+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-07-17T16:12:44+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Visualizing medical code hierarchy with treemaps\" \/>\n\t\t<meta name=\"twitter:description\" content=\"The first letters of ICD-10 codes and HCPCS codes are not evenly distributed. Many more codes start with some letters than others. Visualization using treeplots.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Visualizing medical code hierarchy with treemaps","description":"The first letters of ICD-10 codes and HCPCS codes are not evenly distributed. Many more codes start with some letters than others. Visualization using treeplots.","canonical_url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/visualizing-medical-code-hierarchy\/","robots":"max-image-preview:large","keywords":"medical codes","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"John D. Cook | Applied Mathematics Consulting","og:type":"article","og:title":"Visualizing medical code hierarchy with treemaps","og:description":"The first letters of ICD-10 codes and HCPCS codes are not evenly distributed. Many more codes start with some letters than others. Visualization using treeplots.","og:url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/visualizing-medical-code-hierarchy\/","article:published_time":"2026-07-17T16:12:31+00:00","article:modified_time":"2026-07-17T16:12:44+00:00","twitter:card":"summary","twitter:title":"Visualizing medical code hierarchy with treemaps","twitter:description":"The first letters of ICD-10 codes and HCPCS codes are not evenly distributed. Many more codes start with some letters than others. Visualization using treeplots.","twitter:image":"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png"},"aioseo_meta_data":{"post_id":"247369","title":"Visualizing medical code hierarchy with treemaps","description":"The first letters of ICD-10 codes and HCPCS codes are not evenly distributed. Many more codes start with some letters than others. Visualization using treeplots.","keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"created":"2026-07-17 16:00:31","updated":"2026-07-18 00:54:35","ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\/category\/uncategorized\/\" title=\"Uncategorized\">Uncategorized<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tVisualizing Medical Code Hierarchy\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.johndcook.com\/blog"},{"label":"Uncategorized","link":"https:\/\/www.johndcook.com\/blog\/category\/uncategorized\/"},{"label":"Visualizing Medical Code Hierarchy","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/visualizing-medical-code-hierarchy\/"}],"_links":{"self":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247369","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/comments?post=247369"}],"version-history":[{"count":3,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247369\/revisions"}],"predecessor-version":[{"id":247372,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247369\/revisions\/247372"}],"wp:attachment":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/media?parent=247369"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/categories?post=247369"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/tags?post=247369"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}},{"id":247363,"date":"2026-07-17T09:02:52","date_gmt":"2026-07-17T14:02:52","guid":{"rendered":"https:\/\/www.johndcook.com\/blog\/?p=247363"},"modified":"2026-07-18T08:22:03","modified_gmt":"2026-07-18T13:22:03","slug":"regular-expressions-for-hcpcs-codes","status":"publish","type":"post","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regular-expressions-for-hcpcs-codes\/","title":{"rendered":"Regular expressions for HCPCS codes"},"content":{"rendered":"<p>Since I revisited my old post on ICD code matching, I thought I&#8217;d revisit by <a href=\"https:\/\/www.johndcook.com\/blog\/2022\/09\/23\/hcpcs-codes\/\">post on HCPCS codes<\/a> too.<\/p>\n<p>HCPCS stands for Healthcare Common Procedure Coding System, and is pronounced &#8220;hick picks.&#8221; When most people say HCPCS, they technically mean HCPCS Level II, and that&#8217;s what I mean here.<\/p>\n<p>The format of a HCPCS code is simple: one letter and four digits. In regex terms,<\/p>\n<pre>    [A-Z]\\d{4}<\/pre>\n<p>Not all letters are used, so you can get more specific and say<\/p>\n<pre>    [A-CEGHJ-MP-V][0-9]\\d{4}<\/pre>\n<p>Some sources say no codes begin with U, but there are currently five codes that begin with U.<\/p>\n<p>When I was doing some research on HCPCS codes recently using AI, I was told there is a D code for dentistry, but that was a hallucination.<\/p>\n<p>HCPCS codes can also have modifiers. These consist of a letter and either a letter or digit:<\/p>\n<pre>    [A-Z][A-Z0-9]<\/pre>\n<p>Not all letters actually appear in modifiers\u2014I, O, W, and Y are missing\u2014so you could be more specific. At the time of writing there are 384 official modifiers.<\/p>\n<p>Modifiers are often stored in a separate column in a database, but in text you&#8217;ll see a HCPCS code optionally followed by a dash and a modifier. So a regex to match HCPCS codes with possible modifiers would be<\/p>\n<pre>    [A-CEGHJ-MP-V][0-9]\\d{4}(-[A-Z][A-Z0-9])?<\/pre>\n<p>This regex will have some false positives, but it should not have false negatives: every real HCPCS code should match.<\/p>\n<p>Of course you could search against a complete list of HCPCS codes. This would be more accurate and slower. I did a test similar to the one in the <a href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regex-speed-error\/\">previous post<\/a> and found a search with the regex above took 20 milliseconds, while a search against the list of HCPCS codes took 46 seconds.<\/p>\n<p>However, the regex searched for possible modifiers and the exhaustive search only looked for unmodified HCPCS codes. A complete list of HCPCS codes with possible modifiers would be tedious to create because some combinations of codes and modifiers make no sense. And I imagine that some combinations that would make sense are not used in practice.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Since I revisited my old post on ICD code matching, I thought I&#8217;d revisit by post on HCPCS codes too. HCPCS stands for Healthcare Common Procedure Coding System, and is pronounced &#8220;hick picks.&#8221; When most people say HCPCS, they technically mean HCPCS Level II, and that&#8217;s what I mean here. The format of a HCPCS [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[5],"tags":[327,116],"class_list":["post-247363","post","type-post","status-publish","format-standard","hentry","category-computing","tag-medical-codes","tag-regular-expressions"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"Regular expressions for HCPCS codes. Comparing the search speed for a regex approximation to an exhaustive search.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"John\"\/>\n\t<meta name=\"keywords\" content=\"medical codes,regular expressions\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regular-expressions-for-hcpcs-codes\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"John D. Cook | Applied Mathematics Consulting\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Regular expressions for HCPCS codes\" \/>\n\t\t<meta property=\"og:description\" content=\"Regular expressions for HCPCS codes. Comparing the search speed for a regex approximation to an exhaustive search.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regular-expressions-for-hcpcs-codes\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-07-17T14:02:52+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-07-18T13:22:03+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Regular expressions for HCPCS codes\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Regular expressions for HCPCS codes. Comparing the search speed for a regex approximation to an exhaustive search.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Regular expressions for HCPCS codes","description":"Regular expressions for HCPCS codes. Comparing the search speed for a regex approximation to an exhaustive search.","canonical_url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regular-expressions-for-hcpcs-codes\/","robots":"max-image-preview:large","keywords":"medical codes,regular expressions","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"John D. Cook | Applied Mathematics Consulting","og:type":"article","og:title":"Regular expressions for HCPCS codes","og:description":"Regular expressions for HCPCS codes. Comparing the search speed for a regex approximation to an exhaustive search.","og:url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regular-expressions-for-hcpcs-codes\/","article:published_time":"2026-07-17T14:02:52+00:00","article:modified_time":"2026-07-18T13:22:03+00:00","twitter:card":"summary","twitter:title":"Regular expressions for HCPCS codes","twitter:description":"Regular expressions for HCPCS codes. Comparing the search speed for a regex approximation to an exhaustive search.","twitter:image":"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png"},"aioseo_meta_data":{"post_id":"247363","title":null,"description":"Regular expressions for HCPCS codes. Comparing the search speed for a regex approximation to an exhaustive search.","keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"created":"2026-07-17 13:27:27","updated":"2026-07-18 14:53:07","ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\/category\/computing\/\" title=\"Computing\">Computing<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tRegular expressions for HCPCS codes\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.johndcook.com\/blog"},{"label":"Computing","link":"https:\/\/www.johndcook.com\/blog\/category\/computing\/"},{"label":"Regular expressions for HCPCS codes","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regular-expressions-for-hcpcs-codes\/"}],"_links":{"self":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247363","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/comments?post=247363"}],"version-history":[{"count":5,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247363\/revisions"}],"predecessor-version":[{"id":247373,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247363\/revisions\/247373"}],"wp:attachment":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/media?parent=247363"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/categories?post=247363"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/tags?post=247363"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}},{"id":247356,"date":"2026-07-17T06:26:19","date_gmt":"2026-07-17T11:26:19","guid":{"rendered":"https:\/\/www.johndcook.com\/blog\/?p=247356"},"modified":"2026-07-17T08:41:24","modified_gmt":"2026-07-17T13:41:24","slug":"regex-speed-error","status":"publish","type":"post","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regex-speed-error\/","title":{"rendered":"Regular expression speed and error rates"},"content":{"rendered":"<p><a href=\"https:\/\/www.johndcook.com\/blog\/2019\/05\/05\/regex_icd_codes\/\">Seven years ago<\/a> I wrote a post about regular expressions to match diagnosis codes. I wanted to revisit that post looking at speed and error rates.<\/p>\n<p>Regular expressions usually do not exactly match what you&#8217;re looking for and nothing else. They have error false positives and false negatives. But they also have advantages, and context determines whether the advantages make the error rates tolerable.<\/p>\n<p>The post mentioned above gave the following regular expression for ICD-10 diagnosis codes.<\/p>\n<pre>    [A-TV-Z][0-9][0-9AB]\\.?[0-9A-TV-Z]{0,4}<\/pre>\n<p>As cryptic as this may look at first glance, it&#8217;s straight-forward to interpret. It says that an ICD-10 code<\/p>\n<ol>\n<li>Begins with a capital letter, excluding U<\/li>\n<li>Followed by a digit<\/li>\n<li>Followed by a digit or A or B<\/li>\n<li>Optionally followed by a period<\/li>\n<li>Followed by up to 4 digits or capital letters, excluding U.<\/li>\n<\/ol>\n<h2>Speed<\/h2>\n<p>Now suppose you want to scan a text document for ICD-10 codes. One approach would be to use the regex above. Another would be to compare every alphanumeric sequence in the document to a list of ICD-10. Currently this list has 74,719 codes. <\/p>\n<p>I tested both approaches on a 800kb text file. The regex search<\/p>\n<pre>    egrep -o '[A-TV-Z][0-9][0-9AB]\\.?[0-9A-TV-Z]{0,4}' notes.txt<\/pre>\n<p>took 18 milliseconds. Searching against the list of codes<\/p>\n<pre>    grep -w -F -o -f icd10codes.txt notes.txt<\/pre>\n<p>took 386 seconds, about six and a half minutes or five orders of magnitude longer.<\/p>\n<h2>Error rates<\/h2>\n<p>The regex<\/p>\n<pre>    [A-TV-Z][0-9][0-9AB]\\.?[0-9A-TV-Z]{0,4}<\/pre>\n<p>had a false negative rate of zero at the time it was written. I tested the regex against the current list of codes with the following command.<\/p>\n<pre>    egrep -v '[A-TV-Z][0-9][0-9AB]\\.?[0-9A-TV-Z]{0,4}' icd10codes.txt<\/pre>\n<p>The <code>-v<\/code> flag reverses the sense of the search, reporting lines that do not match the regular expression. This returned three matches: U070, U071, and U099. So 3 out of 74,719 valid ICD-10 codes were reported as invalid.<\/p>\n<p>Codes beginning with U are designated for provisional\/emergency\/special purposes, but these three have become essentially permanent. A change in the application of the ICD-10 standard caused an error in the regular expression. <\/p>\n<p>But the change would also have caused an error in code that did an exhaustive search against the list of ICD-10 codes at the time. In fact, every new code not starting with U would also be reported in error. So the regex is actually more future-proof than an exhaustive search. Presumably the simplified regex<\/p>\n<pre>    [A-Z][0-9][0-9AB]\\.?[0-9A-Z]{0,4}<\/pre>\n<p>will remain valid for the foreseeable future.<\/p>\n<p>We&#8217;ve looked at false negatives. What about false positives? That depends on context. The false positive rate when searching medical notes is low: a word matching the regex above in a medical record is most likely an ICD-10 code. But the number of conceivable false positives is enormous. If you were searching a file of randomly generated alphanumeric text, the regex matches would overwhelmingly be false positives [1].<\/p>\n<p>The number of strings matching<\/p>\n<pre>    [A-Z][0-9][0-9AB]\\.?[0-9A-Z]{0,4}<\/pre>\n<p>would be<\/p>\n<p style=\"padding-left: 40px;\">26 \u00d7 10 \u00d7 12 \u00d7 (1 + 36 + 36<sup>2<\/sup> + 36<sup>3<\/sup> + 36<sup>4<\/sup>) = 5,390,127,600.<\/p>\n<p>Out of over five billion strings matching the regular expression, only around 75,000 are valid ICD-10 codes. So a naive theoretical calculation would say the false positive rate is 99.9986%, whereas in practice the false positive rate is very low, though there&#8217;s no way to say\u00a0<em>a priori<\/em> exactly how low.<\/p>\n<h2>Related posts<\/h2>\n<ul>\n<li class='link'><a href='https:\/\/www.johndcook.com\/blog\/2022\/09\/23\/hcpcs-codes\/'>HCPCS (\u201chick pics\u201d) codes<\/a><\/li>\n<li class='link'><a href='https:\/\/www.johndcook.com\/blog\/2024\/06\/26\/npi-number\/'>NPI numbers and checksum<\/a><\/li>\n<li class='link'><a href='https:\/\/www.johndcook.com\/blog\/expert-hipaa-deidentification\/'>HIPAA expert determination<\/a><\/li>\n<\/ul>\n<p>[1] You could argue that all positives would be false positives in this context because you&#8217;re looking at noise. You couldn&#8217;t find an ICD code, though you could find a string of characters that coincides with an ICD code. That may sound like a pedantic distinction, but it matters in the context of evaluating deidentification quality: you want to find instances of PHI, not instances of strings that match the character pattern of PHI.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Seven years ago I wrote a post about regular expressions to match diagnosis codes. I wanted to revisit that post looking at speed and error rates. Regular expressions usually do not exactly match what you&#8217;re looking for and nothing else. They have error false positives and false negatives. But they also have advantages, and context [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[5],"tags":[327,116],"class_list":["post-247356","post","type-post","status-publish","format-standard","hentry","category-computing","tag-medical-codes","tag-regular-expressions"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"Looking at match speed and error rates for regular expressions, using ICD-10 diagnosis codes as a case study.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"John\"\/>\n\t<meta name=\"keywords\" content=\"medical codes,regular expressions\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regex-speed-error\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"John D. Cook | Applied Mathematics Consulting\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Regular expression speed and error rates\" \/>\n\t\t<meta property=\"og:description\" content=\"Looking at match speed and error rates for regular expressions, using ICD-10 diagnosis codes as a case study.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regex-speed-error\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-07-17T11:26:19+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-07-17T13:41:24+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Regular expression speed and error rates\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Looking at match speed and error rates for regular expressions, using ICD-10 diagnosis codes as a case study.\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Regular expression speed and error rates","description":"Looking at match speed and error rates for regular expressions, using ICD-10 diagnosis codes as a case study.","canonical_url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regex-speed-error\/","robots":"max-image-preview:large","keywords":"medical codes,regular expressions","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"John D. Cook | Applied Mathematics Consulting","og:type":"article","og:title":"Regular expression speed and error rates","og:description":"Looking at match speed and error rates for regular expressions, using ICD-10 diagnosis codes as a case study.","og:url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regex-speed-error\/","article:published_time":"2026-07-17T11:26:19+00:00","article:modified_time":"2026-07-17T13:41:24+00:00","twitter:card":"summary","twitter:title":"Regular expression speed and error rates","twitter:description":"Looking at match speed and error rates for regular expressions, using ICD-10 diagnosis codes as a case study.","twitter:image":"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png"},"aioseo_meta_data":{"post_id":"247356","title":null,"description":"Looking at match speed and error rates for regular expressions, using ICD-10 diagnosis codes as a case study.","keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"created":"2026-07-17 10:00:47","updated":"2026-07-17 16:01:03","ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\/category\/computing\/\" title=\"Computing\">Computing<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tRegular expression speed and error rates\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.johndcook.com\/blog"},{"label":"Computing","link":"https:\/\/www.johndcook.com\/blog\/category\/computing\/"},{"label":"Regular expression speed and error rates","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/17\/regex-speed-error\/"}],"_links":{"self":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247356","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/comments?post=247356"}],"version-history":[{"count":7,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247356\/revisions"}],"predecessor-version":[{"id":247364,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247356\/revisions\/247364"}],"wp:attachment":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/media?parent=247356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/categories?post=247356"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/tags?post=247356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}},{"id":247340,"date":"2026-07-14T09:24:12","date_gmt":"2026-07-14T14:24:12","guid":{"rendered":"https:\/\/www.johndcook.com\/blog\/?p=247340"},"modified":"2026-07-14T09:29:14","modified_gmt":"2026-07-14T14:29:14","slug":"icd-10-chapters-letters","status":"publish","type":"post","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/14\/icd-10-chapters-letters\/","title":{"rendered":"ICD-10 chapters and code letters"},"content":{"rendered":"<p>I&#8217;ve been thinking about ICD-10 codes; they come up a lot in my work. <\/p>\n<p>The ICD-10-CM standard is divided into 21 chapters, which <em>generally<\/em> correspond to the first letter of a code. However, a chapter may contain blocks beginning with more than one letter, and codes starting with a single letter, namely D, can span two chapters.<\/p>\n<p>Here&#8217;s a diagram I made to visualize the relationship between chapters and initial letters of codes.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.johndcook.com\/icd10_chapters_letters.svg\" width=\"400\" height=\"1056\" class=\"aligncenter size-medium\" style=\"background-color:white\" \/><\/p>\n<p>Notice there&#8217;s no letter U on the diagram. That&#8217;s because U is reserved for special\/provisional codes.<\/p>\n<h2>Related posts<\/h2>\n<ul>\n<li class='link'><a href='https:\/\/www.johndcook.com\/blog\/2019\/04\/27\/rare-and-strange-icd-10-codes\/'>Rare and strange ICD-10 codes<\/a><\/li>\n<li class='link'><a href='https:\/\/www.johndcook.com\/blog\/2019\/05\/05\/regex_icd_codes\/'>Regex to match ICD-9 and ICD-10 codes<\/a><\/li>\n<li class='link'><a href='https:\/\/www.johndcook.com\/blog\/2021\/04\/20\/new-icd-10-weirdness\/'>New ICD-10 code weirdness<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been thinking about ICD-10 codes; they come up a lot in my work. The ICD-10-CM standard is divided into 21 chapters, which generally correspond to the first letter of a code. However, a chapter may contain blocks beginning with more than one letter, and codes starting with a single letter, namely D, can span [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[327],"class_list":["post-247340","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-medical-codes"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"Diagram for visualizing the relationship between ICD-10 chapters and initial letters of ICD-10 codes\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"John\"\/>\n\t<meta name=\"keywords\" content=\"medical codes\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/14\/icd-10-chapters-letters\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"John D. Cook | Applied Mathematics Consulting\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"ICD-10 chapters and code letters\" \/>\n\t\t<meta property=\"og:description\" content=\"Diagram for visualizing the relationship between ICD-10 chapters and initial letters of ICD-10 codes\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.johndcook.com\/blog\/2026\/07\/14\/icd-10-chapters-letters\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-07-14T14:24:12+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-07-14T14:29:14+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"ICD-10 chapters and code letters\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Diagram for visualizing the relationship between ICD-10 chapters and initial letters of ICD-10 codes\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"ICD-10 chapters and code letters","description":"Diagram for visualizing the relationship between ICD-10 chapters and initial letters of ICD-10 codes","canonical_url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/14\/icd-10-chapters-letters\/","robots":"max-image-preview:large","keywords":"medical codes","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"John D. Cook | Applied Mathematics Consulting","og:type":"article","og:title":"ICD-10 chapters and code letters","og:description":"Diagram for visualizing the relationship between ICD-10 chapters and initial letters of ICD-10 codes","og:url":"https:\/\/www.johndcook.com\/blog\/2026\/07\/14\/icd-10-chapters-letters\/","article:published_time":"2026-07-14T14:24:12+00:00","article:modified_time":"2026-07-14T14:29:14+00:00","twitter:card":"summary","twitter:title":"ICD-10 chapters and code letters","twitter:description":"Diagram for visualizing the relationship between ICD-10 chapters and initial letters of ICD-10 codes","twitter:image":"https:\/\/www.johndcook.com\/blog\/wp-content\/uploads\/2022\/05\/twittercard.png"},"aioseo_meta_data":{"post_id":"247340","title":null,"description":"Diagram for visualizing the relationship between ICD-10 chapters and initial letters of ICD-10 codes","keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"created":"2026-07-14 14:06:42","updated":"2026-07-15 22:15:59","ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.johndcook.com\/blog\/category\/uncategorized\/\" title=\"Uncategorized\">Uncategorized<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tICD-10 chapters and code letters\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.johndcook.com\/blog"},{"label":"Uncategorized","link":"https:\/\/www.johndcook.com\/blog\/category\/uncategorized\/"},{"label":"ICD-10 chapters and code letters","link":"https:\/\/www.johndcook.com\/blog\/2026\/07\/14\/icd-10-chapters-letters\/"}],"_links":{"self":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247340","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/comments?post=247340"}],"version-history":[{"count":4,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247340\/revisions"}],"predecessor-version":[{"id":247345,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/posts\/247340\/revisions\/247345"}],"wp:attachment":[{"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/media?parent=247340"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/categories?post=247340"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.johndcook.com\/blog\/wp-json\/wp\/v2\/tags?post=247340"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}]