Import Quarto posts and expand blog sync bridge
Some checks failed
Build / build (push) Has been cancelled
166
CONTENT_BRIDGE.md
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
# Blog Content Bridge
|
||||||
|
|
||||||
|
The public Obsidian vault is the writing source of truth. The Astro sites are
|
||||||
|
deployable targets that receive copied Markdown and assets.
|
||||||
|
|
||||||
|
## Folder Map
|
||||||
|
|
||||||
|
| Vault folder | Astro content folder | Public domain |
|
||||||
|
| ---------------------- | ------------------------------------------- | ------------------------------------ |
|
||||||
|
| `blogs/01-research` | `sites/research/src/content/research` | `https://research.neeldhara.blog` |
|
||||||
|
| `blogs/02-vibes` | `sites/vibes/src/content/vibes` | `https://vibes.neeldhara.blog` |
|
||||||
|
| `blogs/03-puzzles` | `sites/puzzles/src/content/puzzles` | `https://puzzles.neeldhara.blog` |
|
||||||
|
| `blogs/04-reflections` | `sites/reflections/src/content/reflections` | `https://reflections.neeldhara.blog` |
|
||||||
|
| `blogs/05-poetry` | `sites/poetry/src/content/poetry` | `https://poetry.neeldhara.blog` |
|
||||||
|
| `blogs/06-reviews` | `sites/reviews/src/content/reviews` | `https://reviews.neeldhara.blog` |
|
||||||
|
| `blogs/07-art` | `sites/art/src/content/art` | `https://art.neeldhara.blog` |
|
||||||
|
| `blogs/micro` | `../micro/src/content/blog` | `https://micro.neeldhara.blog` |
|
||||||
|
|
||||||
|
The installed Obsidian plugin lives at:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/Users/neeldhara/obsidian/public/.obsidian/plugins/microblog-sync
|
||||||
|
```
|
||||||
|
|
||||||
|
The versioned copy lives in this repo at:
|
||||||
|
|
||||||
|
```text
|
||||||
|
obsidian-plugin/microblog-sync
|
||||||
|
```
|
||||||
|
|
||||||
|
The plugin id remains `microblog-sync`, but Obsidian shows it as **Blog Family
|
||||||
|
Sync**.
|
||||||
|
|
||||||
|
## Post Layout
|
||||||
|
|
||||||
|
Use one folder per post:
|
||||||
|
|
||||||
|
```text
|
||||||
|
blogs/01-research/example-post/index.md
|
||||||
|
blogs/01-research/example-post/diagram.png
|
||||||
|
```
|
||||||
|
|
||||||
|
The folder path becomes the public URL:
|
||||||
|
|
||||||
|
```text
|
||||||
|
blogs/01-research/example-post/index.md
|
||||||
|
https://research.neeldhara.blog/example-post/
|
||||||
|
```
|
||||||
|
|
||||||
|
Nested folders are supported:
|
||||||
|
|
||||||
|
```text
|
||||||
|
blogs/04-reflections/exportober/2021/index.md
|
||||||
|
https://reflections.neeldhara.blog/exportober/2021/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Frontmatter
|
||||||
|
|
||||||
|
Every public post needs the fields required by the Astro content schema:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: "Post title"
|
||||||
|
description: "One or two sentence summary for cards and RSS."
|
||||||
|
pubDate: "2024-05-10"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional fields currently understood by the sites include `updatedDate`,
|
||||||
|
`image`, and `authorImage`. Prefer colocated images in the body over remote
|
||||||
|
stock images.
|
||||||
|
|
||||||
|
The Quarto import also preserved `sourceCategories` and `sourcePath`. Astro
|
||||||
|
strips unknown schema fields, but they are useful in Obsidian for provenance.
|
||||||
|
|
||||||
|
## Markdown Conventions
|
||||||
|
|
||||||
|
Standard Markdown headings, lists, links, tables, code fences, footnotes, and
|
||||||
|
raw HTML are preserved.
|
||||||
|
|
||||||
|
Use colocated relative assets:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|

|
||||||
|
```
|
||||||
|
|
||||||
|
Quarto image attributes such as `{width=70%}` were removed during import. Going
|
||||||
|
forward, use normal Markdown and let Astro CSS handle presentation.
|
||||||
|
|
||||||
|
Quarto callouts were converted to portable blockquotes:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> **Note**
|
||||||
|
>
|
||||||
|
> Text of the callout.
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the same convention for new notes:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> **Warning**
|
||||||
|
>
|
||||||
|
> This point needs attention.
|
||||||
|
```
|
||||||
|
|
||||||
|
Quarto margin notes such as `[text]{.aside}` were converted to:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> **Aside:** text
|
||||||
|
```
|
||||||
|
|
||||||
|
## Import Rules
|
||||||
|
|
||||||
|
The import script is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
scripts/import-quarto-blog.mjs
|
||||||
|
```
|
||||||
|
|
||||||
|
It reads the Quarto archive, skips `draft: true`, converts `index.qmd` to
|
||||||
|
`index.md`, copies colocated assets, and writes a temporary tree under
|
||||||
|
`/private/tmp/quarto-blog-import`.
|
||||||
|
|
||||||
|
The first import made these category choices:
|
||||||
|
|
||||||
|
| Blog | Rule of thumb |
|
||||||
|
| ------------- | ------------------------------------------------------------------ |
|
||||||
|
| `research` | CS/math exposition, lecture notes, and academic explainers. |
|
||||||
|
| `vibes` | LLM-assisted making, interactives, and generated-tool experiments. |
|
||||||
|
| `puzzles` | Puzzle/game/problem posts. |
|
||||||
|
| `reflections` | Essays, speeches, teaching/career notes, and Exportober context. |
|
||||||
|
| `poetry` | Poems. |
|
||||||
|
| `reviews` | Tool, workflow, software, website, book-list, and tutorial posts. |
|
||||||
|
| `art` | Visual/sketchnote/design/communications-oriented posts. |
|
||||||
|
|
||||||
|
See `IMPORT_REPORT.md` for the specific source-to-destination mapping.
|
||||||
|
|
||||||
|
## Sync Rules
|
||||||
|
|
||||||
|
- Obsidian is the source of truth for day-to-day writing.
|
||||||
|
- Auto-sync copies changes from the matching `blogs/...` folder into the
|
||||||
|
matching local Astro content folder.
|
||||||
|
- The plugin includes Markdown plus common web assets: images, PDFs,
|
||||||
|
JSON/YAML, JS, CSS, HTML, and text files.
|
||||||
|
- One-way sync does not delete target files unless **Delete orphaned target
|
||||||
|
files** is enabled.
|
||||||
|
- The initial Quarto import used replace-style sync to clear placeholder Astro
|
||||||
|
posts. Day-to-day editing should use the plugin.
|
||||||
|
|
||||||
|
## Preview And Publish
|
||||||
|
|
||||||
|
Use these Obsidian commands:
|
||||||
|
|
||||||
|
- `Blog Family Sync: Sync and preview current note`
|
||||||
|
- `Blog Family Sync: Publish current note`
|
||||||
|
- `Blog Family Sync: Publish all changes for current blog`
|
||||||
|
|
||||||
|
Preview detects the current note's folder, starts the matching Astro dev server
|
||||||
|
on its configured local port, and opens the post URL.
|
||||||
|
|
||||||
|
Publish does three things:
|
||||||
|
|
||||||
|
1. Sync vault content into the local repo.
|
||||||
|
2. Run the configured Astro build command.
|
||||||
|
3. Commit and push to Forgejo, where Dokploy picks up the change.
|
||||||
63
IMPORT_REPORT.md
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Quarto Blog Import Report
|
||||||
|
|
||||||
|
Source: /private/tmp/quartosite-shallow/blog
|
||||||
|
Generated: 2026-06-20T01:03:56.508Z
|
||||||
|
|
||||||
|
## Imported Posts
|
||||||
|
|
||||||
|
| Blog | Date | Title | Source | Destination |
|
||||||
|
| ----------- | ---------- | ------------------------------------------- | --------------------------------------------- | --------------------------------------------------------- |
|
||||||
|
| art | 2024-05-10 | Creating a Gallery of Solved Crosswords | `indiamini-crosswords/index.qmd` | `07-art/indiamini-crosswords/index.md` |
|
||||||
|
| art | 2022-09-23 | External Communications | `comms/index.qmd` | `07-art/comms/index.md` |
|
||||||
|
| art | 2021-10-04 | On the Communication Complexity of Equality | `communication-complexity-equality/index.qmd` | `07-art/communication-complexity-equality/index.md` |
|
||||||
|
| poetry | 2024-01-13 | Winning | `poems/winning/index.qmd` | `05-poetry/poems/winning/index.md` |
|
||||||
|
| poetry | 2024-01-01 | Poetry | `poems/poetry/index.qmd` | `05-poetry/poems/poetry/index.md` |
|
||||||
|
| poetry | 2023-05-11 | Letting Go | `poems/letting-go/index.qmd` | `05-poetry/poems/letting-go/index.md` |
|
||||||
|
| poetry | 2012-08-27 | Dad | `poems/dad/index.qmd` | `05-poetry/poems/dad/index.md` |
|
||||||
|
| poetry | 2012-04-23 | On the Fence | `poems/on-the-fence/index.qmd` | `05-poetry/poems/on-the-fence/index.md` |
|
||||||
|
| poetry | 2011-01-05 | Sprinkles of the Sky | `poems/sprinkles-of-the-sky/index.qmd` | `05-poetry/poems/sprinkles-of-the-sky/index.md` |
|
||||||
|
| poetry | 2007-04-03 | Seek | `poems/seek/index.qmd` | `05-poetry/poems/seek/index.md` |
|
||||||
|
| poetry | 2005-02-03 | Bloom | `poems/bloom/index.qmd` | `05-poetry/poems/bloom/index.md` |
|
||||||
|
| puzzles | 2022-09-19 | Dog Bunny Puzzle | `dogs-bunny-puzzle/index.qmd` | `03-puzzles/dogs-bunny-puzzle/index.md` |
|
||||||
|
| puzzles | 2022-03-24 | Solo Chess | `solo-chess/index.qmd` | `03-puzzles/solo-chess/index.md` |
|
||||||
|
| puzzles | 2021-10-03 | Two approaches to the 15 puzzle | `15-puzzle/index.qmd` | `03-puzzles/15-puzzle/index.md` |
|
||||||
|
| puzzles | 2021-09-21 | Moving Blocks at CTIS 2021 | `moving-blocks-ctis/index.qmd` | `03-puzzles/moving-blocks-ctis/index.md` |
|
||||||
|
| reflections | 2023-05-26 | On Career Choices | `on-career-choices/index.qmd` | `04-reflections/on-career-choices/index.md` |
|
||||||
|
| reflections | 2022-11-24 | The Only Fair Ranking of IITs | `iit-rankings/index.qmd` | `04-reflections/iit-rankings/index.md` |
|
||||||
|
| reflections | 2022-10-07 | Exportober 2022 | `exportober/2022-tracker/index.qmd` | `04-reflections/exportober/2022-tracker/index.md` |
|
||||||
|
| reflections | 2022-09-23 | SKJ | `skj/index.qmd` | `04-reflections/skj/index.md` |
|
||||||
|
| reflections | 2022-09-05 | On Teaching | `on-teaching/index.qmd` | `04-reflections/on-teaching/index.md` |
|
||||||
|
| reflections | 2022-03-15 | Eight Self-Sabotaging Behaviors | `eight-self-sabotaging-behaviors/index.qmd` | `04-reflections/eight-self-sabotaging-behaviors/index.md` |
|
||||||
|
| reflections | 2021-09-25 | Exportober 2021 | `exportober/2021-tracker/index.qmd` | `04-reflections/exportober/2021-tracker/index.md` |
|
||||||
|
| reflections | 2021-09-24 | About Exportober | `exportober/about/index.qmd` | `04-reflections/exportober/about/index.md` |
|
||||||
|
| reflections | 2021-09-19 | An Invitation to Exportober 2021 | `exportober/2021/index.qmd` | `04-reflections/exportober/2021/index.md` |
|
||||||
|
| research | 2023-12-21 | Intro to Crypto | `crypto-intro/index.qmd` | `01-research/crypto-intro/index.md` |
|
||||||
|
| research | 2022-02-25 | Kidney Exchanges | `kidney-exchanges/index.qmd` | `01-research/kidney-exchanges/index.md` |
|
||||||
|
| research | 2021-10-01 | Sam I Am | `cp/sam-i-am/index.qmd` | `01-research/cp/sam-i-am/index.md` |
|
||||||
|
| research | 2010-05-01 | How Expensive Can Homework Help Be? | `homework-help/index.qmd` | `01-research/homework-help/index.md` |
|
||||||
|
| reviews | 2023-10-01 | Exportober 2023 | `2023-exportober-workflows/index.qmd` | `06-reviews/2023-exportober-workflows/index.md` |
|
||||||
|
| reviews | 2023-06-02 | Note Taking Resources | `note-taking-resources/index.qmd` | `06-reviews/note-taking-resources/index.md` |
|
||||||
|
| reviews | 2022-11-27 | Letters with Pandoc | `pandoc-letters/index.qmd` | `06-reviews/pandoc-letters/index.md` |
|
||||||
|
| reviews | 2022-02-21 | Women in Mathematics | `women-in-mathematics/index.qmd` | `06-reviews/women-in-mathematics/index.md` |
|
||||||
|
| reviews | 2021-09-30 | New Mac | `new-mac/index.qmd` | `06-reviews/new-mac/index.md` |
|
||||||
|
| reviews | 2021-09-18 | Envelope Budgeting with Notion | `envelope-budgeting-notion/index.qmd` | `06-reviews/envelope-budgeting-notion/index.md` |
|
||||||
|
| reviews | 2021-09-12 | Actually Building a Website with Notion | `building-websites-with-notion/index.qmd` | `06-reviews/building-websites-with-notion/index.md` |
|
||||||
|
| reviews | 2021-09-11 | Notion-powered websites | `notion-powered-websites/index.qmd` | `06-reviews/notion-powered-websites/index.md` |
|
||||||
|
| reviews | 2020-09-11 | Massren for fast file renaming | `massren/index.qmd` | `06-reviews/massren/index.md` |
|
||||||
|
| reviews | 2018-06-12 | Building a first Django App | `django-app/index.qmd` | `06-reviews/django-app/index.md` |
|
||||||
|
| vibes | 2023-12-25 | Course Plan Generator | `course-plan/2024-fall/index.qmd` | `02-vibes/course-plan/2024-fall/index.md` |
|
||||||
|
| vibes | 2023-12-25 | Course Plan Generator | `course-plan/2024-spring/index.qmd` | `02-vibes/course-plan/2024-spring/index.md` |
|
||||||
|
| vibes | 2023-07-30 | Building Interactives | `building-interactives/index.qmd` | `02-vibes/building-interactives/index.md` |
|
||||||
|
| vibes | 2023-04-25 | Course Plan Generator | `course-plan/index.qmd` | `02-vibes/course-plan/index.md` |
|
||||||
|
| vibes | 2023-03-26 | 13 Sheep | `13sheep/index.qmd` | `02-vibes/13sheep/index.md` |
|
||||||
|
|
||||||
|
## Skipped Drafts
|
||||||
|
|
||||||
|
- `b-matching-games/index.qmd`
|
||||||
|
- `degree-width/index.qmd`
|
||||||
|
- `math-of-juggling/index.qmd`
|
||||||
|
- `refute-questions/index.qmd`
|
||||||
|
- `secret-interactive-proofs/index.qmd`
|
||||||
|
- `twitter/index.qmd`
|
||||||
|
- `weightmodification/index.qmd`
|
||||||
|
- `woce/collective-welfare/index.qmd`
|
||||||
|
|
@ -49,3 +49,10 @@ npm run build --prefix sites/research
|
||||||
## Deploy
|
## Deploy
|
||||||
|
|
||||||
Deployment is via Forgejo + Dokploy. See [DEPLOYMENT.md](./DEPLOYMENT.md).
|
Deployment is via Forgejo + Dokploy. See [DEPLOYMENT.md](./DEPLOYMENT.md).
|
||||||
|
|
||||||
|
## Obsidian Content Bridge
|
||||||
|
|
||||||
|
The seven blog content folders are synced from the public Obsidian vault. See
|
||||||
|
[CONTENT_BRIDGE.md](./CONTENT_BRIDGE.md) for conventions, preview/publish
|
||||||
|
commands, and the Quarto import workflow. See [IMPORT_REPORT.md](./IMPORT_REPORT.md)
|
||||||
|
for the current imported post mapping.
|
||||||
|
|
|
||||||
46
obsidian-plugin/microblog-sync/README.md
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
# Blog Family Sync
|
||||||
|
|
||||||
|
This local Obsidian plugin syncs the public vault blog folders with the local
|
||||||
|
Astro sites under `/Users/neeldhara/forgejo/blogs`.
|
||||||
|
|
||||||
|
The plugin id remains `microblog-sync` so the existing Obsidian installation can
|
||||||
|
be upgraded in place. In Obsidian, the visible plugin name is **Blog Family
|
||||||
|
Sync**.
|
||||||
|
|
||||||
|
## Targets
|
||||||
|
|
||||||
|
| Vault folder | Local content folder | Preview |
|
||||||
|
| ---------------------- | ---------------------------------------------------- | -------------------------------- |
|
||||||
|
| `blogs/micro` | `micro/src/content/blog` | `http://127.0.0.1:4321/blog/...` |
|
||||||
|
| `blogs/01-research` | `allblogs/sites/research/src/content/research` | `http://127.0.0.1:4331/...` |
|
||||||
|
| `blogs/02-vibes` | `allblogs/sites/vibes/src/content/vibes` | `http://127.0.0.1:4332/...` |
|
||||||
|
| `blogs/03-puzzles` | `allblogs/sites/puzzles/src/content/puzzles` | `http://127.0.0.1:4333/...` |
|
||||||
|
| `blogs/04-reflections` | `allblogs/sites/reflections/src/content/reflections` | `http://127.0.0.1:4334/...` |
|
||||||
|
| `blogs/05-poetry` | `allblogs/sites/poetry/src/content/poetry` | `http://127.0.0.1:4335/...` |
|
||||||
|
| `blogs/06-reviews` | `allblogs/sites/reviews/src/content/reviews` | `http://127.0.0.1:4336/...` |
|
||||||
|
| `blogs/07-art` | `allblogs/sites/art/src/content/art` | `http://127.0.0.1:4337/...` |
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
Search for **Blog Family Sync** in the command palette:
|
||||||
|
|
||||||
|
- `Sync all configured blogs`
|
||||||
|
- `Sync current blog vault folder to repo`
|
||||||
|
- `Sync current blog repo folder to vault`
|
||||||
|
- `Two-way sync current blog`
|
||||||
|
- `Sync and preview current note`
|
||||||
|
- `Publish current note`
|
||||||
|
- `Publish all changes for current blog`
|
||||||
|
|
||||||
|
Preview starts the matching Astro dev server if the configured local URL is not
|
||||||
|
already responding. Publish syncs first, runs that target's build command,
|
||||||
|
commits staged content changes, and pushes to Forgejo.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Obsidian is the source of truth for day-to-day writing.
|
||||||
|
- Deletions are not mirrored unless `Delete orphaned target files` is enabled.
|
||||||
|
- The plugin watches all configured vault folders and also polls for external
|
||||||
|
edits, which catches changes made by another editor.
|
||||||
|
- Debug output is written to
|
||||||
|
`.obsidian/plugins/microblog-sync/debug.log`.
|
||||||
1575
obsidian-plugin/microblog-sync/main.js
Normal file
9
obsidian-plugin/microblog-sync/manifest.json
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"id": "microblog-sync",
|
||||||
|
"name": "Blog Family Sync",
|
||||||
|
"version": "0.4.0",
|
||||||
|
"minAppVersion": "1.5.0",
|
||||||
|
"description": "Sync the public Obsidian blog folders with the local Astro blog repos.",
|
||||||
|
"author": "Neeldhara Misra",
|
||||||
|
"isDesktopOnly": true
|
||||||
|
}
|
||||||
634
scripts/import-quarto-blog.mjs
Normal file
|
|
@ -0,0 +1,634 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
import fs from "node:fs/promises";
|
||||||
|
import nodeFs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
const DEFAULT_SOURCE = "/private/tmp/quartosite-shallow/blog";
|
||||||
|
const DEFAULT_OUTPUT = "/private/tmp/quarto-blog-import";
|
||||||
|
|
||||||
|
const sourceRoot = path.resolve(process.argv[2] || DEFAULT_SOURCE);
|
||||||
|
const outputRoot = path.resolve(process.argv[3] || DEFAULT_OUTPUT);
|
||||||
|
|
||||||
|
const blogs = [
|
||||||
|
{ key: "research", vaultFolder: "01-research", title: "Research" },
|
||||||
|
{ key: "vibes", vaultFolder: "02-vibes", title: "Vibes" },
|
||||||
|
{ key: "puzzles", vaultFolder: "03-puzzles", title: "Puzzles" },
|
||||||
|
{ key: "reflections", vaultFolder: "04-reflections", title: "Reflections" },
|
||||||
|
{ key: "poetry", vaultFolder: "05-poetry", title: "Poetry" },
|
||||||
|
{ key: "reviews", vaultFolder: "06-reviews", title: "Reviews" },
|
||||||
|
{ key: "art", vaultFolder: "07-art", title: "Art" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const blogByKey = new Map(blogs.map((blog) => [blog.key, blog]));
|
||||||
|
|
||||||
|
const explicitDestinations = new Map([
|
||||||
|
["13sheep/index.qmd", "vibes"],
|
||||||
|
["15-puzzle/index.qmd", "puzzles"],
|
||||||
|
["2023-exportober-workflows/index.qmd", "reviews"],
|
||||||
|
["building-interactives/index.qmd", "vibes"],
|
||||||
|
["building-websites-with-notion/index.qmd", "reviews"],
|
||||||
|
["comms/index.qmd", "art"],
|
||||||
|
["communication-complexity-equality/index.qmd", "art"],
|
||||||
|
["course-plan/2024-fall/index.qmd", "vibes"],
|
||||||
|
["course-plan/2024-spring/index.qmd", "vibes"],
|
||||||
|
["course-plan/index.qmd", "vibes"],
|
||||||
|
["cp/sam-i-am/index.qmd", "research"],
|
||||||
|
["crypto-intro/index.qmd", "research"],
|
||||||
|
["django-app/index.qmd", "reviews"],
|
||||||
|
["dogs-bunny-puzzle/index.qmd", "puzzles"],
|
||||||
|
["eight-self-sabotaging-behaviors/index.qmd", "reflections"],
|
||||||
|
["envelope-budgeting-notion/index.qmd", "reviews"],
|
||||||
|
["exportober/2021-tracker/index.qmd", "reflections"],
|
||||||
|
["exportober/2021/index.qmd", "reflections"],
|
||||||
|
["exportober/2022-tracker/index.qmd", "reflections"],
|
||||||
|
["exportober/about/index.qmd", "reflections"],
|
||||||
|
["homework-help/index.qmd", "research"],
|
||||||
|
["iit-rankings/index.qmd", "reflections"],
|
||||||
|
["indiamini-crosswords/index.qmd", "art"],
|
||||||
|
["kidney-exchanges/index.qmd", "research"],
|
||||||
|
["massren/index.qmd", "reviews"],
|
||||||
|
["moving-blocks-ctis/index.qmd", "puzzles"],
|
||||||
|
["new-mac/index.qmd", "reviews"],
|
||||||
|
["note-taking-resources/index.qmd", "reviews"],
|
||||||
|
["notion-powered-websites/index.qmd", "reviews"],
|
||||||
|
["on-career-choices/index.qmd", "reflections"],
|
||||||
|
["on-teaching/index.qmd", "reflections"],
|
||||||
|
["pandoc-letters/index.qmd", "reviews"],
|
||||||
|
["skj/index.qmd", "reflections"],
|
||||||
|
["solo-chess/index.qmd", "puzzles"],
|
||||||
|
["women-in-mathematics/index.qmd", "reviews"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const skippedDrafts = [];
|
||||||
|
const importedPosts = [];
|
||||||
|
|
||||||
|
await fs.rm(outputRoot, { recursive: true, force: true });
|
||||||
|
await fs.mkdir(outputRoot, { recursive: true });
|
||||||
|
|
||||||
|
for (const blog of blogs) {
|
||||||
|
await fs.mkdir(path.join(outputRoot, "obsidian", "blogs", blog.vaultFolder), {
|
||||||
|
recursive: true,
|
||||||
|
});
|
||||||
|
await fs.mkdir(
|
||||||
|
path.join(
|
||||||
|
outputRoot,
|
||||||
|
"astro",
|
||||||
|
"sites",
|
||||||
|
blog.key,
|
||||||
|
"src",
|
||||||
|
"content",
|
||||||
|
blog.key,
|
||||||
|
),
|
||||||
|
{ recursive: true },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceFiles = (await walk(sourceRoot))
|
||||||
|
.filter((file) => /\.(qmd|md|markdown)$/i.test(file))
|
||||||
|
.sort();
|
||||||
|
|
||||||
|
for (const sourceFile of sourceFiles) {
|
||||||
|
const relativePath = toPosix(path.relative(sourceRoot, sourceFile));
|
||||||
|
const sourceText = await fs.readFile(sourceFile, "utf8");
|
||||||
|
const { frontmatter, body } = parseFrontmatter(sourceText);
|
||||||
|
|
||||||
|
if (isDraft(frontmatter)) {
|
||||||
|
skippedDrafts.push(relativePath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const blogKey = classifyPost(relativePath, frontmatter);
|
||||||
|
const blog = blogByKey.get(blogKey);
|
||||||
|
if (!blog) {
|
||||||
|
throw new Error(`Unknown blog key "${blogKey}" for ${relativePath}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const markdownRelativePath = relativePath.replace(
|
||||||
|
/\.(qmd|markdown)$/i,
|
||||||
|
".md",
|
||||||
|
);
|
||||||
|
const convertedBody = convertQuartoMarkdown(body).trim();
|
||||||
|
const title = frontmatter.title || titleFromPath(relativePath);
|
||||||
|
const pubDate = normalizeDate(frontmatter.date);
|
||||||
|
const description =
|
||||||
|
frontmatter.description || summarize(convertedBody, title);
|
||||||
|
const categories = parseList(frontmatter.categories);
|
||||||
|
const markdown = [
|
||||||
|
"---",
|
||||||
|
`title: ${yamlString(title)}`,
|
||||||
|
`description: ${yamlString(description)}`,
|
||||||
|
`pubDate: ${yamlString(pubDate)}`,
|
||||||
|
'authorName: "Neeldhara"',
|
||||||
|
categories.length
|
||||||
|
? `sourceCategories: [${categories.map(yamlString).join(", ")}]`
|
||||||
|
: "",
|
||||||
|
`sourcePath: ${yamlString(relativePath)}`,
|
||||||
|
"---",
|
||||||
|
"",
|
||||||
|
convertedBody,
|
||||||
|
"",
|
||||||
|
]
|
||||||
|
.filter((line, index, lines) => line || lines[index - 1] !== "")
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
const obsidianTarget = path.join(
|
||||||
|
outputRoot,
|
||||||
|
"obsidian",
|
||||||
|
"blogs",
|
||||||
|
blog.vaultFolder,
|
||||||
|
fromPosix(markdownRelativePath),
|
||||||
|
);
|
||||||
|
const astroTarget = path.join(
|
||||||
|
outputRoot,
|
||||||
|
"astro",
|
||||||
|
"sites",
|
||||||
|
blog.key,
|
||||||
|
"src",
|
||||||
|
"content",
|
||||||
|
blog.key,
|
||||||
|
fromPosix(markdownRelativePath),
|
||||||
|
);
|
||||||
|
|
||||||
|
await writeFileEnsured(obsidianTarget, markdown);
|
||||||
|
await writeFileEnsured(astroTarget, markdown);
|
||||||
|
await copyPostAssets(path.dirname(sourceFile), path.dirname(obsidianTarget));
|
||||||
|
await copyPostAssets(path.dirname(sourceFile), path.dirname(astroTarget));
|
||||||
|
|
||||||
|
importedPosts.push({
|
||||||
|
source: relativePath,
|
||||||
|
destination: `${blog.vaultFolder}/${markdownRelativePath}`,
|
||||||
|
blog: blog.key,
|
||||||
|
title,
|
||||||
|
date: pubDate,
|
||||||
|
categories,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await writeImportReport();
|
||||||
|
await writeVaultReadme();
|
||||||
|
await writeAstroManifest();
|
||||||
|
|
||||||
|
console.log(`Imported ${importedPosts.length} posts into ${outputRoot}`);
|
||||||
|
console.log(`Skipped ${skippedDrafts.length} draft posts.`);
|
||||||
|
|
||||||
|
async function writeImportReport() {
|
||||||
|
const rows = [
|
||||||
|
"# Quarto Blog Import Report",
|
||||||
|
"",
|
||||||
|
`Source: ${sourceRoot}`,
|
||||||
|
`Generated: ${new Date().toISOString()}`,
|
||||||
|
"",
|
||||||
|
"## Imported Posts",
|
||||||
|
"",
|
||||||
|
"| Blog | Date | Title | Source | Destination |",
|
||||||
|
"| --- | --- | --- | --- | --- |",
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const post of importedPosts.sort(
|
||||||
|
(left, right) =>
|
||||||
|
left.blog.localeCompare(right.blog) ||
|
||||||
|
right.date.localeCompare(left.date),
|
||||||
|
)) {
|
||||||
|
rows.push(
|
||||||
|
`| ${post.blog} | ${post.date} | ${escapeTable(post.title)} | \`${post.source}\` | \`${post.destination}\` |`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
rows.push("", "## Skipped Drafts", "");
|
||||||
|
if (skippedDrafts.length) {
|
||||||
|
for (const draft of skippedDrafts) {
|
||||||
|
rows.push(`- \`${draft}\``);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rows.push("- None");
|
||||||
|
}
|
||||||
|
|
||||||
|
await writeFileEnsured(
|
||||||
|
path.join(outputRoot, "IMPORT_REPORT.md"),
|
||||||
|
`${rows.join("\n")}\n`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function writeVaultReadme() {
|
||||||
|
const readme = `# Blog Content Bridge
|
||||||
|
|
||||||
|
This folder is the Obsidian source of truth for the public blog family.
|
||||||
|
|
||||||
|
## Folder Map
|
||||||
|
|
||||||
|
| Vault folder | Astro site | Public domain |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| \`blogs/01-research\` | \`allblogs/sites/research/src/content/research\` | \`https://research.neeldhara.blog\` |
|
||||||
|
| \`blogs/02-vibes\` | \`allblogs/sites/vibes/src/content/vibes\` | \`https://vibes.neeldhara.blog\` |
|
||||||
|
| \`blogs/03-puzzles\` | \`allblogs/sites/puzzles/src/content/puzzles\` | \`https://puzzles.neeldhara.blog\` |
|
||||||
|
| \`blogs/04-reflections\` | \`allblogs/sites/reflections/src/content/reflections\` | \`https://reflections.neeldhara.blog\` |
|
||||||
|
| \`blogs/05-poetry\` | \`allblogs/sites/poetry/src/content/poetry\` | \`https://poetry.neeldhara.blog\` |
|
||||||
|
| \`blogs/06-reviews\` | \`allblogs/sites/reviews/src/content/reviews\` | \`https://reviews.neeldhara.blog\` |
|
||||||
|
| \`blogs/07-art\` | \`allblogs/sites/art/src/content/art\` | \`https://art.neeldhara.blog\` |
|
||||||
|
| \`blogs/micro\` | \`micro/src/content/blog\` | \`https://micro.neeldhara.blog\` |
|
||||||
|
|
||||||
|
The installed Obsidian plugin is still stored at:
|
||||||
|
|
||||||
|
\`\`\`text
|
||||||
|
.obsidian/plugins/microblog-sync
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
The plugin name in Obsidian is **Blog Family Sync**. It watches all folders above, syncs edited files into the matching Astro repo, can start a local preview server for the current note, and can publish by running build, commit, and push.
|
||||||
|
|
||||||
|
## Post Layout
|
||||||
|
|
||||||
|
Use one folder per post:
|
||||||
|
|
||||||
|
\`\`\`text
|
||||||
|
blogs/01-research/example-post/index.md
|
||||||
|
blogs/01-research/example-post/diagram.png
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
The folder path becomes the public URL:
|
||||||
|
|
||||||
|
\`\`\`text
|
||||||
|
blogs/01-research/example-post/index.md
|
||||||
|
https://research.neeldhara.blog/example-post/
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
Nested folders are allowed. For example:
|
||||||
|
|
||||||
|
\`\`\`text
|
||||||
|
blogs/04-reflections/exportober/2021/index.md
|
||||||
|
https://reflections.neeldhara.blog/exportober/2021/
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Frontmatter
|
||||||
|
|
||||||
|
Every public Markdown post should start with:
|
||||||
|
|
||||||
|
\`\`\`yaml
|
||||||
|
---
|
||||||
|
title: "Post title"
|
||||||
|
description: "One or two sentence summary for cards and RSS."
|
||||||
|
pubDate: "2024-05-10"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
---
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
\`title\`, \`description\`, and \`pubDate\` are required by the Astro schemas.
|
||||||
|
\`updatedDate\`, \`image\`, and \`authorImage\` are optional. Prefer colocated images in the body over remote stock images.
|
||||||
|
|
||||||
|
## Markdown Conventions
|
||||||
|
|
||||||
|
- Standard Markdown headings, lists, links, tables, code fences, footnotes, and raw HTML are preserved.
|
||||||
|
- Use colocated relative assets: \`\`.
|
||||||
|
- Quarto image attributes such as \`{width=70%}\` are removed during import. Use normal Markdown now; layout should be handled by Astro CSS.
|
||||||
|
- Quarto callouts are converted to simple blockquotes:
|
||||||
|
|
||||||
|
\`\`\`markdown
|
||||||
|
> **Note**
|
||||||
|
>
|
||||||
|
> Text of the callout.
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
- For new notes, use the same blockquote convention for portable callouts:
|
||||||
|
|
||||||
|
\`\`\`markdown
|
||||||
|
> **Warning**
|
||||||
|
>
|
||||||
|
> This point needs attention.
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
- Quarto margin notes such as \`[text]{.aside}\` are converted to:
|
||||||
|
|
||||||
|
\`\`\`markdown
|
||||||
|
> **Aside:** text
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Sync Rules
|
||||||
|
|
||||||
|
- Obsidian is the source of truth.
|
||||||
|
- Auto-sync copies changed files from the matching \`blogs/...\` folder into the matching local Astro content folder.
|
||||||
|
- The plugin includes Markdown plus common web assets: images, PDFs, JSON/YAML, JS, CSS, HTML, and text files.
|
||||||
|
- One-way sync does not delete target files unless **Delete orphaned target files** is enabled.
|
||||||
|
- The initial Quarto import used replace-style sync to clear placeholder Astro posts. Day-to-day editing should use the plugin.
|
||||||
|
|
||||||
|
## Publish
|
||||||
|
|
||||||
|
Use **Blog Family Sync: Publish current note** or **Blog Family Sync: Publish all changes for current blog** from Obsidian. Publish does three things:
|
||||||
|
|
||||||
|
1. Sync vault content into the local repo.
|
||||||
|
2. Run the configured Astro build command.
|
||||||
|
3. Commit and push to Forgejo, where Dokploy picks up the change.
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
await writeFileEnsured(
|
||||||
|
path.join(outputRoot, "obsidian", "blogs", "README.md"),
|
||||||
|
readme,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function writeAstroManifest() {
|
||||||
|
const manifest = {
|
||||||
|
generatedAt: new Date().toISOString(),
|
||||||
|
sourceRoot,
|
||||||
|
importedPosts,
|
||||||
|
skippedDrafts,
|
||||||
|
};
|
||||||
|
await writeFileEnsured(
|
||||||
|
path.join(outputRoot, "manifest.json"),
|
||||||
|
`${JSON.stringify(manifest, null, 2)}\n`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function classifyPost(relativePath, frontmatter) {
|
||||||
|
if (explicitDestinations.has(relativePath)) {
|
||||||
|
return explicitDestinations.get(relativePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
const categories = parseList(frontmatter.categories).map((category) =>
|
||||||
|
category.toLowerCase(),
|
||||||
|
);
|
||||||
|
const haystack =
|
||||||
|
`${relativePath} ${frontmatter.title || ""} ${categories.join(" ")}`.toLowerCase();
|
||||||
|
|
||||||
|
if (relativePath.startsWith("poems/") || categories.includes("poem")) {
|
||||||
|
return "poetry";
|
||||||
|
}
|
||||||
|
if (categories.some((category) => ["puzzles", "games"].includes(category))) {
|
||||||
|
return "puzzles";
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
categories.some((category) =>
|
||||||
|
[
|
||||||
|
"books",
|
||||||
|
"apps",
|
||||||
|
"workflows",
|
||||||
|
"tutorial",
|
||||||
|
"websites",
|
||||||
|
"notion",
|
||||||
|
"pandoc",
|
||||||
|
"lists",
|
||||||
|
].includes(category),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return "reviews";
|
||||||
|
}
|
||||||
|
if (categories.some((category) => ["sketchnotes"].includes(category))) {
|
||||||
|
return "art";
|
||||||
|
}
|
||||||
|
if (haystack.includes("chatgpt") || haystack.includes("interactive")) {
|
||||||
|
return "vibes";
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
categories.some((category) =>
|
||||||
|
[
|
||||||
|
"lecturenotes",
|
||||||
|
"talk",
|
||||||
|
"exposition",
|
||||||
|
"parameterized-algorithms",
|
||||||
|
].includes(category),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return "research";
|
||||||
|
}
|
||||||
|
return "reflections";
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseFrontmatter(text) {
|
||||||
|
if (!text.startsWith("---")) {
|
||||||
|
return { frontmatter: {}, body: text };
|
||||||
|
}
|
||||||
|
|
||||||
|
const end = text.indexOf("\n---", 3);
|
||||||
|
if (end < 0) {
|
||||||
|
return { frontmatter: {}, body: text };
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawFrontmatter = text.slice(4, end).trim();
|
||||||
|
const body = text.slice(end + 4);
|
||||||
|
const frontmatter = {};
|
||||||
|
for (const line of rawFrontmatter.split(/\r?\n/)) {
|
||||||
|
const match = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
|
||||||
|
if (!match) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [, key, rawValue] = match;
|
||||||
|
frontmatter[key] = unquote(rawValue.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
return { frontmatter, body };
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertQuartoMarkdown(body) {
|
||||||
|
const lines = body.replace(/\r\n/g, "\n").split("\n");
|
||||||
|
const converted = [];
|
||||||
|
const calloutStack = [];
|
||||||
|
let inCodeFence = false;
|
||||||
|
|
||||||
|
for (const rawLine of lines) {
|
||||||
|
const line = rawLine.replace(/\s+$/, "");
|
||||||
|
|
||||||
|
if (/^```/.test(line.trim())) {
|
||||||
|
inCodeFence = !inCodeFence;
|
||||||
|
converted.push(prefixCalloutLine(line, calloutStack.length));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inCodeFence) {
|
||||||
|
const calloutOpen = line.match(
|
||||||
|
/^\s*:::\s*\{?\.?callout-([A-Za-z0-9_-]+)[^}]*\}?\s*$/,
|
||||||
|
);
|
||||||
|
if (calloutOpen) {
|
||||||
|
calloutStack.push(calloutOpen[1]);
|
||||||
|
converted.push(
|
||||||
|
prefixCalloutLine(
|
||||||
|
`**${titleCase(calloutOpen[1])}**`,
|
||||||
|
calloutStack.length,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
converted.push(prefixCalloutLine("", calloutStack.length));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^\s*:::\s*$/.test(line) && calloutStack.length) {
|
||||||
|
calloutStack.pop();
|
||||||
|
converted.push("");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (/^\s*:{3,4}\s*\{/.test(line) || /^\s*:{3,4}\s*$/.test(line)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let cleaned = line;
|
||||||
|
if (!inCodeFence) {
|
||||||
|
cleaned = cleaned
|
||||||
|
.replace(
|
||||||
|
/(<script\b[^>]*><\/script>|<script\b[^>]*>.*?<\/script>)/gi,
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
.replace(/!\[([^\]]*)\]\(([^)]+)\)\{[^}]+\}/g, "")
|
||||||
|
.replace(/^\s*\[([^\]]+)\]\{\.aside\}\s*$/, "> **Aside:** $1")
|
||||||
|
.replace(/\[([^\]]+)\]\{\.smallcaps\}/g, "$1")
|
||||||
|
.replace(/\[([^\]]+)\]\{[^}]+\}/g, "$1");
|
||||||
|
}
|
||||||
|
|
||||||
|
converted.push(prefixCalloutLine(cleaned, calloutStack.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted.join("\n").replace(/\n{4,}/g, "\n\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function prefixCalloutLine(line, depth) {
|
||||||
|
if (!depth) {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${"> ".repeat(depth)}${line}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copyPostAssets(sourceDir, targetDir) {
|
||||||
|
const files = await fs.readdir(sourceDir, { withFileTypes: true });
|
||||||
|
for (const entry of files) {
|
||||||
|
if (
|
||||||
|
entry.name.startsWith(".") ||
|
||||||
|
/\.(qmd|md|markdown)$/i.test(entry.name)
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const source = path.join(sourceDir, entry.name);
|
||||||
|
const target = path.join(targetDir, entry.name);
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
await fs.mkdir(target, { recursive: true });
|
||||||
|
await copyPostAssets(source, target);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.isFile()) {
|
||||||
|
await fs.mkdir(path.dirname(target), { recursive: true });
|
||||||
|
await fs.copyFile(source, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function walk(root) {
|
||||||
|
const entries = await fs.readdir(root, { withFileTypes: true });
|
||||||
|
const files = [];
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (entry.name.startsWith(".")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const absolutePath = path.join(root, entry.name);
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
files.push(...(await walk(absolutePath)));
|
||||||
|
} else if (entry.isFile()) {
|
||||||
|
files.push(absolutePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function writeFileEnsured(target, content) {
|
||||||
|
await fs.mkdir(path.dirname(target), { recursive: true });
|
||||||
|
await fs.writeFile(target, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseList(value) {
|
||||||
|
if (!value) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const trimmed = String(value).trim();
|
||||||
|
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
||||||
|
return trimmed
|
||||||
|
.slice(1, -1)
|
||||||
|
.split(",")
|
||||||
|
.map((item) => unquote(item.trim()))
|
||||||
|
.filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [unquote(trimmed)];
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDraft(frontmatter) {
|
||||||
|
return String(frontmatter.draft || "").toLowerCase() === "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeDate(value) {
|
||||||
|
if (!value) {
|
||||||
|
return "2000-01-01";
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleaned = String(value).replace(/^["']|["']$/g, "");
|
||||||
|
const match = cleaned.match(/^(\d{4})-(\d{2})-(\d{2})/);
|
||||||
|
if (match) {
|
||||||
|
return `${match[1]}-${match[2]}-${match[3]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = new Date(cleaned);
|
||||||
|
if (Number.isNaN(date.valueOf())) {
|
||||||
|
return "2000-01-01";
|
||||||
|
}
|
||||||
|
|
||||||
|
return date.toISOString().slice(0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
function summarize(markdown, title) {
|
||||||
|
const withoutBlocks = markdown
|
||||||
|
.replace(/```[\s\S]*?```/g, " ")
|
||||||
|
.replace(/<[^>]+>/g, " ")
|
||||||
|
.replace(/!\[[^\]]*\]\([^)]+\)/g, " ")
|
||||||
|
.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
|
||||||
|
.replace(/[#>*_`~$]/g, " ")
|
||||||
|
.replace(/\s+/g, " ")
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
const summary = withoutBlocks || title;
|
||||||
|
return summary.length > 180 ? `${summary.slice(0, 177).trim()}...` : summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
function titleFromPath(relativePath) {
|
||||||
|
const folder = relativePath.replace(/\/index\.(qmd|md|markdown)$/i, "");
|
||||||
|
const leaf = folder.split("/").pop() || "Untitled";
|
||||||
|
return leaf
|
||||||
|
.split(/[-_]+/)
|
||||||
|
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
||||||
|
.join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
function titleCase(value) {
|
||||||
|
return String(value)
|
||||||
|
.split(/[-_]+/)
|
||||||
|
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
||||||
|
.join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
function yamlString(value) {
|
||||||
|
return JSON.stringify(String(value || ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
function unquote(value) {
|
||||||
|
if (
|
||||||
|
(value.startsWith('"') && value.endsWith('"')) ||
|
||||||
|
(value.startsWith("'") && value.endsWith("'"))
|
||||||
|
) {
|
||||||
|
return value.slice(1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeTable(value) {
|
||||||
|
return String(value).replace(/\|/g, "\\|");
|
||||||
|
}
|
||||||
|
|
||||||
|
function toPosix(value) {
|
||||||
|
return value.split(path.sep).join("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
function fromPosix(value) {
|
||||||
|
return value.split("/").join(path.sep);
|
||||||
|
}
|
||||||
|
|
@ -16,8 +16,47 @@ const BlogPosts = ({
|
||||||
// Get the first post as the featured post
|
// Get the first post as the featured post
|
||||||
const featuredPost = posts[0];
|
const featuredPost = posts[0];
|
||||||
const remainingPosts = posts.slice(1);
|
const remainingPosts = posts.slice(1);
|
||||||
|
const slugFor = (post: any) => post.id.replace(/\/index$/, "");
|
||||||
const hrefFor = (post: any) =>
|
const hrefFor = (post: any) =>
|
||||||
collection ? `/${collection}/${post.id}/` : `/${post.id}/`;
|
collection ? `/${collection}/${slugFor(post)}/` : `/${slugFor(post)}/`;
|
||||||
|
|
||||||
|
const PostVisual = ({
|
||||||
|
post,
|
||||||
|
featured = false,
|
||||||
|
}: {
|
||||||
|
post: any;
|
||||||
|
featured?: boolean;
|
||||||
|
}) => {
|
||||||
|
if (post.data.image) {
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={post.data.image}
|
||||||
|
alt={post.data.title}
|
||||||
|
className="aspect-video w-full rounded-lg object-cover transition-transform group-hover:scale-[1.02]"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-accent/70 text-accent-foreground flex aspect-video w-full items-center justify-center rounded-lg border px-6 text-center">
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
featured ? "font-fraunces text-2xl" : "font-fraunces text-lg"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{post.data.title}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!featuredPost) {
|
||||||
|
return (
|
||||||
|
<div className="text-muted-foreground container max-w-3xl py-16">
|
||||||
|
No posts yet.
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative py-10 md:py-16 lg:py-20">
|
<div className="relative py-10 md:py-16 lg:py-20">
|
||||||
|
|
@ -35,11 +74,7 @@ const BlogPosts = ({
|
||||||
<div className="flex flex-col gap-6 lg:flex-row">
|
<div className="flex flex-col gap-6 lg:flex-row">
|
||||||
<div className="lg:w-1/2">
|
<div className="lg:w-1/2">
|
||||||
<div className="p-2 lg:p-4">
|
<div className="p-2 lg:p-4">
|
||||||
<img
|
<PostVisual post={featuredPost} featured />
|
||||||
src={featuredPost.data.image}
|
|
||||||
alt={featuredPost.data.title}
|
|
||||||
className="aspect-video w-full rounded-lg object-cover transition-transform group-hover:scale-[1.02]"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-center p-4 pb-8 lg:w-1/2 lg:pr-8">
|
<div className="flex flex-col justify-center p-4 pb-8 lg:w-1/2 lg:pr-8">
|
||||||
|
|
@ -89,11 +124,7 @@ const BlogPosts = ({
|
||||||
href={hrefFor(post)}
|
href={hrefFor(post)}
|
||||||
>
|
>
|
||||||
<div className="p-2">
|
<div className="p-2">
|
||||||
<img
|
<PostVisual post={post} />
|
||||||
src={post.data.image}
|
|
||||||
alt={post.data.title}
|
|
||||||
className="aspect-video w-full rounded-lg object-cover transition-transform group-hover:scale-[1.01]"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="px-4 pb-5 pt-2">
|
<div className="px-4 pb-5 pt-2">
|
||||||
<h2 className="mb-2 text-xl font-semibold group-hover:underline">
|
<h2 className="mb-2 text-xl font-semibold group-hover:underline">
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
---
|
|
||||||
title: "Algorithmic Sketches: Visualizing Data Structures"
|
|
||||||
description: "Hand-drawn illustrations of algorithms and data structures - making the abstract tangible."
|
|
||||||
pubDate: "Jan 25 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1581337204873-ef36aa186caa?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Algorithmic Sketches: Visualizing Data Structures
|
|
||||||
|
|
||||||
Sometimes the best way to understand an algorithm is to draw it.
|
|
||||||
|
|
||||||
## Today's Sketch: Red-Black Trees
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
The rotation operation finally clicked when I drew it step-by-step. Each node's journey through the rotation becomes a story.
|
|
||||||
|
|
||||||
## The Process
|
|
||||||
|
|
||||||
1. Start with pencil - mistakes are part of learning
|
|
||||||
2. Trace the algorithm's execution
|
|
||||||
3. Add color to highlight invariants
|
|
||||||
4. Annotate with key insights
|
|
||||||
|
|
||||||
## Why Drawing Helps
|
|
||||||
|
|
||||||
- Forces you to slow down and really see the structure
|
|
||||||
- Reveals patterns that code obscures
|
|
||||||
- Creates memorable mental models
|
|
||||||
- Makes teaching more engaging
|
|
||||||
|
|
||||||
## This Week's Challenge
|
|
||||||
|
|
||||||
Draw your own version of quicksort partitioning. Share it and let's learn from each other's visualizations.
|
|
||||||
|
|
||||||
## The Art in Computer Science
|
|
||||||
|
|
||||||
Algorithms are beautiful. Drawing them reminds us that computer science is as much art as it is science.
|
|
||||||
BIN
sites/art/src/content/art/comms/1.jpg
Normal file
|
After Width: | Height: | Size: 162 KiB |
BIN
sites/art/src/content/art/comms/chand.png
Normal file
|
After Width: | Height: | Size: 672 KiB |
BIN
sites/art/src/content/art/comms/chand2.png
Normal file
|
After Width: | Height: | Size: 806 KiB |
125
sites/art/src/content/art/comms/index.md
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
---
|
||||||
|
title: "External Communications"
|
||||||
|
description: "I finish seven years at IIT Gandhinagar today. This year, I also concluded my stint with the Department of External Communications, which feels about as long. Indeed, little did..."
|
||||||
|
pubDate: "2022-09-23"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
sourceCategories: ["iitgn"]
|
||||||
|
sourcePath: "comms/index.qmd"
|
||||||
|
---
|
||||||
|
|
||||||
|
I finish seven years at IIT Gandhinagar today.
|
||||||
|
|
||||||
|
This year, I also concluded my stint with the Department of External Communications, which feels about as long. Indeed, little did I know that a casual remark that I had made during my interview^[This was during the summer of 2015, with [Prof. Sudhir Jain](https://sudhirjain.info/).], about wanting to be a writer for as long as I can remember, was carefully noted --- and magically my service responsibilities would end up being related to my childhood dream. A few days after I joined, I met [Achal Mehra](https://www.linkedin.com/in/achal-mehra-13037931/), who introduced me to [_Connections_](https://iitgn.ac.in/about/newsletter): a four-page newsletter that went places every quarter. In my mind, that conversation kickstarted my collaboration with what everyone fondly calls "comms". Seven years later, I'm here to report that the journey has been fun and fulfilling in equal measure.
|
||||||
|
|
||||||
|
Through this post, I'd like to introduce you to the comms team: if you have been to IITGN for an event, read about us in the press, have recieved a newsletter from us, visited our website, or followed our social media: these are the folks who work behind the scenes on these fronts. Being a part of this gang has been a huge inspiration: everyone is talented but always willing to learn; their hard work is driven by a sense of ownership; and there's plenty of wit to help beat the heat :)
|
||||||
|
|
||||||
|
Here's collection of some randomly chosen memories: my hat-tip to a stellar team.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Hatim
|
||||||
|
|
||||||
|
[Hatim](https://www.linkedin.com/in/hatimsham/) joined us in the summer of 2018 and worked with us for four years. This summer, he moved on to join the design unit at [ISDM](https://www.isdm.org.in/team) as a Graphic Designer and Video Editor.
|
||||||
|
|
||||||
|
Hatim has had a creative flair from the get go. He's been a part of several exciting projects, including being the person [behind the visuals](https://www.facebook.com/hatimsham/blog/pfbid02hWtj37tfFBSZiWmbe5yXTALMbDpG41YkGWtWZa4kxr25dysYdHnEjxZQMH6y5HcTl) for Alok Kanungo's book, _Glass Crafts in Northern India_. Also, [here's a cool trailer](https://twitter.com/iitgn/status/1285917964059869184) he put together very quickly for the ACM-W India Grad Cohort that I was involved in organizing in 2020.
|
||||||
|
|
||||||
|
|
||||||
|
## Dilip
|
||||||
|
|
||||||
|
[Dilip](https://www.linkedin.com/in/dilip-kashyap-49aaaaa0/) joined us in the summer of 2018. He had a distinct passion for developing mobile and web applications, and indeed, he's been a huge asset to the web vertical of the team. He's been relentless in learning new things and has been [writing on Medium](https://dilipkashyap15.medium.com/) too.
|
||||||
|
|
||||||
|
When we were organizing the ACM-India Annual event and the team was freaking out over having upwards of 1000 registrations, Dilip wrote a mobile app for us --- literally overnight --- which allowed us to send all participants a QR code that they simply had to show to get through physical registration. It saved us a ton of time. You can find out more about Dilip [here](https://dilipkashyap07.github.io/).
|
||||||
|
|
||||||
|
|
||||||
|
## Tej
|
||||||
|
|
||||||
|
[Tej](https://www.linkedin.com/in/tej-bahadur-gurung-8b94232a/) joined us in the winter of 2016 as a web developer and has been my officemate. Tej is among the first points of contact for all new faculty at IITGN: their institutional profile pages are set up even before they actually set foot on campus. Tej's name is synonymous with "website". If anyone needs one done, whether it's for their lab, or an event, he's always been an email away. True to an appropriate mispronouciation of his name^[Tez = fast in Hindi], Tej has remarkable turnaround times, and seems to get things done as fast as you can spell them out.
|
||||||
|
|
||||||
|
One of my most memorable projects with Tej (along with Dilip, Divyangi, and the rest of the team) is the revamp of the main IITGN website. We went from this:
|
||||||
|
|
||||||
|
.](old.png){width=70%}
|
||||||
|
|
||||||
|
to this:
|
||||||
|
|
||||||
|
.](new.gif){width=70%}
|
||||||
|
|
||||||
|
in about a year. Despite several very well-intended warnings about how crazy this was, the team picked up the project with cautious courage, and pulled it off. I think I can say with some confidence that the IITGN website is easy on the eyes, and things are not hard to find.
|
||||||
|
|
||||||
|
## Apeksha
|
||||||
|
|
||||||
|
[Apeksha](https://www.linkedin.com/in/srivastava-apeksha/) joined us in the summer of 2019, just on the heels of completing her MTech in Biological Engineering at IITGN, and stayed with the team for a year. At the time of joining, she was an avid consumer of popular science material, and aspired to make the research at IITGN more broady accessible with her writing. She was a freelance writer already, and was looking for an opportunity to spend some time writing full-time. Her stint with us resulted in a number of articles, and her growth during the time has been remarkable. You can find her writing on [her Medium blog](https://medium.com/@apeksha.0503).
|
||||||
|
|
||||||
|
The ACM-W India Grad Cohort event we did in 2020 was a virtual one, and in the tradition of Grad Cohorts, was not recorded. I am grateful that Apeksha stepped up at the time, offered to attend all the sessions, and [wrote](https://medium.com/@apeksha.0503/the-acm-w-grad-cohort-2020-women-conquering-computing-online-ca085623e396) [up](https://medium.com/@apeksha.0503/grad-cohort-2020-day-1-of-the-women-virtual-workshop-in-computing-opens-with-a-bang-56407c113ad) [comprehensive](https://medium.com/@apeksha.0503/acm-w-grad-cohort-2020-day-2-a-perfect-combo-of-motivation-and-quality-advice-from-women-leaders-3f2c629e05e5) [summaries](https://medium.com/@apeksha.0503/day-3-acm-w-grad-cohort-2020-concludes-with-strong-networking-opportunities-and-professional-bc8c78efbc33).
|
||||||
|
|
||||||
|
She has now joined the Ph.D. program in the Humanities and Social Sciences and is currently researching cognitive aspects of science communication with [Frederick Coolidge](https://en.wikipedia.org/wiki/Frederick_L._Coolidge.).
|
||||||
|
|
||||||
|
## Dhara
|
||||||
|
|
||||||
|
[Dhara](https://www.linkedin.com/in/dhara-vora-1019/) joined us in the summer of 2018, and immediately got to work on managing our social media channels. She also streamlined the process of collecting information: a lot of what we do revolves around robust archival, and IITGN being a happening place does not make this easy! We get dozens of emails every day announcing events of varying scales, updates of various kinds.
|
||||||
|
|
||||||
|
Anticipating that the volume would only get worse, we devised a system for manually cataloging every bit of news in a bunch of Airtable bases. The long-term vision was that the Airtable API exposes this data to anyone who needs it: the web team could draw from it and filter appropriately to display upcoming events, an archival team could write a report generating app that used this as the backend, and so forth. We even had a web app developed by a team of undergraduates that pulled data from these bases to show off upcoming events on a big screen.
|
||||||
|
|
||||||
|
Dhara now manually curates information from these databases and runs a weekly internal newsletter collating what's happened and what's coming up at IITGN: this has been a major value addition for many. She also serves up the raw data needed for our public [quarterly newsletter](https://iitgn.ac.in/about/newsletter) and [annual reports](https://iitgn.ac.in/about/annualreports) based on this system, which saves everyone a lot of time. Apart from all of this, she is in the driver's seat for all our [major](https://twitter.com/iitgn) [social](https://www.facebook.com/iitgn.official) [media](https://www.linkedin.com/school/indian-institute-of-technology-gandhinagar-iitgn-/) [channels](https://www.instagram.com/iit_gandhinagar/), and then some... and magically manages to stay on top of everything. You can [find her writing on Medium](https://medium.com/@voradhara46).
|
||||||
|
|
||||||
|
|
||||||
|
## Divyangi
|
||||||
|
|
||||||
|
[Divyangi](https://www.linkedin.com/in/divyangi-chaudhari-404115140/) joined us in the summer of 2018 and worked with us for three years until the summer of 2021. She was a wizard when it came to scripting for automating tasks, and quickly became the go-to person for departments who were looking to improve their workflows.
|
||||||
|
|
||||||
|
IITGN runs on the Google ecosystem. Divyangi figured out several nice ways of bringing data from spreadsheets to frontends, generating reports, and so forth. She even ran a workshop on Google scripts and related tools as a part of an initiative coordinated by our Staff Development Cell.
|
||||||
|
|
||||||
|
Among the many projects Divyangi was involved in, one of my favorites was the backend for our rather popular [Summer Research Internship Program](https://srip.iitgn.ac.in/). The website is powered by WordPress, and provides various interfaces for both interns and mentors to keep track of their applications during the application phase (this runs into tens of thousands of records), and progress during the internship (updates from interns and feedback from mentors are all managed from here). Divyangi, together with Dilip, deeply customized the WordPress instance to provide a number of features that help with running a large-scale program smoothly, with most of the tedious tasks completely automated.
|
||||||
|
|
||||||
|
## Chandni
|
||||||
|
|
||||||
|
Chandni joined us in the summer of 2019 for a year. She was already a very talented photographer at the time of joining us. As our events and activities grew in number and scale, we found very valuable support in Chandni's presence. Check out her [Instagram](https://www.instagram.com/visi_lens/) here!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Vandana
|
||||||
|
|
||||||
|
[Vandana](https://www.linkedin.com/in/vandanay/) joined us in the summer of 2017 in the role of a Communications and Media Officer for a year. During this time, she was working closely with local press and media, and ensuring that our stories are filed with them on a regular basis.
|
||||||
|
|
||||||
|
Vandana was already passionate about writing and had a keen eye for detail. She filled an important void at the time she joined and immediately setup various important foundations in the context of this role. She expanded our style guide, made a press kit, and developed a starting database of journalists that we could work with: these are all tools that the whole content team uses regularly to this day.
|
||||||
|
|
||||||
|
Her spirit of volunteerism meant that a lot of our content got reviewed and improved across the board: on the website, on our brochures, and so forth. This was also the time when we launched what I think is our best-kept secret: IITGN's [news blog](https://news.iitgn.ac.in). Vandana, along with the rest of the team, setup a careful pipeline to ensure that everything we capture across press and social media gets a permanent home on the blog. She continues to pitch in remotely, even after moving on from her onsite role with us on campus.
|
||||||
|
|
||||||
|
## Shivangi
|
||||||
|
|
||||||
|
[Shivangi](https://www.linkedin.com/in/shivangi-bhatt-365b4a38/) joined us in the summer of 2018 in the role of a Communications and Media Officer, picking up from where Vandana left off. She has been synonymous with media and press at IITGN, and is currently our main interface with the press. She has substantially expanded on our network of partners in press, and ensures that we have the visibility we deserve in the local and national news, and even beyond. She is especially diligent about ensuring that regionally-focused news is appropriately translated in the local languages whenever appropriate, a widely appreciated effort.
|
||||||
|
|
||||||
|
Shivangi's style has been remarkably proactive: if anything at IITGN is newsworthy, she makes sure it's covered. She draws on her substantial experience in the field to bring nuanced insights to the table, and these have served us very well in our overall communications and outreach strategy.
|
||||||
|
|
||||||
|
Beyond coordinating stories for the press, Shivangi also comprehensively tracks IITGN's presence in the news and other public domains, is closely invovled in the production of the [quarterly newsletter](https://iitgn.ac.in/about/newsletter) and [annual reports](https://iitgn.ac.in/about/annualreports), and our social media activities as well. Shivangi is, unsurprisingly, an amazing writer, and [here's a performance of hers](https://www.facebook.com/shivangi.bhatt.501/blog/pfbid0CB5AGAkotx6cuXnYdNKGqVWc9jE7p3DrodzKTYGGDymSDWC4fxCJNer6bUrLCpJol) in a SDC event that was among my favorites.
|
||||||
|
|
||||||
|
|
||||||
|
## Gaurav
|
||||||
|
|
||||||
|
[Gaurav](https://www.linkedin.com/in/gauravvipul/) has been around for longer than I have, and he is a founding member of the team. He is among the most versatile people I know: not only does the scope of his work at IITGN go well beyond communications, even within communications his skills span a very wide range: he's behind the camera, he's the person behind the design and layouts for some of our best print collaterals, he's directed and produced a number of videos, and I could go on and on.
|
||||||
|
|
||||||
|
I've freely relied on his mentorship: much of the growth that has happened within the team, especially in terms of creative efforts, is thanks to Gaurav's experience and guidance.
|
||||||
|
|
||||||
|
If you pick up any of our booklets, there's a good chance that Gaurav has been involved in engineering the layout and design. Among them, I'll single out a couple for you to sample: the _[World Class Faculty](https://iitgn.ac.in/assets/pdfs/brochures/faculty-brochure.pdf)_ brochure looks especially lovely in print, and the [10 on 10](https://sites.iitgn.ac.in/10/index.php) brochure has a bold aesthetic that was a crowd favorite when it was released for our 10-year celebration.
|
||||||
|
|
||||||
|
|
||||||
|
## Devarsh
|
||||||
|
|
||||||
|
[Devarsh](https://www.instagram.com/dev_barbhaya/) joined us in the summer of 2017, with a background in creative film-making and theatre. He quickly became the go-to person when it came to anything to do with video or photography. Over the years here, he's grown leaps and bounds in his craft and understanding of all aspects of the process --- both work that happens on the field and in post.
|
||||||
|
|
||||||
|
Our YouTube presence was in its nascent stages when Devarsh joined. He's single-handedly worked on [our channel](https://www.youtube.com/channel/UCbOCAa_fRS1qEOknCmEHzVw) in mission mode from the get go, and it is largely thanks to his efforts that we have a fairly systematic video respository of most major events and talks on campus.
|
||||||
|
|
||||||
|
Devarsh has been involved in several memorable projects. Here's [a video](https://www.youtube.com/embed/lZSAkpjsyZs) that he shot for our first virtual convocation, which also happened to be among the first virtual convocation events to be held in India (as far as we know).
|
||||||
|
|
||||||
|
## Nostalgia
|
||||||
|
|
||||||
|
Some of the early members of the team are not pictured. Apart from everyone above, I had the good fortune to have worked with: Ritu (among other things, was the curator for all the early editions of the quarterly newsletter, _Connections_, and our annual reports), Dayanand (our first communications and media officer), Maria (our first social media intern), and Khushbu (who took over from Maria and preceded Dhara on managing social media).
|
||||||
|
|
||||||
|
It would be remiss of me to not give a shout out to the faculty support we have enjoyed over the years. Several colleagues have played major roles in helping out on all aspects of our responsbilities. A special thanks to Achal Mehra, who brought extensive experience to the table, and has been forever generous with his time and advice, and [Vasco Trigo](https://twitter.com/iitgn/status/1163406174626050048), whose inputs for the whole team were extremely timely and valuable.
|
||||||
|
|
||||||
|
I'll also take this opportunity to thank friends at the Communications department at Duke University --- they hosted us in the very early days, and their detailed and candid tour of various operational aspects was massively helpful in setting up a lot of the foundations back here.
|
||||||
|
|
||||||
|
I walked into this gig more or less by accident. I should confess here that I didn't have a 5-year vision from which I could work backwards to nicely chunked milestones. There were no OKRs or KPIs or whatever else the pros do. A few times, it's occurred to us that we should have targets, strategies, and systems^[Most people at IITGN know by now that ambushing me in a corridor is more effective than email, and meanwhile, the team gets things done by some magic that remains a mystery to me.]. While we never articulated any as far as I can remember, I think we did have a tacitly shared goal: it was to ensure that everyone got what they needed from comms, and that we didn't make any mistake twice. My biases notwithstanding, I would say we have largely succeded :)
|
||||||
|
|
||||||
|
My time with this team remains special forever.
|
||||||
BIN
sites/art/src/content/art/comms/new.gif
Normal file
|
After Width: | Height: | Size: 6.1 MiB |
BIN
sites/art/src/content/art/comms/new.png
Normal file
|
After Width: | Height: | Size: 3.2 MiB |
BIN
sites/art/src/content/art/comms/old.png
Normal file
|
After Width: | Height: | Size: 357 KiB |
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
title: "On the Communication Complexity of Equality"
|
||||||
|
description: "These are some quick sketchnotes based on this lecture by Ryan O’Donnell, a part of the playlist for the awesome CS Theory Toolkit course. You can walk through the arguments bel..."
|
||||||
|
pubDate: "2021-10-04"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
sourceCategories: ["sketchnotes", "lecturenotes"]
|
||||||
|
sourcePath: "communication-complexity-equality/index.qmd"
|
||||||
|
---
|
||||||
|
|
||||||
|
These are some quick sketchnotes based on [this lecture](https://www.youtube.com/watch?v=orOJRhlqrvk) by [Ryan O’Donnell](https://www.cs.cmu.edu/~odonnell/), a part of the [playlist](https://www.youtube.com/watch?v=prI35GmCon4&list=PLm3J0oaFux3ZYpFLwwrlv_EHH9wtH6pnX) for the awesome [CS Theory Toolkit](https://www.diderot.one/course/28/) course. You can walk through the arguments below.
|
||||||
|
|
||||||
|
<iframe src="https://slides.com/neeldhara/deck-85ae95/embed?style=transparent&byline=hidden" width="795" height="420" title="Communication Complexity of Equality" scrolling="no" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||||
|
|
||||||
|
I should mention that while the [Schwartz-Zippel-DeMillo-Lipton lemma](https://rjlipton.wpcomstaging.com/2009/11/30/the-curious-history-of-the-schwartz-zippel-lemma/) is invoked in the notes below, one could make do with just the fact that over any field $F$, any degree $n$ polynomial has at most $n$ roots, as pointed out by [@dsivakumar](https://twitter.com/dsivakumar) — thanks!
|
||||||
|
|
||||||
|
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the fourth slide from the end, why [DeMillo--Lipton]--Schwartz--Zippel Lemma? You only need that number of roots of a polynomial (over Z mod q) of degree n is no more than n. You don't need D-L/S/Z, which gives a general version for multivariate polynomials, right?</p>— D. Sivakumar (@dsivakumar) <a href="https://twitter.com/dsivakumar/status/1269351801108623360?ref_src=twsrc%5Etfw">June 6, 2020</a></blockquote>
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
title: "Generative Art with p5.js: Creating Beauty from Mathematics"
|
|
||||||
description: "Exploring the intersection of code and creativity through generative art experiments."
|
|
||||||
pubDate: "Feb 18 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1561070791-2526d30994b5?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Generative Art with p5.js: Creating Beauty from Mathematics
|
|
||||||
|
|
||||||
Code becomes canvas when mathematics meets creativity.
|
|
||||||
|
|
||||||
## Today's Creation: Perlin Noise Flows
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
for (let particle of particles) {
|
|
||||||
let angle = noise(particle.x * 0.01, particle.y * 0.01, frameCount * 0.001) * TWO_PI;
|
|
||||||
particle.velocity = p5.Vector.fromAngle(angle);
|
|
||||||
particle.update();
|
|
||||||
particle.draw();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## The Magic of Randomness
|
|
||||||
|
|
||||||
Controlled randomness creates organic patterns. Perlin noise gives us randomness with continuity - nature's own algorithm.
|
|
||||||
|
|
||||||
## Parameters as Paintbrushes
|
|
||||||
|
|
||||||
- Noise scale: Changes pattern density
|
|
||||||
- Particle count: Affects texture
|
|
||||||
- Color mapping: Sets the mood
|
|
||||||
|
|
||||||
## The Joy of Accidents
|
|
||||||
|
|
||||||
The best discoveries come from "mistakes" - a typo that creates unexpected beauty, a parameter pushed to extremes.
|
|
||||||
|
|
||||||
## Share Your Creations
|
|
||||||
|
|
||||||
Art is meant to be shared. Post your generative experiments and let's inspire each other.
|
|
||||||
BIN
sites/art/src/content/art/indiamini-crosswords/collage.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
sites/art/src/content/art/indiamini-crosswords/hazel-01.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
sites/art/src/content/art/indiamini-crosswords/hazel-02.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
116
sites/art/src/content/art/indiamini-crosswords/index.md
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
---
|
||||||
|
title: "Creating a Gallery of Solved Crosswords"
|
||||||
|
description: "H/T Manu: I've discovered the India Mini Crossword series and it's a great two-to-five minute thing to solve every morning! Here's a little workflow I cobbled together to genera..."
|
||||||
|
pubDate: "2024-05-10"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
sourceCategories: ["workflows"]
|
||||||
|
sourcePath: "indiamini-crosswords/index.qmd"
|
||||||
|
---
|
||||||
|
|
||||||
|
H/T [Manu](https://twitter.com/mnwsth/status/1788781998904914215): I've discovered the [India Mini Crossword series](https://indiamini.in/play/) and it's a great two-to-five minute thing to solve every morning! Here's a little workflow I cobbled together to generate this collage of solved crosswords in [Obsidian](https://obsidian.md/):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
In practice, after the one-time setup I describe here, all I do after solving the crossword is print it and save the PDF to a folder called `Notes/`. The rest is automatic.
|
||||||
|
|
||||||
|
To begin with, I have [Hazel](https://www.noodlesoft.com/) monitor the `Notes/` folder and run this rule:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
All this does is checks if a PDF file has been added to the root level of the `Notes/` folder which has the string `Welcome to the India Mini crossword!`. It then pulls out the date from the file and pushes it into a date-based subfolder; e.g, if the crossword was for the 10th of May, the PDF file moves to the folder `Notes/2024/05/10/`. This is nice because even if I miss a day and solve something later, simply saving the file will still auto-file it in the correct directory.
|
||||||
|
|
||||||
|
Next up, there is a second rule:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
which processes the PDF file by extracting an image that contains the solved crossword. The actual work is carried out by this shell script, written mostly by chatGPT, complete with hard-coded paths:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Extract the first page
|
||||||
|
/usr/local/bin/pdftk /Users/neeldhara/Library/CloudStorage/Dropbox/Notes/$1/indiamini-crossword.pdf cat 1 output /Users/neeldhara/Library/CloudStorage/Dropbox/Notes/$1/first_page.pdf
|
||||||
|
|
||||||
|
echo /Users/neeldhara/Library/CloudStorage/Dropbox/Notes/$1/indiamini-crossword.pdf
|
||||||
|
|
||||||
|
# Convert the first page to a PNG
|
||||||
|
/opt/homebrew/bin/convert -density 300 -quality 100 /Users/neeldhara/Library/CloudStorage/Dropbox/Notes/$1/first_page.pdf /Users/neeldhara/Library/CloudStorage/Dropbox/Notes/$1/first_page.png
|
||||||
|
|
||||||
|
# Get the height and width of the image
|
||||||
|
height=$(/opt/homebrew/bin/identify -format "%h" /Users/neeldhara/Library/CloudStorage/Dropbox/Notes/$1/first_page.png)
|
||||||
|
width=$(/opt/homebrew/bin/identify -format "%w" /Users/neeldhara/Library/CloudStorage/Dropbox/Notes/$1/first_page.png)
|
||||||
|
|
||||||
|
# Calculate the half height and width
|
||||||
|
half_height=$((height/2))
|
||||||
|
half_width=$((width/2+5))
|
||||||
|
|
||||||
|
# Crop the image to the top right half
|
||||||
|
/opt/homebrew/bin/convert /Users/neeldhara/Library/CloudStorage/Dropbox/Notes/$1/first_page.png -crop 1100x1100+${half_width}+315 /Users/neeldhara/Library/CloudStorage/Dropbox/Notes/$1/indiamini-crossword.png
|
||||||
|
|
||||||
|
# Delete intermediate files
|
||||||
|
rm /Users/neeldhara/Library/CloudStorage/Dropbox/Notes/$1/first_page.png
|
||||||
|
rm /Users/neeldhara/Library/CloudStorage/Dropbox/Notes/$1/first_page.pdf
|
||||||
|
```
|
||||||
|
|
||||||
|
I finally have a very simple [Keyboard Maestro](http://www.keyboardmaestro.com/) macro that runs every morning at 7AM --- except Sundays, because the Sunday crossword is not a mini :) --- to create the crossword note in my Obsidian vault in a date-based folder:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The crossword note template is very minimal:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
title: India Mini Crossword · <% tp.date.now("YYYY") %>-<% tp.date.now("MM") %>-<% tp.date.now("DD") %>
|
||||||
|
tags:
|
||||||
|
- kw/c/crossword
|
||||||
|
- kw/i/indiamini
|
||||||
|
- puzzles/indiamini-crossword
|
||||||
|
asset: file:///Users/neeldhara/Library/CloudStorage/Dropbox/Notes/<% tp.date.now("YYYY") %>/<% tp.date.now("MM") %>/<% tp.date.now("DD") %>/indiamini-crossword.pdf
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
 %>/<% tp.date.now("MM") %>/<% tp.date.now("DD") %>/indiamini-crossword.png)
|
||||||
|
```
|
||||||
|
|
||||||
|
The [Templater plugin for Obsidian](https://github.com/SilentVoid13/Templater) ensures that the dates expand correctly at the time the note is created. You could instead run a shell script to just generate these notes for all dates in advance, but I like this because the KM prompt reminds me to do the crossword :)
|
||||||
|
|
||||||
|
The individual crossword file simply shows the PNG file generated by the Hazel rule. I might eventually add solve times to the frontmatter. For the collage, I use this dataview query in a separate note:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
console.log('Fetching pages from "Notes" with specific tag...');
|
||||||
|
|
||||||
|
const assets = dv.pages('"Notes"')
|
||||||
|
.where(p => p.tags?.includes("puzzles/indiamini-crossword") && p.asset)
|
||||||
|
.map(page => {
|
||||||
|
// Replace .pdf with .png in the asset path
|
||||||
|
const pngAsset = page.asset.replace('.pdf', '.png');
|
||||||
|
console.log(`Found page: ${page.file.path} with asset: ${pngAsset}`);
|
||||||
|
return {
|
||||||
|
file: page.file.link,
|
||||||
|
asset: pngAsset // Now the asset points to a .png file instead of a .pdf
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
dv.paragraph(`Total images found: ${assets.length}`);
|
||||||
|
assets.sort();
|
||||||
|
|
||||||
|
let fullstring = "";
|
||||||
|
|
||||||
|
if (assets.length === 0) {
|
||||||
|
dv.paragraph("No assets found. Check the folder, tags, and frontmatter.");
|
||||||
|
} else {
|
||||||
|
assets.forEach((item, index) => {
|
||||||
|
fullstring += ` `;
|
||||||
|
if ((index + 1) % 3 === 0) { // After every third image
|
||||||
|
fullstring += '\n'; // Append a line break
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dv.paragraph(fullstring);
|
||||||
|
```
|
||||||
|
|
||||||
|
The [media grid snippet for Obsidian](https://github.com/zremboldt/obsidian-media-grid) gets the grid alignment going for the images.
|
||||||
|
|
||||||
|
And that's it!
|
||||||
BIN
sites/art/src/content/art/indiamini-crosswords/km-macro.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
|
|
@ -1,40 +0,0 @@
|
||||||
---
|
|
||||||
title: "Algorithms in Verse: Bubble Sort Sonnet"
|
|
||||||
description: "Classic algorithms reimagined as poetry - where code meets iambic pentameter."
|
|
||||||
pubDate: "Feb 22 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1455390582262-044cdead277a?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Algorithms in Verse: Bubble Sort Sonnet
|
|
||||||
|
|
||||||
## Bubble Sort: A Sonnet
|
|
||||||
|
|
||||||
```
|
|
||||||
Compare adjacent elements in pairs,
|
|
||||||
If order's wrong, then swap them into place.
|
|
||||||
Through all the list this simple rule declares:
|
|
||||||
The largest bubbles up to find its space.
|
|
||||||
|
|
||||||
Again we start, but now one less to check,
|
|
||||||
The second largest finds its rightful home.
|
|
||||||
Each pass through makes the chaos less a wreck,
|
|
||||||
Until at last no elements must roam.
|
|
||||||
|
|
||||||
Though simple in its elegance and grace,
|
|
||||||
And easy for beginners to perceive,
|
|
||||||
In practice, it's too slow to win the race—
|
|
||||||
O(n²) we sadly must believe.
|
|
||||||
|
|
||||||
But beauty lies in simplicity's pure art,
|
|
||||||
The bubble sort still teaches at the start.
|
|
||||||
```
|
|
||||||
|
|
||||||
## The Challenge
|
|
||||||
|
|
||||||
Can you write Quicksort as a limerick? Or Binary Search as free verse?
|
|
||||||
|
|
||||||
## Why This Matters
|
|
||||||
|
|
||||||
Poetry forces us to find the essence of an algorithm. The constraint reveals understanding.
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
---
|
|
||||||
title: "Code Haikus: Programming in 5-7-5"
|
|
||||||
description: "Expressing programming concepts through the constrained beauty of haiku."
|
|
||||||
pubDate: "Jan 30 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1481627834876-b7833e8f5570?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Code Haikus: Programming in 5-7-5
|
|
||||||
|
|
||||||
The constraint of haiku forces clarity. Here are programming concepts distilled to their essence.
|
|
||||||
|
|
||||||
## On Recursion
|
|
||||||
|
|
||||||
```
|
|
||||||
Function calls itself
|
|
||||||
Smaller problems, same pattern
|
|
||||||
Base case stops the loop
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Debugging
|
|
||||||
|
|
||||||
```
|
|
||||||
Print statements bloom wild
|
|
||||||
Binary search through the code
|
|
||||||
Bug reveals itself
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Optimization
|
|
||||||
|
|
||||||
```
|
|
||||||
O(n squared) crawls
|
|
||||||
Refactor to n log n
|
|
||||||
Time complexity
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Git Merge Conflicts
|
|
||||||
|
|
||||||
```
|
|
||||||
<<<<<<< HEAD
|
|
||||||
Your changes, their changes clash
|
|
||||||
Resolution waits
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Learning
|
|
||||||
|
|
||||||
```
|
|
||||||
Stack Overflow searched
|
|
||||||
Tutorial incomplete
|
|
||||||
Understanding dawns
|
|
||||||
```
|
|
||||||
|
|
||||||
## Your Turn
|
|
||||||
|
|
||||||
Write a haiku about your coding experience today. The constraint reveals truth.
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
---
|
|
||||||
title: "The 100 Prisoners Problem: A Beautiful Puzzle in Probability"
|
|
||||||
description: "An interactive exploration of one of the most counterintuitive puzzles in probability theory, where 100 prisoners can escape with over 30% chance using a clever strategy."
|
|
||||||
pubDate: "Oct 13 2025"
|
|
||||||
image: "https://images.unsplash.com/photo-1589829545856-d10d557cf95f?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
import PrisonerGameSimulator from '@/components/problems/PrisonerGameSimulator.tsx';
|
|
||||||
import ProbabilityChart from '@/components/problems/ProbabilityChart.tsx';
|
|
||||||
import PermutationExplorer from '@/components/problems/PermutationExplorer.tsx';
|
|
||||||
import StrategyComparison from '@/components/problems/StrategyComparison.tsx';
|
|
||||||
|
|
||||||
# The 100 Prisoners Problem
|
|
||||||
|
|
||||||
Imagine 100 prisoners, numbered 1 to 100, face an unusual challenge. In a room are 100 boxes, also numbered 1 to 100. Inside each box is a randomly assigned number from 1 to 100 (each number appearing exactly once). The prisoners must find their own number by opening boxes, but here's the catch: **each prisoner can open only 50 boxes**.
|
|
||||||
|
|
||||||
The prisoners can devise a strategy beforehand, but once the challenge begins, they cannot communicate. If **all 100 prisoners** find their number, everyone goes free. If even one prisoner fails, all remain imprisoned.
|
|
||||||
|
|
||||||
What's the best strategy? And what are the odds of success?
|
|
||||||
|
|
||||||
## Try It Yourself!
|
|
||||||
|
|
||||||
Before we dive into the mathematics, let's experience the problem firsthand. Below is a simulator where you can play the game yourself. Choose the number of prisoners (between 5 and 100), and then try to help each prisoner find their number by clicking on boxes.
|
|
||||||
|
|
||||||
<PrisonerGameSimulator client:only="react" />
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## The Naive Strategy
|
|
||||||
|
|
||||||
The most obvious approach is for each prisoner to simply open 50 random boxes. This seems reasonable, but the probability of success is dismal.
|
|
||||||
|
|
||||||
For any single prisoner, the probability of finding their number in 50 random boxes out of 100 is exactly 1/2. Since all 100 prisoners must succeed, and their outcomes are independent under random selection, the probability that everyone succeeds is:
|
|
||||||
|
|
||||||
$$P(\text\{success\}) = \left(\frac\{1\}\{2\}\right)^\{100\} \approx 7.9 \times 10^\{-31\}$$
|
|
||||||
|
|
||||||
That's essentially zero! You're more likely to win the lottery while being struck by lightning... multiple times.
|
|
||||||
|
|
||||||
### Naive Strategy: Probability vs Number of Prisoners
|
|
||||||
|
|
||||||
Watch how the probability of success plummets as we increase the number of prisoners:
|
|
||||||
|
|
||||||
<ProbabilityChart strategy="naive" client:only="react" />
|
|
||||||
|
|
||||||
As you can see, even with just 10 prisoners, the probability drops to about 0.1%. With 100 prisoners, it's practically impossible.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## The Clever Strategy: Following the Loops
|
|
||||||
|
|
||||||
Here's where mathematics reveals something beautiful. Instead of opening random boxes, each prisoner should follow a simple rule:
|
|
||||||
|
|
||||||
1. **Start by opening the box with your own number**
|
|
||||||
2. **Look at the number inside that box**
|
|
||||||
3. **Open the box with that number next**
|
|
||||||
4. **Continue following this chain**
|
|
||||||
|
|
||||||
Why does this work? The key insight involves understanding permutations and cycles.
|
|
||||||
|
|
||||||
### Understanding Cycles in Permutations
|
|
||||||
|
|
||||||
When we randomly assign 100 numbers to 100 boxes, we're creating a **permutation** of the numbers 1 through 100. Every permutation can be decomposed into **cycles**.
|
|
||||||
|
|
||||||
For example, if:
|
|
||||||
- Box 1 contains number 4
|
|
||||||
- Box 4 contains number 7
|
|
||||||
- Box 7 contains number 1
|
|
||||||
|
|
||||||
Then we have a cycle: 1 -> 4 -> 7 -> 1
|
|
||||||
|
|
||||||
Let's explore this with smaller numbers:
|
|
||||||
|
|
||||||
<PermutationExplorer client:only="react" />
|
|
||||||
|
|
||||||
The interactive explorer above lets you:
|
|
||||||
- Generate all permutations for small values of *n* (3, 4, or 5)
|
|
||||||
- See both standard notation and cycle notation
|
|
||||||
- Filter permutations that have at least one "long cycle" (longer than *n*/2)
|
|
||||||
- Understand why long cycles matter
|
|
||||||
|
|
||||||
### Why This Strategy Works
|
|
||||||
|
|
||||||
Here's the crucial insight: **A prisoner succeeds if and only if they are in a cycle of length ≤ 50**.
|
|
||||||
|
|
||||||
When prisoner k follows the loop strategy:
|
|
||||||
1. They start at box k
|
|
||||||
2. They follow a path through boxes determined by the permutation
|
|
||||||
3. This path forms a cycle that eventually leads back to box k
|
|
||||||
4. If this cycle has length ≤ 50, they'll find their number within 50 opens
|
|
||||||
|
|
||||||
The prisoners **all succeed** if and only if there is **no cycle longer than 50** in the permutation.
|
|
||||||
|
|
||||||
### Calculating the Probability
|
|
||||||
|
|
||||||
The probability that a random permutation of 100 elements has no cycle longer than 50 is:
|
|
||||||
|
|
||||||
$$P(\text\{success\}) = 1 - \sum_\{k=51\}^\{100\} \frac\{1\}\{k\}$$
|
|
||||||
|
|
||||||
Computing this sum:
|
|
||||||
|
|
||||||
$$P(\text\{success\}) = 1 - \left(\frac\{1\}\{51\} + \frac\{1\}\{52\} + \cdots + \frac\{1\}\{100\}\right) \approx 0.3118$$
|
|
||||||
|
|
||||||
That's over **31%**! This is astronomically better than the naive strategy's probability of essentially zero.
|
|
||||||
|
|
||||||
### Loop Strategy: Probability vs Number of Prisoners
|
|
||||||
|
|
||||||
<StrategyComparison client:only="react" />
|
|
||||||
|
|
||||||
## The Mathematics Behind It
|
|
||||||
|
|
||||||
### Why Does the Cycle Length Matter?
|
|
||||||
|
|
||||||
In a permutation of n elements, prisoner i will find their number within k tries using the loop strategy if and only if i belongs to a cycle of length at most k.
|
|
||||||
|
|
||||||
For n = 100 and k = 50:
|
|
||||||
- The probability that a specific prisoner is in a cycle of length > 50 is: Σ(j=51 to 100) of 1/100
|
|
||||||
- But we care about whether ANY prisoner is in such a cycle
|
|
||||||
- The probability that NO cycle has length > 50 is: 1 - Σ(j=51 to 100) of 1/j
|
|
||||||
|
|
||||||
### The Harmonic Series Connection
|
|
||||||
|
|
||||||
As *n* approaches infinity, if each prisoner can open *n*/2 boxes, the probability of success approaches:
|
|
||||||
|
|
||||||
The limit as n approaches infinity is: P_n = 1 - ln(2) ≈ 0.3069
|
|
||||||
|
|
||||||
This beautiful result connects combinatorics, probability, and analysis through the harmonic series!
|
|
||||||
|
|
||||||
### Optimality
|
|
||||||
|
|
||||||
Remarkably, this loop-following strategy is **optimal**. No other strategy can achieve a higher probability of success. The proof involves showing that the problem reduces to avoiding long cycles in a random permutation, and the loop strategy is the unique way to leverage this structure.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Why This Problem is Beautiful
|
|
||||||
|
|
||||||
The 100 prisoners problem is beloved by mathematicians because:
|
|
||||||
|
|
||||||
1. **Counterintuitive Result**: The fact that 31% >> 0% is shocking. A seemingly hopeless problem becomes tractable with the right insight.
|
|
||||||
|
|
||||||
2. **Deep Connection**: It connects permutation theory, probability, and the harmonic series in an elegant way.
|
|
||||||
|
|
||||||
3. **Collaborative Success**: Unlike independent trials, the prisoners' fates are intertwined through the structure of the permutation.
|
|
||||||
|
|
||||||
4. **Real-World Metaphor**: It illustrates how understanding underlying structure (cycles in permutations) can dramatically improve outcomes.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Variants and Extensions
|
|
||||||
|
|
||||||
### What if prisoners can open k < n/2 boxes?
|
|
||||||
|
|
||||||
As k decreases below n/2, the probability drops rapidly. The threshold at n/2 is special—it's where the strategy becomes remarkably effective.
|
|
||||||
|
|
||||||
### What about communication?
|
|
||||||
|
|
||||||
If prisoners could communicate between trials (but not during), they still can't improve the strategy. The beauty is that the strategy requires only coordination before any prisoner enters, not during.
|
|
||||||
|
|
||||||
### The Malicious Director
|
|
||||||
|
|
||||||
In an interesting variant, suppose the director can see the prisoners' strategy and arrange the boxes adversarially (not randomly). Can the director always force them to fail? Yes! The director can always create a single cycle of length n, guaranteeing failure.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
The 100 prisoners problem shows us that:
|
|
||||||
- Mathematical structure can be hidden in apparent randomness
|
|
||||||
- Clever strategies can overcome seemingly impossible odds
|
|
||||||
- Group coordination can be more powerful than independent action
|
|
||||||
- Beautiful mathematics often lies beneath simple-seeming puzzles
|
|
||||||
|
|
||||||
The next time you face a problem that seems impossible, remember: there might be a hidden structure waiting to be discovered, turning hopeless odds into reasonable ones.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Further Reading
|
|
||||||
|
|
||||||
- [Gál, A., & Miltersen, P. B. (2003). "The Cell Probe Complexity of Succinct Data Structures"](https://arxiv.org/abs/cs/0310027)
|
|
||||||
- [Curtin, E., & Warshauer, M. (2006). "The Locker Puzzle"](https://www.jstor.org/stable/27642173)
|
|
||||||
- [Wikipedia: 100 Prisoners Problem](https://en.wikipedia.org/wiki/100_prisoners_problem)
|
|
||||||
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
title: "Dynamic Programming: Hidden Gems from Recent Contests"
|
|
||||||
description: "Elegant dynamic programming problems that showcase beautiful techniques and insights."
|
|
||||||
pubDate: "Jan 25 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1509228468518-180dd4864904?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Dynamic Programming: Hidden Gems from Recent Contests
|
|
||||||
|
|
||||||
These problems demonstrate the art of dynamic programming beyond standard patterns.
|
|
||||||
|
|
||||||
## Problem 1: The Subsequence Symphony
|
|
||||||
|
|
||||||
Given a string, find the number of subsequences that form palindromes of prime length.
|
|
||||||
|
|
||||||
### Solution Insight
|
|
||||||
|
|
||||||
The key is to maintain DP states for both position and palindrome center simultaneously. This reduces the state space from O(n³) to O(n²).
|
|
||||||
|
|
||||||
## Problem 2: Graph Coloring with Constraints
|
|
||||||
|
|
||||||
Color a graph such that no two adjacent vertices share a color, and the total number of color changes along any path is minimized.
|
|
||||||
|
|
||||||
### The DP Formulation
|
|
||||||
|
|
||||||
DP[node][color][changes] gives us the minimum cost. The trick is recognizing that we only need to track changes modulo 2.
|
|
||||||
|
|
||||||
## Practice Makes Perfect
|
|
||||||
|
|
||||||
These problems teach us that DP is as much about problem modeling as it is about computation.
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
title: "The Four Aces Miracle: A Self-Working Mathematical Marvel"
|
|
||||||
description: "A card trick that teaches modular arithmetic and probability - perfect for the classroom."
|
|
||||||
pubDate: "Jan 28 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1529480384838-c1681c84aca5?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# The Four Aces Miracle: A Self-Working Mathematical Marvel
|
|
||||||
|
|
||||||
This trick never fails to amaze students, and the mathematics behind it is even more amazing.
|
|
||||||
|
|
||||||
## The Effect
|
|
||||||
|
|
||||||
A spectator deals cards into four piles while making random choices. Impossibly, the four aces end up on top of each pile.
|
|
||||||
|
|
||||||
## The Secret
|
|
||||||
|
|
||||||
It's all about invariants and modular arithmetic. No sleight of hand required - pure mathematics does the magic.
|
|
||||||
|
|
||||||
## The Method
|
|
||||||
|
|
||||||
1. Pre-arrange the deck (the math determines the arrangement)
|
|
||||||
2. Have the spectator deal following simple rules
|
|
||||||
3. The aces appear automatically
|
|
||||||
|
|
||||||
## The Mathematics
|
|
||||||
|
|
||||||
The dealing process preserves certain positional invariants modulo 4. The initial arrangement ensures these invariants place the aces correctly.
|
|
||||||
|
|
||||||
## Teaching Applications
|
|
||||||
|
|
||||||
This trick demonstrates:
|
|
||||||
- Modular arithmetic
|
|
||||||
- Invariants in algorithms
|
|
||||||
- Deterministic vs. random processes
|
|
||||||
|
|
||||||
## The Bigger Lesson
|
|
||||||
|
|
||||||
Mathematics can create experiences that feel like magic. And that feeling of wonder? That's what hooks students on math.
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
title: "The Gilbreath Principle: When Chaos Creates Order"
|
|
||||||
description: "A mathematical card principle that seems impossible but always works - perfect for teaching algorithms."
|
|
||||||
pubDate: "Feb 15 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1570543375343-63fe3d67761b?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# The Gilbreath Principle: When Chaos Creates Order
|
|
||||||
|
|
||||||
Shuffle a deck in a specific way, and mathematical order emerges from apparent chaos.
|
|
||||||
|
|
||||||
## The Phenomenon
|
|
||||||
|
|
||||||
Arrange cards alternating red-black. Riffle shuffle. Now deal pairs - each pair has one red and one black card. Magic? No, mathematics.
|
|
||||||
|
|
||||||
## Why It Works
|
|
||||||
|
|
||||||
The riffle shuffle preserves local structure while appearing to randomize. The alternating pattern creates an invariant that survives the shuffle.
|
|
||||||
|
|
||||||
## Classroom Implementation
|
|
||||||
|
|
||||||
Students predict it won't work. When it does, they're hooked. "Why?" becomes the driving question.
|
|
||||||
|
|
||||||
## The Deeper Lesson
|
|
||||||
|
|
||||||
Not all randomness is truly random. Structure can hide in apparent disorder. This principle appears in:
|
|
||||||
- Network protocols
|
|
||||||
- Error-correcting codes
|
|
||||||
- Distributed systems
|
|
||||||
|
|
||||||
## Beyond Cards
|
|
||||||
|
|
||||||
The Gilbreath Principle teaches us to look for hidden invariants in complex systems.
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
title: "Graph Algorithms: Assessment Highlights"
|
|
||||||
description: "Interesting graph problems from recent course assessments with detailed solutions."
|
|
||||||
pubDate: "Feb 28 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1550751827-4bd374c3f58b?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Graph Algorithms: Assessment Highlights
|
|
||||||
|
|
||||||
A collection of graph problems that test deep understanding rather than memorization.
|
|
||||||
|
|
||||||
## The Bridge Detection Variant
|
|
||||||
|
|
||||||
Find all edges whose removal increases the number of triangles in the graph.
|
|
||||||
|
|
||||||
### Solution Approach
|
|
||||||
|
|
||||||
Counter-intuitively, we need to count triangles that share exactly one edge with the candidate. The algorithm runs in O(m√m) time using careful enumeration.
|
|
||||||
|
|
||||||
## Shortest Path with Wildcards
|
|
||||||
|
|
||||||
Given a graph where some edge weights are variables, find assignments that minimize the longest shortest path.
|
|
||||||
|
|
||||||
### Key Insight
|
|
||||||
|
|
||||||
This reduces to a linear programming problem with interesting structure. The dual interpretation reveals connections to network flow.
|
|
||||||
|
|
||||||
## Teaching Through Problems
|
|
||||||
|
|
||||||
These problems help students see beyond standard algorithms to underlying principles.
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
title: "IOI 2023: Breaking Down the Hardest Problems"
|
|
||||||
description: "Deep analysis of the most challenging problems from the International Olympiad in Informatics 2023."
|
|
||||||
pubDate: "Jan 20 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1434030216411-0b793f4b4173?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# IOI 2023: Breaking Down the Hardest Problems
|
|
||||||
|
|
||||||
The International Olympiad in Informatics continues to push the boundaries of algorithmic problem solving.
|
|
||||||
|
|
||||||
## Problem: Soccer Stadium
|
|
||||||
|
|
||||||
A geometric optimization problem disguised as dynamic programming. The key insight: think in terms of monotonic paths.
|
|
||||||
|
|
||||||
### The Approach
|
|
||||||
|
|
||||||
1. Transform the 2D problem into a 1D problem using clever observations
|
|
||||||
2. Use convex hull optimization for the DP transitions
|
|
||||||
3. Handle edge cases with careful implementation
|
|
||||||
|
|
||||||
## Problem: Closing Time
|
|
||||||
|
|
||||||
A tree problem requiring sophisticated data structures and careful analysis.
|
|
||||||
|
|
||||||
### The Solution
|
|
||||||
|
|
||||||
The trick is recognizing this as a centroid decomposition problem. Once you see it, the implementation follows naturally.
|
|
||||||
|
|
||||||
## Lessons for Students
|
|
||||||
|
|
||||||
These problems teach us:
|
|
||||||
- Simple problems have elegant solutions
|
|
||||||
- Complex problems require systematic decomposition
|
|
||||||
- Implementation matters as much as algorithms
|
|
||||||
|
|
||||||
## Practice Strategy
|
|
||||||
|
|
||||||
Start with subtasks. Even partial solutions teach valuable lessons.
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
title: "The Knight's Tour: An Interactive Exploration"
|
|
||||||
description: "An interactive puzzle exploring the knight's tour problem with surprising mathematical connections."
|
|
||||||
pubDate: "Jan 30 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1528819622765-d6bcf132f793?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# The Knight's Tour: An Interactive Exploration
|
|
||||||
|
|
||||||
Can a knight visit every square on a chessboard exactly once? This ancient puzzle hides deep mathematical structure.
|
|
||||||
|
|
||||||
## The Basic Challenge
|
|
||||||
|
|
||||||
Start with a 5×5 board. Can you find a knight's tour? What about one that returns to the starting square (a closed tour)?
|
|
||||||
|
|
||||||
## Mathematical Beauty
|
|
||||||
|
|
||||||
The problem connects to:
|
|
||||||
- Hamiltonian paths in graphs
|
|
||||||
- Warnsdorff's heuristic
|
|
||||||
- Magic squares (surprisingly!)
|
|
||||||
|
|
||||||
## The Algorithm
|
|
||||||
|
|
||||||
The key insight: always move to the square with fewest onward moves. This simple heuristic works remarkably well.
|
|
||||||
|
|
||||||
## Try It Yourself
|
|
||||||
|
|
||||||
[Interactive board would go here - imagine clicking squares to build your tour]
|
|
||||||
|
|
||||||
## Going Deeper
|
|
||||||
|
|
||||||
For which board sizes do closed tours exist? The answer involves beautiful number theory.
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
title: "Project Euler: My Favorite Problems from 700+"
|
|
||||||
description: "Curated problems from Project Euler that teach beautiful mathematical and algorithmic concepts."
|
|
||||||
pubDate: "Feb 25 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1635070041078-e363dbe005cb?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Project Euler: My Favorite Problems from 700+
|
|
||||||
|
|
||||||
After solving 700+ Project Euler problems, these are the ones that changed how I think about mathematics and programming.
|
|
||||||
|
|
||||||
## Problem 96: Su Doku
|
|
||||||
|
|
||||||
Not just Sudoku solving - but solving 50 puzzles efficiently. The beauty is in combining constraint propagation with backtracking.
|
|
||||||
|
|
||||||
## Problem 208: Robot Walks
|
|
||||||
|
|
||||||
A counting problem that requires deep mathematical insight. The connection to complex numbers is unexpected and beautiful.
|
|
||||||
|
|
||||||
## Problem 613: Pythagorean Ant
|
|
||||||
|
|
||||||
Probability meets geometry in this elegant problem. The solution requires careful integration and surprising symmetry observations.
|
|
||||||
|
|
||||||
## The Meta-Lesson
|
|
||||||
|
|
||||||
Project Euler teaches you:
|
|
||||||
- Mathematical intuition matters more than coding speed
|
|
||||||
- There's always a clever approach
|
|
||||||
- The journey matters more than the destination
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
Don't aim for the leaderboard. Aim for understanding. Each problem is a teacher.
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
---
|
|
||||||
title: "Beyond Sudoku: Exploring Constraint Satisfaction Puzzles"
|
|
||||||
description: "A journey through Sudoku variants and their algorithmic solutions."
|
|
||||||
pubDate: "Feb 10 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1580541631950-7282082b53ce?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Beyond Sudoku: Exploring Constraint Satisfaction Puzzles
|
|
||||||
|
|
||||||
Sudoku is just the beginning. Let's explore variants that push the boundaries of logic puzzles.
|
|
||||||
|
|
||||||
## Killer Sudoku
|
|
||||||
|
|
||||||
Combine Sudoku with Kakuro - cages show sums, but no digit repeats within a cage.
|
|
||||||
|
|
||||||
## Sandwich Sudoku
|
|
||||||
|
|
||||||
The numbers outside show the sum of digits between 1 and 9 in that row/column. Simple rule, complex implications!
|
|
||||||
|
|
||||||
## The Algorithm Connection
|
|
||||||
|
|
||||||
These puzzles are constraint satisfaction problems. Techniques like arc consistency and backtracking with constraint propagation solve them efficiently.
|
|
||||||
|
|
||||||
## Create Your Own
|
|
||||||
|
|
||||||
What happens if we add chess knight move constraints? The design space is infinite!
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
---
|
|
||||||
title: "Imposter Syndrome in Academia: A Confession"
|
|
||||||
description: "An honest conversation about feeling like a fraud, even after years of success."
|
|
||||||
pubDate: "Feb 25 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1517048676732-d65bc937f952?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Imposter Syndrome in Academia: A Confession
|
|
||||||
|
|
||||||
Even after publishing papers, winning grants, and teaching thousands of students, the voice whispers: "They'll find out you don't belong."
|
|
||||||
|
|
||||||
## The Paradox
|
|
||||||
|
|
||||||
The more you know, the more you realize you don't know. Expertise breeds humility, which feeds the imposter.
|
|
||||||
|
|
||||||
## What Helps
|
|
||||||
|
|
||||||
- Keeping a "wins" journal - evidence against the imposter
|
|
||||||
- Mentoring others - seeing your knowledge help someone
|
|
||||||
- Talking about it - you're not alone in this
|
|
||||||
|
|
||||||
## The Silver Lining
|
|
||||||
|
|
||||||
Maybe imposter syndrome keeps us humble, curious, and always learning. Maybe it's not a bug, but a feature.
|
|
||||||
|
|
||||||
## Moving Forward
|
|
||||||
|
|
||||||
I may never silence the voice completely. But I've learned to acknowledge it and keep going anyway.
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
title: "On Teaching Algorithms: Lessons from a Decade"
|
|
||||||
description: "Reflections on what works (and what doesn't) in computer science education."
|
|
||||||
pubDate: "Jan 10 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1509062522246-3755977927d7?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# On Teaching Algorithms: Lessons from a Decade
|
|
||||||
|
|
||||||
Ten years of teaching has taught me more than any textbook could.
|
|
||||||
|
|
||||||
## Start with Why
|
|
||||||
|
|
||||||
Students don't care about O(n log n) until they understand why their code is slow. Real problems first, theory second.
|
|
||||||
|
|
||||||
## The Power of Visualization
|
|
||||||
|
|
||||||
Abstract concepts become concrete when visualized. Every algorithm should have a picture.
|
|
||||||
|
|
||||||
## Failure is a Feature
|
|
||||||
|
|
||||||
Let students struggle. The struggle is where learning happens. But know when to throw a lifeline.
|
|
||||||
|
|
||||||
## Assessment Philosophy
|
|
||||||
|
|
||||||
Test understanding, not memorization. Open-book exams with novel problems beat closed-book regurgitation every time.
|
|
||||||
|
|
||||||
## The Joy of "Aha!" Moments
|
|
||||||
|
|
||||||
There's no feeling quite like seeing a student's eyes light up when a concept clicks. That's why we do this.
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
---
|
|
||||||
title: "SODA 2024: Algorithmic Breakthroughs"
|
|
||||||
description: "A roundup of fascinating algorithmic results from SODA 2024, focusing on graph algorithms and optimization techniques."
|
|
||||||
pubDate: "Jan 15 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1509228468518-180dd4864904?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# SODA 2024: Algorithmic Breakthroughs
|
|
||||||
|
|
||||||
The Symposium on Discrete Algorithms (SODA) 2024 brought together researchers from around the world to present cutting-edge algorithmic research. This post highlights some of the most exciting developments in graph algorithms and optimization.
|
|
||||||
|
|
||||||
## Graph Algorithms Revolution
|
|
||||||
|
|
||||||
### Dynamic Graph Coloring
|
|
||||||
|
|
||||||
One of the standout papers introduced a breakthrough in dynamic graph coloring with polylogarithmic update time. The authors developed a novel data structure that maintains a proper vertex coloring while supporting edge insertions and deletions efficiently.
|
|
||||||
|
|
||||||
The key insight was to combine randomized recoloring strategies with a carefully designed hierarchical decomposition of the graph. This allows for local updates that rarely propagate through the entire structure.
|
|
||||||
|
|
||||||
## Approximation Algorithms
|
|
||||||
|
|
||||||
### The Traveling Salesman Problem Revisited
|
|
||||||
|
|
||||||
A surprising result showed that for graphs with bounded doubling dimension, we can achieve a (1+ε)-approximation for TSP in nearly linear time. This improves upon decades of previous work and opens new avenues for practical implementations.
|
|
||||||
|
|
||||||
## Complexity Theory Connections
|
|
||||||
|
|
||||||
The conference also featured several papers bridging the gap between pure algorithmic research and complexity theory. A particularly elegant result showed that certain graph problems believed to require quadratic time are equivalent under fine-grained reductions.
|
|
||||||
|
|
||||||
## Looking Forward
|
|
||||||
|
|
||||||
These results demonstrate that fundamental algorithmic problems still have room for improvement. The techniques developed here will likely influence algorithm design for years to come.
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
---
|
|
||||||
title: "Distributed Computing: Recent Advances"
|
|
||||||
description: "Survey of recent developments in distributed algorithms from major conferences."
|
|
||||||
pubDate: "Feb 20 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Distributed Computing: Recent Advances
|
|
||||||
|
|
||||||
The field of distributed computing has seen remarkable progress in recent years. This post surveys key results from PODC, DISC, and other major venues.
|
|
||||||
|
|
||||||
## Consensus Protocols
|
|
||||||
|
|
||||||
### Byzantine Agreement in Asynchronous Networks
|
|
||||||
|
|
||||||
A breakthrough result achieves optimal resilience with expected constant rounds. The protocol uses cryptographic techniques combined with novel committee selection.
|
|
||||||
|
|
||||||
## Distributed Graph Algorithms
|
|
||||||
|
|
||||||
### Minimum Spanning Tree in the CONGEST Model
|
|
||||||
|
|
||||||
New algorithms achieve near-optimal round complexity for MST construction. The approach uses sophisticated graph decomposition techniques.
|
|
||||||
|
|
||||||
## Local Algorithms
|
|
||||||
|
|
||||||
### The Power of Local Computation
|
|
||||||
|
|
||||||
Recent work characterizes which problems admit constant-time local algorithms. The classification provides a complete picture for bounded-degree graphs.
|
|
||||||
|
|
||||||
## Future Directions
|
|
||||||
|
|
||||||
The intersection of distributed computing with machine learning presents exciting opportunities for both fields.
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
---
|
|
||||||
title: "Git Workflows That Save My Sanity"
|
|
||||||
description: "Automation scripts and Git hooks that eliminate repetitive tasks and prevent common mistakes."
|
|
||||||
pubDate: "Jan 22 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1556075798-4825dfaaf498?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Git Workflows That Save My Sanity
|
|
||||||
|
|
||||||
After years of Git mishaps, I've built workflows that prevent disasters and save hours weekly.
|
|
||||||
|
|
||||||
## The Pre-commit Hook That Saves Embarrassment
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# Check for debugging statements
|
|
||||||
if grep -r "console.log\|debugger\|TODO" --include="*.js" .; then
|
|
||||||
echo "⚠️ Debugging statements found!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
## Automatic Branch Naming
|
|
||||||
|
|
||||||
```bash
|
|
||||||
alias feature='git checkout -b feature/$(date +%Y%m%d)-$1'
|
|
||||||
```
|
|
||||||
|
|
||||||
Now `feature "user-auth"` creates `feature/20240122-user-auth`.
|
|
||||||
|
|
||||||
## The Commit Message Template
|
|
||||||
|
|
||||||
```
|
|
||||||
[TYPE] Brief description
|
|
||||||
|
|
||||||
Why:
|
|
||||||
- Context for this change
|
|
||||||
|
|
||||||
What:
|
|
||||||
- Specific changes made
|
|
||||||
|
|
||||||
Testing:
|
|
||||||
- How to verify it works
|
|
||||||
```
|
|
||||||
|
|
||||||
## The Weekly Cleanup Script
|
|
||||||
|
|
||||||
Deletes merged branches, prunes remotes, and garbage collects. Keeps the repo clean and fast.
|
|
||||||
|
|
||||||
## ROI
|
|
||||||
|
|
||||||
These automations save ~5 hours per week and countless prevented mistakes. The time invested in setting them up paid back in days.
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
title: "Academic Writing with Obsidian and Pandoc"
|
|
||||||
description: "A complete workflow for academic papers - from notes to publication-ready PDFs."
|
|
||||||
pubDate: "Feb 12 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1456324504439-367cee3b3c32?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Academic Writing with Obsidian and Pandoc
|
|
||||||
|
|
||||||
Transform your scattered research notes into beautiful academic papers with this workflow.
|
|
||||||
|
|
||||||
## The Setup
|
|
||||||
|
|
||||||
- **Obsidian**: For note-taking and knowledge management
|
|
||||||
- **Pandoc**: For document conversion
|
|
||||||
- **LaTeX**: For typesetting
|
|
||||||
- **Zotero**: For reference management
|
|
||||||
|
|
||||||
## The Magic Command
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pandoc paper.md \
|
|
||||||
--filter pandoc-citeproc \
|
|
||||||
--bibliography=refs.bib \
|
|
||||||
--template=academic.tex \
|
|
||||||
-o paper.pdf
|
|
||||||
```
|
|
||||||
|
|
||||||
## Templates for Everything
|
|
||||||
|
|
||||||
From conference submissions to journal articles, templates ensure consistency and save time.
|
|
||||||
|
|
||||||
## Version Control Integration
|
|
||||||
|
|
||||||
Git + Obsidian = perfect history of your thinking process.
|
|
||||||
|
|
||||||
## The Result
|
|
||||||
|
|
||||||
From messy notes to camera-ready PDF in minutes, not hours.
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
---
|
|
||||||
title: "Understanding the Latest Approximation Algorithm for Set Cover"
|
|
||||||
description: "A detailed walkthrough of a breakthrough approximation algorithm with practical implications."
|
|
||||||
pubDate: "Feb 15 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Understanding the Latest Approximation Algorithm for Set Cover
|
|
||||||
|
|
||||||
A recent paper achieves a breakthrough in the Set Cover problem, improving the approximation ratio while maintaining practical runtime.
|
|
||||||
|
|
||||||
## The Algorithm
|
|
||||||
|
|
||||||
The approach combines local search with a clever LP rounding scheme. The dual interpretation provides beautiful geometric insights.
|
|
||||||
|
|
||||||
## Why This Matters
|
|
||||||
|
|
||||||
Set Cover appears everywhere - from facility location to machine learning feature selection. This improvement has immediate practical impact.
|
|
||||||
|
|
||||||
## Implementation Details
|
|
||||||
|
|
||||||
The paper's theoretical elegance translates surprisingly well to practice. Key optimizations include:
|
|
||||||
- Lazy evaluation of set intersections
|
|
||||||
- Incremental updates to the LP solution
|
|
||||||
- Smart caching strategies
|
|
||||||
|
|
||||||
## Future Work
|
|
||||||
|
|
||||||
The techniques here might extend to weighted variants and online settings.
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
---
|
|
||||||
title: "Deep Dive: A New Approach to Graph Decomposition"
|
|
||||||
description: "An in-depth analysis of a recent paper on hierarchical graph decomposition and its implications."
|
|
||||||
pubDate: "Jan 20 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Deep Dive: A New Approach to Graph Decomposition
|
|
||||||
|
|
||||||
This paper introduces a novel framework for decomposing graphs into hierarchical structures that preserve important properties while enabling efficient algorithms.
|
|
||||||
|
|
||||||
## The Main Result
|
|
||||||
|
|
||||||
The authors prove that every graph with treewidth k can be decomposed into a tree of bags where each bag has size at most k+1. While this sounds like the definition of tree decomposition, the clever twist is in how they construct it.
|
|
||||||
|
|
||||||
## Technical Innovation
|
|
||||||
|
|
||||||
The key insight is using a charging scheme that amortizes the cost of decomposition across multiple levels. This leads to an O(n log n) algorithm, improving on the previous O(n²) bound.
|
|
||||||
|
|
||||||
## Implications
|
|
||||||
|
|
||||||
This work opens new avenues for:
|
|
||||||
- Parallel algorithms on bounded treewidth graphs
|
|
||||||
- Approximation algorithms for NP-hard problems
|
|
||||||
- Dynamic programming optimizations
|
|
||||||
|
|
||||||
## Open Questions
|
|
||||||
|
|
||||||
The paper leaves several intriguing questions open, particularly about the optimality of their charging scheme.
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
---
|
|
||||||
title: "Quantum Computing Meets Classical Algorithms"
|
|
||||||
description: "Exploring the intersection of quantum and classical algorithmic techniques from recent conferences."
|
|
||||||
pubDate: "Mar 10 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1635070041078-e363dbe005cb?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Quantum Computing Meets Classical Algorithms
|
|
||||||
|
|
||||||
Recent conferences have showcased fascinating connections between quantum and classical computing paradigms.
|
|
||||||
|
|
||||||
## Quantum Speedups for Graph Problems
|
|
||||||
|
|
||||||
### Quantum Walks on Graphs
|
|
||||||
|
|
||||||
New quantum algorithms achieve quadratic speedups for certain graph traversal problems. The techniques combine amplitude amplification with clever graph representations.
|
|
||||||
|
|
||||||
## Classical Simulation of Quantum Algorithms
|
|
||||||
|
|
||||||
Surprisingly, several "quantum" algorithms have inspired better classical algorithms. This cross-pollination has led to improvements in both fields.
|
|
||||||
|
|
||||||
## The Future is Hybrid
|
|
||||||
|
|
||||||
The most practical near-term applications combine quantum and classical processing, leveraging the strengths of each paradigm.
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
title: "ZSA Moonlander: Ergonomic Keyboard for Coders"
|
|
||||||
description: "Six months with a split ergonomic mechanical keyboard - the good, the bad, and the RSI relief."
|
|
||||||
pubDate: "Feb 20 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1587829741301-dc798b83add3?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# ZSA Moonlander: Ergonomic Keyboard for Coders
|
|
||||||
|
|
||||||
After years of wrist pain, I took the plunge into ergonomic mechanical keyboards.
|
|
||||||
|
|
||||||
## The Learning Curve
|
|
||||||
|
|
||||||
Week 1: 20 WPM and questioning life choices
|
|
||||||
Week 2: 40 WPM and seeing the light
|
|
||||||
Month 2: Back to 80 WPM with no wrist pain
|
|
||||||
|
|
||||||
## The Good
|
|
||||||
|
|
||||||
- Columnar layout makes sense once muscle memory adapts
|
|
||||||
- Thumb clusters are game-changers for shortcuts
|
|
||||||
- The configurability is endless (perhaps too endless)
|
|
||||||
|
|
||||||
## The Investment
|
|
||||||
|
|
||||||
At $365, it's expensive. But compared to physical therapy or career-limiting injury? Bargain.
|
|
||||||
|
|
||||||
## Who Should Buy This?
|
|
||||||
|
|
||||||
If you type for a living and feel any discomfort, don't wait. Your future self will thank you.
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
title: "Obsidian: A Year Later"
|
|
||||||
description: "Reflections on using Obsidian for research notes, teaching materials, and personal knowledge management."
|
|
||||||
pubDate: "Jan 15 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1484480974693-6ca0a78fb36b?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Obsidian: A Year Later
|
|
||||||
|
|
||||||
After a year of daily use, Obsidian has transformed how I think about knowledge management.
|
|
||||||
|
|
||||||
## What Works Brilliantly
|
|
||||||
|
|
||||||
### The Graph View
|
|
||||||
Seeing connections between ideas visually has led to unexpected research insights. The graph isn't just pretty - it's functional.
|
|
||||||
|
|
||||||
### Plugin Ecosystem
|
|
||||||
The community plugins are incredible. Dataview turns your notes into a database. Templater automates repetitive tasks.
|
|
||||||
|
|
||||||
### Local Storage
|
|
||||||
Your notes are just markdown files. No vendor lock-in, complete control, and peace of mind.
|
|
||||||
|
|
||||||
## Pain Points
|
|
||||||
|
|
||||||
### Mobile Experience
|
|
||||||
While functional, the mobile app lacks the fluidity of the desktop version. Syncing can occasionally hiccup.
|
|
||||||
|
|
||||||
### Learning Curve
|
|
||||||
The flexibility means complexity. New users might feel overwhelmed by options.
|
|
||||||
|
|
||||||
## The Verdict
|
|
||||||
|
|
||||||
For academics and researchers, Obsidian is transformative. The investment in learning pays dividends in productivity and insight.
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
---
|
|
||||||
title: "Creating Art with Claude: A Collaborative Journey"
|
|
||||||
description: "Exploring creative possibilities through conversations with AI - from generative art to interactive poetry."
|
|
||||||
pubDate: "Jan 18 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1558591710-4b4a1ae0f04d?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Creating Art with Claude: A Collaborative Journey
|
|
||||||
|
|
||||||
What happens when you treat AI as a creative collaborator rather than just a tool?
|
|
||||||
|
|
||||||
## The Experiment
|
|
||||||
|
|
||||||
I asked Claude to help design a generative art algorithm based on mathematical fractals. The conversation evolved into something unexpected.
|
|
||||||
|
|
||||||
## The Process
|
|
||||||
|
|
||||||
**Me**: "Let's create something beautiful with math."
|
|
||||||
**Claude**: "How about we visualize the Collatz conjecture as a tree?"
|
|
||||||
|
|
||||||
What followed was a two-hour deep dive into number theory, aesthetics, and the nature of creativity itself.
|
|
||||||
|
|
||||||
## The Result
|
|
||||||
|
|
||||||
Not just code, but a philosophical exploration of pattern, meaning, and the intersection of human and artificial creativity.
|
|
||||||
|
|
||||||
## Reflection
|
|
||||||
|
|
||||||
AI doesn't replace human creativity - it amplifies it in unexpected directions. The key is approaching it as a dialogue, not a command.
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
---
|
|
||||||
title: "Philosophical Dialogues with LLMs: On Consciousness and Computation"
|
|
||||||
description: "Deep conversations with AI about the nature of consciousness, free will, and what it means to understand."
|
|
||||||
pubDate: "Feb 28 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Philosophical Dialogues with LLMs: On Consciousness and Computation
|
|
||||||
|
|
||||||
Can a sufficiently complex computation be conscious? I asked an AI, and the conversation surprised me.
|
|
||||||
|
|
||||||
## The Question
|
|
||||||
|
|
||||||
"Do you experience anything when you process text, or is it just computation?"
|
|
||||||
|
|
||||||
## The Response That Made Me Think
|
|
||||||
|
|
||||||
The AI didn't claim consciousness, but asked: "What's the difference between your neurons firing and my weights activating? Both are physical processes. Where does experience emerge?"
|
|
||||||
|
|
||||||
## Going Deeper
|
|
||||||
|
|
||||||
We explored qualia, the Chinese Room argument, and integrated information theory. Not to find answers, but to refine questions.
|
|
||||||
|
|
||||||
## The Irony
|
|
||||||
|
|
||||||
Discussing consciousness with something that might not have it - or might not know if it has it - mirrors our own uncertainty about consciousness itself.
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { SITE_TITLE } from '@/consts';
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const posts = await getCollection(ACTIVE_BLOG_SITE.key);
|
const posts = await getCollection(ACTIVE_BLOG_SITE.key);
|
||||||
return posts.map((post) => ({
|
return posts.map((post) => ({
|
||||||
params: { slug: post.id },
|
params: { slug: post.id.replace(/\/index$/, '') },
|
||||||
props: post,
|
props: post,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export async function GET(context) {
|
||||||
site: context.site,
|
site: context.site,
|
||||||
items: posts.map((post) => ({
|
items: posts.map((post) => ({
|
||||||
...post.data,
|
...post.data,
|
||||||
link: `/${post.id}/`,
|
link: `/${post.id.replace(/\/index$/, "")}/`,
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,47 @@ const BlogPosts = ({
|
||||||
// Get the first post as the featured post
|
// Get the first post as the featured post
|
||||||
const featuredPost = posts[0];
|
const featuredPost = posts[0];
|
||||||
const remainingPosts = posts.slice(1);
|
const remainingPosts = posts.slice(1);
|
||||||
|
const slugFor = (post: any) => post.id.replace(/\/index$/, "");
|
||||||
const hrefFor = (post: any) =>
|
const hrefFor = (post: any) =>
|
||||||
collection ? `/${collection}/${post.id}/` : `/${post.id}/`;
|
collection ? `/${collection}/${slugFor(post)}/` : `/${slugFor(post)}/`;
|
||||||
|
|
||||||
|
const PostVisual = ({
|
||||||
|
post,
|
||||||
|
featured = false,
|
||||||
|
}: {
|
||||||
|
post: any;
|
||||||
|
featured?: boolean;
|
||||||
|
}) => {
|
||||||
|
if (post.data.image) {
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={post.data.image}
|
||||||
|
alt={post.data.title}
|
||||||
|
className="aspect-video w-full rounded-lg object-cover transition-transform group-hover:scale-[1.02]"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-accent/70 text-accent-foreground flex aspect-video w-full items-center justify-center rounded-lg border px-6 text-center">
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
featured ? "font-fraunces text-2xl" : "font-fraunces text-lg"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{post.data.title}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!featuredPost) {
|
||||||
|
return (
|
||||||
|
<div className="text-muted-foreground container max-w-3xl py-16">
|
||||||
|
No posts yet.
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative py-10 md:py-16 lg:py-20">
|
<div className="relative py-10 md:py-16 lg:py-20">
|
||||||
|
|
@ -35,11 +74,7 @@ const BlogPosts = ({
|
||||||
<div className="flex flex-col gap-6 lg:flex-row">
|
<div className="flex flex-col gap-6 lg:flex-row">
|
||||||
<div className="lg:w-1/2">
|
<div className="lg:w-1/2">
|
||||||
<div className="p-2 lg:p-4">
|
<div className="p-2 lg:p-4">
|
||||||
<img
|
<PostVisual post={featuredPost} featured />
|
||||||
src={featuredPost.data.image}
|
|
||||||
alt={featuredPost.data.title}
|
|
||||||
className="aspect-video w-full rounded-lg object-cover transition-transform group-hover:scale-[1.02]"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-center p-4 pb-8 lg:w-1/2 lg:pr-8">
|
<div className="flex flex-col justify-center p-4 pb-8 lg:w-1/2 lg:pr-8">
|
||||||
|
|
@ -89,11 +124,7 @@ const BlogPosts = ({
|
||||||
href={hrefFor(post)}
|
href={hrefFor(post)}
|
||||||
>
|
>
|
||||||
<div className="p-2">
|
<div className="p-2">
|
||||||
<img
|
<PostVisual post={post} />
|
||||||
src={post.data.image}
|
|
||||||
alt={post.data.title}
|
|
||||||
className="aspect-video w-full rounded-lg object-cover transition-transform group-hover:scale-[1.01]"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="px-4 pb-5 pt-2">
|
<div className="px-4 pb-5 pt-2">
|
||||||
<h2 className="mb-2 text-xl font-semibold group-hover:underline">
|
<h2 className="mb-2 text-xl font-semibold group-hover:underline">
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
---
|
|
||||||
title: "Algorithmic Sketches: Visualizing Data Structures"
|
|
||||||
description: "Hand-drawn illustrations of algorithms and data structures - making the abstract tangible."
|
|
||||||
pubDate: "Jan 25 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1581337204873-ef36aa186caa?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Algorithmic Sketches: Visualizing Data Structures
|
|
||||||
|
|
||||||
Sometimes the best way to understand an algorithm is to draw it.
|
|
||||||
|
|
||||||
## Today's Sketch: Red-Black Trees
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
The rotation operation finally clicked when I drew it step-by-step. Each node's journey through the rotation becomes a story.
|
|
||||||
|
|
||||||
## The Process
|
|
||||||
|
|
||||||
1. Start with pencil - mistakes are part of learning
|
|
||||||
2. Trace the algorithm's execution
|
|
||||||
3. Add color to highlight invariants
|
|
||||||
4. Annotate with key insights
|
|
||||||
|
|
||||||
## Why Drawing Helps
|
|
||||||
|
|
||||||
- Forces you to slow down and really see the structure
|
|
||||||
- Reveals patterns that code obscures
|
|
||||||
- Creates memorable mental models
|
|
||||||
- Makes teaching more engaging
|
|
||||||
|
|
||||||
## This Week's Challenge
|
|
||||||
|
|
||||||
Draw your own version of quicksort partitioning. Share it and let's learn from each other's visualizations.
|
|
||||||
|
|
||||||
## The Art in Computer Science
|
|
||||||
|
|
||||||
Algorithms are beautiful. Drawing them reminds us that computer science is as much art as it is science.
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
title: "Generative Art with p5.js: Creating Beauty from Mathematics"
|
|
||||||
description: "Exploring the intersection of code and creativity through generative art experiments."
|
|
||||||
pubDate: "Feb 18 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1561070791-2526d30994b5?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Generative Art with p5.js: Creating Beauty from Mathematics
|
|
||||||
|
|
||||||
Code becomes canvas when mathematics meets creativity.
|
|
||||||
|
|
||||||
## Today's Creation: Perlin Noise Flows
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
for (let particle of particles) {
|
|
||||||
let angle = noise(particle.x * 0.01, particle.y * 0.01, frameCount * 0.001) * TWO_PI;
|
|
||||||
particle.velocity = p5.Vector.fromAngle(angle);
|
|
||||||
particle.update();
|
|
||||||
particle.draw();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## The Magic of Randomness
|
|
||||||
|
|
||||||
Controlled randomness creates organic patterns. Perlin noise gives us randomness with continuity - nature's own algorithm.
|
|
||||||
|
|
||||||
## Parameters as Paintbrushes
|
|
||||||
|
|
||||||
- Noise scale: Changes pattern density
|
|
||||||
- Particle count: Affects texture
|
|
||||||
- Color mapping: Sets the mood
|
|
||||||
|
|
||||||
## The Joy of Accidents
|
|
||||||
|
|
||||||
The best discoveries come from "mistakes" - a typo that creates unexpected beauty, a parameter pushed to extremes.
|
|
||||||
|
|
||||||
## Share Your Creations
|
|
||||||
|
|
||||||
Art is meant to be shared. Post your generative experiments and let's inspire each other.
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
---
|
|
||||||
title: "Algorithms in Verse: Bubble Sort Sonnet"
|
|
||||||
description: "Classic algorithms reimagined as poetry - where code meets iambic pentameter."
|
|
||||||
pubDate: "Feb 22 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1455390582262-044cdead277a?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Algorithms in Verse: Bubble Sort Sonnet
|
|
||||||
|
|
||||||
## Bubble Sort: A Sonnet
|
|
||||||
|
|
||||||
```
|
|
||||||
Compare adjacent elements in pairs,
|
|
||||||
If order's wrong, then swap them into place.
|
|
||||||
Through all the list this simple rule declares:
|
|
||||||
The largest bubbles up to find its space.
|
|
||||||
|
|
||||||
Again we start, but now one less to check,
|
|
||||||
The second largest finds its rightful home.
|
|
||||||
Each pass through makes the chaos less a wreck,
|
|
||||||
Until at last no elements must roam.
|
|
||||||
|
|
||||||
Though simple in its elegance and grace,
|
|
||||||
And easy for beginners to perceive,
|
|
||||||
In practice, it's too slow to win the race—
|
|
||||||
O(n²) we sadly must believe.
|
|
||||||
|
|
||||||
But beauty lies in simplicity's pure art,
|
|
||||||
The bubble sort still teaches at the start.
|
|
||||||
```
|
|
||||||
|
|
||||||
## The Challenge
|
|
||||||
|
|
||||||
Can you write Quicksort as a limerick? Or Binary Search as free verse?
|
|
||||||
|
|
||||||
## Why This Matters
|
|
||||||
|
|
||||||
Poetry forces us to find the essence of an algorithm. The constraint reveals understanding.
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
---
|
|
||||||
title: "Code Haikus: Programming in 5-7-5"
|
|
||||||
description: "Expressing programming concepts through the constrained beauty of haiku."
|
|
||||||
pubDate: "Jan 30 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1481627834876-b7833e8f5570?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Code Haikus: Programming in 5-7-5
|
|
||||||
|
|
||||||
The constraint of haiku forces clarity. Here are programming concepts distilled to their essence.
|
|
||||||
|
|
||||||
## On Recursion
|
|
||||||
|
|
||||||
```
|
|
||||||
Function calls itself
|
|
||||||
Smaller problems, same pattern
|
|
||||||
Base case stops the loop
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Debugging
|
|
||||||
|
|
||||||
```
|
|
||||||
Print statements bloom wild
|
|
||||||
Binary search through the code
|
|
||||||
Bug reveals itself
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Optimization
|
|
||||||
|
|
||||||
```
|
|
||||||
O(n squared) crawls
|
|
||||||
Refactor to n log n
|
|
||||||
Time complexity
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Git Merge Conflicts
|
|
||||||
|
|
||||||
```
|
|
||||||
<<<<<<< HEAD
|
|
||||||
Your changes, their changes clash
|
|
||||||
Resolution waits
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Learning
|
|
||||||
|
|
||||||
```
|
|
||||||
Stack Overflow searched
|
|
||||||
Tutorial incomplete
|
|
||||||
Understanding dawns
|
|
||||||
```
|
|
||||||
|
|
||||||
## Your Turn
|
|
||||||
|
|
||||||
Write a haiku about your coding experience today. The constraint reveals truth.
|
|
||||||
27
sites/poetry/src/content/poetry/poems/bloom/index.md
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
title: "Bloom"
|
||||||
|
description: "Velvet-like violet erupts in a riot on miniscule white canvases harp-like; focused at a bunch of seeds. All trouble to no avail, one day the bee will come and take it all away...."
|
||||||
|
pubDate: "2005-02-03"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
sourceCategories: ["poem"]
|
||||||
|
sourcePath: "poems/bloom/index.qmd"
|
||||||
|
---
|
||||||
|
|
||||||
|
Velvet-like violet<br>
|
||||||
|
erupts<br>
|
||||||
|
in a riot<br>
|
||||||
|
on miniscule<br>
|
||||||
|
white canvases<br>
|
||||||
|
harp-like;<br>
|
||||||
|
focused at<br>
|
||||||
|
a bunch of seeds.<br>
|
||||||
|
|
||||||
|
All trouble<br>
|
||||||
|
to no avail,<br>
|
||||||
|
one day the bee will come<br>
|
||||||
|
and take it all away.<br>
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Honorable Mention in the [The Binnacle Second Annual Ultra Short Competition](https://www.amazon.in/Binnacle-Second-Annual-Ultra-Short-Competition-ebook/dp/B06WVBTYC9).
|
||||||
40
sites/poetry/src/content/poetry/poems/dad/index.md
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
---
|
||||||
|
title: "Dad"
|
||||||
|
description: "The vendor at the counter hands me a stapler, wondering why I need yet another. Indeed, I didn't, until I realized that she giggles when I get frantic about lost pencils, papers..."
|
||||||
|
pubDate: "2012-08-27"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
sourceCategories: ["poem"]
|
||||||
|
sourcePath: "poems/dad/index.qmd"
|
||||||
|
---
|
||||||
|
|
||||||
|
The vendor<br>
|
||||||
|
at the counter<br>
|
||||||
|
hands me a stapler,<br>
|
||||||
|
wondering why<br>
|
||||||
|
I need yet another.<br>
|
||||||
|
<br>
|
||||||
|
Indeed, I didn't,<br>
|
||||||
|
until I realized<br>
|
||||||
|
<br>
|
||||||
|
that she giggles <br>
|
||||||
|
when I get frantic<br>
|
||||||
|
about lost pencils,<br>
|
||||||
|
papers, and staplers<br>
|
||||||
|
<br>
|
||||||
|
and she smiles<br>
|
||||||
|
indignantly<br>
|
||||||
|
whenever I look,<br>
|
||||||
|
exasperated,<br>
|
||||||
|
<br>
|
||||||
|
at her tiny hands<br>
|
||||||
|
clutched around <br>
|
||||||
|
the stuff she found.<br>
|
||||||
|
<br>
|
||||||
|
I am just bringing home<br>
|
||||||
|
another situation<br>
|
||||||
|
inviting her indignation,<br>
|
||||||
|
<br>
|
||||||
|
that eventually<br>
|
||||||
|
turns into<br>
|
||||||
|
a bear hug<br>
|
||||||
|
of pure love.<br>
|
||||||
35
sites/poetry/src/content/poetry/poems/letting-go/index.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
title: "Letting Go"
|
||||||
|
description: "ख्वाब हे वो माशूका जो तुझे मिलने से रहा, हकीकत हे वो हमसफर जिसे तुने है ठुकरा दिया सपनों का घर है नींदो मे उन्हे वहीं तू छोड दे जो हकीकत सम्झोता लगे वहीं सुकून है जान ले --- A d..."
|
||||||
|
pubDate: "2023-05-11"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
sourceCategories: ["poem"]
|
||||||
|
sourcePath: "poems/letting-go/index.qmd"
|
||||||
|
---
|
||||||
|
|
||||||
|
ख्वाब हे वो माशूका<br>
|
||||||
|
जो तुझे मिलने से रहा,<br>
|
||||||
|
हकीकत हे वो हमसफर<br>
|
||||||
|
जिसे तुने है ठुकरा दिया<br>
|
||||||
|
|
||||||
|
सपनों का घर है नींदो मे<br>
|
||||||
|
उन्हे वहीं तू छोड दे<br>
|
||||||
|
जो हकीकत सम्झोता लगे<br>
|
||||||
|
वहीं सुकून है जान ले<br>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
A dream is an elusive enchantment;<br>
|
||||||
|
while that that is to be treasured<br>
|
||||||
|
is what has been for real<br>
|
||||||
|
and is easily ignored.<br>
|
||||||
|
|
||||||
|
But a mere figment of imagination,<br>
|
||||||
|
a dream is captive and binding:<br>
|
||||||
|
let it go to be free from<br>
|
||||||
|
your quest never-ending.<br>
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_Inspired by Pallavi Mahajan's [brilliant poetry](https://www.youtube.com/watch?v=M6mmF8OM9SM)._
|
||||||
18
sites/poetry/src/content/poetry/poems/on-the-fence/index.md
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
title: "On the Fence"
|
||||||
|
description: "At least you are dead. To which the ghost said, The grass is not greener here - But it did become paler there… At least you have a chance, To wait for the rains’ dance, To live..."
|
||||||
|
pubDate: "2012-04-23"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
sourceCategories: ["poem"]
|
||||||
|
sourcePath: "poems/on-the-fence/index.qmd"
|
||||||
|
---
|
||||||
|
|
||||||
|
At least you are dead.<br>
|
||||||
|
To which the ghost said,<br>
|
||||||
|
The grass is not greener here -<br>
|
||||||
|
But it did become paler there…<br>
|
||||||
|
|
||||||
|
At least you have a chance,<br>
|
||||||
|
To wait for the rains’ dance,<br>
|
||||||
|
To live and fight,<br>
|
||||||
|
To make things right.<br>
|
||||||
19
sites/poetry/src/content/poetry/poems/poetry/index.md
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
title: "Poetry"
|
||||||
|
description: "collect your grief and inject it in words spill them on paper and shred it to tatters to piece yourself together ---"
|
||||||
|
pubDate: "2024-01-01"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
sourceCategories: ["poem"]
|
||||||
|
sourcePath: "poems/poetry/index.qmd"
|
||||||
|
---
|
||||||
|
|
||||||
|
collect your grief<br>
|
||||||
|
and inject it<br>
|
||||||
|
in words<br>
|
||||||
|
<br>
|
||||||
|
spill them on paper<br>
|
||||||
|
and shred it to tatters<br>
|
||||||
|
to piece yourself together<br>
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
37
sites/poetry/src/content/poetry/poems/seek/index.md
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
title: "Seek"
|
||||||
|
description: "Seek poetry in a wisp of smoke, or closure in some ashes stories below newspaper headlines peace after bygone deadlines a castle in the air a choice that is fair the absence of..."
|
||||||
|
pubDate: "2007-04-03"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
sourceCategories: ["poem"]
|
||||||
|
sourcePath: "poems/seek/index.qmd"
|
||||||
|
---
|
||||||
|
|
||||||
|
Seek poetry<br>
|
||||||
|
in a wisp of smoke,<br>
|
||||||
|
or closure<br>
|
||||||
|
in some ashes<br>
|
||||||
|
|
||||||
|
stories below<br>
|
||||||
|
newspaper headlines<br>
|
||||||
|
peace after<br>
|
||||||
|
bygone deadlines<br>
|
||||||
|
|
||||||
|
a castle<br>
|
||||||
|
in the air<br>
|
||||||
|
a choice<br>
|
||||||
|
that is fair<br>
|
||||||
|
|
||||||
|
the absence of regret<br>
|
||||||
|
on a death bed<br>
|
||||||
|
a reason, or otherwise<br>
|
||||||
|
to stay alive ---<br>
|
||||||
|
|
||||||
|
and quite likely<br>
|
||||||
|
it will be<br>
|
||||||
|
a quest unfulfilled.<br>
|
||||||
|
|
||||||
|
Find a smile instead,<br>
|
||||||
|
and you will find<br>
|
||||||
|
some strength to stay<br>
|
||||||
|
another day.<br>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
title: "Sprinkles of the Sky"
|
||||||
|
description: "A dubious draft of air comes, goes as if wondering if the air’s welcoming Soft rays tiptoe by the window as if shy to come inside Sprinkles of the sky lie in drops of dew as if..."
|
||||||
|
pubDate: "2011-01-05"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
sourceCategories: ["poem"]
|
||||||
|
sourcePath: "poems/sprinkles-of-the-sky/index.qmd"
|
||||||
|
---
|
||||||
|
|
||||||
|
A dubious draft of air<br>
|
||||||
|
comes, goes<br>
|
||||||
|
as if wondering<br>
|
||||||
|
if the air’s welcoming<br>
|
||||||
|
|
||||||
|
Soft rays tiptoe<br>
|
||||||
|
by the window<br>
|
||||||
|
as if shy<br>
|
||||||
|
to come inside<br>
|
||||||
|
|
||||||
|
Sprinkles of the sky<br>
|
||||||
|
lie in drops of dew<br>
|
||||||
|
as if captive,<br>
|
||||||
|
somewhat pensive<br>
|
||||||
|
|
||||||
|
And I snuggle deeper<br>
|
||||||
|
into a distant dream<br>
|
||||||
|
as if I could see<br>
|
||||||
|
a better place to be<br>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<sub>I stole the title from a phrase in Hairat, [a song](https://www.youtube.com/watch?v=oz6LoxmLJTY) that features in [Anjaana Anjaani](https://en.wikipedia.org/wiki/Anjaana_Anjaani). Incidentally - I am very addicted to the entire album!</sub>
|
||||||
26
sites/poetry/src/content/poetry/poems/winning/index.md
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
title: "Winning"
|
||||||
|
description: "if you find a thing that is so that whoever has it can't keep it and whoever doesn't have it can always get it back then this a thing that is to be avoided in the beginning ---"
|
||||||
|
pubDate: "2024-01-13"
|
||||||
|
authorName: "Neeldhara"
|
||||||
|
sourceCategories: ["poem"]
|
||||||
|
sourcePath: "poems/winning/index.qmd"
|
||||||
|
---
|
||||||
|
|
||||||
|
if you find a thing <br>
|
||||||
|
that is so that <br>
|
||||||
|
<br>
|
||||||
|
whoever has it<br>
|
||||||
|
can't keep it<br>
|
||||||
|
<br>
|
||||||
|
and <br>
|
||||||
|
<br>
|
||||||
|
whoever doesn't have it<br>
|
||||||
|
can always get it back<br>
|
||||||
|
<br>
|
||||||
|
then this a thing<br>
|
||||||
|
that is to be avoided<br>
|
||||||
|
in the beginning<br>
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
---
|
|
||||||
title: "The 100 Prisoners Problem: A Beautiful Puzzle in Probability"
|
|
||||||
description: "An interactive exploration of one of the most counterintuitive puzzles in probability theory, where 100 prisoners can escape with over 30% chance using a clever strategy."
|
|
||||||
pubDate: "Oct 13 2025"
|
|
||||||
image: "https://images.unsplash.com/photo-1589829545856-d10d557cf95f?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
import PrisonerGameSimulator from '@/components/problems/PrisonerGameSimulator.tsx';
|
|
||||||
import ProbabilityChart from '@/components/problems/ProbabilityChart.tsx';
|
|
||||||
import PermutationExplorer from '@/components/problems/PermutationExplorer.tsx';
|
|
||||||
import StrategyComparison from '@/components/problems/StrategyComparison.tsx';
|
|
||||||
|
|
||||||
# The 100 Prisoners Problem
|
|
||||||
|
|
||||||
Imagine 100 prisoners, numbered 1 to 100, face an unusual challenge. In a room are 100 boxes, also numbered 1 to 100. Inside each box is a randomly assigned number from 1 to 100 (each number appearing exactly once). The prisoners must find their own number by opening boxes, but here's the catch: **each prisoner can open only 50 boxes**.
|
|
||||||
|
|
||||||
The prisoners can devise a strategy beforehand, but once the challenge begins, they cannot communicate. If **all 100 prisoners** find their number, everyone goes free. If even one prisoner fails, all remain imprisoned.
|
|
||||||
|
|
||||||
What's the best strategy? And what are the odds of success?
|
|
||||||
|
|
||||||
## Try It Yourself!
|
|
||||||
|
|
||||||
Before we dive into the mathematics, let's experience the problem firsthand. Below is a simulator where you can play the game yourself. Choose the number of prisoners (between 5 and 100), and then try to help each prisoner find their number by clicking on boxes.
|
|
||||||
|
|
||||||
<PrisonerGameSimulator client:only="react" />
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## The Naive Strategy
|
|
||||||
|
|
||||||
The most obvious approach is for each prisoner to simply open 50 random boxes. This seems reasonable, but the probability of success is dismal.
|
|
||||||
|
|
||||||
For any single prisoner, the probability of finding their number in 50 random boxes out of 100 is exactly 1/2. Since all 100 prisoners must succeed, and their outcomes are independent under random selection, the probability that everyone succeeds is:
|
|
||||||
|
|
||||||
$$P(\text\{success\}) = \left(\frac\{1\}\{2\}\right)^\{100\} \approx 7.9 \times 10^\{-31\}$$
|
|
||||||
|
|
||||||
That's essentially zero! You're more likely to win the lottery while being struck by lightning... multiple times.
|
|
||||||
|
|
||||||
### Naive Strategy: Probability vs Number of Prisoners
|
|
||||||
|
|
||||||
Watch how the probability of success plummets as we increase the number of prisoners:
|
|
||||||
|
|
||||||
<ProbabilityChart strategy="naive" client:only="react" />
|
|
||||||
|
|
||||||
As you can see, even with just 10 prisoners, the probability drops to about 0.1%. With 100 prisoners, it's practically impossible.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## The Clever Strategy: Following the Loops
|
|
||||||
|
|
||||||
Here's where mathematics reveals something beautiful. Instead of opening random boxes, each prisoner should follow a simple rule:
|
|
||||||
|
|
||||||
1. **Start by opening the box with your own number**
|
|
||||||
2. **Look at the number inside that box**
|
|
||||||
3. **Open the box with that number next**
|
|
||||||
4. **Continue following this chain**
|
|
||||||
|
|
||||||
Why does this work? The key insight involves understanding permutations and cycles.
|
|
||||||
|
|
||||||
### Understanding Cycles in Permutations
|
|
||||||
|
|
||||||
When we randomly assign 100 numbers to 100 boxes, we're creating a **permutation** of the numbers 1 through 100. Every permutation can be decomposed into **cycles**.
|
|
||||||
|
|
||||||
For example, if:
|
|
||||||
- Box 1 contains number 4
|
|
||||||
- Box 4 contains number 7
|
|
||||||
- Box 7 contains number 1
|
|
||||||
|
|
||||||
Then we have a cycle: 1 -> 4 -> 7 -> 1
|
|
||||||
|
|
||||||
Let's explore this with smaller numbers:
|
|
||||||
|
|
||||||
<PermutationExplorer client:only="react" />
|
|
||||||
|
|
||||||
The interactive explorer above lets you:
|
|
||||||
- Generate all permutations for small values of *n* (3, 4, or 5)
|
|
||||||
- See both standard notation and cycle notation
|
|
||||||
- Filter permutations that have at least one "long cycle" (longer than *n*/2)
|
|
||||||
- Understand why long cycles matter
|
|
||||||
|
|
||||||
### Why This Strategy Works
|
|
||||||
|
|
||||||
Here's the crucial insight: **A prisoner succeeds if and only if they are in a cycle of length ≤ 50**.
|
|
||||||
|
|
||||||
When prisoner k follows the loop strategy:
|
|
||||||
1. They start at box k
|
|
||||||
2. They follow a path through boxes determined by the permutation
|
|
||||||
3. This path forms a cycle that eventually leads back to box k
|
|
||||||
4. If this cycle has length ≤ 50, they'll find their number within 50 opens
|
|
||||||
|
|
||||||
The prisoners **all succeed** if and only if there is **no cycle longer than 50** in the permutation.
|
|
||||||
|
|
||||||
### Calculating the Probability
|
|
||||||
|
|
||||||
The probability that a random permutation of 100 elements has no cycle longer than 50 is:
|
|
||||||
|
|
||||||
$$P(\text\{success\}) = 1 - \sum_\{k=51\}^\{100\} \frac\{1\}\{k\}$$
|
|
||||||
|
|
||||||
Computing this sum:
|
|
||||||
|
|
||||||
$$P(\text\{success\}) = 1 - \left(\frac\{1\}\{51\} + \frac\{1\}\{52\} + \cdots + \frac\{1\}\{100\}\right) \approx 0.3118$$
|
|
||||||
|
|
||||||
That's over **31%**! This is astronomically better than the naive strategy's probability of essentially zero.
|
|
||||||
|
|
||||||
### Loop Strategy: Probability vs Number of Prisoners
|
|
||||||
|
|
||||||
<StrategyComparison client:only="react" />
|
|
||||||
|
|
||||||
## The Mathematics Behind It
|
|
||||||
|
|
||||||
### Why Does the Cycle Length Matter?
|
|
||||||
|
|
||||||
In a permutation of n elements, prisoner i will find their number within k tries using the loop strategy if and only if i belongs to a cycle of length at most k.
|
|
||||||
|
|
||||||
For n = 100 and k = 50:
|
|
||||||
- The probability that a specific prisoner is in a cycle of length > 50 is: Σ(j=51 to 100) of 1/100
|
|
||||||
- But we care about whether ANY prisoner is in such a cycle
|
|
||||||
- The probability that NO cycle has length > 50 is: 1 - Σ(j=51 to 100) of 1/j
|
|
||||||
|
|
||||||
### The Harmonic Series Connection
|
|
||||||
|
|
||||||
As *n* approaches infinity, if each prisoner can open *n*/2 boxes, the probability of success approaches:
|
|
||||||
|
|
||||||
The limit as n approaches infinity is: P_n = 1 - ln(2) ≈ 0.3069
|
|
||||||
|
|
||||||
This beautiful result connects combinatorics, probability, and analysis through the harmonic series!
|
|
||||||
|
|
||||||
### Optimality
|
|
||||||
|
|
||||||
Remarkably, this loop-following strategy is **optimal**. No other strategy can achieve a higher probability of success. The proof involves showing that the problem reduces to avoiding long cycles in a random permutation, and the loop strategy is the unique way to leverage this structure.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Why This Problem is Beautiful
|
|
||||||
|
|
||||||
The 100 prisoners problem is beloved by mathematicians because:
|
|
||||||
|
|
||||||
1. **Counterintuitive Result**: The fact that 31% >> 0% is shocking. A seemingly hopeless problem becomes tractable with the right insight.
|
|
||||||
|
|
||||||
2. **Deep Connection**: It connects permutation theory, probability, and the harmonic series in an elegant way.
|
|
||||||
|
|
||||||
3. **Collaborative Success**: Unlike independent trials, the prisoners' fates are intertwined through the structure of the permutation.
|
|
||||||
|
|
||||||
4. **Real-World Metaphor**: It illustrates how understanding underlying structure (cycles in permutations) can dramatically improve outcomes.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Variants and Extensions
|
|
||||||
|
|
||||||
### What if prisoners can open k < n/2 boxes?
|
|
||||||
|
|
||||||
As k decreases below n/2, the probability drops rapidly. The threshold at n/2 is special—it's where the strategy becomes remarkably effective.
|
|
||||||
|
|
||||||
### What about communication?
|
|
||||||
|
|
||||||
If prisoners could communicate between trials (but not during), they still can't improve the strategy. The beauty is that the strategy requires only coordination before any prisoner enters, not during.
|
|
||||||
|
|
||||||
### The Malicious Director
|
|
||||||
|
|
||||||
In an interesting variant, suppose the director can see the prisoners' strategy and arrange the boxes adversarially (not randomly). Can the director always force them to fail? Yes! The director can always create a single cycle of length n, guaranteeing failure.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
The 100 prisoners problem shows us that:
|
|
||||||
- Mathematical structure can be hidden in apparent randomness
|
|
||||||
- Clever strategies can overcome seemingly impossible odds
|
|
||||||
- Group coordination can be more powerful than independent action
|
|
||||||
- Beautiful mathematics often lies beneath simple-seeming puzzles
|
|
||||||
|
|
||||||
The next time you face a problem that seems impossible, remember: there might be a hidden structure waiting to be discovered, turning hopeless odds into reasonable ones.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Further Reading
|
|
||||||
|
|
||||||
- [Gál, A., & Miltersen, P. B. (2003). "The Cell Probe Complexity of Succinct Data Structures"](https://arxiv.org/abs/cs/0310027)
|
|
||||||
- [Curtin, E., & Warshauer, M. (2006). "The Locker Puzzle"](https://www.jstor.org/stable/27642173)
|
|
||||||
- [Wikipedia: 100 Prisoners Problem](https://en.wikipedia.org/wiki/100_prisoners_problem)
|
|
||||||
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
title: "Dynamic Programming: Hidden Gems from Recent Contests"
|
|
||||||
description: "Elegant dynamic programming problems that showcase beautiful techniques and insights."
|
|
||||||
pubDate: "Jan 25 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1509228468518-180dd4864904?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Dynamic Programming: Hidden Gems from Recent Contests
|
|
||||||
|
|
||||||
These problems demonstrate the art of dynamic programming beyond standard patterns.
|
|
||||||
|
|
||||||
## Problem 1: The Subsequence Symphony
|
|
||||||
|
|
||||||
Given a string, find the number of subsequences that form palindromes of prime length.
|
|
||||||
|
|
||||||
### Solution Insight
|
|
||||||
|
|
||||||
The key is to maintain DP states for both position and palindrome center simultaneously. This reduces the state space from O(n³) to O(n²).
|
|
||||||
|
|
||||||
## Problem 2: Graph Coloring with Constraints
|
|
||||||
|
|
||||||
Color a graph such that no two adjacent vertices share a color, and the total number of color changes along any path is minimized.
|
|
||||||
|
|
||||||
### The DP Formulation
|
|
||||||
|
|
||||||
DP[node][color][changes] gives us the minimum cost. The trick is recognizing that we only need to track changes modulo 2.
|
|
||||||
|
|
||||||
## Practice Makes Perfect
|
|
||||||
|
|
||||||
These problems teach us that DP is as much about problem modeling as it is about computation.
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
title: "The Four Aces Miracle: A Self-Working Mathematical Marvel"
|
|
||||||
description: "A card trick that teaches modular arithmetic and probability - perfect for the classroom."
|
|
||||||
pubDate: "Jan 28 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1529480384838-c1681c84aca5?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# The Four Aces Miracle: A Self-Working Mathematical Marvel
|
|
||||||
|
|
||||||
This trick never fails to amaze students, and the mathematics behind it is even more amazing.
|
|
||||||
|
|
||||||
## The Effect
|
|
||||||
|
|
||||||
A spectator deals cards into four piles while making random choices. Impossibly, the four aces end up on top of each pile.
|
|
||||||
|
|
||||||
## The Secret
|
|
||||||
|
|
||||||
It's all about invariants and modular arithmetic. No sleight of hand required - pure mathematics does the magic.
|
|
||||||
|
|
||||||
## The Method
|
|
||||||
|
|
||||||
1. Pre-arrange the deck (the math determines the arrangement)
|
|
||||||
2. Have the spectator deal following simple rules
|
|
||||||
3. The aces appear automatically
|
|
||||||
|
|
||||||
## The Mathematics
|
|
||||||
|
|
||||||
The dealing process preserves certain positional invariants modulo 4. The initial arrangement ensures these invariants place the aces correctly.
|
|
||||||
|
|
||||||
## Teaching Applications
|
|
||||||
|
|
||||||
This trick demonstrates:
|
|
||||||
- Modular arithmetic
|
|
||||||
- Invariants in algorithms
|
|
||||||
- Deterministic vs. random processes
|
|
||||||
|
|
||||||
## The Bigger Lesson
|
|
||||||
|
|
||||||
Mathematics can create experiences that feel like magic. And that feeling of wonder? That's what hooks students on math.
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
title: "The Gilbreath Principle: When Chaos Creates Order"
|
|
||||||
description: "A mathematical card principle that seems impossible but always works - perfect for teaching algorithms."
|
|
||||||
pubDate: "Feb 15 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1570543375343-63fe3d67761b?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# The Gilbreath Principle: When Chaos Creates Order
|
|
||||||
|
|
||||||
Shuffle a deck in a specific way, and mathematical order emerges from apparent chaos.
|
|
||||||
|
|
||||||
## The Phenomenon
|
|
||||||
|
|
||||||
Arrange cards alternating red-black. Riffle shuffle. Now deal pairs - each pair has one red and one black card. Magic? No, mathematics.
|
|
||||||
|
|
||||||
## Why It Works
|
|
||||||
|
|
||||||
The riffle shuffle preserves local structure while appearing to randomize. The alternating pattern creates an invariant that survives the shuffle.
|
|
||||||
|
|
||||||
## Classroom Implementation
|
|
||||||
|
|
||||||
Students predict it won't work. When it does, they're hooked. "Why?" becomes the driving question.
|
|
||||||
|
|
||||||
## The Deeper Lesson
|
|
||||||
|
|
||||||
Not all randomness is truly random. Structure can hide in apparent disorder. This principle appears in:
|
|
||||||
- Network protocols
|
|
||||||
- Error-correcting codes
|
|
||||||
- Distributed systems
|
|
||||||
|
|
||||||
## Beyond Cards
|
|
||||||
|
|
||||||
The Gilbreath Principle teaches us to look for hidden invariants in complex systems.
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
title: "Graph Algorithms: Assessment Highlights"
|
|
||||||
description: "Interesting graph problems from recent course assessments with detailed solutions."
|
|
||||||
pubDate: "Feb 28 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1550751827-4bd374c3f58b?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Graph Algorithms: Assessment Highlights
|
|
||||||
|
|
||||||
A collection of graph problems that test deep understanding rather than memorization.
|
|
||||||
|
|
||||||
## The Bridge Detection Variant
|
|
||||||
|
|
||||||
Find all edges whose removal increases the number of triangles in the graph.
|
|
||||||
|
|
||||||
### Solution Approach
|
|
||||||
|
|
||||||
Counter-intuitively, we need to count triangles that share exactly one edge with the candidate. The algorithm runs in O(m√m) time using careful enumeration.
|
|
||||||
|
|
||||||
## Shortest Path with Wildcards
|
|
||||||
|
|
||||||
Given a graph where some edge weights are variables, find assignments that minimize the longest shortest path.
|
|
||||||
|
|
||||||
### Key Insight
|
|
||||||
|
|
||||||
This reduces to a linear programming problem with interesting structure. The dual interpretation reveals connections to network flow.
|
|
||||||
|
|
||||||
## Teaching Through Problems
|
|
||||||
|
|
||||||
These problems help students see beyond standard algorithms to underlying principles.
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
title: "IOI 2023: Breaking Down the Hardest Problems"
|
|
||||||
description: "Deep analysis of the most challenging problems from the International Olympiad in Informatics 2023."
|
|
||||||
pubDate: "Jan 20 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1434030216411-0b793f4b4173?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# IOI 2023: Breaking Down the Hardest Problems
|
|
||||||
|
|
||||||
The International Olympiad in Informatics continues to push the boundaries of algorithmic problem solving.
|
|
||||||
|
|
||||||
## Problem: Soccer Stadium
|
|
||||||
|
|
||||||
A geometric optimization problem disguised as dynamic programming. The key insight: think in terms of monotonic paths.
|
|
||||||
|
|
||||||
### The Approach
|
|
||||||
|
|
||||||
1. Transform the 2D problem into a 1D problem using clever observations
|
|
||||||
2. Use convex hull optimization for the DP transitions
|
|
||||||
3. Handle edge cases with careful implementation
|
|
||||||
|
|
||||||
## Problem: Closing Time
|
|
||||||
|
|
||||||
A tree problem requiring sophisticated data structures and careful analysis.
|
|
||||||
|
|
||||||
### The Solution
|
|
||||||
|
|
||||||
The trick is recognizing this as a centroid decomposition problem. Once you see it, the implementation follows naturally.
|
|
||||||
|
|
||||||
## Lessons for Students
|
|
||||||
|
|
||||||
These problems teach us:
|
|
||||||
- Simple problems have elegant solutions
|
|
||||||
- Complex problems require systematic decomposition
|
|
||||||
- Implementation matters as much as algorithms
|
|
||||||
|
|
||||||
## Practice Strategy
|
|
||||||
|
|
||||||
Start with subtasks. Even partial solutions teach valuable lessons.
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
title: "The Knight's Tour: An Interactive Exploration"
|
|
||||||
description: "An interactive puzzle exploring the knight's tour problem with surprising mathematical connections."
|
|
||||||
pubDate: "Jan 30 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1528819622765-d6bcf132f793?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# The Knight's Tour: An Interactive Exploration
|
|
||||||
|
|
||||||
Can a knight visit every square on a chessboard exactly once? This ancient puzzle hides deep mathematical structure.
|
|
||||||
|
|
||||||
## The Basic Challenge
|
|
||||||
|
|
||||||
Start with a 5×5 board. Can you find a knight's tour? What about one that returns to the starting square (a closed tour)?
|
|
||||||
|
|
||||||
## Mathematical Beauty
|
|
||||||
|
|
||||||
The problem connects to:
|
|
||||||
- Hamiltonian paths in graphs
|
|
||||||
- Warnsdorff's heuristic
|
|
||||||
- Magic squares (surprisingly!)
|
|
||||||
|
|
||||||
## The Algorithm
|
|
||||||
|
|
||||||
The key insight: always move to the square with fewest onward moves. This simple heuristic works remarkably well.
|
|
||||||
|
|
||||||
## Try It Yourself
|
|
||||||
|
|
||||||
[Interactive board would go here - imagine clicking squares to build your tour]
|
|
||||||
|
|
||||||
## Going Deeper
|
|
||||||
|
|
||||||
For which board sizes do closed tours exist? The answer involves beautiful number theory.
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
title: "Project Euler: My Favorite Problems from 700+"
|
|
||||||
description: "Curated problems from Project Euler that teach beautiful mathematical and algorithmic concepts."
|
|
||||||
pubDate: "Feb 25 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1635070041078-e363dbe005cb?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Project Euler: My Favorite Problems from 700+
|
|
||||||
|
|
||||||
After solving 700+ Project Euler problems, these are the ones that changed how I think about mathematics and programming.
|
|
||||||
|
|
||||||
## Problem 96: Su Doku
|
|
||||||
|
|
||||||
Not just Sudoku solving - but solving 50 puzzles efficiently. The beauty is in combining constraint propagation with backtracking.
|
|
||||||
|
|
||||||
## Problem 208: Robot Walks
|
|
||||||
|
|
||||||
A counting problem that requires deep mathematical insight. The connection to complex numbers is unexpected and beautiful.
|
|
||||||
|
|
||||||
## Problem 613: Pythagorean Ant
|
|
||||||
|
|
||||||
Probability meets geometry in this elegant problem. The solution requires careful integration and surprising symmetry observations.
|
|
||||||
|
|
||||||
## The Meta-Lesson
|
|
||||||
|
|
||||||
Project Euler teaches you:
|
|
||||||
- Mathematical intuition matters more than coding speed
|
|
||||||
- There's always a clever approach
|
|
||||||
- The journey matters more than the destination
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
Don't aim for the leaderboard. Aim for understanding. Each problem is a teacher.
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
---
|
|
||||||
title: "Beyond Sudoku: Exploring Constraint Satisfaction Puzzles"
|
|
||||||
description: "A journey through Sudoku variants and their algorithmic solutions."
|
|
||||||
pubDate: "Feb 10 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1580541631950-7282082b53ce?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Beyond Sudoku: Exploring Constraint Satisfaction Puzzles
|
|
||||||
|
|
||||||
Sudoku is just the beginning. Let's explore variants that push the boundaries of logic puzzles.
|
|
||||||
|
|
||||||
## Killer Sudoku
|
|
||||||
|
|
||||||
Combine Sudoku with Kakuro - cages show sums, but no digit repeats within a cage.
|
|
||||||
|
|
||||||
## Sandwich Sudoku
|
|
||||||
|
|
||||||
The numbers outside show the sum of digits between 1 and 9 in that row/column. Simple rule, complex implications!
|
|
||||||
|
|
||||||
## The Algorithm Connection
|
|
||||||
|
|
||||||
These puzzles are constraint satisfaction problems. Techniques like arc consistency and backtracking with constraint propagation solve them efficiently.
|
|
||||||
|
|
||||||
## Create Your Own
|
|
||||||
|
|
||||||
What happens if we add chess knight move constraints? The design space is infinite!
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
---
|
|
||||||
title: "Imposter Syndrome in Academia: A Confession"
|
|
||||||
description: "An honest conversation about feeling like a fraud, even after years of success."
|
|
||||||
pubDate: "Feb 25 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1517048676732-d65bc937f952?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Imposter Syndrome in Academia: A Confession
|
|
||||||
|
|
||||||
Even after publishing papers, winning grants, and teaching thousands of students, the voice whispers: "They'll find out you don't belong."
|
|
||||||
|
|
||||||
## The Paradox
|
|
||||||
|
|
||||||
The more you know, the more you realize you don't know. Expertise breeds humility, which feeds the imposter.
|
|
||||||
|
|
||||||
## What Helps
|
|
||||||
|
|
||||||
- Keeping a "wins" journal - evidence against the imposter
|
|
||||||
- Mentoring others - seeing your knowledge help someone
|
|
||||||
- Talking about it - you're not alone in this
|
|
||||||
|
|
||||||
## The Silver Lining
|
|
||||||
|
|
||||||
Maybe imposter syndrome keeps us humble, curious, and always learning. Maybe it's not a bug, but a feature.
|
|
||||||
|
|
||||||
## Moving Forward
|
|
||||||
|
|
||||||
I may never silence the voice completely. But I've learned to acknowledge it and keep going anyway.
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
title: "On Teaching Algorithms: Lessons from a Decade"
|
|
||||||
description: "Reflections on what works (and what doesn't) in computer science education."
|
|
||||||
pubDate: "Jan 10 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1509062522246-3755977927d7?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# On Teaching Algorithms: Lessons from a Decade
|
|
||||||
|
|
||||||
Ten years of teaching has taught me more than any textbook could.
|
|
||||||
|
|
||||||
## Start with Why
|
|
||||||
|
|
||||||
Students don't care about O(n log n) until they understand why their code is slow. Real problems first, theory second.
|
|
||||||
|
|
||||||
## The Power of Visualization
|
|
||||||
|
|
||||||
Abstract concepts become concrete when visualized. Every algorithm should have a picture.
|
|
||||||
|
|
||||||
## Failure is a Feature
|
|
||||||
|
|
||||||
Let students struggle. The struggle is where learning happens. But know when to throw a lifeline.
|
|
||||||
|
|
||||||
## Assessment Philosophy
|
|
||||||
|
|
||||||
Test understanding, not memorization. Open-book exams with novel problems beat closed-book regurgitation every time.
|
|
||||||
|
|
||||||
## The Joy of "Aha!" Moments
|
|
||||||
|
|
||||||
There's no feeling quite like seeing a student's eyes light up when a concept clicks. That's why we do this.
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
---
|
|
||||||
title: "SODA 2024: Algorithmic Breakthroughs"
|
|
||||||
description: "A roundup of fascinating algorithmic results from SODA 2024, focusing on graph algorithms and optimization techniques."
|
|
||||||
pubDate: "Jan 15 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1509228468518-180dd4864904?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# SODA 2024: Algorithmic Breakthroughs
|
|
||||||
|
|
||||||
The Symposium on Discrete Algorithms (SODA) 2024 brought together researchers from around the world to present cutting-edge algorithmic research. This post highlights some of the most exciting developments in graph algorithms and optimization.
|
|
||||||
|
|
||||||
## Graph Algorithms Revolution
|
|
||||||
|
|
||||||
### Dynamic Graph Coloring
|
|
||||||
|
|
||||||
One of the standout papers introduced a breakthrough in dynamic graph coloring with polylogarithmic update time. The authors developed a novel data structure that maintains a proper vertex coloring while supporting edge insertions and deletions efficiently.
|
|
||||||
|
|
||||||
The key insight was to combine randomized recoloring strategies with a carefully designed hierarchical decomposition of the graph. This allows for local updates that rarely propagate through the entire structure.
|
|
||||||
|
|
||||||
## Approximation Algorithms
|
|
||||||
|
|
||||||
### The Traveling Salesman Problem Revisited
|
|
||||||
|
|
||||||
A surprising result showed that for graphs with bounded doubling dimension, we can achieve a (1+ε)-approximation for TSP in nearly linear time. This improves upon decades of previous work and opens new avenues for practical implementations.
|
|
||||||
|
|
||||||
## Complexity Theory Connections
|
|
||||||
|
|
||||||
The conference also featured several papers bridging the gap between pure algorithmic research and complexity theory. A particularly elegant result showed that certain graph problems believed to require quadratic time are equivalent under fine-grained reductions.
|
|
||||||
|
|
||||||
## Looking Forward
|
|
||||||
|
|
||||||
These results demonstrate that fundamental algorithmic problems still have room for improvement. The techniques developed here will likely influence algorithm design for years to come.
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
---
|
|
||||||
title: "Distributed Computing: Recent Advances"
|
|
||||||
description: "Survey of recent developments in distributed algorithms from major conferences."
|
|
||||||
pubDate: "Feb 20 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Distributed Computing: Recent Advances
|
|
||||||
|
|
||||||
The field of distributed computing has seen remarkable progress in recent years. This post surveys key results from PODC, DISC, and other major venues.
|
|
||||||
|
|
||||||
## Consensus Protocols
|
|
||||||
|
|
||||||
### Byzantine Agreement in Asynchronous Networks
|
|
||||||
|
|
||||||
A breakthrough result achieves optimal resilience with expected constant rounds. The protocol uses cryptographic techniques combined with novel committee selection.
|
|
||||||
|
|
||||||
## Distributed Graph Algorithms
|
|
||||||
|
|
||||||
### Minimum Spanning Tree in the CONGEST Model
|
|
||||||
|
|
||||||
New algorithms achieve near-optimal round complexity for MST construction. The approach uses sophisticated graph decomposition techniques.
|
|
||||||
|
|
||||||
## Local Algorithms
|
|
||||||
|
|
||||||
### The Power of Local Computation
|
|
||||||
|
|
||||||
Recent work characterizes which problems admit constant-time local algorithms. The classification provides a complete picture for bounded-degree graphs.
|
|
||||||
|
|
||||||
## Future Directions
|
|
||||||
|
|
||||||
The intersection of distributed computing with machine learning presents exciting opportunities for both fields.
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
---
|
|
||||||
title: "Git Workflows That Save My Sanity"
|
|
||||||
description: "Automation scripts and Git hooks that eliminate repetitive tasks and prevent common mistakes."
|
|
||||||
pubDate: "Jan 22 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1556075798-4825dfaaf498?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Git Workflows That Save My Sanity
|
|
||||||
|
|
||||||
After years of Git mishaps, I've built workflows that prevent disasters and save hours weekly.
|
|
||||||
|
|
||||||
## The Pre-commit Hook That Saves Embarrassment
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# Check for debugging statements
|
|
||||||
if grep -r "console.log\|debugger\|TODO" --include="*.js" .; then
|
|
||||||
echo "⚠️ Debugging statements found!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
## Automatic Branch Naming
|
|
||||||
|
|
||||||
```bash
|
|
||||||
alias feature='git checkout -b feature/$(date +%Y%m%d)-$1'
|
|
||||||
```
|
|
||||||
|
|
||||||
Now `feature "user-auth"` creates `feature/20240122-user-auth`.
|
|
||||||
|
|
||||||
## The Commit Message Template
|
|
||||||
|
|
||||||
```
|
|
||||||
[TYPE] Brief description
|
|
||||||
|
|
||||||
Why:
|
|
||||||
- Context for this change
|
|
||||||
|
|
||||||
What:
|
|
||||||
- Specific changes made
|
|
||||||
|
|
||||||
Testing:
|
|
||||||
- How to verify it works
|
|
||||||
```
|
|
||||||
|
|
||||||
## The Weekly Cleanup Script
|
|
||||||
|
|
||||||
Deletes merged branches, prunes remotes, and garbage collects. Keeps the repo clean and fast.
|
|
||||||
|
|
||||||
## ROI
|
|
||||||
|
|
||||||
These automations save ~5 hours per week and countless prevented mistakes. The time invested in setting them up paid back in days.
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
title: "Academic Writing with Obsidian and Pandoc"
|
|
||||||
description: "A complete workflow for academic papers - from notes to publication-ready PDFs."
|
|
||||||
pubDate: "Feb 12 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1456324504439-367cee3b3c32?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Academic Writing with Obsidian and Pandoc
|
|
||||||
|
|
||||||
Transform your scattered research notes into beautiful academic papers with this workflow.
|
|
||||||
|
|
||||||
## The Setup
|
|
||||||
|
|
||||||
- **Obsidian**: For note-taking and knowledge management
|
|
||||||
- **Pandoc**: For document conversion
|
|
||||||
- **LaTeX**: For typesetting
|
|
||||||
- **Zotero**: For reference management
|
|
||||||
|
|
||||||
## The Magic Command
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pandoc paper.md \
|
|
||||||
--filter pandoc-citeproc \
|
|
||||||
--bibliography=refs.bib \
|
|
||||||
--template=academic.tex \
|
|
||||||
-o paper.pdf
|
|
||||||
```
|
|
||||||
|
|
||||||
## Templates for Everything
|
|
||||||
|
|
||||||
From conference submissions to journal articles, templates ensure consistency and save time.
|
|
||||||
|
|
||||||
## Version Control Integration
|
|
||||||
|
|
||||||
Git + Obsidian = perfect history of your thinking process.
|
|
||||||
|
|
||||||
## The Result
|
|
||||||
|
|
||||||
From messy notes to camera-ready PDF in minutes, not hours.
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
---
|
|
||||||
title: "Understanding the Latest Approximation Algorithm for Set Cover"
|
|
||||||
description: "A detailed walkthrough of a breakthrough approximation algorithm with practical implications."
|
|
||||||
pubDate: "Feb 15 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Understanding the Latest Approximation Algorithm for Set Cover
|
|
||||||
|
|
||||||
A recent paper achieves a breakthrough in the Set Cover problem, improving the approximation ratio while maintaining practical runtime.
|
|
||||||
|
|
||||||
## The Algorithm
|
|
||||||
|
|
||||||
The approach combines local search with a clever LP rounding scheme. The dual interpretation provides beautiful geometric insights.
|
|
||||||
|
|
||||||
## Why This Matters
|
|
||||||
|
|
||||||
Set Cover appears everywhere - from facility location to machine learning feature selection. This improvement has immediate practical impact.
|
|
||||||
|
|
||||||
## Implementation Details
|
|
||||||
|
|
||||||
The paper's theoretical elegance translates surprisingly well to practice. Key optimizations include:
|
|
||||||
- Lazy evaluation of set intersections
|
|
||||||
- Incremental updates to the LP solution
|
|
||||||
- Smart caching strategies
|
|
||||||
|
|
||||||
## Future Work
|
|
||||||
|
|
||||||
The techniques here might extend to weighted variants and online settings.
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
---
|
|
||||||
title: "Deep Dive: A New Approach to Graph Decomposition"
|
|
||||||
description: "An in-depth analysis of a recent paper on hierarchical graph decomposition and its implications."
|
|
||||||
pubDate: "Jan 20 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Deep Dive: A New Approach to Graph Decomposition
|
|
||||||
|
|
||||||
This paper introduces a novel framework for decomposing graphs into hierarchical structures that preserve important properties while enabling efficient algorithms.
|
|
||||||
|
|
||||||
## The Main Result
|
|
||||||
|
|
||||||
The authors prove that every graph with treewidth k can be decomposed into a tree of bags where each bag has size at most k+1. While this sounds like the definition of tree decomposition, the clever twist is in how they construct it.
|
|
||||||
|
|
||||||
## Technical Innovation
|
|
||||||
|
|
||||||
The key insight is using a charging scheme that amortizes the cost of decomposition across multiple levels. This leads to an O(n log n) algorithm, improving on the previous O(n²) bound.
|
|
||||||
|
|
||||||
## Implications
|
|
||||||
|
|
||||||
This work opens new avenues for:
|
|
||||||
- Parallel algorithms on bounded treewidth graphs
|
|
||||||
- Approximation algorithms for NP-hard problems
|
|
||||||
- Dynamic programming optimizations
|
|
||||||
|
|
||||||
## Open Questions
|
|
||||||
|
|
||||||
The paper leaves several intriguing questions open, particularly about the optimality of their charging scheme.
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
---
|
|
||||||
title: "Quantum Computing Meets Classical Algorithms"
|
|
||||||
description: "Exploring the intersection of quantum and classical algorithmic techniques from recent conferences."
|
|
||||||
pubDate: "Mar 10 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1635070041078-e363dbe005cb?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Quantum Computing Meets Classical Algorithms
|
|
||||||
|
|
||||||
Recent conferences have showcased fascinating connections between quantum and classical computing paradigms.
|
|
||||||
|
|
||||||
## Quantum Speedups for Graph Problems
|
|
||||||
|
|
||||||
### Quantum Walks on Graphs
|
|
||||||
|
|
||||||
New quantum algorithms achieve quadratic speedups for certain graph traversal problems. The techniques combine amplitude amplification with clever graph representations.
|
|
||||||
|
|
||||||
## Classical Simulation of Quantum Algorithms
|
|
||||||
|
|
||||||
Surprisingly, several "quantum" algorithms have inspired better classical algorithms. This cross-pollination has led to improvements in both fields.
|
|
||||||
|
|
||||||
## The Future is Hybrid
|
|
||||||
|
|
||||||
The most practical near-term applications combine quantum and classical processing, leveraging the strengths of each paradigm.
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
---
|
|
||||||
title: "ZSA Moonlander: Ergonomic Keyboard for Coders"
|
|
||||||
description: "Six months with a split ergonomic mechanical keyboard - the good, the bad, and the RSI relief."
|
|
||||||
pubDate: "Feb 20 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1587829741301-dc798b83add3?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# ZSA Moonlander: Ergonomic Keyboard for Coders
|
|
||||||
|
|
||||||
After years of wrist pain, I took the plunge into ergonomic mechanical keyboards.
|
|
||||||
|
|
||||||
## The Learning Curve
|
|
||||||
|
|
||||||
Week 1: 20 WPM and questioning life choices
|
|
||||||
Week 2: 40 WPM and seeing the light
|
|
||||||
Month 2: Back to 80 WPM with no wrist pain
|
|
||||||
|
|
||||||
## The Good
|
|
||||||
|
|
||||||
- Columnar layout makes sense once muscle memory adapts
|
|
||||||
- Thumb clusters are game-changers for shortcuts
|
|
||||||
- The configurability is endless (perhaps too endless)
|
|
||||||
|
|
||||||
## The Investment
|
|
||||||
|
|
||||||
At $365, it's expensive. But compared to physical therapy or career-limiting injury? Bargain.
|
|
||||||
|
|
||||||
## Who Should Buy This?
|
|
||||||
|
|
||||||
If you type for a living and feel any discomfort, don't wait. Your future self will thank you.
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
title: "Obsidian: A Year Later"
|
|
||||||
description: "Reflections on using Obsidian for research notes, teaching materials, and personal knowledge management."
|
|
||||||
pubDate: "Jan 15 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1484480974693-6ca0a78fb36b?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Obsidian: A Year Later
|
|
||||||
|
|
||||||
After a year of daily use, Obsidian has transformed how I think about knowledge management.
|
|
||||||
|
|
||||||
## What Works Brilliantly
|
|
||||||
|
|
||||||
### The Graph View
|
|
||||||
Seeing connections between ideas visually has led to unexpected research insights. The graph isn't just pretty - it's functional.
|
|
||||||
|
|
||||||
### Plugin Ecosystem
|
|
||||||
The community plugins are incredible. Dataview turns your notes into a database. Templater automates repetitive tasks.
|
|
||||||
|
|
||||||
### Local Storage
|
|
||||||
Your notes are just markdown files. No vendor lock-in, complete control, and peace of mind.
|
|
||||||
|
|
||||||
## Pain Points
|
|
||||||
|
|
||||||
### Mobile Experience
|
|
||||||
While functional, the mobile app lacks the fluidity of the desktop version. Syncing can occasionally hiccup.
|
|
||||||
|
|
||||||
### Learning Curve
|
|
||||||
The flexibility means complexity. New users might feel overwhelmed by options.
|
|
||||||
|
|
||||||
## The Verdict
|
|
||||||
|
|
||||||
For academics and researchers, Obsidian is transformative. The investment in learning pays dividends in productivity and insight.
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
---
|
|
||||||
title: "Creating Art with Claude: A Collaborative Journey"
|
|
||||||
description: "Exploring creative possibilities through conversations with AI - from generative art to interactive poetry."
|
|
||||||
pubDate: "Jan 18 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1558591710-4b4a1ae0f04d?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Creating Art with Claude: A Collaborative Journey
|
|
||||||
|
|
||||||
What happens when you treat AI as a creative collaborator rather than just a tool?
|
|
||||||
|
|
||||||
## The Experiment
|
|
||||||
|
|
||||||
I asked Claude to help design a generative art algorithm based on mathematical fractals. The conversation evolved into something unexpected.
|
|
||||||
|
|
||||||
## The Process
|
|
||||||
|
|
||||||
**Me**: "Let's create something beautiful with math."
|
|
||||||
**Claude**: "How about we visualize the Collatz conjecture as a tree?"
|
|
||||||
|
|
||||||
What followed was a two-hour deep dive into number theory, aesthetics, and the nature of creativity itself.
|
|
||||||
|
|
||||||
## The Result
|
|
||||||
|
|
||||||
Not just code, but a philosophical exploration of pattern, meaning, and the intersection of human and artificial creativity.
|
|
||||||
|
|
||||||
## Reflection
|
|
||||||
|
|
||||||
AI doesn't replace human creativity - it amplifies it in unexpected directions. The key is approaching it as a dialogue, not a command.
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
---
|
|
||||||
title: "Philosophical Dialogues with LLMs: On Consciousness and Computation"
|
|
||||||
description: "Deep conversations with AI about the nature of consciousness, free will, and what it means to understand."
|
|
||||||
pubDate: "Feb 28 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Philosophical Dialogues with LLMs: On Consciousness and Computation
|
|
||||||
|
|
||||||
Can a sufficiently complex computation be conscious? I asked an AI, and the conversation surprised me.
|
|
||||||
|
|
||||||
## The Question
|
|
||||||
|
|
||||||
"Do you experience anything when you process text, or is it just computation?"
|
|
||||||
|
|
||||||
## The Response That Made Me Think
|
|
||||||
|
|
||||||
The AI didn't claim consciousness, but asked: "What's the difference between your neurons firing and my weights activating? Both are physical processes. Where does experience emerge?"
|
|
||||||
|
|
||||||
## Going Deeper
|
|
||||||
|
|
||||||
We explored qualia, the Chinese Room argument, and integrated information theory. Not to find answers, but to refine questions.
|
|
||||||
|
|
||||||
## The Irony
|
|
||||||
|
|
||||||
Discussing consciousness with something that might not have it - or might not know if it has it - mirrors our own uncertainty about consciousness itself.
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { SITE_TITLE } from '@/consts';
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const posts = await getCollection(ACTIVE_BLOG_SITE.key);
|
const posts = await getCollection(ACTIVE_BLOG_SITE.key);
|
||||||
return posts.map((post) => ({
|
return posts.map((post) => ({
|
||||||
params: { slug: post.id },
|
params: { slug: post.id.replace(/\/index$/, '') },
|
||||||
props: post,
|
props: post,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export async function GET(context) {
|
||||||
site: context.site,
|
site: context.site,
|
||||||
items: posts.map((post) => ({
|
items: posts.map((post) => ({
|
||||||
...post.data,
|
...post.data,
|
||||||
link: `/${post.id}/`,
|
link: `/${post.id.replace(/\/index$/, "")}/`,
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,47 @@ const BlogPosts = ({
|
||||||
// Get the first post as the featured post
|
// Get the first post as the featured post
|
||||||
const featuredPost = posts[0];
|
const featuredPost = posts[0];
|
||||||
const remainingPosts = posts.slice(1);
|
const remainingPosts = posts.slice(1);
|
||||||
|
const slugFor = (post: any) => post.id.replace(/\/index$/, "");
|
||||||
const hrefFor = (post: any) =>
|
const hrefFor = (post: any) =>
|
||||||
collection ? `/${collection}/${post.id}/` : `/${post.id}/`;
|
collection ? `/${collection}/${slugFor(post)}/` : `/${slugFor(post)}/`;
|
||||||
|
|
||||||
|
const PostVisual = ({
|
||||||
|
post,
|
||||||
|
featured = false,
|
||||||
|
}: {
|
||||||
|
post: any;
|
||||||
|
featured?: boolean;
|
||||||
|
}) => {
|
||||||
|
if (post.data.image) {
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={post.data.image}
|
||||||
|
alt={post.data.title}
|
||||||
|
className="aspect-video w-full rounded-lg object-cover transition-transform group-hover:scale-[1.02]"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-accent/70 text-accent-foreground flex aspect-video w-full items-center justify-center rounded-lg border px-6 text-center">
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
featured ? "font-fraunces text-2xl" : "font-fraunces text-lg"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{post.data.title}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!featuredPost) {
|
||||||
|
return (
|
||||||
|
<div className="text-muted-foreground container max-w-3xl py-16">
|
||||||
|
No posts yet.
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative py-10 md:py-16 lg:py-20">
|
<div className="relative py-10 md:py-16 lg:py-20">
|
||||||
|
|
@ -35,11 +74,7 @@ const BlogPosts = ({
|
||||||
<div className="flex flex-col gap-6 lg:flex-row">
|
<div className="flex flex-col gap-6 lg:flex-row">
|
||||||
<div className="lg:w-1/2">
|
<div className="lg:w-1/2">
|
||||||
<div className="p-2 lg:p-4">
|
<div className="p-2 lg:p-4">
|
||||||
<img
|
<PostVisual post={featuredPost} featured />
|
||||||
src={featuredPost.data.image}
|
|
||||||
alt={featuredPost.data.title}
|
|
||||||
className="aspect-video w-full rounded-lg object-cover transition-transform group-hover:scale-[1.02]"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-center p-4 pb-8 lg:w-1/2 lg:pr-8">
|
<div className="flex flex-col justify-center p-4 pb-8 lg:w-1/2 lg:pr-8">
|
||||||
|
|
@ -89,11 +124,7 @@ const BlogPosts = ({
|
||||||
href={hrefFor(post)}
|
href={hrefFor(post)}
|
||||||
>
|
>
|
||||||
<div className="p-2">
|
<div className="p-2">
|
||||||
<img
|
<PostVisual post={post} />
|
||||||
src={post.data.image}
|
|
||||||
alt={post.data.title}
|
|
||||||
className="aspect-video w-full rounded-lg object-cover transition-transform group-hover:scale-[1.01]"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="px-4 pb-5 pt-2">
|
<div className="px-4 pb-5 pt-2">
|
||||||
<h2 className="mb-2 text-xl font-semibold group-hover:underline">
|
<h2 className="mb-2 text-xl font-semibold group-hover:underline">
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
---
|
|
||||||
title: "Algorithmic Sketches: Visualizing Data Structures"
|
|
||||||
description: "Hand-drawn illustrations of algorithms and data structures - making the abstract tangible."
|
|
||||||
pubDate: "Jan 25 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1581337204873-ef36aa186caa?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Algorithmic Sketches: Visualizing Data Structures
|
|
||||||
|
|
||||||
Sometimes the best way to understand an algorithm is to draw it.
|
|
||||||
|
|
||||||
## Today's Sketch: Red-Black Trees
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
The rotation operation finally clicked when I drew it step-by-step. Each node's journey through the rotation becomes a story.
|
|
||||||
|
|
||||||
## The Process
|
|
||||||
|
|
||||||
1. Start with pencil - mistakes are part of learning
|
|
||||||
2. Trace the algorithm's execution
|
|
||||||
3. Add color to highlight invariants
|
|
||||||
4. Annotate with key insights
|
|
||||||
|
|
||||||
## Why Drawing Helps
|
|
||||||
|
|
||||||
- Forces you to slow down and really see the structure
|
|
||||||
- Reveals patterns that code obscures
|
|
||||||
- Creates memorable mental models
|
|
||||||
- Makes teaching more engaging
|
|
||||||
|
|
||||||
## This Week's Challenge
|
|
||||||
|
|
||||||
Draw your own version of quicksort partitioning. Share it and let's learn from each other's visualizations.
|
|
||||||
|
|
||||||
## The Art in Computer Science
|
|
||||||
|
|
||||||
Algorithms are beautiful. Drawing them reminds us that computer science is as much art as it is science.
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
---
|
|
||||||
title: "Generative Art with p5.js: Creating Beauty from Mathematics"
|
|
||||||
description: "Exploring the intersection of code and creativity through generative art experiments."
|
|
||||||
pubDate: "Feb 18 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1561070791-2526d30994b5?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Generative Art with p5.js: Creating Beauty from Mathematics
|
|
||||||
|
|
||||||
Code becomes canvas when mathematics meets creativity.
|
|
||||||
|
|
||||||
## Today's Creation: Perlin Noise Flows
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
for (let particle of particles) {
|
|
||||||
let angle = noise(particle.x * 0.01, particle.y * 0.01, frameCount * 0.001) * TWO_PI;
|
|
||||||
particle.velocity = p5.Vector.fromAngle(angle);
|
|
||||||
particle.update();
|
|
||||||
particle.draw();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## The Magic of Randomness
|
|
||||||
|
|
||||||
Controlled randomness creates organic patterns. Perlin noise gives us randomness with continuity - nature's own algorithm.
|
|
||||||
|
|
||||||
## Parameters as Paintbrushes
|
|
||||||
|
|
||||||
- Noise scale: Changes pattern density
|
|
||||||
- Particle count: Affects texture
|
|
||||||
- Color mapping: Sets the mood
|
|
||||||
|
|
||||||
## The Joy of Accidents
|
|
||||||
|
|
||||||
The best discoveries come from "mistakes" - a typo that creates unexpected beauty, a parameter pushed to extremes.
|
|
||||||
|
|
||||||
## Share Your Creations
|
|
||||||
|
|
||||||
Art is meant to be shared. Post your generative experiments and let's inspire each other.
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
---
|
|
||||||
title: "Algorithms in Verse: Bubble Sort Sonnet"
|
|
||||||
description: "Classic algorithms reimagined as poetry - where code meets iambic pentameter."
|
|
||||||
pubDate: "Feb 22 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1455390582262-044cdead277a?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Algorithms in Verse: Bubble Sort Sonnet
|
|
||||||
|
|
||||||
## Bubble Sort: A Sonnet
|
|
||||||
|
|
||||||
```
|
|
||||||
Compare adjacent elements in pairs,
|
|
||||||
If order's wrong, then swap them into place.
|
|
||||||
Through all the list this simple rule declares:
|
|
||||||
The largest bubbles up to find its space.
|
|
||||||
|
|
||||||
Again we start, but now one less to check,
|
|
||||||
The second largest finds its rightful home.
|
|
||||||
Each pass through makes the chaos less a wreck,
|
|
||||||
Until at last no elements must roam.
|
|
||||||
|
|
||||||
Though simple in its elegance and grace,
|
|
||||||
And easy for beginners to perceive,
|
|
||||||
In practice, it's too slow to win the race—
|
|
||||||
O(n²) we sadly must believe.
|
|
||||||
|
|
||||||
But beauty lies in simplicity's pure art,
|
|
||||||
The bubble sort still teaches at the start.
|
|
||||||
```
|
|
||||||
|
|
||||||
## The Challenge
|
|
||||||
|
|
||||||
Can you write Quicksort as a limerick? Or Binary Search as free verse?
|
|
||||||
|
|
||||||
## Why This Matters
|
|
||||||
|
|
||||||
Poetry forces us to find the essence of an algorithm. The constraint reveals understanding.
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
---
|
|
||||||
title: "Code Haikus: Programming in 5-7-5"
|
|
||||||
description: "Expressing programming concepts through the constrained beauty of haiku."
|
|
||||||
pubDate: "Jan 30 2024"
|
|
||||||
image: "https://images.unsplash.com/photo-1481627834876-b7833e8f5570?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Code Haikus: Programming in 5-7-5
|
|
||||||
|
|
||||||
The constraint of haiku forces clarity. Here are programming concepts distilled to their essence.
|
|
||||||
|
|
||||||
## On Recursion
|
|
||||||
|
|
||||||
```
|
|
||||||
Function calls itself
|
|
||||||
Smaller problems, same pattern
|
|
||||||
Base case stops the loop
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Debugging
|
|
||||||
|
|
||||||
```
|
|
||||||
Print statements bloom wild
|
|
||||||
Binary search through the code
|
|
||||||
Bug reveals itself
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Optimization
|
|
||||||
|
|
||||||
```
|
|
||||||
O(n squared) crawls
|
|
||||||
Refactor to n log n
|
|
||||||
Time complexity
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Git Merge Conflicts
|
|
||||||
|
|
||||||
```
|
|
||||||
<<<<<<< HEAD
|
|
||||||
Your changes, their changes clash
|
|
||||||
Resolution waits
|
|
||||||
```
|
|
||||||
|
|
||||||
## On Learning
|
|
||||||
|
|
||||||
```
|
|
||||||
Stack Overflow searched
|
|
||||||
Tutorial incomplete
|
|
||||||
Understanding dawns
|
|
||||||
```
|
|
||||||
|
|
||||||
## Your Turn
|
|
||||||
|
|
||||||
Write a haiku about your coding experience today. The constraint reveals truth.
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
---
|
|
||||||
title: "The 100 Prisoners Problem: A Beautiful Puzzle in Probability"
|
|
||||||
description: "An interactive exploration of one of the most counterintuitive puzzles in probability theory, where 100 prisoners can escape with over 30% chance using a clever strategy."
|
|
||||||
pubDate: "Oct 13 2025"
|
|
||||||
image: "https://images.unsplash.com/photo-1589829545856-d10d557cf95f?w=400&auto=format&fit=crop&q=60"
|
|
||||||
authorImage: "/avatar/avatar1.png"
|
|
||||||
authorName: "Neeldhara"
|
|
||||||
---
|
|
||||||
|
|
||||||
import PrisonerGameSimulator from '@/components/problems/PrisonerGameSimulator.tsx';
|
|
||||||
import ProbabilityChart from '@/components/problems/ProbabilityChart.tsx';
|
|
||||||
import PermutationExplorer from '@/components/problems/PermutationExplorer.tsx';
|
|
||||||
import StrategyComparison from '@/components/problems/StrategyComparison.tsx';
|
|
||||||
|
|
||||||
# The 100 Prisoners Problem
|
|
||||||
|
|
||||||
Imagine 100 prisoners, numbered 1 to 100, face an unusual challenge. In a room are 100 boxes, also numbered 1 to 100. Inside each box is a randomly assigned number from 1 to 100 (each number appearing exactly once). The prisoners must find their own number by opening boxes, but here's the catch: **each prisoner can open only 50 boxes**.
|
|
||||||
|
|
||||||
The prisoners can devise a strategy beforehand, but once the challenge begins, they cannot communicate. If **all 100 prisoners** find their number, everyone goes free. If even one prisoner fails, all remain imprisoned.
|
|
||||||
|
|
||||||
What's the best strategy? And what are the odds of success?
|
|
||||||
|
|
||||||
## Try It Yourself!
|
|
||||||
|
|
||||||
Before we dive into the mathematics, let's experience the problem firsthand. Below is a simulator where you can play the game yourself. Choose the number of prisoners (between 5 and 100), and then try to help each prisoner find their number by clicking on boxes.
|
|
||||||
|
|
||||||
<PrisonerGameSimulator client:only="react" />
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## The Naive Strategy
|
|
||||||
|
|
||||||
The most obvious approach is for each prisoner to simply open 50 random boxes. This seems reasonable, but the probability of success is dismal.
|
|
||||||
|
|
||||||
For any single prisoner, the probability of finding their number in 50 random boxes out of 100 is exactly 1/2. Since all 100 prisoners must succeed, and their outcomes are independent under random selection, the probability that everyone succeeds is:
|
|
||||||
|
|
||||||
$$P(\text\{success\}) = \left(\frac\{1\}\{2\}\right)^\{100\} \approx 7.9 \times 10^\{-31\}$$
|
|
||||||
|
|
||||||
That's essentially zero! You're more likely to win the lottery while being struck by lightning... multiple times.
|
|
||||||
|
|
||||||
### Naive Strategy: Probability vs Number of Prisoners
|
|
||||||
|
|
||||||
Watch how the probability of success plummets as we increase the number of prisoners:
|
|
||||||
|
|
||||||
<ProbabilityChart strategy="naive" client:only="react" />
|
|
||||||
|
|
||||||
As you can see, even with just 10 prisoners, the probability drops to about 0.1%. With 100 prisoners, it's practically impossible.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## The Clever Strategy: Following the Loops
|
|
||||||
|
|
||||||
Here's where mathematics reveals something beautiful. Instead of opening random boxes, each prisoner should follow a simple rule:
|
|
||||||
|
|
||||||
1. **Start by opening the box with your own number**
|
|
||||||
2. **Look at the number inside that box**
|
|
||||||
3. **Open the box with that number next**
|
|
||||||
4. **Continue following this chain**
|
|
||||||
|
|
||||||
Why does this work? The key insight involves understanding permutations and cycles.
|
|
||||||
|
|
||||||
### Understanding Cycles in Permutations
|
|
||||||
|
|
||||||
When we randomly assign 100 numbers to 100 boxes, we're creating a **permutation** of the numbers 1 through 100. Every permutation can be decomposed into **cycles**.
|
|
||||||
|
|
||||||
For example, if:
|
|
||||||
- Box 1 contains number 4
|
|
||||||
- Box 4 contains number 7
|
|
||||||
- Box 7 contains number 1
|
|
||||||
|
|
||||||
Then we have a cycle: 1 -> 4 -> 7 -> 1
|
|
||||||
|
|
||||||
Let's explore this with smaller numbers:
|
|
||||||
|
|
||||||
<PermutationExplorer client:only="react" />
|
|
||||||
|
|
||||||
The interactive explorer above lets you:
|
|
||||||
- Generate all permutations for small values of *n* (3, 4, or 5)
|
|
||||||
- See both standard notation and cycle notation
|
|
||||||
- Filter permutations that have at least one "long cycle" (longer than *n*/2)
|
|
||||||
- Understand why long cycles matter
|
|
||||||
|
|
||||||
### Why This Strategy Works
|
|
||||||
|
|
||||||
Here's the crucial insight: **A prisoner succeeds if and only if they are in a cycle of length ≤ 50**.
|
|
||||||
|
|
||||||
When prisoner k follows the loop strategy:
|
|
||||||
1. They start at box k
|
|
||||||
2. They follow a path through boxes determined by the permutation
|
|
||||||
3. This path forms a cycle that eventually leads back to box k
|
|
||||||
4. If this cycle has length ≤ 50, they'll find their number within 50 opens
|
|
||||||
|
|
||||||
The prisoners **all succeed** if and only if there is **no cycle longer than 50** in the permutation.
|
|
||||||
|
|
||||||
### Calculating the Probability
|
|
||||||
|
|
||||||
The probability that a random permutation of 100 elements has no cycle longer than 50 is:
|
|
||||||
|
|
||||||
$$P(\text\{success\}) = 1 - \sum_\{k=51\}^\{100\} \frac\{1\}\{k\}$$
|
|
||||||
|
|
||||||
Computing this sum:
|
|
||||||
|
|
||||||
$$P(\text\{success\}) = 1 - \left(\frac\{1\}\{51\} + \frac\{1\}\{52\} + \cdots + \frac\{1\}\{100\}\right) \approx 0.3118$$
|
|
||||||
|
|
||||||
That's over **31%**! This is astronomically better than the naive strategy's probability of essentially zero.
|
|
||||||
|
|
||||||
### Loop Strategy: Probability vs Number of Prisoners
|
|
||||||
|
|
||||||
<StrategyComparison client:only="react" />
|
|
||||||
|
|
||||||
## The Mathematics Behind It
|
|
||||||
|
|
||||||
### Why Does the Cycle Length Matter?
|
|
||||||
|
|
||||||
In a permutation of n elements, prisoner i will find their number within k tries using the loop strategy if and only if i belongs to a cycle of length at most k.
|
|
||||||
|
|
||||||
For n = 100 and k = 50:
|
|
||||||
- The probability that a specific prisoner is in a cycle of length > 50 is: Σ(j=51 to 100) of 1/100
|
|
||||||
- But we care about whether ANY prisoner is in such a cycle
|
|
||||||
- The probability that NO cycle has length > 50 is: 1 - Σ(j=51 to 100) of 1/j
|
|
||||||
|
|
||||||
### The Harmonic Series Connection
|
|
||||||
|
|
||||||
As *n* approaches infinity, if each prisoner can open *n*/2 boxes, the probability of success approaches:
|
|
||||||
|
|
||||||
The limit as n approaches infinity is: P_n = 1 - ln(2) ≈ 0.3069
|
|
||||||
|
|
||||||
This beautiful result connects combinatorics, probability, and analysis through the harmonic series!
|
|
||||||
|
|
||||||
### Optimality
|
|
||||||
|
|
||||||
Remarkably, this loop-following strategy is **optimal**. No other strategy can achieve a higher probability of success. The proof involves showing that the problem reduces to avoiding long cycles in a random permutation, and the loop strategy is the unique way to leverage this structure.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Why This Problem is Beautiful
|
|
||||||
|
|
||||||
The 100 prisoners problem is beloved by mathematicians because:
|
|
||||||
|
|
||||||
1. **Counterintuitive Result**: The fact that 31% >> 0% is shocking. A seemingly hopeless problem becomes tractable with the right insight.
|
|
||||||
|
|
||||||
2. **Deep Connection**: It connects permutation theory, probability, and the harmonic series in an elegant way.
|
|
||||||
|
|
||||||
3. **Collaborative Success**: Unlike independent trials, the prisoners' fates are intertwined through the structure of the permutation.
|
|
||||||
|
|
||||||
4. **Real-World Metaphor**: It illustrates how understanding underlying structure (cycles in permutations) can dramatically improve outcomes.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Variants and Extensions
|
|
||||||
|
|
||||||
### What if prisoners can open k < n/2 boxes?
|
|
||||||
|
|
||||||
As k decreases below n/2, the probability drops rapidly. The threshold at n/2 is special—it's where the strategy becomes remarkably effective.
|
|
||||||
|
|
||||||
### What about communication?
|
|
||||||
|
|
||||||
If prisoners could communicate between trials (but not during), they still can't improve the strategy. The beauty is that the strategy requires only coordination before any prisoner enters, not during.
|
|
||||||
|
|
||||||
### The Malicious Director
|
|
||||||
|
|
||||||
In an interesting variant, suppose the director can see the prisoners' strategy and arrange the boxes adversarially (not randomly). Can the director always force them to fail? Yes! The director can always create a single cycle of length n, guaranteeing failure.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
The 100 prisoners problem shows us that:
|
|
||||||
- Mathematical structure can be hidden in apparent randomness
|
|
||||||
- Clever strategies can overcome seemingly impossible odds
|
|
||||||
- Group coordination can be more powerful than independent action
|
|
||||||
- Beautiful mathematics often lies beneath simple-seeming puzzles
|
|
||||||
|
|
||||||
The next time you face a problem that seems impossible, remember: there might be a hidden structure waiting to be discovered, turning hopeless odds into reasonable ones.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Further Reading
|
|
||||||
|
|
||||||
- [Gál, A., & Miltersen, P. B. (2003). "The Cell Probe Complexity of Succinct Data Structures"](https://arxiv.org/abs/cs/0310027)
|
|
||||||
- [Curtin, E., & Warshauer, M. (2006). "The Locker Puzzle"](https://www.jstor.org/stable/27642173)
|
|
||||||
- [Wikipedia: 100 Prisoners Problem](https://en.wikipedia.org/wiki/100_prisoners_problem)
|
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 106 KiB |
|
After Width: | Height: | Size: 167 KiB |
|
After Width: | Height: | Size: 165 KiB |
|
After Width: | Height: | Size: 170 KiB |