<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Senthil Kumaran</title>
    <description>The latest articles on DEV Community by Senthil Kumaran (@orsenthil).</description>
    <link>https://dev.to/orsenthil</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F760714%2F6ef82fd5-4a1b-4dc9-9e1c-b758eec6a8a8.jpg</url>
      <title>DEV Community: Senthil Kumaran</title>
      <link>https://dev.to/orsenthil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/orsenthil"/>
    <language>en</language>
    <item>
      <title>The Prow Upgrade Story</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Mon, 16 Mar 2026 05:40:35 +0000</pubDate>
      <link>https://dev.to/orsenthil/the-prow-upgrade-story-44oi</link>
      <guid>https://dev.to/orsenthil/the-prow-upgrade-story-44oi</guid>
      <description>&lt;p&gt;One of my first experiences with Kubernetes was with using Prow. Prow is a Kubernetes CI/CD system. In the Mesosphere/D2IQ days, I had to transition the CI jobs that we were running in Jenkins on Mesos/Marathon to Prow on Kubernetes. In order to learn Kubernetes, I suggested we set up Prow to run the CI jobs for our Mesosphere/D2IQ frontend. That was the first task that I undertook that would help me understand Kubernetes . It was simple but a critical CI/CD system that handles job execution and GitHub automation through policy enforcement. Anyone who has either contributed to Kubernetes or worked with the testing-sig will have come across the weird-looking Prow robots working with your pull requests. And in the GitHub-based ChatOps, there are multiple &lt;code&gt;/slash-commands&lt;/code&gt; that are utilized to interact with the state of the pull request.&lt;/p&gt;

&lt;p&gt;The component listeners listen to these webhooks and act on the state and the command. Just like regular CI/CD systems, they trigger a job on the event, and the job usually clones the repository at the pull request HEAD and runs a script that exercises the tests and finally gives a success or failure signal.&lt;br&gt;
The intelligence of running the tests is baked into the script that runs the tests. Prow does not do anything fancy that is expected from any continuous integration system. It simply runs the job and returns the results.&lt;/p&gt;

&lt;p&gt;The first task before setting up the jobs was setting up the Kubernetes cluster and then deploying Prow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphuvpf2a7p1zznuj228v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphuvpf2a7p1zznuj228v.png" width="666" height="646"&gt;&lt;/a&gt;&lt;br&gt;
The various nouns in this diagram are the components of the Prow that we will see.&lt;/p&gt;

&lt;p&gt;GitHub sends webhooks to Prow. Prow runs your tests as Kubernetes pods. Prow reports the results back to GitHub. That's it. The core pipeline flows down the center: Hook receives GitHub webhooks, creates a &lt;strong&gt;ProwJob&lt;/strong&gt; custom resource, the &lt;strong&gt;Controller Manager&lt;/strong&gt; picks it up and schedules a pod in the &lt;strong&gt;Cluster&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So the setup chain was simple.&lt;/p&gt;

&lt;p&gt;I used Terraform to manage the infrastructure state. Terraform was used to create the S3 buckets to store the Terraform state. We used to have a DynamoDB table for locking. It surprises me in hindsight, and perhaps even surprised me back then, but we did use a DynamoDB table just for locking. This is to avoid multiple &lt;code&gt;terraform apply&lt;/code&gt; commands acting on the same cluster. The cluster creation was controlled with users with IAM permissions for various operations.&lt;/p&gt;

&lt;p&gt;This is how we built the infrastructure for Kubernetes. Any Kubernetes distribution can be used; at that time, I remember we were using a home-built one, which the company, D2IQ  was selling. For the worker nodes, I had provisioned very large instances — ones with 16 vCPUs and 64 GB of RAM — plenty of headroom for Prow's microservices and the test pods they'd spawn. Since Prow runs the CI job as a Kubernetes job, it needs those resources to spawn the job and run.&lt;/p&gt;

&lt;p&gt;I had the cluster infrastructure stored in &lt;strong&gt;Terraform state files&lt;/strong&gt;; Terraform created the S3 buckets, DynamoDB lock table, and the IAM users.&lt;br&gt;
For our Kubernetes cluster, I had a &lt;strong&gt;Native K8s cluster&lt;/strong&gt; on EC2 using a home-grown technology called Konvoy while at Mesosphere/D2IQ.&lt;br&gt;
I set up the Prow application on the cluster using the Custom Resource Definitions, and since CI systems are often internal, I had to set up an &lt;strong&gt;Internal domain&lt;/strong&gt; configured to point to Prow's Hook and Deck endpoints, and set up &lt;strong&gt;cert-manager&lt;/strong&gt; for TLS on that internal domain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyzrpic0rwie2x5l5l5i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyzrpic0rwie2x5l5l5i.png" width="800" height="202"&gt;&lt;/a&gt;&lt;br&gt;
Once the Kubernetes cluster was provisioned, the cluster came up cleanly. The nodes were healthy, the API server responding, CoreDNS resolving.&lt;/p&gt;

&lt;p&gt;I had to apply the ProwJob Custom Resource Definitions to set up the application. We created two secrets that Prow needs to talk to GitHub: an HMAC (Hash-Based Message Authentication Code, a shared secret) token for validating incoming webhooks, and a GitHub App's private key for authenticating API calls.&lt;br&gt;
I deployed this full set of Prow components using the S3-backed starter manifest.&lt;/p&gt;

&lt;p&gt;Once the Prow system was set up, the Prow services would be running. The Hook component would be waiting for webhooks, Deck serving the UI, the Prow Controller Manager ready to schedule jobs. Components like Tide watch for mergeable PRs, a component called Horologium handles periodic jobs. Systems like Crier report back to GitHub, and Sinker quietly cleans up after everyone else.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Wiring up the domain&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When you architect a CI system for developers, as I did, the primary responsibility is to make the system reliable. Prow needs to be reachable from the public internet — specifically, GitHub needs to send HTTPS webhook requests to Hook's endpoint whenever something happens in the subscribed repositories.&lt;/p&gt;

&lt;p&gt;That means in the Kubernetes world, you need a domain, an Ingress, and a valid TLS (Transport Layer Security) certificate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9i31tsu5p15w7qv1maek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9i31tsu5p15w7qv1maek.png" width="742" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The internal domain had to be provisioned using Terraform, and with the domain I set up the Ingress that routed &lt;code&gt;/hook&lt;/code&gt; traffic to the Hook Service and everything else to Deck. Even these were provisioned in the Terraform state files.&lt;/p&gt;

&lt;p&gt;We used cert-manager to handle the TLS. I pointed an internal domain at the cluster, set up an Ingress that routed &lt;code&gt;/hook&lt;/code&gt; traffic to the Hook service and everything else to Deck, and used cert-manager to handle TLS. cert-manager would automatically provision and renew certificates, wiring them into the Ingress as a Kubernetes Secret. For cert-manager, we configured a ClusterIssuer, created a Certificate resource for the Prow domain, and let cert-manager do its thing.&lt;/p&gt;

&lt;p&gt;All of these were done in Terraform state files, so that when we did a &lt;code&gt;terraform apply&lt;/code&gt;, the domain was created, the certificate manager was set up, certificates were gathered, and the system was operational serving traffic over HTTPS.&lt;br&gt;
Once the certificate was issued and the Ingress had valid TLS termination, we went to the GitHub App at the org-level, set the webhook URL to point at the Prow domain's &lt;code&gt;/hook&lt;/code&gt; path, and plugged in the HMAC secret.&lt;/p&gt;

&lt;p&gt;It works. Open a test PR, and within seconds the Hook receives the webhook, the trigger plugin creates the ProwJob, the Controller Manager scheduled a pod, the Crier reported results back to GitHub. The green checkmark appearing on the PR status means all is good, and life is good.&lt;/p&gt;

&lt;p&gt;Kubernetes Upgrades&lt;/p&gt;

&lt;p&gt;Kubernetes upgrades are talked about as a frequent source of pain points. Even when you use a Managed Kubernetes Provider, when you have made complex changes to your cluster and operate business-critical workloads, teams are seldom confident to upgrade their Kubernetes clusters without a good plan in place. So, in my Kubernetes cluster, as we updated our Kubernetes version and Prow version, we had to upgrade the components too. As I explained above, the internal domain over HTTPS was set up with a separate Terraform plan.&lt;br&gt;
And when we upgraded cert-manager, it started to fail. That's when the Hook endpoint stopped receiving webhooks from GitHub.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Failure Chain
&lt;/h3&gt;

&lt;p&gt;Here's what happened:&lt;/p&gt;

&lt;p&gt;The cert-manager upgrade caused the webhook pod to restart. During the upgrade, cert-manager's own internal webhook — which validates cert-manager CRDs — went through a transition period where it was unavailable. This was due to a bug in the version of cert-manager we were upgrading to.&lt;br&gt;
When cert-manager's cainjector or controller had issues during the upgrade, the Certificate resource couldn't renew and the Secret wasn't properly updated, as the TLS certificate for Prow's Ingress was tied to cert-manager. During the upgrade, the Ingress lost its valid TLS certificate, and without a valid cert, the HTTPS endpoint that GitHub was hitting for webhooks started returning TLS errors.&lt;/p&gt;

&lt;p&gt;GitHub webhook deliveries started failing — this can be seen in the GitHub interface showing that webhook deliveries had failed — and all CI/CD stopped. No webhooks meant no presubmit jobs, no postsubmit jobs, no &lt;code&gt;/retest&lt;/code&gt; commands, nothing. Prow was running perfectly fine internally, but it was invisible to the outside world.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fywadc1irgzkwg9gej0rl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fywadc1irgzkwg9gej0rl.png" width="595" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything &lt;em&gt;inside&lt;/em&gt; the cluster looked healthy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# All pods running?&lt;/span&gt;

kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; prow
kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; cert-manager

&lt;span class="c"&gt;# ProwJobs being created?  No new ones&lt;/span&gt;
kubectl get prowjobs &lt;span class="nt"&gt;-n&lt;/span&gt; prow &lt;span class="nt"&gt;--sort-by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;.metadata.creationTimestamp

&lt;span class="c"&gt;# Hook logs showing any incoming webhooks? Nothing&lt;/span&gt;
kubectl logs &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hook &lt;span class="nt"&gt;-n&lt;/span&gt; prow &lt;span class="nt"&gt;-f&lt;/span&gt;

&lt;span class="c"&gt;# Certificate status?&lt;/span&gt;
kubectl describe certificate prow-tls &lt;span class="nt"&gt;-n&lt;/span&gt; prow
&lt;span class="c"&gt;# This is where I finally saw the problem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;kubectl describe certificate&lt;/code&gt; output showed the certificate was in a failed state — cert-manager couldn't issue or renew it because the upgrade had left its internal state inconsistent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check cert-manager's own health&lt;/span&gt;
kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; cert-manager
kubectl logs &lt;span class="nt"&gt;-l&lt;/span&gt; app.kubernetes.io/name&lt;span class="o"&gt;=&lt;/span&gt;webhook &lt;span class="nt"&gt;-n&lt;/span&gt; cert-manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The webhooks were unhealthy, so I had to delete and reinstall cert-manager cleanly.&lt;/p&gt;

&lt;p&gt;I was doing everything using Terraform. Manually mutating state when everything else is maintained in Terraform was going to be tricky. Terraform does not like that. Also, certain versions and dependencies of cert-manager were a problem, so I had to find the right combination of versions and encode it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# If the webhook is unhealthy, you may need to&lt;/span&gt;
&lt;span class="c"&gt;# delete and reinstall cert-manager cleanly&lt;/span&gt;

kubectl delete &lt;span class="nt"&gt;-f&lt;/span&gt; https://github.com/cert-manager/cert-manager/releases/download/v&amp;lt;OLD&amp;gt;/cert-manager.yaml
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; https://github.com/cert-manager/cert-manager/releases/download/v&amp;lt;NEW&amp;gt;/cert-manager.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once everything was stable, I had to wait for the cert-manager rollout to stabilize and force the certificate renewal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Wait for everything to stabilize&lt;/span&gt;
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; cert-manager rollout status deployment/cert-manager-webhook

&lt;span class="c"&gt;# Force certificate renewal&lt;/span&gt;
kubectl delete secret prow-tls-secret &lt;span class="nt"&gt;-n&lt;/span&gt; prow
&lt;span class="c"&gt;# cert-manager will recreate it from the Certificate resource&lt;/span&gt;

&lt;span class="c"&gt;# Verify&lt;/span&gt;
kubectl describe certificate prow-tls &lt;span class="nt"&gt;-n&lt;/span&gt; prow
&lt;span class="c"&gt;# Should show "Certificate is up to date and has not expired"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once cert-manager was stable, the GitHub webhook deliveries should be back and hooks succeeding again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl logs &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hook &lt;span class="nt"&gt;-n&lt;/span&gt; prow &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;span class="c"&gt;# Should see incoming webhook events&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This downtime affected the productivity of my group for multiple hours. And fixing something when things were down was a challenging one.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Some of the Important Lessons I have learned from this experience are&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Cert-manager upgrades are not zero-downtime for your services.&lt;/p&gt;

&lt;p&gt;When you upgrade cert-manager, its internal admission webhook restarts. During that window, if any Certificate resources need to be reconciled, things can break. If your Ingress TLS depends on cert-manager and the timing is bad, your endpoints go dark.&lt;br&gt;
The best way would be to decouple the TLS from cert-manager for critical webhook endpoints during the upgrade.&lt;/p&gt;

&lt;p&gt;The Prow Hook endpoint is the single point of entry.&lt;/p&gt;

&lt;p&gt;Everything in Prow depends on Hook receiving webhooks. If Hook is unreachable, whether due to TLS issues, DNS problems, or network configuration, the CI/CD pipeline goes silent. This is an important design consideration for anyone designing an application architecture on Prow.&lt;/p&gt;

&lt;p&gt;Having a "break glass" procedure for webhook endpoints.&lt;/p&gt;

&lt;p&gt;As in, you can manually create a TLS secret and attach it to your Ingress without cert-manager. When cert-manager is the thing that's broken, you need a way to get your endpoints back up while you fix it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a self-signed cert to restore connectivity&lt;/span&gt;
openssl req &lt;span class="nt"&gt;-x509&lt;/span&gt; &lt;span class="nt"&gt;-nodes&lt;/span&gt; &lt;span class="nt"&gt;-days&lt;/span&gt; 30 &lt;span class="nt"&gt;-newkey&lt;/span&gt; rsa:2048 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-keyout&lt;/span&gt; /tmp/tls.key &lt;span class="nt"&gt;-out&lt;/span&gt; /tmp/tls.crt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s2"&gt;"/CN=prow.your-internal-domain.com"&lt;/span&gt;

kubectl create secret tls prow-tls-secret &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/tls.crt &lt;span class="nt"&gt;--key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/tls.key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-n&lt;/span&gt; prow &lt;span class="nt"&gt;--dry-run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;client &lt;span class="nt"&gt;-o&lt;/span&gt; yaml | kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was a firefighting story that helped me realize how infrastructure and complex applications stand on some very simple dependencies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmtpzzz2emqi9g0yaaq03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmtpzzz2emqi9g0yaaq03.png" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>firefightingkubernetes</category>
    </item>
    <item>
      <title>Hitori</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Sun, 18 Jan 2026 19:22:56 +0000</pubDate>
      <link>https://dev.to/orsenthil/hitori-4bn6</link>
      <guid>https://dev.to/orsenthil/hitori-4bn6</guid>
      <description>&lt;p&gt;I wrote an implementation of the game Hitori using Claude Code in agent mode.&lt;/p&gt;

&lt;p&gt;It is a puzzle that I developed after looking at a game called Hitori in Linux. I was studying the architecture of it and noted down how that game was written.&lt;/p&gt;

&lt;p&gt;I thought that I should make an implementation of it.&lt;/p&gt;

&lt;p&gt;I tried to make a Django implementation where Django serves as the backend and the frontend is in JavaScript. I set up the foundation for it and then pointed Claude Code to the original implementation of Hitori, which is written in C in Linux. I asked it to develop a similar one for a client-server architecture that I could play in a web browser using a Python backend and JavaScript frontend.&lt;/p&gt;

&lt;p&gt;I enabled it in agent mode and gave it to dangerously skip permissions. I asked it to implement the game and gave some Yes's for the prompts it asked, then went about with it. I had asked it to make a game and then went to sleep.&lt;/p&gt;

&lt;p&gt;When I woke up the next morning, I saw that the complete game was implemented. To my surprise, I didn't have to do anything. The whole game was there and I just played it. I was like, "Oh my goodness." I was amazed for a full day at what had just happened.&lt;/p&gt;

&lt;p&gt;But then, to take it further, I thought there should be a login system and game board improvements. That took some time, and then I deployed it on a Kubernetes cluster. Even that was easy - I didn't have to do anything.&lt;/p&gt;

&lt;p&gt;This is the first game I developed where I didn't have to open an editor or IDE at all. I did everything completely from the command prompt. This was something new. I thought I should capture this moment, so I'm writing about it in my blog. That's pretty much it.&lt;/p&gt;

&lt;p&gt;You can enjoy playing this game at &lt;a href="https://hitori.learntosolveit.com" rel="noopener noreferrer"&gt;https://hitori.learntosolveit.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>gamedev</category>
      <category>puzzle</category>
    </item>
    <item>
      <title>Visionary - Photo Of the Day Browser Extension</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Sat, 10 Jan 2026 16:23:38 +0000</pubDate>
      <link>https://dev.to/orsenthil/visionary-photo-of-the-day-browser-extension-275h</link>
      <guid>https://dev.to/orsenthil/visionary-photo-of-the-day-browser-extension-275h</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyn65zoxu49jaondd4aoy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyn65zoxu49jaondd4aoy.png" alt=" " width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built a browser plugin called "Visionary" that overlays meaningful descriptions and context directly onto stunning pictures of the day. &lt;/p&gt;

&lt;p&gt;I noticed that existing picture-of-the-day plugins were built over two decades ago and never evolved to harness the capabilities of modern artificial intelligence. AI can transform the picture viewing experience by distilling complex descriptions into accessible insights and providing references to explore the core concepts in the photo more deeply.&lt;/p&gt;

&lt;p&gt;You can get a sense of how this works by visiting &lt;br&gt;
&lt;a href="https://picture.learntosolveit.com" rel="noopener noreferrer"&gt;https://picture.learntosolveit.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Get it for Chrome or other Stores&lt;/p&gt;

&lt;p&gt;&lt;a href="https://chromewebstore.google.com/detail/picture-of-the-day/conkiboijidpjkmflbmagmcebddpphli" rel="noopener noreferrer"&gt;https://chromewebstore.google.com/detail/picture-of-the-day/conkiboijidpjkmflbmagmcebddpphli&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>extensions</category>
      <category>browser</category>
      <category>picture</category>
    </item>
    <item>
      <title>Games: Hitori</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Sat, 22 Nov 2025 15:07:58 +0000</pubDate>
      <link>https://dev.to/orsenthil/games-hitori-k5j</link>
      <guid>https://dev.to/orsenthil/games-hitori-k5j</guid>
      <description>&lt;p&gt;Hitori is a Japanese logic puzzle played on a grid of numbers. The objective is to eliminate numbers so that no row or column contains duplicate numbers, all shaded cells are isolated (not touching horizontally or vertically), and unshaded cells create a single connected group, that is you can you move from one unshaded cell to another unshaded cell following the path vertically or horizontally.&lt;/p&gt;

&lt;p&gt;Here’s how a typical Hitori puzzle appears:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn1s0jins5y2zbc4m5jps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn1s0jins5y2zbc4m5jps.png" alt="Hitori puzzle grid" width="355" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to Play:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shade cells to eliminate duplicate numbers from each row and column.&lt;/li&gt;
&lt;li&gt;Shaded (black) cells cannot be adjacent to each other vertically or horizontally.&lt;/li&gt;
&lt;li&gt;All non-shaded (white) cells must be connected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The source code of this project is here &lt;a href="https://gitlab.gnome.org/GNOME/hitori" rel="noopener noreferrer"&gt;https://gitlab.gnome.org/GNOME/hitori&lt;/a&gt; and the architecture is explained &lt;a href="https://gitlab.gnome.org/orsenthil/hitori/-/blob/main/architecture.md" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>games</category>
    </item>
    <item>
      <title>Games: Biniax 2</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Sun, 16 Nov 2025 15:54:18 +0000</pubDate>
      <link>https://dev.to/orsenthil/games-biniax-2-1dm9</link>
      <guid>https://dev.to/orsenthil/games-biniax-2-1dm9</guid>
      <description>&lt;p&gt;Biniax is a very simple, but interesting, vertical scrolling , matching game. You have to move you piece to collapse against the piece&lt;br&gt;
of same color. The game ends when you are no longer able to collapse the pieces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwt2c5zzpc5lcp2fjgvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwt2c5zzpc5lcp2fjgvc.png" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how we start.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwt2c5zzpc5lcp2fjgvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwt2c5zzpc5lcp2fjgvc.png" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The game is written in ANSI C and uses SDL. I had to fix the source code for compilation, it is maintained here&lt;br&gt;
&lt;a href="https://github.com/orsenthil/biniax2/tree/main" rel="noopener noreferrer"&gt;https://github.com/orsenthil/biniax2/tree/main&lt;/a&gt;, and the &lt;a href="https://github.com/orsenthil/biniax2/blob/main/architecture.md" rel="noopener noreferrer"&gt;architecture&lt;/a&gt; gives the architectural concepts for developement.&lt;/p&gt;

</description>
      <category>games</category>
    </item>
    <item>
      <title>Games: Chromono</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Sun, 16 Nov 2025 07:11:46 +0000</pubDate>
      <link>https://dev.to/orsenthil/games-chromono-513m</link>
      <guid>https://dev.to/orsenthil/games-chromono-513m</guid>
      <description>&lt;p&gt;Chromono is a visually appealing and aesthetic circular puzzle game. The game engine and physics is enticing. The rules are simple, you only have to make the circle of the same color overlap/touch with circle with the same patch. The game introduce challenges with bounce, physics and tricky circular structures.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyo7bvhp5t9h6z3v19lh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyo7bvhp5t9h6z3v19lh.png" width="794" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The source code lives here, &lt;a href="https://github.com/orsenthil/chromono/tree/main" rel="noopener noreferrer"&gt;https://github.com/orsenthil/chromono/tree/main&lt;/a&gt;, and I had to fix for the build and runtime issues on Linux for OpenGL.&lt;/p&gt;

&lt;p&gt;The game is written in C++11, and uses OpenGL. The &lt;a href="https://github.com/orsenthil/chromono/blob/main/architecture.md" rel="noopener noreferrer"&gt;architecture and technologies to learn&lt;/a&gt; are exciting and modern too.&lt;/p&gt;

</description>
      <category>games</category>
    </item>
    <item>
      <title>Games: Atomix</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Sat, 15 Nov 2025 15:52:20 +0000</pubDate>
      <link>https://dev.to/orsenthil/games-atomix-2ofj</link>
      <guid>https://dev.to/orsenthil/games-atomix-2ofj</guid>
      <description>&lt;p&gt;Atomix is a very simple sliding block tiling puzzle game, in which, the user has to slide the atoms to form the molecule given as a challenge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojjbrak2epnvgctcesl4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fojjbrak2epnvgctcesl4.png" width="672" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The source code is maintained here &lt;a href="https://gitlab.gnome.org/GNOME/atomix/-/tree/main" rel="noopener noreferrer"&gt;https://gitlab.gnome.org/GNOME/atomix/-/tree/main&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The game is written in C, with the object-oriented capabilities provided by a system called GObject. The windowing toolkit used is GTK.&lt;br&gt;
The &lt;a href="https://gitlab.gnome.org/orsenthil/atomix/-/blob/main/ARCHITECTURE.md" rel="noopener noreferrer"&gt;architecture and learning concepts&lt;/a&gt; make it a highly approachable game.&lt;/p&gt;

</description>
      <category>games</category>
    </item>
    <item>
      <title>Games: achilles-1</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Sat, 15 Nov 2025 14:32:21 +0000</pubDate>
      <link>https://dev.to/orsenthil/games-achilles-1-7pj</link>
      <guid>https://dev.to/orsenthil/games-achilles-1-7pj</guid>
      <description>&lt;p&gt;Achilles is a simulation, not really a game. In Achilles, the world is given an X coordinate, Z coordinate, number of food items and number of organisms.&lt;br&gt;
The organisms are not given any objective. But they have functions like they have vision, and learning systems powered by neural networks.&lt;br&gt;
Food spawns randomly across the world. Food decays if it is left alone.&lt;br&gt;
When the organisms see food in proximity, they eat the food. When the organisms see each other, if they are similar, they mate. If there is enough strength and difference, they can attack each other.&lt;/p&gt;

&lt;p&gt;And the world evolves!&lt;/p&gt;

&lt;p&gt;Here is a screenshot of the evolution&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuuix0zt5jcun01ozuvk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuuix0zt5jcun01ozuvk.png" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the attack in progress.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fej0hkyqpak7120at4zsb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fej0hkyqpak7120at4zsb.png" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The program is written in C++ and uses OpenGL to display the world. The package that is present in many Linux operating systems does not behave the way we want. I had to check out the source code, and fix the bugs in the program.&lt;/p&gt;

&lt;p&gt;The source of the maintained version lives in GitHub here: &lt;a href="https://github.com/orsenthil/achilles-1" rel="noopener noreferrer"&gt;https://github.com/orsenthil/achilles-1&lt;/a&gt;; there is &lt;a href="https://github.com/orsenthil/achilles-1/blob/main/LEARNING_RESOURCES.md" rel="noopener noreferrer"&gt;a lifetime worth of learning concepts&lt;/a&gt; used by this simple program.&lt;/p&gt;

</description>
      <category>games</category>
    </item>
    <item>
      <title>Games 2048-QT</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Tue, 11 Nov 2025 14:28:05 +0000</pubDate>
      <link>https://dev.to/orsenthil/games-2048-qt-ji5</link>
      <guid>https://dev.to/orsenthil/games-2048-qt-ji5</guid>
      <description>&lt;p&gt;This is a port of 2048 game written in QT framework&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3977f5el6g4u1hv9suc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3977f5el6g4u1hv9suc.png" width="546" height="775"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The source code here &lt;a href="https://github.com/xiaoyong/2048-Qt" rel="noopener noreferrer"&gt;https://github.com/xiaoyong/2048-Qt&lt;/a&gt; shows a very simple, and modular approach.&lt;br&gt;
The QT game load is written in C++, but the game logic itself is written in qml and javascript. The interface components are in C++, the game logic is in Javascript, which has a native integration with QML, Qt Markup Language; and this whole program is orchestrated via QT framework.&lt;/p&gt;

</description>
      <category>games</category>
    </item>
    <item>
      <title>Games- Amoebax</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Sun, 09 Nov 2025 18:37:16 +0000</pubDate>
      <link>https://dev.to/orsenthil/games-amoebax-mkn</link>
      <guid>https://dev.to/orsenthil/games-amoebax-mkn</guid>
      <description>&lt;p&gt;Amoebax is a falling puzzle game, tetris like game. The player has to arrange a group of four.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2uz8l0rd2kw8ki3hyx1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2uz8l0rd2kw8ki3hyx1g.png" width="774" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You have to arrange the falling tiles into groups of four. It has a two player game mechanics too, where in, while you try to ensure that you dont crash to the top, when you remove the paired blocks, you send it to your opponent. You win when your opponent's game is full.&lt;/p&gt;

&lt;p&gt;The opponent is usually an AI. The game is written in C++, and uses libraries like &lt;a href="https://en.wikipedia.org/wiki/Simple_DirectMedia_Layer" rel="noopener noreferrer"&gt;SDL&lt;/a&gt;, zlib, ogg and vorbis.&lt;/p&gt;

&lt;p&gt;The source code here is &lt;a href="https://gitlab.com/perita/amoebax/" rel="noopener noreferrer"&gt;https://gitlab.com/perita/amoebax/&lt;/a&gt;, there is an &lt;a href="https://en.wikipedia.org/wiki/Emscripten" rel="noopener noreferrer"&gt;emscripten&lt;/a&gt; port of the game &lt;a href="https://peritasoft.com/amoebax/index.html" rel="noopener noreferrer"&gt;https://peritasoft.com/amoebax/index.html&lt;/a&gt; which can be played online by the author, Jordi Frita. &lt;/p&gt;

&lt;p&gt;When examining the source code, it is written in modular C++ and uses multiple game design concepts like state design pattern to manage different game states, singleton for creating an instance of the game, factory to create ai players, strategy to implement player behaviors, template for customizable steps, observer for communication, and RAII for dealing with sound and image resources.&lt;/p&gt;

</description>
      <category>games</category>
    </item>
    <item>
      <title>Games - AisleRiot Zebra</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Sun, 09 Nov 2025 15:02:51 +0000</pubDate>
      <link>https://dev.to/orsenthil/games-aisleriot-zebra-2apo</link>
      <guid>https://dev.to/orsenthil/games-aisleriot-zebra-2apo</guid>
      <description>&lt;p&gt;It has become very easy to learn new things. In these series of blog poss, I will be sharing #100games2025, I will be sharing about 100 different new games I have learned in 2025.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://help.gnome.org/users/aisleriot/stable/Zebra.html.en" rel="noopener noreferrer"&gt;Zebra&lt;/a&gt; variant of AisleRiot game is played with two decks. The top row has the two decks to arrange. The player has to arrange the cards with opposite colors. Like Black and Red go alternate on top of each. The bottom is same as solitaire, but in the zebra variant, the top row is arranged alternately. When a slot in the bottom row, called tableau has an empty slot, it is automatically filled in with the latest in the waste pile or from the stock pile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk9cbcvield5v2v5jm915.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk9cbcvield5v2v5jm915.png" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>100games2025</category>
      <category>game1</category>
    </item>
    <item>
      <title>Coin Flip Simulator</title>
      <dc:creator>Senthil Kumaran</dc:creator>
      <pubDate>Wed, 25 Jun 2025 22:48:53 +0000</pubDate>
      <link>https://dev.to/orsenthil/coin-flip-simulator-pno</link>
      <guid>https://dev.to/orsenthil/coin-flip-simulator-pno</guid>
      <description>&lt;p&gt;This is a coin flip simulator. It compare theoretical binomial distribution with experimental results&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fao0xss41imxkpmmtgro3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fao0xss41imxkpmmtgro3.png" alt=" " width="800" height="405"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;Nchoosek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;binomial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Nchoosek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_experiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_flips&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_experiments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p_heads&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Simulate coin flips and count number of heads.

    :param n_flips: Number of coin flips per experiment.
    :param n_experiments: Number of experiments to run.
    :param p_heads: Probability of getting heads (default 0.5 for a fair coin)

    :return: List of head counts for each experiment.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;experiment&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_experiments&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;flips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;p_heads&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_flips&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="n"&gt;heads_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flips&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;heads_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compare_theoretical_vs_experimental&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Compare theoretical binomial distribution with experimental results.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Parameters
&lt;/span&gt;    &lt;span class="n"&gt;n_flips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;          &lt;span class="c1"&gt;# Number of coin flips per experiment
&lt;/span&gt;    &lt;span class="n"&gt;n_experiments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;  &lt;span class="c1"&gt;# Number of experiments to run
&lt;/span&gt;    &lt;span class="n"&gt;p_heads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;         &lt;span class="c1"&gt;# Probability of heads (fair coin)
&lt;/span&gt;
    &lt;span class="c1"&gt;# Run the experiment
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Running &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n_experiments&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; experiments with &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n_flips&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; coin flips each...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;run_experiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_flips&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_experiments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p_heads&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Count occurrences of each number of heads
&lt;/span&gt;    &lt;span class="n"&gt;result_counts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Convert to probabilities
&lt;/span&gt;    &lt;span class="n"&gt;experimental_probs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;n_experiments&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result_counts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;

    &lt;span class="c1"&gt;# Calculate theoretical probabilities using your binomial function
&lt;/span&gt;    &lt;span class="n"&gt;theoretical_probs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;binomial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_flips&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p_heads&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_flips&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

    &lt;span class="c1"&gt;# Prepare data for plotting
&lt;/span&gt;    &lt;span class="n"&gt;k_values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_flips&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;theoretical_values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;theoretical_probs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;k_values&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;experimental_values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;experimental_probs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;k_values&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Plot the results
&lt;/span&gt;    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Bar width and positions
&lt;/span&gt;    &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.35&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k_values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Create bars
&lt;/span&gt;    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;theoretical_values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Theoretical Probability&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;experimental_values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Experimental Probability&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Add labels and title
&lt;/span&gt;    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Number of Heads&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Probability&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Binomial Distribution: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n_flips&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; coin flips, p(heads)=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p_heads&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xticks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k_values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;y&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;linestyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Add a text box with statistics
&lt;/span&gt;    &lt;span class="n"&gt;mean_theoretical&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n_flips&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p_heads&lt;/span&gt;
    &lt;span class="n"&gt;var_theoretical&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n_flips&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p_heads&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;p_heads&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mean_experimental&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result_counts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n_experiments&lt;/span&gt;

    &lt;span class="n"&gt;stats_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Theoretical Mean: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mean_theoretical&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;stats_text&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Theoretical Variance: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;var_theoretical&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;stats_text&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Experimental Mean: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mean_experimental&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;figtext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stats_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bbox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;facecolor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;white&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Show plot
&lt;/span&gt;    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tight_layout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;#plt.show()
&lt;/span&gt;    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;savefig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;coinflip.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Print summary
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Summary:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Theoretical Mean: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mean_theoretical&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Theoretical Variance: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;var_theoretical&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Experimental Mean: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mean_experimental&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Print probabilities table
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Probabilities Table:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Heads | Theoretical | Experimental | Difference&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;k_values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;theo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;theoretical_probs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;exp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;experimental_probs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exp&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;theo&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;theo&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;compare_theoretical_vs_experimental&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>plot</category>
    </item>
  </channel>
</rss>
