<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>royvanrijn</title>
    <description>Java, algorithms, math, science and more!</description>
    <link>https://royvanrijn.com/</link>
    <atom:link href="https://royvanrijn.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 04 Aug 2026 16:58:50 +0200</pubDate>
    <lastBuildDate>Tue, 04 Aug 2026 16:58:50 +0200</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>Vibe-mathing: the Generalized Vanishing Conjecture</title>
        <description>&lt;p&gt;&lt;strong&gt;I am a developer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Right now it is difficult to ignore the argument around “&lt;strong&gt;vibe coding&lt;/strong&gt;.”&lt;/p&gt;

&lt;p&gt;People who could not have written an application in the traditional way are
&lt;strong&gt;describing&lt;/strong&gt; what they want to an AI, running the result, reporting what broke,
and iterating. Some of the resulting software is &lt;strong&gt;fragile&lt;/strong&gt;. Some of it is
surprisingly capable.&lt;/p&gt;

&lt;p&gt;Either way, the &lt;strong&gt;phenomenon is real&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;uncomfortable&lt;/strong&gt; part for &lt;em&gt;experienced&lt;/em&gt; developers is not only that code is
being generated. It is that the people producing it do not necessarily &lt;strong&gt;read
or understand&lt;/strong&gt; every line of code. They generate tests and just look at the result.&lt;/p&gt;

&lt;p&gt;Vibe-coders sometimes even seem to have a &lt;strong&gt;major advantage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Their unwillingness or unability to read the code makes it possible to work with several agents
in parallel, producing &lt;strong&gt;incredible&lt;/strong&gt; speedups. However, I am &lt;strong&gt;not&lt;/strong&gt; going to settle the
questions of viability or quality of vibe-coded software here… I’m too invested.&lt;/p&gt;

&lt;p&gt;Instead, I decided to take that instinct somewhere else: to vibe &lt;strong&gt;my way&lt;/strong&gt; into
a field about which I had very limited knowledge, not burdened by &lt;strong&gt;knowledge,
deep understanding, or preconceptions&lt;/strong&gt;:&lt;/p&gt;

&lt;h2 id=&quot;straight-into-mathematics&quot;&gt;Straight into: Mathematics&lt;/h2&gt;

&lt;p&gt;As a developer, I have spent a lot of time using tools like Codex, refining prompts, and running
parallel experiments. Also, large software systems have always exceeded the
understanding of any &lt;strong&gt;one person&lt;/strong&gt;. So abstractions and unknowns is part of what we do.&lt;/p&gt;

&lt;p&gt;We navigate them through interfaces, types, tests, logs, debuggers, reproducible builds, and carefully chosen
experiments. None of these makes a program correct. Together, however, they
let us ask much better questions than “does this code accomplish the goal(s)?”&lt;/p&gt;

&lt;p&gt;I began to wonder whether something similar was possible in &lt;strong&gt;mathematics&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Could I enter a field in which I did not have the expected training, use AI
to navigate definitions and possible constructions, generate exact data,
loop through failed ideas, and gradually replace intuition with artifacts
that could be checked? Could I begin exploring before I understood the whole
territory in the traditional order?&lt;/p&gt;

&lt;p&gt;Or, stated more &lt;strong&gt;provocatively&lt;/strong&gt;: could I too vibe-math my way to a genuine
mathematical frontier?&lt;/p&gt;

&lt;h2 id=&quot;the-tweet&quot;&gt;The tweet…&lt;/h2&gt;

&lt;p&gt;The real spark here was Levent posting the &lt;a href=&quot;https://x.com/__alpoge__/status/2079028340955197566&quot;&gt;JC(3) counterexample&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;hello there the jacobian conjecture is false thanx to my close friend akhil for asking about it and my other close friend fable for working during the world cup final&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suddenly there was a concrete mathematical object to inspect:
&lt;strong&gt;a three-variable construction&lt;/strong&gt; connected to the &lt;strong&gt;Jacobian Conjecture&lt;/strong&gt;, with
a new algebraic structure that could be tested, generalized,
formalized, and attacked from several directions.&lt;/p&gt;

&lt;p&gt;This was my starting point. Instead of just asking whether AI could “do a breakthrough”, or produce mathematics that looked plausible, I could ask whether an AI-assisted process could locate the exact boundary or a new counterexample.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Counterexamples&lt;/strong&gt; are especially useful here, they are &lt;strong&gt;easy to check&lt;/strong&gt; and &lt;strong&gt;verify&lt;/strong&gt;. Do the calculation, and done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proofs&lt;/strong&gt; require way more human feedback, analysis and &lt;strong&gt;scrutiny&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The experiment was never supposed to be “can AI produce a paper that looks like mathematics?” We already know that it can. There is more than enough &lt;strong&gt;slob&lt;/strong&gt; online. That is precisely the problem: A plausible-looking proof is now almost free, while the time needed to find the hidden gap still belongs to a human reader.&lt;/p&gt;

&lt;p&gt;The real question was:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Can AI-assisted exploration turn this counterexample into a result that survives exact computation, independent implementations, formal proof, explicit statement boundaries, and eventually human mathematical review?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Generalized Vanishing Conjecture became one of my test cases, one of my goals. And the result is a
sharp boundary: it holds for every constant-coefficient differential operator in one or two variables, and it fails from dimension three onward.&lt;/p&gt;

&lt;p&gt;This is the story of how Levent’s post became a theorem, a counterexample, and a collection of steps/receipts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://zenodo.org/records/21782342&quot;&gt;The Generalized Vanishing Conjecture: The Two-Variable Theorem and the First Failing Dimension&lt;/a&gt;&lt;/strong&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The counterexample and failure in every dimension at least three are fully Lean-verified; nearly all supporting algebraic machinery and much of the binary proof infrastructure are checked as well&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Repository source: &lt;a href=&quot;https://github.com/royvanrijn/jacobian-research/blob/main/papers/generalized-vanishing-two-variables/main.tex&quot;&gt;papers/generalized-vanishing-two-variables/main.tex&lt;/a&gt;&lt;br /&gt;
Lean proof: &lt;a href=&quot;https://github.com/royvanrijn/jacobian-research/tree/main/formal/gvc&quot;&gt;github.com/royvanrijn/jacobian-research/tree/main/formal/gvc&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;a-conjecture-with-an-infinite-premise&quot;&gt;A conjecture with an infinite premise&lt;/h2&gt;

&lt;p&gt;Lets start with the &lt;strong&gt;Generalized Vanishing Conjecture (GVC)&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Let \(\Lambda\) be a constant-coefficient differential operator and let
\(P\) be a polynomial. GVC asks whether&lt;/p&gt;

\[\Lambda^m(P^m)=0\quad\text{for every }m\geq1\]

&lt;p&gt;forces&lt;/p&gt;

\[\Lambda^m(QP^m)=0\quad\text{for all sufficiently large }m\]

&lt;p&gt;for every fixed polynomial multiplier \(Q\).&lt;/p&gt;

&lt;p&gt;The statement grew out of work around the Vanishing Conjecture and the
Jacobian Conjecture. But what made it especially interesting to me was its
shape. The premise is an infinite sequence of exact identities, and the
conclusion is eventual vanishing after inserting any fixed multiplier.&lt;/p&gt;

&lt;p&gt;This is exactly the kind of statement on which vibe-mathing can go wrong.
A search can verify the first ten powers, or the first hundred, and still
prove nothing about the next one. Perhaps we can explain why a visible pattern
“should” continue and bury the missing quantifier inside a polished proof.&lt;/p&gt;

&lt;p&gt;My biggest rule became:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A bounded search will not proof GVC.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It does not mean bounded searches are useless, but it changed what I allowed them
to mean.&lt;/p&gt;

&lt;h2 id=&quot;the-long-route-through-exact-computation&quot;&gt;The long route through exact computation&lt;/h2&gt;

&lt;p&gt;I began classifying low-degree cases in &lt;strong&gt;two variables&lt;/strong&gt;. The calculations
separated operator symbols by root type, exposed exceptional coefficient
branches, and tracked which weighted faces could survive the first several
pure identities.&lt;/p&gt;

&lt;p&gt;Again and again, the same patterns appeared. Surviving supports became
one-sided. Moment ideals developed staircase-shaped radicals. A complicated
coefficient system would collapse onto a face where a simple weighted
degree deficit forced every mixed expression to vanish eventually.&lt;/p&gt;

&lt;p&gt;Degree by degree, exact calculations closed polynomial degrees four, five,
&lt;strong&gt;six&lt;/strong&gt;, and &lt;strong&gt;seven&lt;/strong&gt; for arbitrary binary constant-coefficient operators. These
were real theorems in their stated ranges. They were not a license to draw
an all-degree curve through four data points.&lt;/p&gt;

&lt;p&gt;The attempted general proof grew into a much larger machine: Hall
matchings, factorial packets, prime-power carries, characters, Graver
bases, and finite traces. AI was useful here in the same way it is useful in
an unfamiliar codebase. It could suggest representations, translate between
formulations, generate experiments, and help turn a failed idea into a
smaller exact question.&lt;/p&gt;

&lt;p&gt;Many pieces of that machine became valid mathematics. The machine as a
whole did not close the conjecture. One promotion step kept moving away: I
could understand a packet after it had been isolated, but I could not prove
that the original infinite vanishing premise always exposed one fixed
packet in the required way.&lt;/p&gt;

&lt;p&gt;This was an important part of the experiment. The repository accumulated
more positive results without quietly changing the status of the missing
step. The route was productive, but it remained incomplete.&lt;/p&gt;

&lt;p&gt;I kept telling Codex to &lt;em&gt;“find general patterns, try to think about global structures at play here”&lt;/em&gt;. Sometimes I would have one thread list ideas, and spin up agent threads to experiment until they either reach an extension, elimination, or a dead end.&lt;/p&gt;

&lt;p&gt;Then the proof became shorter.&lt;/p&gt;

&lt;h2 id=&quot;two-moving-newton-faces&quot;&gt;Two moving Newton faces&lt;/h2&gt;

&lt;p&gt;Take the symbol of \(\Lambda\) and the support of \(P\). For every positive
weight&lt;/p&gt;

\[w_s=(s,1),\]

&lt;p&gt;look at two faces:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the lowest-weight face of the operator symbol;&lt;/li&gt;
  &lt;li&gt;the highest-weight face of the polynomial.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pure vanishing identity passes to these extremal faces. Hall’s marriage
theorem orders their horizontal Newton intervals just after ordinary
degree. A separate prime-dilation argument shows that, while the two faces
have unequal weights, their intervals cannot overlap.&lt;/p&gt;

&lt;p&gt;In two variables, this has a decisive consequence. The projection of each
face is an interval on a line. Two disjoint intervals cannot exchange order
without meeting.&lt;/p&gt;

&lt;p&gt;Now define the lower operator envelope \(L(s)\) and the upper polynomial
envelope \(U(s)\). Their gap&lt;/p&gt;

\[\Delta(s)=U(s)-L(s)\]

&lt;p&gt;is piecewise linear because both supports are finite. Just after \(s=1\),
Hall localization puts the operator interval strictly to the right of the
polynomial interval. Shifted-ray rigidity prevents the intervals from
overlapping, so they cannot pass one another while \(\Delta(s)&amp;gt;0\).&lt;/p&gt;

&lt;p&gt;The gap cannot stay positive forever. After the last breakpoint its slope
is &lt;strong&gt;forced&lt;/strong&gt; to be negative, so it must reach zero. At the first meeting, every
operator monomial lies on or above one common weighted threshold and every
polynomial monomial lies on or below it. A fixed multiplier contributes
only a bounded defect; it cannot repair a deficit that grows linearly with
the power \(m\).&lt;/p&gt;

&lt;p&gt;That proves:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Over a characteristic-zero field, every constant-coefficient differential operator in two variables satisfies the Generalized Vanishing Conjecture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The short proof also explains the staircase radicals from the earlier
computer algebra. They were not mysterious survivors. They were finite
shadows of a geometric fact: the moving Newton intervals were forbidden to
overlap.&lt;/p&gt;

&lt;p&gt;Years of imagined mathematical labor had collapsed into following two
piecewise-linear envelopes until they met.&lt;/p&gt;

&lt;h2 id=&quot;then-the-conjecture-broke-completely&quot;&gt;Then the conjecture broke completely&lt;/h2&gt;

&lt;p&gt;The binary theorem raised the obvious question: was two variables merely
the first case of a higher-dimensional principle?&lt;/p&gt;

&lt;p&gt;It turns out: &lt;strong&gt;no&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Put&lt;/p&gt;

\[\rho=t^2+xy,\qquad A=\rho+x^2,\]

\[C=y\rho^2-2xt^2\rho-x^3t^2,
\qquad P=AC^2,\]

&lt;p&gt;and let&lt;/p&gt;

\[\Delta=4\partial_x\partial_y+\partial_t^2,
\qquad \Lambda=\Delta^6.\]

&lt;p&gt;Then, for every \(m\geq1\),&lt;/p&gt;

\[\Lambda^m(P^m)=0,
\qquad
\Lambda^m(x^2P^m)\ne0.\]

&lt;p&gt;The first identity supplies the complete pure premise. The second uses the
single fixed multiplier \(Q=x^2\) and fails at every power, not merely
infinitely often. This is a homogeneous counterexample in three variables.&lt;/p&gt;

&lt;p&gt;And once it fails in &lt;strong&gt;three variables&lt;/strong&gt;, every larger dimension follows almost
&lt;strong&gt;for free&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Rename the three variables \(x_1,x_2,x_3\) and regard the same polynomial as
one in \(ngeq4\) variables:&lt;/p&gt;

\[\widetilde P(x_1,\ldots,x_n)=P(x_1,x_2,x_3),\]

&lt;p&gt;so \(\widetilde P\) is completely independent of
\(x_4,\ldots,x_n\). Extend the three-variable quadratic operator by putting&lt;/p&gt;

\[\widetilde\Delta_n
=4\partial_{x_1}\partial_{x_2}+\partial_{x_3}^2
+\sum_{i=4}^n\partial_{x_i}^2.\]

&lt;p&gt;For every polynomial \(f\) depending only on the first three variables,&lt;/p&gt;

\[\widetilde\Delta_n f
=\left(4\partial_{x_1}\partial_{x_2}+\partial_{x_3}^2\right)f
=\Delta_3f,\]

&lt;p&gt;because&lt;/p&gt;

\[\partial_{x_i}f=0\qquad(i\geq4).\]

&lt;p&gt;Applying the same observation repeatedly gives&lt;/p&gt;

\[\widetilde\Delta_n^k f=\Delta_3^k f\]

&lt;p&gt;for every \(k\geq0\). We can therefore take&lt;/p&gt;

\[\Lambda_n=\widetilde\Delta_n^6.\]

&lt;p&gt;The pure identity is inherited verbatim:&lt;/p&gt;

\[\Lambda_n^m(\widetilde P^m)
=\widetilde\Delta_n^{6m}(\widetilde P^m)
=\Delta_3^{6m}(P^m)
=0.\]

&lt;p&gt;And for the same multiplier \(Q(x_1,x_2,x_3)\), the obstruction survives:&lt;/p&gt;

\[\Lambda_n^m(Q\widetilde P^m)
=\Delta_3^{6m}(QP^m)
\neq0.\]

&lt;p&gt;So the counterexample in three variables automatically produces one in
every dimension \(n\geq3\). Combined with the binary theorem, the exact
dimensional classification is:&lt;/p&gt;

\[\boxed{\operatorname{GVC}(n)\text{ holds if and only if }n\leq2.}\]

&lt;p&gt;The same boundary already holds when the differential operator is required
to be homogeneous.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;two variables&lt;/strong&gt;, Newton faces project to intervals
and inherit a total order. In &lt;strong&gt;three variables&lt;/strong&gt;, higher-dimensional faces can
move around one another. The mechanism that makes the binary proof work is
precisely what &lt;strong&gt;disappears&lt;/strong&gt; at the first failing dimension.&lt;/p&gt;

&lt;h2 id=&quot;from-a-witness-to-an-all-order-lean-theorem&quot;&gt;From a witness to an all-order Lean theorem&lt;/h2&gt;

&lt;p&gt;Because we’re using AI here, we want to be &lt;strong&gt;extra careful&lt;/strong&gt; and &lt;strong&gt;complete&lt;/strong&gt;. One way to achieve this is formal verification in Lean, next to the Python, SymPy and Singluar scripts used in the discovery.&lt;/p&gt;

&lt;p&gt;The GVC &lt;a href=&quot;https://github.com/royvanrijn/jacobian-research/tree/main/formal/gvc&quot;&gt;public Lean development&lt;/a&gt;
is not a small certificate attached to the end of the project. It currently
contains more than 3,100 lines across sixteen modules and 164 theorem or
lemma declarations, with no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sorry&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;admit&lt;/code&gt;, or explicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;axiom&lt;/code&gt;
declarations. We have now checked almost every part of the argument that can
be cleanly isolated into an algebraic interface.&lt;/p&gt;

&lt;p&gt;Most importantly, the three-variable counterexample is formalized &lt;strong&gt;end to
end&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The development does &lt;strong&gt;not&lt;/strong&gt; check a list of sample powers. It defines the
literal polynomials \(\rho,A,C,P\), the operator \(\Delta\), its sixth
power \(\Lambda\), and the multiplier \(Q\). It then proves the algebraic
machinery connecting them:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;coefficientwise semantics for constant-coefficient differential
operators;&lt;/li&gt;
  &lt;li&gt;composition of operator symbols and apolar top contraction;&lt;/li&gt;
  &lt;li&gt;the cusp identity behind the construction;&lt;/li&gt;
  &lt;li&gt;the Reynolds–phase identity by exact coefficient expansion;&lt;/li&gt;
  &lt;li&gt;the endpoint coefficient extraction for every power;&lt;/li&gt;
  &lt;li&gt;the zero pure coefficient and exact nonzero neighboring coefficient;&lt;/li&gt;
  &lt;li&gt;base change from the rationals to every characteristic-zero field;&lt;/li&gt;
  &lt;li&gt;padding from three variables to every larger finite dimension.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The resulting Lean theorem is &lt;strong&gt;unconditional&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;GVC fails over every characteristic-zero field in every finite dimension at least three&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the entire negative half of the dimensional classification, fully
checked for all powers, fields, and finite dimensions in its stated scope.
Nothing in the counterexample is left as an assumed computational bridge.&lt;/p&gt;

&lt;p&gt;The formalization goes &lt;strong&gt;considerably further&lt;/strong&gt;. It checks the coefficientwise
definition of GVC, operator composition, top contraction, the full endpoint
coefficient ladder, formal beta evaluation, exact factorial valuations,
Reynolds expansion, Laurent phase extraction, coefficient-ring base change,
unused-variable padding, the winding–profile–radial degree formulas, and
the final piecewise-linear envelope crossing used by the positive theorem.&lt;/p&gt;

&lt;p&gt;What remains &lt;strong&gt;outside&lt;/strong&gt; Lean is concentrated: the
global Hall-localization and shifted-ray separation bridge that drives the
short binary proof, together with its no-reversal and common-threshold
termination argument. Those steps are common and proved in the paper. Everything
around that bridge has been reduced to explicit definitions, exact lemmas,
or independent degree-four through degree-seven regressions.&lt;/p&gt;

&lt;p&gt;This combination matters to me. Exploration &lt;strong&gt;found&lt;/strong&gt; the construction and the
proof architecture. Exact computation kept &lt;strong&gt;killing false branches&lt;/strong&gt;.
Formalization then converted the entire negative half of the dimensional
classification, and as much of the positive machinery as possible, into declarations that
can be &lt;strong&gt;checked from definitions&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-i-think-i-learned&quot;&gt;What (I think) I learned&lt;/h2&gt;

&lt;p&gt;The strongest version of “vibe-mathing” is not mathematics &lt;em&gt;without&lt;/em&gt;
understanding.&lt;/p&gt;

&lt;p&gt;It is mathematics in which understanding does not always have to arrive
first.&lt;/p&gt;

&lt;p&gt;I could begin by navigating representations, generating examples, asking AI
for possible bridges, and trying to falsify every bridge that appeared.
Exact computation let me reject bad directions. Formalization forced vague
claims to split into precise ones. Writing the proof forced me to explain
why the surviving path worked.&lt;/p&gt;

&lt;p&gt;Most of my understanding &lt;em&gt;followed&lt;/em&gt; the artifacts. It did not precede all of them.&lt;/p&gt;

&lt;p&gt;That changes what may be possible for people outside the normal research
pipeline. It does not abolish expertise, and I would not say that it makes
the work easier for them. It creates a new and confusing landscape and experience: people will begin
exploring unfamiliar mathematics before they have the usual training, but they will probably also produce a great deal of &lt;strong&gt;low-quality&lt;/strong&gt; material
that needs to be filtered.&lt;/p&gt;

&lt;p&gt;AI may actually be very useful for a first pass, helping &lt;strong&gt;rate, sort, and identify&lt;/strong&gt; which
artifacts deserve closer human attention. But that is only a pre-check, not
a substitute for expert judgment. The remaining human questions become:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Is this the right theorem?&lt;/li&gt;
  &lt;li&gt;Is the interface with the literature correct?&lt;/li&gt;
  &lt;li&gt;Is an apparently small hypothesis carrying hidden mathematical content?&lt;/li&gt;
  &lt;li&gt;Is the ordinary proof outside the formal boundary sound?&lt;/li&gt;
  &lt;li&gt;Has the result already appeared in another language?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are &lt;strong&gt;exactly&lt;/strong&gt; the questions on which I now want expert criticism.&lt;/p&gt;

&lt;p&gt;The GVC project forced the process in &lt;em&gt;both directions&lt;/em&gt; at once: a &lt;strong&gt;general
positive theorem in two variables&lt;/strong&gt; and a &lt;strong&gt;concrete failure in three&lt;/strong&gt;. Crossing
between those modes was far harder than generating plausible candidates. It
required a growing system of definitions, tests, exact certificates, failed
searches, formal proofs, literature boundaries, and prose.&lt;/p&gt;

&lt;p&gt;I do not know yet how the mathematical community will judge the result.
That judgment cannot be automated, sped up, made easier…&lt;/p&gt;

&lt;p&gt;As a software developer struggling with accepting vibe-coded codebases, I can imagine what mathematicians are going through right now. But the right response is the same, now we inspect the statement, run the checks, read the proof, and try to break it.&lt;/p&gt;

&lt;p&gt;The vibes helped find the path. Verification decided what survives, counterexamples are easy to verify, proofs are definitely not.&lt;/p&gt;

&lt;p&gt;There was &lt;strong&gt;one final twist&lt;/strong&gt;. On the very same day, &lt;strong&gt;Christopher D. Long&lt;/strong&gt; messaged me and &lt;a href=&quot;https://x.com/octonion/status/2084445366972244168&quot;&gt;reported&lt;/a&gt;
that he had independently found &lt;strong&gt;two other proofs&lt;/strong&gt;, using ideas unrelated
to this one. We had reached the same conclusion from three different
directions, without coordination.&lt;/p&gt;

&lt;p&gt;For a result about the exact boundary
between truth and failure, that convergence felt especially remarkable.&lt;/p&gt;

&lt;h2 id=&quot;links&quot;&gt;Links&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://zenodo.org/records/21782342&quot;&gt;Published GVC preprint on Zenodo&lt;/a&gt;, DOI &lt;a href=&quot;https://doi.org/10.5281/zenodo.21782342&quot;&gt;10.5281/zenodo.21782342&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/royvanrijn/jacobian-research/tree/main/formal/gvc&quot;&gt;Public Lean proof and formalization&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/royvanrijn/jacobian-research/blob/main/papers/generalized-vanishing-two-variables/main.tex&quot;&gt;Repository source&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/royvanrijn/jacobian-research/blob/main/extended-geometry/BINARY_GVC_ENVELOPE_CLOSURE.md&quot;&gt;Unrestricted binary GVC by Hall-envelope separation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/royvanrijn/jacobian-research/blob/main/extended-geometry/THREE_VARIABLE_HOMOGENEOUS_GVC_COUNTEREXAMPLE.md&quot;&gt;Homogeneous three-variable counterexample&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/royvanrijn/jacobian-research/blob/main/formal/gvc/README.md&quot;&gt;Lean coverage and build instructions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/royvanrijn/jacobian-research/blob/main/REPRODUCE.md&quot;&gt;Reproduction catalogue&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The formal development is pinned to Lean and Mathlib versions recorded in
the repository. From the repository root, build the GVC verification with:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make verify-gvc-lean
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Tue, 04 Aug 2026 16:25:21 +0200</pubDate>
        <link>https://royvanrijn.com/blog/2026/08/vibe-mathing-the-generalized-vanishing-conjecture/</link>
        <guid isPermaLink="true">https://royvanrijn.com/blog/2026/08/vibe-mathing-the-generalized-vanishing-conjecture/</guid>
        
        <category>ai</category>
        
        <category>mathematics</category>
        
        <category>lean</category>
        
        <category>formal-verification</category>
        
        <category>generalized-vanishing-conjecture</category>
        
        
        <category>Mathematics</category>
        
      </item>
    
      <item>
        <title>The Anatomy of an LLM</title>
        <description>&lt;p&gt;I think I’ve finished something I’ve been building for a while:&lt;/p&gt;

&lt;h2 id=&quot;the-anatomy-of-an-llm&quot;&gt;&lt;a href=&quot;https://www.royvanrijn.com/anatomy-of-an-llm/&quot;&gt;The Anatomy of an LLM&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;It is a visual, interactive walk-through of the main machinery inside a large language model.&lt;/p&gt;

&lt;p&gt;Not just “it predicts the next token”, but what actually happens before that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How text becomes tokens&lt;/li&gt;
  &lt;li&gt;How tokens become vectors&lt;/li&gt;
  &lt;li&gt;How neural networks process those vectors&lt;/li&gt;
  &lt;li&gt;How attention works&lt;/li&gt;
  &lt;li&gt;How transformer blocks are stacked together&lt;/li&gt;
  &lt;li&gt;How the model ends up choosing the next token&lt;/li&gt;
  &lt;li&gt;And why things like context windows, KV cache and quantization matter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It started as a small explanation, but of course that quickly got out of hand.&lt;/p&gt;

&lt;p&gt;It is still marked beta, and I’m sure there are things that can be improved. But at some point you have to stop tweaking and publish.&lt;/p&gt;

&lt;p&gt;Take a look:
&lt;strong&gt;&lt;a href=&quot;https://www.royvanrijn.com/anatomy-of-an-llm/&quot;&gt;The Anatomy of an LLM&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 28 May 2026 13:00:00 +0200</pubDate>
        <link>https://royvanrijn.com/blog/2026/05/the-anatomy-of-an-llm/</link>
        <guid isPermaLink="true">https://royvanrijn.com/blog/2026/05/the-anatomy-of-an-llm/</guid>
        
        <category>llm</category>
        
        <category>machine-learning</category>
        
        <category>transformers</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Introduction to Java Notebooks</title>
        <description>&lt;p&gt;&lt;strong&gt;Java Notebook&lt;/strong&gt; is a new and exciting way to explore the &lt;a href=&quot;https://www.java.org&quot;&gt;Java&lt;/a&gt; programming language. It works a lot like &lt;a href=&quot;https://jupyter.org/try-jupyter/retro/notebooks/?path=notebooks/Intro.ipynb&quot;&gt;Jupyter Notebooks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Notebooks are a community standard for communicating and performing interactive computing. They are a document that blends computations, outputs, explanatory text, mathematics, images, and rich media representations of objects.&lt;/p&gt;

&lt;p&gt;It allows you to interleave blocks of text (in &lt;a href=&quot;https://en.wikipedia.org/wiki/Markdown&quot;&gt;Markdown&lt;/a&gt;), editable &lt;em&gt;and&lt;/em&gt; executable &lt;strong&gt;Java&lt;/strong&gt; code blocks and output blocks.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Edit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello world!&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; Hello world!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, when we run the code block above, the output is immediately updated. It is similar to &lt;a href=&quot;https://dev.java/learn/jshell-tool/&quot;&gt;JShell&lt;/a&gt;, but in the browser.&lt;/p&gt;

&lt;h2 id=&quot;maven-support&quot;&gt;Maven support&lt;/h2&gt;

&lt;p&gt;Notebooks are an ideal tool to teach programming languages and to display and explore libraries and frameworks. Notebooks also support the import of external libraries using &lt;a href=&quot;https://maven.apache.org/&quot;&gt;Apache Maven&lt;/a&gt;. Here is an example using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;load&lt;/code&gt; command to import &lt;a href=&quot;https://commons.apache.org/&quot;&gt;Apache Commons&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Edit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commons&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;commons&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lang3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.apache.commons.lang3.StringUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;StringUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello world!&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; !dlrow olleH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;data-processing-with-jandas&quot;&gt;Data processing with jandas&lt;/h2&gt;

&lt;p&gt;It is also possible to directly import resources from internet and parse them to &lt;strong&gt;Java&lt;/strong&gt; objects and records using frameworks like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jandas&lt;/code&gt; (loosely based on &lt;a href=&quot;https://pandas.pydata.org/&quot;&gt;pandas&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Here is an interactive example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Edit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;jandas:jandas:&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.24&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.jandas.*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Song&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rank&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;songName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amountStreams&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;artist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Date&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;releaseDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;songs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CsvReader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.royvanrijn.com/examples/data/spotify_top_1000.csv&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Song&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Lady Gaga currently has &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;artist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Lady Gaga&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; top 1000 hits.&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Ed Sheeran has &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;artist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Ed Sheeran&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;mapToLong&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;amountStreams&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; total streams&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Bohemian Rhapsody was released: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;songs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;songName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Bohemian Rhapsody&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;releaseDate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;findAny&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; Lady Gaga currently has 6 top 1000 hits.
&amp;gt; Ed Sheeran has 26513653 total streams.
&amp;gt; Bohemian Rhapsody was released: Fri Oct 31 00:00:00 CET 1975
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;hosting-your-own-notebooks&quot;&gt;Hosting your own Notebooks&lt;/h2&gt;

&lt;p&gt;It is very easy to host your own notebooks. Users can run notebooks locally (using &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;) or use one of the following free cloud services to run your &lt;strong&gt;Java Notebook&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.oracle.com/this_does_not_exist/&quot;&gt;Oracle Cloud Notebooks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://colab.research.google.com/&quot;&gt;Google Colab&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/java_notebooks_should_become_a_reality/&quot;&gt;Azure JBooks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.azul.com/java_notebooks_is_a_dream/&quot;&gt;Azul Cloudrunner&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;And many others..&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If &lt;strong&gt;you&lt;/strong&gt; build or maintain a framework or library, or if you have a website explaining Java programming: Please add these &lt;em&gt;interactive&lt;/em&gt; notebooks to your website. This makes it incredibly easy for new developers to get acquainted with your code.&lt;/p&gt;

&lt;h2 id=&quot;wake-up&quot;&gt;Wake up!&lt;/h2&gt;

&lt;p&gt;Sadly (as you might have noticed) the examples above do not work. It was all just a dream. There is no such thing as a (widely used) Java Notebook.&lt;/p&gt;

&lt;p&gt;The reason I wrote this post is the famous &lt;a href=&quot;https://www.tiobe.com/tiobe-index/&quot;&gt;TIOBE Index&lt;/a&gt; of programming languages.&lt;/p&gt;

&lt;p&gt;Today is the first day since &lt;strong&gt;2001&lt;/strong&gt; that &lt;strong&gt;Java &lt;em&gt;isn’t&lt;/em&gt; in the top 3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That is why we, as the Java community, should look at our competition. What &lt;em&gt;did&lt;/em&gt; Python do &lt;em&gt;right&lt;/em&gt;? Why is &lt;em&gt;it&lt;/em&gt; topping the chart?&lt;/p&gt;

&lt;p&gt;A major reason, I think, is the feedback and steep learning curve of Java. If you want to parse some data, would you rather download a Java Runtime, install an IDE, install Maven etc? Or would you rather open the browser, have documentation and tutorials inlined with running examples? This is &lt;strong&gt;SO&lt;/strong&gt; much easier.&lt;/p&gt;

&lt;p&gt;The same is true for learning frontend/Javascript, there are so many websites that allow you to jump right in and test your code, sites like &lt;a href=&quot;https://jsfiddle.net/&quot;&gt;jsfiddle&lt;/a&gt; or &lt;a href=&quot;https://codepen.io/&quot;&gt;codepen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My wish for &lt;strong&gt;2023&lt;/strong&gt;: Oracle, Microsoft, Google, Azul… &lt;em&gt;PLEASE make this a reality&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;they-do-exist&quot;&gt;They do exist…&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Update 2023-05-01&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Almost forgot: There are some online Java Notebooks that provide much of the functionality given above, here are some options you can consider:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://zeppelin.apache.org/&quot;&gt;Apache Zeppelin&lt;/a&gt; (a Jupyter-like runtime that has &lt;a href=&quot;https://zeppelin.apache.org/docs/0.10.1/interpreter/java.html&quot;&gt;Java bindings&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/SpencerPark/IJava&quot;&gt;IJava&lt;/a&gt; (a Jupyter kernel for executing Java code)&lt;/li&gt;
  &lt;li&gt;And more, mostly single developer hacked/weekend projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main problem I have isn’t that these project don’t exist; we just don’t &lt;strong&gt;utilize them&lt;/strong&gt;, at all. There is no widespread support for this. It would be such a &lt;em&gt;powermove&lt;/em&gt; if Oracle launched a similar product and encouraged libraries to embed it (running on their cloud for example).&lt;/p&gt;

&lt;p&gt;If you want to get into AI/deep learning for example, here are two examples, Java or Python, I know which I’d pick:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Java&lt;/strong&gt;: &lt;a href=&quot;https://deeplearning4j.konduit.ai/multi-project/tutorials/quickstart&quot;&gt;Quickstart DeepLearning4J&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Twenty steps of installing Java, Maven, git, IntelliJ, check out a project…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt;: &lt;a href=&quot;https://colab.research.google.com/github/tensorflow/docs/blob/master/site/en/tutorials/quickstart/beginner.ipynb&quot;&gt;Tensorflow Quickstart for Beginners&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;No setup at all; from the start you’re importing Tensorflow and running the examples.&lt;/p&gt;

&lt;p&gt;It isn’t all bad, here is an example where it &lt;em&gt;does&lt;/em&gt; work:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Java&lt;/strong&gt;: &lt;a href=&quot;https://docs.djl.ai/jupyter/tutorial/01_create_your_first_network.html&quot;&gt;DJL&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Easy to overlook, but press the top button “Run this notebook online”. Using IJava and Jupyter, yay!&lt;/p&gt;

&lt;h2 id=&quot;perfect-for-httpsdevjava&quot;&gt;Perfect for: https:://dev.java&lt;/h2&gt;

&lt;p&gt;I’d love for &lt;a href=&quot;https://dev.java/&quot;&gt;dev.java&lt;/a&gt; to become more engaging or interactive, something like a notebook. Have a place online where you can “Try now” without having to install everything.&lt;/p&gt;

&lt;p&gt;Currently the &lt;a href=&quot;https://dev.java/learn/getting-started-with-java/&quot;&gt;Getting Started&lt;/a&gt; goes as follows:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open a plain text file, write your first class, without code formatting etc.&lt;/li&gt;
  &lt;li&gt;Now you &lt;em&gt;could&lt;/em&gt; compile it and run &lt;strong&gt;TADAA!&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;But wait, you need to install a JDK first&lt;/li&gt;
  &lt;li&gt;Download JDK&lt;/li&gt;
  &lt;li&gt;Install JDK&lt;/li&gt;
  &lt;li&gt;Learn to use the compiler&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Now&lt;/strong&gt; run it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nobody got time for that anymore, sure, perhaps after you’ve decided to really go for it. But with notebooks you get instant results, you can tinker away, run stuff in the browser and see the results, perfect.&lt;/p&gt;

&lt;p&gt;Anywaaaay, enough ranting for today ✌️&lt;/p&gt;
</description>
        <pubDate>Wed, 04 Jan 2023 23:35:00 +0100</pubDate>
        <link>https://royvanrijn.com/blog/2023/01/java-notebooks/</link>
        <guid isPermaLink="true">https://royvanrijn.com/blog/2023/01/java-notebooks/</guid>
        
        <category>java</category>
        
        <category>notebooks</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Solving the daily calendar puzzle</title>
        <description>&lt;p&gt;About a month ago I was watching a YouTube video where YouTuber &lt;a href=&quot;https://www.youtube.com/c/DrewGooden1/videos&quot;&gt;Drew Gooden&lt;/a&gt; was struggling with a “weird” puzzle:&lt;/p&gt;

&lt;iframe type=&quot;text/html&quot; width=&quot;640&quot; height=&quot;390&quot; frameborder=&quot;0&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot; src=&quot;https://www.youtube.com/embed/WbAuL4fg5LI?start=888&amp;amp;title=0&amp;amp;byline=0&amp;amp;portrait=0&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;This is what the puzzle looks like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/daily-calendar-puzzle.jpg&quot; alt=&quot;example of the Daily Calendar Puzzle&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It has 10 pieces that can be flipped/rotated and placed on a calendar. They claim there is a solution for each day/month/weekday combination. In the YouTube video Drew is struggling and says:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The problem is, I’ll never be able to prove that&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But… what if we &lt;strong&gt;can&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;As a programmer this sounds like a perfect little puzzle to solve.&lt;/p&gt;

&lt;h1 id=&quot;solving-the-puzzle&quot;&gt;Solving the puzzle&lt;/h1&gt;

&lt;p&gt;To solve this, I first encoded all the puzzle pieces, this is relatively easy to do because it’s just a 2D grid.&lt;/p&gt;

&lt;p&gt;Next I wrote the code to generate all the possible rotations of a certain puzzle piece (and eliminated duplicates). Some pieces have more rotations than others because some are the same after a 180 degree rotation, others are not.&lt;/p&gt;

&lt;p&gt;Next I blocked the target puzzle solutions on the board, for example “2nd June Monday”, placing three markers.&lt;/p&gt;

&lt;p&gt;After that I just go through all possible piece/location combinations, placing the first puzzle piece in the top position and continuing down.&lt;/p&gt;

&lt;p&gt;This was fast enough to solve the first puzzle after a couple of minutes.&lt;/p&gt;

&lt;p&gt;But… not fast enough to generate &lt;strong&gt;all&lt;/strong&gt;: 12 (months) x 31 (days) x 7 (weekdays) = 2.604 solutions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example output&lt;/strong&gt;: The image above has a solution for Thursday 8th of April. The code outputs this as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Solution for: 8/4 [5]:
0 0 0 X 1 1 X 
2 2 0 0 4 1 X 
2 2 3 3 4 1 1 
X 2 3 4 4 5 5 
7 6 3 3 5 5 9 
7 6 6 6 6 8 9 
7 7 7 8 8 8 9 
X X X X X 8 9 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each number 0-9 stands for a certain puzzle piece. The X’s are blocked off (solution and edge).&lt;/p&gt;

&lt;h1 id=&quot;improve-solving-speed&quot;&gt;Improve solving speed&lt;/h1&gt;

&lt;p&gt;To improve the speed of the solver I decided to do a small flood fill after placing each puzzle piece. If we’ve created a spot where there are just 4 places left (a small island) I stopped looking further, because no puzzle piece will ever fill this spot.&lt;/p&gt;

&lt;p&gt;This small algorithmic improvement was enough to make it fast enough to generate a puzzle solution for every single combination.&lt;/p&gt;

&lt;h1 id=&quot;links&quot;&gt;Links&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Solutions:&lt;/strong&gt; If you’re just looking for all the solutions: &lt;a href=&quot;https://github.com/royvanrijn/Daily-Calendar-Puzzle/blob/main/solutions.txt&quot;&gt;solutions.txt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt; If you want to take a look at the (Java) code, check out &lt;a href=&quot;https://github.com/royvanrijn/Daily-Calendar-Puzzle/blob/main/PuzzleADaySolver.java&quot;&gt;PuzzleADaySolver.java&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Thu, 07 Jul 2022 20:42:12 +0200</pubDate>
        <link>https://royvanrijn.com/blog/2022/07/daily-calendar-puzzle-solutions/</link>
        <guid isPermaLink="true">https://royvanrijn.com/blog/2022/07/daily-calendar-puzzle-solutions/</guid>
        
        <category>daily</category>
        
        <category>puzzle</category>
        
        <category>calendar</category>
        
        <category>algorithm</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>All The Music: the Megamix</title>
        <description>&lt;p&gt;Or a clickbait title:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;How I became the world’s most prolific DJ, using code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This week I stumbled across a cool project: &lt;a href=&quot;http://allthemusic.info/&quot;&gt;All The Music&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Damien Riehl (programmer/copyright attorney) and Noah Rubin (programmer) decided to generate &lt;strong&gt;all possible songs&lt;/strong&gt; with the basic 8 major notes (C4,D4,E4,F4,G4,A4,B4 and C5) with length 12. All these songs have been ‘freely’ released under the ‘Creative Commons’ license. Their goal is to stop copyright claims on melodies.&lt;/p&gt;

&lt;iframe type=&quot;text/html&quot; width=&quot;640&quot; height=&quot;390&quot; frameborder=&quot;0&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot; src=&quot;https://www.youtube.com/embed/sJtm0MoOgiU?title=0&amp;amp;byline=0&amp;amp;portrait=0&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;While watching their excellent TED talk and hearing about the challenges they had to generate these songs, my head instantly made some connections. They generated &lt;strong&gt;all&lt;/strong&gt; songs of length &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n=12&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k=8&lt;/code&gt; notes, this amounts to a staggering &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n^k = 8^12 = 68,719,476,736&lt;/code&gt; unique songs.&lt;/p&gt;

&lt;p&gt;All these songs are 12 notes long and have their own MIDI file which adds even more overhead. The size of this dataset is &lt;strong&gt;huge&lt;/strong&gt;, 1.2TB compressed using GZIP.&lt;/p&gt;

&lt;h1 id=&quot;using-a-de-bruijn-sequence&quot;&gt;Using a de Bruijn sequence&lt;/h1&gt;

&lt;p&gt;This is when I got an idea: perhaps we can use a &lt;a href=&quot;/blog/2011/02/generating-de-bruijn-sequences-and-lyndon-words/&quot;&gt;de Bruijn sequence&lt;/a&gt; for this?&lt;/p&gt;

&lt;p&gt;I’ve blogged about those sequences before, basically it is an optimal way to arrange these N elements into a single sequence so that each and every combination of K-length is present in the sequence.&lt;/p&gt;

&lt;p&gt;For example if we have all combinations of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0,1,2&lt;/code&gt; of length &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4&lt;/code&gt; the naïve way would be to do it:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0000
0001
0002
0010
0011
0012 (etc)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Instead when creating a de Bruijn we have:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;000012200210002212021211212222011221022211012101001011112001102111002012010202202[000]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Every possible 4-length combination/permutation is present in this single line (check them!).&lt;/p&gt;

&lt;p&gt;What if we could &lt;em&gt;remix&lt;/em&gt; &lt;strong&gt;every&lt;/strong&gt; possible 12 note melody into one huge megamix!?&lt;/p&gt;

&lt;p&gt;That would mean I’m mathematically the world’s best DJ, remixing almost all existing songs including &lt;em&gt;EVERY&lt;/em&gt; song from the &lt;a href=&quot;http://allthemusic.info/&quot;&gt;All The Music&lt;/a&gt; dataset into &lt;strong&gt;one&lt;/strong&gt; song.&lt;/p&gt;

&lt;h1 id=&quot;setting-to-work&quot;&gt;Setting to work&lt;/h1&gt;

&lt;p&gt;I already have some very efficient code to generate these sequences. What if I output the sequence as a single MIDI file?&lt;/p&gt;

&lt;p&gt;Because a de Bruijn sequence usually wraps around, if we want to create all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n=12&lt;/code&gt; length melodies we’ll need to append the first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n-1&lt;/code&gt; notes to the &lt;strong&gt;end&lt;/strong&gt; of the sequence (which I’ve done above as well). This means we’ll need just a single MIDI file with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;68,719,476,747&lt;/code&gt; unique notes in it.&lt;/p&gt;

&lt;p&gt;This gave me a &lt;em&gt;tiny&lt;/em&gt; problem: a MIDI file has a ‘LENGTH’ field stored in just 4-bytes. And &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2^32&lt;/code&gt; is &lt;em&gt;only&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4,294,967,295&lt;/code&gt;. So we’ve hit a technical problem, we can’t fit our remix into a single MIDI file.&lt;/p&gt;

&lt;p&gt;To solve this I decided to cut the single song up into a collection of ‘smaller’ more managable songs. In the end I settled on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2052&lt;/code&gt; unique songs that create one huge megamix album. On this album is every single song possible with notes C4,D4,E4,F4,G4,A4,B4 and C5 of length 12. The same as is contained in the ATM’s dataset.&lt;/p&gt;

&lt;p&gt;When breaking up a de Bruijn sequence, each new song has to repeat the final &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n-1&lt;/code&gt; notes of the previous song, that way each melody is contained in full. For example if we split the above sequence into two parts we’ll need to do:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Song 1: 000012200210002212021211212222011221022211012
Song 2: [012]101001011112001102111002012010202202[000]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This results in the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;1&lt;/strong&gt; remix album: debruijn8-12.tar&lt;/li&gt;
  &lt;li&gt;Size: 16.735.957.504 bytes (16,75 GB on disk)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contains:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;2052&lt;/strong&gt; GZIP-ed MIDI songs&lt;/li&gt;
  &lt;li&gt;2051 songs with a 33,500,000 note melody&lt;/li&gt;
  &lt;li&gt;1 song with a 10,999,308 note melody&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;really-every-song&quot;&gt;Really? Every song?&lt;/h1&gt;

&lt;p&gt;Let’s listen to some songs that are in the dataset (somewhere):&lt;/p&gt;

&lt;p&gt;Example 1, Twinkle Twinkle:&lt;/p&gt;

&lt;midi-player src=&quot;/music/example1.mid&quot; sound-font=&quot;&quot; visualizer=&quot;#myVisualizer-/music/example1.mid&quot;&gt;
&lt;/midi-player&gt;

&lt;p&gt;Example 2, Jingle Bells:&lt;/p&gt;

&lt;midi-player src=&quot;/music/example2.mid&quot; sound-font=&quot;&quot; visualizer=&quot;#myVisualizer-/music/example2.mid&quot;&gt;
&lt;/midi-player&gt;

&lt;p&gt;Example 3, Can You Feel The Love Tonight.&lt;/p&gt;

&lt;midi-player src=&quot;/music/example3.mid&quot; sound-font=&quot;&quot; visualizer=&quot;#myVisualizer-/music/example3.mid&quot;&gt;
&lt;/midi-player&gt;

&lt;p&gt;All possible 12 note melodies are in the remix.&lt;/p&gt;

&lt;h1 id=&quot;is-this-better&quot;&gt;Is this better?&lt;/h1&gt;

&lt;p&gt;This got me thinking, why didn’t Damien and Noah go for this approach? It is much smaller and faster to generate (in a single morning).&lt;/p&gt;

&lt;p&gt;So I turned to Twitter and asked Damien Riehl!
And sure enough: his answer makes total sense:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We had initially considered a “de Bruijn” sequence. But if we were to use a &lt;em&gt;single&lt;/em&gt; file, that would have down sides:&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;
      &lt;p&gt;If someone infringes our work, it would only be a tiny percentage (0.0000000001%?) of the “work” — so someone would argue “fair use”&lt;/p&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;p&gt;Same idea with others incorporating ATM works in theirs (“tiny percentage”)&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;So our technical/legal design is “One MIDI file per melody” — which I think is a legal feature, not a bug.  🙂&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course I should have known there was a valid reason. He encouraged me to continue though and so I generated my own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;de Bruijn album&lt;/code&gt;. Now I can say I’ve officially remixed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;68,719,476,736&lt;/code&gt; songs. Is there like a Guiness Book of World Records entry for me now?&lt;/p&gt;

&lt;p&gt;If you’re curious what this remix sounds like, here is a snippet:&lt;/p&gt;

&lt;midi-player src=&quot;/music/snippet.mid&quot; sound-font=&quot;&quot; visualizer=&quot;#myVisualizer-/music/snippet.mid&quot;&gt;
&lt;/midi-player&gt;

&lt;p&gt;It was a fun exercise! I really love de Bruijn sequences and learned a lot about streaming GZIP/File API’s to easily store everything (generating the sequence first isn’t an option).&lt;/p&gt;

&lt;p&gt;The album is, for now, only stored on my hard disk, but I’m working with Damien to get the songs added to their ATM collection on the &lt;a href=&quot;https://archive.org/details/allthemusicllc-datasets&quot;&gt;Internet Archive&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Oh, and you can’t have a remix album without a proper album cover:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/debruijn_album.jpg&quot; alt=&quot;de Bruijn album cover&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Wed, 23 Mar 2022 22:23:03 +0100</pubDate>
        <link>https://royvanrijn.com/blog/2022/03/all-the-music-megamix/</link>
        <guid isPermaLink="true">https://royvanrijn.com/blog/2022/03/all-the-music-megamix/</guid>
        
        <category>pi</category>
        
        <category>piday</category>
        
        <category>algorithm</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Roadtrip to Ludolph van Ceulen</title>
        <description>&lt;p&gt;Today is March 14th (3/14), otherwise known as Pi Day!&lt;/p&gt;

&lt;h2 id=&quot;calculating-pi&quot;&gt;Calculating Pi&lt;/h2&gt;

&lt;p&gt;To celebrate Pi Day people often try to come up with cool and interesting ways to calculate π, or to celebrate the number in weird ways.&lt;/p&gt;

&lt;p&gt;Here is a great example by the excellent Matt Parker (from Stand-up Maths):&lt;/p&gt;

&lt;iframe type=&quot;text/html&quot; width=&quot;640&quot; height=&quot;390&quot; frameborder=&quot;0&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot; src=&quot;https://www.youtube.com/embed/CKl1B8y4qXw?title=0&amp;amp;byline=0&amp;amp;portrait=0&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;He’s using the “Isaac Newton”-way to calculate π by hand. This method was discovered by Isaac Newton and German mathematician Gottfried Wilhelm Leibniz in 1665. And it uses ‘infinite series’.&lt;/p&gt;

&lt;h2 id=&quot;before-newton&quot;&gt;Before Newton&lt;/h2&gt;

&lt;p&gt;The method Newton used (infinite series) was mathematically superiour to all previous methods of calculating π.&lt;/p&gt;

&lt;p&gt;That does raise a question: How did they calculate π &lt;em&gt;before&lt;/em&gt; 1665?&lt;/p&gt;

&lt;p&gt;First let’s take one step back, what exactly &lt;em&gt;IS&lt;/em&gt; π? π is a mathematical constant: the ratio between a circle’s circumference and diameter. This means that if you have a circle with a diameter of 1, the circumference is π (~ 3.14159…).&lt;/p&gt;

&lt;p&gt;Let’s try to come up with a very rough estimate what this ratio needs to be. What if we put our unit-circle with length 1 inside a square:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/circle-square.png&quot; alt=&quot;Circle inside a square&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can conclude that the circumference, and therefor π, is at most &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4 x 1 = 4&lt;/code&gt;, this gives us the first upper bound.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/circle-in-square.jpeg&quot; alt=&quot;Square inside a circle&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now lets look at the other case, where the square fits inside the circle. In this case we can see that we have an equilateral triangle, with two sides &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; that make the square. The length of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; is easy to calculate using Pythagoras theorom, the long side has a diameter of 1, this means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; needs to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a^2 + a^2 = 1&lt;/code&gt;. If we rearrange everything we’ll come to the conclusion that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a = sqrt(0.5)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means that the circumference of the smaller square is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4 x sqrt(0.5) = ~ 2.82..&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can conclude that π lies somewhere between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.82&lt;/code&gt; 🎉&lt;/p&gt;

&lt;h2 id=&quot;archimedes-method&quot;&gt;Archimedes method&lt;/h2&gt;

&lt;p&gt;But can we do even better? Sure! What if, instead of placing our circle between two squares, we use pentagons, hexagons, or shapes with even more sides?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/750px-Archimedes_pi.png&quot; alt=&quot;Archimedes method&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the shape get more and more rounded. So the upper and lower bounds converge towards our beloved π!&lt;/p&gt;

&lt;p&gt;This method is known as &lt;em&gt;Archimedes method&lt;/em&gt;. Archimedes calculated, using a shape with &lt;strong&gt;128&lt;/strong&gt; sides, that π had to be between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3.141&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3.142&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;ludolph-van-ceulen&quot;&gt;Ludolph van Ceulen&lt;/h2&gt;

&lt;p&gt;Now it’s time to introduce our hero of today: &lt;a href=&quot;https://en.wikipedia.org/wiki/Ludolph_van_Ceulen&quot;&gt;Ludolph van Ceulen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/Ludolf_van_Ceulen.jpeg&quot; alt=&quot;Ludolph van Ceulen&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ludolph spend his entire life to improve the calculated value of π. Instead of using a 128-sided shape like Archimedes, he calculated π using shapes with up to millions of sides. Let that sink in, a shape with a million sides, &lt;strong&gt;by hand&lt;/strong&gt;. By the time of his death van Ceulen managed to calculate π up to 35 digits, an incredible feat.&lt;/p&gt;

&lt;p&gt;Ludolph was so pleased with his life goal that he requested the upper and lower bounds to be carved into his tombstone. Sadly the original tombstone went missing not long after his death. However a new tombstone was added to the famous St. Peter’s Church in Leiden (The Netherlands) in the year 2000.&lt;/p&gt;

&lt;h2 id=&quot;visiting-leiden&quot;&gt;Visiting Leiden&lt;/h2&gt;

&lt;p&gt;About a month ago, my girlfriend and I, bored in lockdown, decided to take a roadtrip and visit the church in Leiden to see the tombstone for ourselves.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/tombstone-leiden.jpeg&quot; alt=&quot;St. Peter’s Church tombstone&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And there it is, here is a better picture of the plaque:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/tombstone-details.jpeg&quot; alt=&quot;St. Peter’s Church tombstone&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I’ve tried to translate the plaque from ‘old Dutch’ into English and it reads something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Buried here is Mr. Ludolph van Ceulen.
He was a Dutch professor of Mathematics at the university of this city (Leiden).
Born in Hildesheim in the year 1540 at 28th of January.
Passed away 31st of December 1610.
During his life, through hard labour, he found the circle&apos;s circumference compared to the diameter to be...

If the diameter is 1
The circumference is at least:

3141592653589793238462643383279502881
-------------------------------------
100000000000000000000000000000000000

And at most:

3141592653589793238462643383279502891
-------------------------------------
100000000000000000000000000000000000

And if the diameter is 100000000000000000000000000000000000

The circumference is at least 
314159265358979323846264338327950288

And at most:
314159265358979323846264338327950289
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;He spend his &lt;strong&gt;entire life&lt;/strong&gt; to improve the upper and lower bounds, using more and more sided shapes, up to millions of sides. He was also the &lt;strong&gt;last&lt;/strong&gt; person to improve the records using this labour intensive method. The method co-discovered by Isaac Newton (using infinite series) proved to be much easier and faster to calculate. After that calculating π by using complex shapes was a thing of the past.&lt;/p&gt;

&lt;p&gt;If you’re ever in Leiden, be sure to visit the church and pay respects to the incredible diligence of Ludolph van Ceulen.&lt;/p&gt;

&lt;p&gt;Happy Pi Day!&lt;/p&gt;

</description>
        <pubDate>Mon, 14 Mar 2022 03:14:15 +0100</pubDate>
        <link>https://royvanrijn.com/blog/2022/03/pi-day-2022/</link>
        <guid isPermaLink="true">https://royvanrijn.com/blog/2022/03/pi-day-2022/</guid>
        
        <category>pi</category>
        
        <category>piday</category>
        
        <category>algorithm</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>From Wordle to Nerdle</title>
        <description>&lt;p&gt;About two months ago I wrote a &lt;a href=&quot;/blog/2022/01/wordle-bot/&quot;&gt;blogpost&lt;/a&gt; about what strategies you could use to solve Wordle in the most efficient way. In the end I wrote a program that looks ahead a single guess and finds the word that gives you the most information.&lt;/p&gt;

&lt;p&gt;The main hype around Wordle (and all of the clones), seems to have settled down now… but I still play &lt;em&gt;some&lt;/em&gt; of them.&lt;/p&gt;

&lt;h2 id=&quot;nerdle&quot;&gt;Nerdle&lt;/h2&gt;

&lt;p&gt;One clone I really enjoyed playing the last couple of weeks has been &lt;a href=&quot;https://nerdlegame.com/&quot;&gt;Nerdle&lt;/a&gt;. In the game Nerdle all your guesses need to be a valid mathematical calculation. For example: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;31 + 56 = 87&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/nerdle_gameplay.png&quot; alt=&quot;Nerdle gameplay screenshot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In this game, you can’t just write down anything, each and every try needs to be a valid calculation.&lt;/p&gt;

&lt;h3 id=&quot;generating-the-guesses&quot;&gt;Generating the guesses&lt;/h3&gt;

&lt;p&gt;Yesterday, when I had a bit of time with a colleague, we set about trying to adapt the Wordle-bot into a Nerdle-bot. In theory this would be extremely easy, the only hard part is getting a valid “wordlist”.&lt;/p&gt;

&lt;p&gt;When I created the Wordle bot, I just downloaded a list of all valid Wordle words. But in this case I set myself the challenge to create all the valid guesses from scratch.&lt;/p&gt;

&lt;h3 id=&quot;patterns&quot;&gt;Patterns&lt;/h3&gt;

&lt;p&gt;First, let’s look at some of the rules. There are 8 characters you can fill, and the final part will always be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=N&lt;/code&gt; with N is a single digit number between 0-9&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=NN&lt;/code&gt; with NN being between 10 and 99; or&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=NNN&lt;/code&gt; with NNN being between 100 and 999&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s easy to generate all those options. However: the part before that is a little bit harder.&lt;/p&gt;

&lt;p&gt;Calculations can, because of the limited size, be just one of two patterns (of various sizes):
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Value1 Operator Value2&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Value1 Operator Value2 Operator Value3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;12+34=46&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10/2+1=6&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;These patterns are build up from left to right, starting first with a single digit number, appending the first operator, etc, until we have all valid 4, 5 or 6-character calculations.&lt;/p&gt;

&lt;p&gt;Now obviously, the tricky part is that we need to evaluate all these calculations and check if the result fits in the amount of characters we have left, for example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=NN&lt;/code&gt;! This code isn’t pretty… at all, even though I tried to make it generic. I won’t share it haha.&lt;/p&gt;

&lt;h3 id=&quot;bugsproblems&quot;&gt;Bugs/problems&lt;/h3&gt;

&lt;p&gt;I quickly ran into the first big obstacle: How do you calculate the result of something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1+10/2&lt;/code&gt;? You’ll first need to evaluate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10/2&lt;/code&gt;, store the result, and finally do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1+5&lt;/code&gt; and check if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=6&lt;/code&gt; fits (which it does).&lt;/p&gt;

&lt;p&gt;After writing some code and making sure we always evaluate in the correct order in case of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Value1 Operator Value2 Operator Value3&lt;/code&gt; I thought we were done. It showed me there are about 13k valid guesses. And this was wrong.&lt;/p&gt;

&lt;p&gt;The first bug I encountered was silly. I falsely put in a rule that no result can be zero. But in some cases zero’s are allowed, for example ending with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=0&lt;/code&gt;. After fixing this bug I found out I was still missing some valid guesses.&lt;/p&gt;

&lt;p&gt;After diff-ing my list with a list I found online I noticed I was missing things like: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9/6*8=12&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Because Nerdle doesn’t handle fractions, I thought that the divides should never have remainders. Thus I marked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9/6&lt;/code&gt; invalid because it doesn’t evenly divide. However… we are multiplying afterwards (!) so the &lt;em&gt;actual&lt;/em&gt; result (12) &lt;strong&gt;IS&lt;/strong&gt; a valid guess for Nerdle.&lt;/p&gt;

&lt;h3 id=&quot;results&quot;&gt;Results&lt;/h3&gt;

&lt;p&gt;After fixing all the bugs I had a complete list of all valid Nerdle guesses, and here are some stats:&lt;/p&gt;

&lt;p&gt;There are 17723 valid Nerdle answers&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;6839 of which contain a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;7810 of which contain a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;5574 of which contain a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;4024 of which contain a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;8607 of which contain two math operators&lt;/li&gt;
  &lt;li&gt;5890 end with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=N&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;10515 end with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=NN&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;1318 of which end with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=NNN&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And when I fired up the Wordle-checker, my code thinks the best start is:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;49-37=12&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Other great starters are:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;39-24=15&lt;/code&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;34+27=61&lt;/code&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9+8/2=13&lt;/code&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;7+8-13=2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After writing the bot I’ve tried it against the last three Nerdle challenges, and each game was solved after just three guesses!&lt;/p&gt;

&lt;p&gt;For example yesterday the bot calculated the following guesses:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;49-37=12 : ⬛⬛🟩🟪🟪🟪🟪⬛
31+56=87 : 🟪🟩⬛⬛⬛🟪⬛🟩
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After just these two guesses there is only &lt;strong&gt;ONE&lt;/strong&gt; valid guess left: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;11-1-3=7&lt;/code&gt;: 🟩🟩🟩🟩🟩🟩🟩🟩&lt;/p&gt;

</description>
        <pubDate>Thu, 03 Mar 2022 08:01:25 +0100</pubDate>
        <link>https://royvanrijn.com/blog/2022/03/wordle-to-nerdle/</link>
        <guid isPermaLink="true">https://royvanrijn.com/blog/2022/03/wordle-to-nerdle/</guid>
        
        <category>java</category>
        
        <category>nerdle</category>
        
        <category>wordle</category>
        
        <category>puzzle</category>
        
        <category>algorithm</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>An algorithm for Wordle</title>
        <description>&lt;p&gt;If you’ve used Twitter during the begining of 2022 you’ll almost certainly have seen people posting tweets like this:&lt;/p&gt;

&lt;pre&gt;
Wordle 202 3/6

⬜⬜⬜⬜🟨
🟨⬜⬜⬜⬜
🟩🟩🟩🟩🟩
&lt;/pre&gt;

&lt;p&gt;This is the result of playing the latest viral game “Wordle”. The concept is very easy, you have to guess a 5-letter word each day. For each guess you get the basic “Mastermind” reply, green for the correct character, yellow if it’s in the wrong spot.&lt;/p&gt;

&lt;p&gt;This game was fun, for a couple of days, but my curious mind started to wonder… what are the &lt;em&gt;BEST&lt;/em&gt; words to play?&lt;/p&gt;

&lt;p&gt;So I downloaded a huge list of 5-character words and started playing around with the dataset.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I’ve updated the post using the ‘correct’ Wordle word-list, there are two lists, one with possible secret words, and one list with all words valid for guessing.&lt;/p&gt;

&lt;h1 id=&quot;eliminate-by-frequency&quot;&gt;Eliminate by frequency&lt;/h1&gt;

&lt;p&gt;The first thing I tried was to try and eliminate the most frequently used characters first. With 5 guesses we can try and guess the most frequently present letters in the English language.&lt;/p&gt;

&lt;p&gt;To get the frequency of the letters I used the following code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;        &lt;span class=&quot;c1&quot;&gt;// Read all the words:&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Files&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;readAllLines&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;wordle.txt&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Count all the characters frequencies:&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frequency&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flatMapToInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;chars&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;mapToObj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Collectors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;groupingBy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
                        &lt;span class=&quot;nc&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt;
                        &lt;span class=&quot;nc&quot;&gt;Collectors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;counting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Sort the characters by frequency and print:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;frequency&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;entrySet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Long&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()))&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This results in the following distribution:&lt;/p&gt;

&lt;pre&gt;
s 6665
e 6662
a 5990
o 4438
r 4158
i 3759
l 3371
t 3295
n 2952
u 2511
d 2453
y 2074
c 2028
p 2019
m 1976
h 1760
g 1644
b 1627
k 1505
... (etc)
&lt;/pre&gt;

&lt;p&gt;Using some simple code it’s easy to find &lt;em&gt;pretty good&lt;/em&gt; words to start with, for example:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;laser -&amp;gt; tonic -&amp;gt; dumpy&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;These &lt;strong&gt;three&lt;/strong&gt; guesses will tell you information about the 15 most common characters in all of the 5-letter words. This is “a” strategy, but it’s far from perfect. We can do much better!&lt;/p&gt;

&lt;h1 id=&quot;most-information-per-guess&quot;&gt;Most information per guess&lt;/h1&gt;

&lt;p&gt;Each time we guess a word, we get a reply back, it can be something like “⬜⬜⬜⬜⬜” or “🟨⬜⬜🟩🟨”. What we want to do is &lt;em&gt;optimize&lt;/em&gt; for the information we’re getting in return. Each guess we do should eliminate most options.&lt;/p&gt;

&lt;p&gt;If we go over the entire list of words, and compare all the replies we could get back against all other words, we get a distribution of the returned patterns.&lt;/p&gt;

&lt;p&gt;I’ve decided to write some code to do this. For example if we pick the word &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;smile&lt;/code&gt;, these patterns can be returned:&lt;/p&gt;

&lt;pre&gt;
🟨⬜⬜⬜⬜: 1464 ⬜⬜⬜⬜⬜: 1352 ⬜⬜⬜⬜🟨: 1122 🟨⬜⬜⬜🟨:  967 ⬜⬜🟨⬜⬜:  690 ⬜⬜⬜🟨⬜:  610 
⬜⬜⬜⬜🟩:  504 🟨⬜🟨⬜⬜:  468 🟩⬜⬜⬜⬜:  467 ⬜🟨⬜⬜⬜:  417 🟨⬜⬜🟨⬜:  263 🟩⬜⬜⬜🟨:  252 
⬜⬜🟨⬜🟨:  251 ⬜⬜🟩⬜⬜:  196 🟨🟨⬜⬜⬜:  191 🟨⬜🟩⬜⬜:  187 ⬜⬜⬜🟨🟨:  183 ⬜⬜🟨🟨⬜:  154 
⬜🟨⬜⬜🟨:  154 🟨⬜🟨⬜🟨:  147 🟨⬜⬜⬜🟩:  136 ⬜⬜🟨⬜🟩:  136 ⬜⬜⬜🟩⬜:  128 🟨⬜⬜🟩⬜:  117 
⬜🟨🟨⬜⬜:  115 ⬜⬜⬜🟨🟩:  115 🟩⬜🟨⬜⬜:  112 🟩⬜⬜⬜🟩:  109 🟩⬜⬜🟨⬜:  107 ⬜🟨⬜🟨⬜:  106 
⬜🟨⬜⬜🟩:   99 🟩⬜🟩⬜⬜:   87 ⬜⬜🟩⬜🟩:   82 ⬜⬜⬜🟩🟩:   79 🟩🟨⬜⬜⬜:   63 ⬜⬜🟩🟨⬜:   63 
🟨⬜⬜🟨🟨:   62 ⬜⬜🟩⬜🟨:   58 🟨🟨⬜⬜🟨:   53 ⬜⬜⬜🟩🟨:   52 🟨⬜⬜🟩🟨:   49 ⬜⬜🟨🟩⬜:   46 
🟩⬜⬜🟩⬜:   43 🟨⬜🟩⬜🟨:   41 🟩⬜🟨⬜🟨:   41 🟨⬜🟨🟩⬜:   36 ⬜⬜🟩🟩⬜:   35 ⬜🟨🟩⬜⬜:   31 
🟩⬜🟩⬜🟩:   27 ⬜🟩⬜⬜🟨:   27 🟩⬜⬜🟨🟨:   27 🟨⬜🟩🟩⬜:   25 🟨⬜🟩🟨⬜:   25 ⬜🟨⬜🟩⬜:   23 
🟩⬜⬜🟩🟨:   20 🟨🟩⬜⬜⬜:   20 🟨⬜🟩⬜🟩:   19 🟨🟨🟩⬜⬜:   19 ⬜⬜🟨🟨🟩:   18 🟩⬜🟩⬜🟨:   18 
🟩⬜⬜🟩🟩:   18 🟩🟩⬜⬜⬜:   18 🟩⬜🟨🟨⬜:   17 ⬜⬜🟨🟨🟨:   17 ⬜⬜🟩🟨🟩:   15 ⬜🟩⬜⬜⬜:   15 
⬜🟩🟨⬜⬜:   15 ⬜⬜🟩🟩🟩:   14 🟩⬜⬜🟨🟩:   14 🟩⬜🟩🟩⬜:   13 🟩⬜🟩🟨⬜:   13 ⬜🟨🟩⬜🟩:   13 
🟩🟨⬜⬜🟨:   13 🟩🟨🟩⬜⬜:   12 ⬜⬜🟨🟩🟩:   12 🟨🟨⬜🟨⬜:   11 ⬜🟩🟩⬜⬜:   11 ⬜🟩⬜⬜🟩:   11 
⬜🟨🟨⬜🟩:   10 🟩🟨🟨⬜⬜:   10 🟨🟩🟩⬜⬜:   10 ⬜🟨⬜🟩🟩:    9 🟨⬜🟨⬜🟩:    9 🟨⬜⬜🟨🟩:    9 
🟩⬜🟨⬜🟩:    8 🟩🟨⬜⬜🟩:    7 🟨⬜🟨🟨⬜:    7 ⬜🟨🟨🟨⬜:    7 🟨🟨🟨⬜⬜:    7 🟨⬜🟩🟩🟨:    6 
🟩⬜🟨🟩⬜:    6 ⬜🟩🟩⬜🟩:    5 🟩🟩⬜⬜🟨:    5 ⬜🟩⬜🟩🟩:    5 🟩🟩⬜⬜🟩:    5 🟨🟩⬜⬜🟨:    5 
🟩🟩🟩⬜⬜:    5 ⬜🟨⬜🟨🟩:    4 🟨⬜⬜🟩🟩:    4 ⬜🟩🟨⬜🟨:    4 🟩🟩⬜🟩⬜:    4 🟨🟨⬜⬜🟩:    4 
🟩⬜🟩🟨🟩:    4 ⬜🟩🟨⬜🟩:    3 ⬜🟩⬜🟨⬜:    3 🟩🟨⬜🟨⬜:    3 🟩⬜🟩🟩🟩:    3 ⬜🟨🟩🟩🟩:    2 
🟩🟨🟩⬜🟩:    2 🟨⬜🟨🟩🟩:    2 ⬜⬜🟩🟩🟨:    2 🟩🟩🟨⬜⬜:    2 🟩🟩⬜🟩🟨:    2 🟨🟩🟨⬜⬜:    2 
⬜🟩⬜🟩⬜:    2 ⬜⬜🟩🟨🟨:    2 🟩🟨⬜🟩⬜:    2 ⬜🟨⬜🟩🟨:    1 ⬜🟩🟨🟨🟨:    1 ⬜🟨🟨⬜🟨:    1 
🟩⬜🟨🟩🟩:    1 ⬜🟨⬜🟨🟨:    1 🟩🟨🟨⬜🟩:    1 ⬜🟨🟨🟩⬜:    1 🟨🟩⬜🟨⬜:    1 🟩🟩🟩🟩🟩:    1 
🟨🟩⬜⬜🟩:    1 🟩🟨⬜🟩🟨:    1 ⬜⬜🟨🟩🟨:    1 🟩🟩🟩⬜🟩:    1 🟨🟩⬜🟩⬜:    1 🟨⬜🟩🟩🟩:    1 
🟨🟩🟩⬜🟨:    1 ⬜🟩🟨🟩⬜:    1 🟨🟨⬜🟩⬜:    1 ⬜🟨🟩🟩⬜:    1 🟩⬜🟩🟩🟨:    1 ⬜🟩🟨🟨⬜:    1 
&lt;/pre&gt;

&lt;p&gt;This means that, if we pick &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;smile&lt;/code&gt;, we can get &lt;strong&gt;101&lt;/strong&gt; different resulting patterns. The largest group we’re left with contains &lt;strong&gt;316&lt;/strong&gt; words. So by guessing this single word, we can eliminate most of the words.&lt;/p&gt;

&lt;p&gt;If we do this for &lt;em&gt;all&lt;/em&gt; the words, my algorithm gives back that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raise&lt;/code&gt; is &lt;em&gt;the&lt;/em&gt; absolute best first word. This word returns 107 different patterns and the &lt;em&gt;worst&lt;/em&gt; case is that we have 168 words left after the initial guess.&lt;/p&gt;

&lt;p&gt;Another good candidate would be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slate&lt;/code&gt;, this splits the words into &lt;em&gt;more&lt;/em&gt; groups: 129. But the worst-case is a little bit worse, leaving just 221 words.&lt;/p&gt;

&lt;h2 id=&quot;after-raise-repeat&quot;&gt;After &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raise&lt;/code&gt;, repeat.&lt;/h2&gt;

&lt;p&gt;After our first guess, we just continue with the following guesses. We calculate which words are still left and we go over &lt;strong&gt;all&lt;/strong&gt; the words to find the one that gives us most &lt;em&gt;information&lt;/em&gt; about the target word. Also: Don’t limit yourself to using/guessing just the possible words. For example look at the following case:&lt;/p&gt;

&lt;pre&gt;
tares: 🟨⬜⬜⬜⬜
pilot: ⬜🟩⬜⬜🟨
dunsh: ⬜⬜⬜⬜🟩
&lt;/pre&gt;

&lt;p&gt;There are now still eight possible words:&lt;/p&gt;

&lt;pre&gt;
hitch, fifth, witch, aitch, bitch, fitch, gitch, mitch
&lt;/pre&gt;

&lt;p&gt;Instead of guessing one of these words, often getting just a single piece of information… it’s much better to guess the word &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awful&lt;/code&gt;. This guess splits the possible words into &lt;strong&gt;5&lt;/strong&gt; groups:&lt;/p&gt;

&lt;pre&gt;
🟩⬜⬜⬜⬜: aitch
⬜🟨⬜⬜⬜: witch
⬜⬜🟩⬜⬜: fifth
⬜⬜🟨⬜⬜: fitch
⬜⬜⬜⬜⬜: hitch, bitch, gitch, mitch
&lt;/pre&gt;

&lt;p&gt;If we get ⬜🟨⬜⬜⬜ in return we can conclude that the only option left to guess is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;witch&lt;/code&gt; and we’re done 🟩🟩🟩🟩🟩.&lt;/p&gt;

&lt;p&gt;This algorithm allows me to solve all words within the given 6 tries you get with Wordle. For a single move I think this algorithm is optimal. However, we might be able to do better if we consider multiple moves into the future. It should be possible to extend this, build a tree and check the depth.&lt;/p&gt;

&lt;p&gt;Perhaps &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raise&lt;/code&gt; is great for a single move, eliminating a lot of options, but what if the largest (worst-case) group is very hard to break up after that?&lt;/p&gt;

&lt;p&gt;I haven’t tried to figure this out… but perhaps you will? What other algorithms can we come up with?&lt;/p&gt;

&lt;h1 id=&quot;bot-tournament&quot;&gt;Bot tournament…?&lt;/h1&gt;

&lt;p&gt;Perhaps we can host a tournament where we have bots playing &lt;em&gt;Wordle&lt;/em&gt;, taking turns solving and giving the opponent a next word to solve. We can even make the bots smart enough to recognise and counter certain words and/or tactics.&lt;/p&gt;

&lt;p&gt;Sounds fun :)&lt;/p&gt;

</description>
        <pubDate>Fri, 07 Jan 2022 08:01:25 +0100</pubDate>
        <link>https://royvanrijn.com/blog/2022/01/wordle-bot/</link>
        <guid isPermaLink="true">https://royvanrijn.com/blog/2022/01/wordle-bot/</guid>
        
        <category>java</category>
        
        <category>wordle</category>
        
        <category>puzzle</category>
        
        <category>algorithm</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Divide by three using shift and add</title>
        <description>&lt;p&gt;Today I stumbled across this excellent short video bij Mathologer:&lt;/p&gt;

&lt;iframe type=&quot;text/html&quot; width=&quot;640&quot; height=&quot;390&quot; frameborder=&quot;0&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot; src=&quot;https://www.youtube.com/embed/SOBz-aFOH2I?title=0&amp;amp;byline=0&amp;amp;portrait=0&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;This simple proof shows that 1/3 is the same as: 1/4 + 1/4^2 + 1/4^3 + 1/4^N…&lt;/p&gt;

&lt;p&gt;As a programmer I wanted to try and program this.&lt;/p&gt;

&lt;p&gt;Dividing by multiples of two (like 4^3) is extremely easy in binary, we just shift a number to the right. So if you have some integer X and we want to divide by 4, we do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X &amp;gt;&amp;gt; 2&lt;/code&gt;, if we want to divide by 4^2 we shift &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X &amp;gt;&amp;gt; 4&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;This means we can just add these fractions together and approximate the result, just by dividing (shifting) up to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt; 30&lt;/code&gt; for an integer (which is 32-bit).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;612644632&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Approximate Using: 1/3 = 1/4 + 1/4^2 + 1/4^3 + etc&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;divless&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; / 3     = &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; + magic = &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;divless&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// 612644632 / 3     = 204214877&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// 612644632 + magic = 204214872 &amp;lt;- close, a bit too low&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The accuracy isn’t great… but it’s pretty close. We’re always a bit below the actual sum because for each part we add, we lose a bit of information which we’re shifted away. To counter this we could first add things and shift the final result, making the accuracy a bit better:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;612644632&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Approximate Using: 1/3 = 1/4 + 1/4^2 + 1/4^3 + etc&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;divless&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; / 3     = &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bignr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; + magic = &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;divless&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// 612644632 / 3     = 204214877&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// 612644632 + magic = 204214876 &amp;lt;- off by one haha&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Probably a useless trick, but fun nonetheless.&lt;/p&gt;
</description>
        <pubDate>Fri, 31 Dec 2021 09:01:25 +0100</pubDate>
        <link>https://royvanrijn.com/blog/2021/12/divide-by-three/</link>
        <guid isPermaLink="true">https://royvanrijn.com/blog/2021/12/divide-by-three/</guid>
        
        <category>java</category>
        
        <category>trick</category>
        
        <category>math</category>
        
        <category>divide</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Hex grid in single integer</title>
        <description>&lt;h2 id=&quot;azspcs-ap-math&quot;&gt;AZsPCs: AP Math&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://azspcs.com/&quot;&gt;Al Zimmermann&lt;/a&gt; hosts awesome Programming Contests every once in a while. They usually run for a long time (multiple months) and it allows mathematicians and programmers to compete in optimization problems. Usually the search space is very large and optimal solutions aren’t found for large N-values.&lt;/p&gt;

&lt;p&gt;This time the contest was called “AP Math” and the goal was:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Given a hexagonal grid of size N, select the maximum amount of cells so no three cells form an arithmetic progression.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/images/azspcs-ap-math.png&quot; alt=&quot;Description of contest&quot; /&gt;&lt;/p&gt;

&lt;p&gt;During this contest I didn’t find the right way to attack the problem, but I did discover a clever way to store all the hex coordinates in a singe integer value and do the math on that; which I wanted to share here.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;arithmetic-progression&quot;&gt;Arithmetic progression?&lt;/h2&gt;

&lt;p&gt;The main goal in the contest is to select cells in a hex grid with this one rule “no three cells form an arithmetic progression”.&lt;/p&gt;

&lt;p&gt;What does this mean? If you look at the example above for a N=3 hex grid you can see that we have to select cells, with the rule that no two points can have another cell in between, on the mid point.&lt;/p&gt;

&lt;p&gt;Look at this website for more examples and a complete description: &lt;a href=&quot;http://azspcs.com/Contest/APMath&quot;&gt;AP Math&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So to find solutions, we need a way to store the coordinates of this hex grid and a way to determine given two cells, which other cells are illegal.&lt;/p&gt;

&lt;h2 id=&quot;storing-coordinates-as-single-32-bit-integer&quot;&gt;Storing coordinates as single 32-bit integer&lt;/h2&gt;

&lt;p&gt;There are multiple ways to store the coordinates of an hexagonal grid. The best write-up I’ve found is located at &lt;a href=&quot;https://www.redblobgames.com/grids/hexagons/&quot;&gt;redblobgames.com&lt;/a&gt;. I’m using an axial grid, so each coordinate has an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;instead&lt;/strong&gt; of working with an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; value, I’m storing each coordinate as a &lt;em&gt;single&lt;/em&gt; 32-bit integer.&lt;/p&gt;

&lt;p&gt;To generate all of them I used the following (Java) code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indexes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HashSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Generate all hex points: (as single int)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Cut off the two triangular edges to make a hex grid:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;indexes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;//&amp;lt;-- store all the positions x, y both into a single integer value.&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As you can see, I’m storing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; in a single integer value, shifted 16 bits.&lt;/p&gt;

&lt;p&gt;Now you might ask: how is storing each coordinate as a single 32-bit value useful? What does it add?&lt;/p&gt;

&lt;p&gt;Well, suppose we have two coordinates from the complete list of all hex grid coordinates mentioned above. With these two indexes in our hex grid we can do the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// A bitmask to check for even numbers&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;BOTH_EVEN_MASK&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;BOTH_EVEN_MASK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Points index1 and index2 has the following midpoint:&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invalidMid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invalid1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invalid2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Using very limited control code and little math we can calculate all three points that are needed for this contest. Given just the two coordinates we get the two or three points that are invalidated. This is much faster than any other coordinate system I tried. A single subtract of two indexes gives the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; of the new point: less work for the CPU.&lt;/p&gt;

&lt;p&gt;Turns out, I didn’t even need to use the actual &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; values anywhere, I could stay in this coordinate-system while searching. If you want to though, just mask and shift:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xFFFF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xFFFF&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This was my little ‘hack’ for this contest. I might be able to use this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xy&lt;/code&gt; as a single integer on more occasions, in other contests. It’s a nice tool to have in the toolbox.&lt;/p&gt;

</description>
        <pubDate>Tue, 28 Dec 2021 11:19:31 +0100</pubDate>
        <link>https://royvanrijn.com/blog/2021/12/hex-grid-coordinates-in-a-single-integer/</link>
        <guid isPermaLink="true">https://royvanrijn.com/blog/2021/12/hex-grid-coordinates-in-a-single-integer/</guid>
        
        <category>java</category>
        
        <category>hex grid</category>
        
        <category>azspcs</category>
        
        
        <category>Programming</category>
        
      </item>
    
  </channel>
</rss>
