Import Quarto posts and expand blog sync bridge
Some checks failed
Build / build (push) Has been cancelled

This commit is contained in:
Neeldhara Misra 2026-06-20 04:01:13 +01:00
parent 4ddaba7c7d
commit e7227844c7
406 changed files with 7943 additions and 7637 deletions

View file

@ -16,8 +16,47 @@ const BlogPosts = ({
// Get the first post as the featured post
const featuredPost = posts[0];
const remainingPosts = posts.slice(1);
const slugFor = (post: any) => post.id.replace(/\/index$/, "");
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 (
<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="lg:w-1/2">
<div className="p-2 lg:p-4">
<img
src={featuredPost.data.image}
alt={featuredPost.data.title}
className="aspect-video w-full rounded-lg object-cover transition-transform group-hover:scale-[1.02]"
/>
<PostVisual post={featuredPost} featured />
</div>
</div>
<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)}
>
<div className="p-2">
<img
src={post.data.image}
alt={post.data.title}
className="aspect-video w-full rounded-lg object-cover transition-transform group-hover:scale-[1.01]"
/>
<PostVisual post={post} />
</div>
<div className="px-4 pb-5 pt-2">
<h2 className="mb-2 text-xl font-semibold group-hover:underline">

View file

@ -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
![Red-Black Tree Rotation](sketch-placeholder)
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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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)

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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!

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

View file

@ -0,0 +1,328 @@
---
title: "13 Sheep"
description: "13 Sheep happens to be a cute roll-and-write game designed by Moritz Dressler that involves protecting a bunch of sheep on a grid by placing small fences that have pre-defined s..."
pubDate: "2023-03-26"
authorName: "Neeldhara"
sourceCategories: ["games", "exposition"]
sourcePath: "13sheep/index.qmd"
---
[13 Sheep](https://www.moritzdressler.de/en/13_Sheep) happens to be a cute roll-and-write game designed by Moritz Dressler that involves protecting a bunch of sheep on a grid by placing small fences that have pre-defined shapes.
![The Roll and Write Game](13sheep.png)
The initial position of a certain number --- typically 13, as the name suggests --- of sheep over a 7x7 grid is given. Some grid edges are not available because there happen to be bushes: so you cannot fence them. The bushes do not protect the sheep either, the wolf can slide under them.
Your goal is to enclose as many sheep as possible: the ones that are not fully protected by fences may, alas, be at considerable risk when the inevitable wolf attack happens.
There are three main constrianing factors in this game:
- The shape of the fences that you can draw are determined by the roll of a die;
- You cannot overwrite lines that are already drawn, you cannot also draw over bushes;
- You have ~11 chances to place your randomly gifted fence shapes.
You can find out more about the game [here](https://www.moritzdressler.de/en/13_Sheep), where you can generate board layouts to print and play as well.
I found this game a lot of fun to play, and I thought it would be lovely to be able to play it on a computer, where the user can decide how many rounds, sheep, and bushes they want to play with. Given also that chatGPT has been apparently [remarkably adept at coding games](https://twitter.com/ammaar/status/1637830530216390658?s=20), I figured I'd give it a shot^[Incidentally, I couldn't find a playable version like this one online. If you know of one please let me know and I'll be sure to add a pointer!].
I describe my conversation with chatGPT below, but if you just want to cut to the case and check the game out, you can find the playable version [here](https://13sheep.netlify.app/) and the source [here](https://github.com/neeldhara/13sheep/).
Here's what we finally built:
![The 13 Sheep UI](finalui.png)
And once you've finished playing you can share your accomplishment like so:
![One of my completed games... where we protect five sheep, can you figure out how many rounds?](download.png)
---
So, back to chatGPT. My first prompt was just a polite inquiry about willingness to participate in this exercise:
> **Note**
>
> We want to code a game called 13 Sheep using HTML, CSS, and Javascript. Ready?
And well, it immediately made [this](https://13-sheep-v3-GPT4-v30.neeldhara.repl.co), based on the prompt above: a game where you get to count to 13 sheep. Huh. Promising.
In my next few prompts, I steered it away from the default game. The first few steps just involved setting up the UI:
> **Note**
>
> Great start! Please make the main canvas a square and draw a 7 x 7 grid in it. I want all the corners of the cells to look like small + signs. Do not draw any grid borders yet.
> **Note**
>
> Nice, how can I make the grid background mediumseagreen?
> **Note**
>
> On load, I want 13 grid cells to be identified at random, and the image sheep.png to be placed at their centers, appropriately scaled to fit.
At this point I already had a nice-looking grid with 13 sheep on it (thanks to Flaticon for the cute sheep icon). The plus signs drawn on the boundary were oddly cropped out, so we fixed that next:
> **Note**
>
> Ok this looks great. Can you update the drawcross function so that crosses are also drawn on the grid boundary? And make the canvas a little bigger if needed so the entire cross is visible?
This didn't immediately work but some nudging fixed it:
> **Note**
>
> The crosses at the bottom are getting cut off and now the sheep are off center. Please fix?
That worked --- phew! Now we draw the bushes:
> **Note**
>
> Very nice. Can you randomly select 7 cells now and for each such cell make one of the cell boundaries colored indianred?
Next we get the dice roll UI up:
> **Note**
>
> Excellent. Now please add six divs below the canvas, centered, evenly spaced, and with a light grey circular background, with the text 1, 2, 3, 4, 5, and 6 written inside them. Note that the first div should have the text 1, the second should have 2, and so on. Make sure the divs have at least 10px spacing between them.
>
> Below these divs, please add a large button in the shape of a rounded rectangle, with the text "Roll Dice" written on it. The background color for this button should be indianred with a transparency of 0.42.
This actually worked out of the box, the next step was to make the roll dice functional:
> **Note**
>
> Super nice!
>
> Now can you make it so that when the user clicks on the button labeled "Roll Dice", we generate a number between 1 and 6 at random, and highlight the corresponding circular div by changing its background to Lavendar, while also resetting any previous highlight?
So far, so good. Now all that was left was to get the fences drawn depending on what dice was rolled out.
> **Tip**
>
>
> # Fence Shapes Based on Dice Rolls
>
> ![Dice Roll 1](1.png)
>
> ---
>
> ![Dice Roll 2](2.png)
>
> ---
>
> ![Dice Roll 3](3.png)
>
> ---
>
> ![Dice Roll 4](4.png)
>
> ---
>
> ![Dice Roll 5](5.png)
>
> ---
>
> ![Dice Roll 6](6.png)
This was perhaps the trickiest bit. My first attempt was this prompt here:
> **Note**
>
> Great! Now can you update it so that:
>
> if the outcome of the dice roll is a 1, the cursor should change to a shape that looks like a U, and nothing outside the grid should be clickable. If the user clicks on a grid cell, then the left, bottom, and right borders of the cell should change color and become a thick line colored in olivedrab. Once the user has clicked on a grid cell the cursor should change back to normal.
>
> if the outcome of the dice roll is a 2, the cursor should change to a shape that looks like a long line, and nothing outside the grid should be clickable, and none of the cells in the last column should be clickable either. If the user clicks on a grid cell, then the bottom border of the cell should change color and become a thick line colored in olivedrab, and the the bottom border of the horizontally adjacent cell should change color and become a thick line colored in olivedrab. Once the user has clicked on a grid cell the cursor should change back to normal.
My hope was that the change of cursor would be a good way for the player to register that they need to move on the grid now. At this point, I was not thinking about the different orientations of the fences, because I was not sure about how to incorporate that into the UI (my first thought was to have the fences rotate on subsequent clicks until the player clicks on a confirm button, but that seemed too messy). I also did not give all six scenarios in one go since --- from recent experience --- the interface dies out on longer requests. You can prod it to continue from where it left off, but it's typically messy.
In any case, we could not get the change of cursor to work. At this point, note that the code is also not tracking what borders are colored, so even as we got things to mildly work, we were often overwriting fences and bushes. So anyway, at some point I gave up and it was back to square one, but smaller steps. First, instead of a change of cursor, I just requested a canvas background color change to subtly communicate a change of game state:
> **Note**
>
> Once the dice roll button is clicked, can you change the background of the canvas to dodgerblue with transparency 0.42, and disable the roll dice button until the user clicks on a grid cell?
Then we added a round tracker:
> **Note**
>
> Add the following text just below the "Roll Dice" button: "Roll a dice now, 11 rounds left". Every time the user clicks on "Roll Dice", change the text to "Place a fence now." Once the user clicks on a grid cell, change the text back to "Roll a dice now, 11 rounds left", but decrease the number of rounds by one each time. Can you do this?
This took some back and forth to get working, since it was getting some details mixed up, but it was finally alright. I had to prompt more to take care of some edge cases and minor details, for instance:
> **Note**
>
> Anyway, can you make it so that when there are 0 rounds left, the text simply says "Game Over"?
>
> Also when the roll dice button is not active, can it have a grey background? Only when it is not active.
Now we are back to actually trying to get the fences to be drawn. With some nervousness, I go:
> **Note**
>
> Very nice. Now, if the dice roll is a 1 and the user clicks on a grid cell, can you do the following?
>
> 1. let us say that a cell is valid if the top, left, and bottom borders of the grid have no visible borders.
> 2. if the cell is valid, then make its top, left, and bottom borders colored olivedrab.
At this point the code generated starts tracking what borders are visible. I did have to prompt it explicitly to update the earlier function that generated the bushes to feed into the visibility states. However, this went off pretty smoothly overall. For quite some time the fences drawn when the user clicked a grid cell were not the ones I wanted, but after a few nudges it got it about right.
Now it occured to me that I could actually show the orientations after the dice is rolled and the user can select one of them, and we can draw the appropriate fence after this selection is made.
> **Note**
>
> Great. This works. Now below the instruction-text element, please add another div with ID "orientation-select" that begins with the text: "Pick an orientation". Below this, add four circular divs with a light grey backgorund with the content: "0", "90", "180", "270". This div should only be visible when the gamestate is "chooseFenceOrientation" or "placeFence".
>
> Once a dice is rolled, the game state should change to chooseFenceOrientation and the user should be allowed to click any of these four divs. Once the user clicks one of the four divs, highlight it with the color burntorange and change the gamestate to placeFence. Store the choice of which div the user clicked on in a variable called fenceorientation and change the game state to placeFence.
>
> Once the user clicks on a grid cell, clear the burntorange highlight and hide the "orientation-select" div, as it should not be visible any more.
Of course in the UI at the moment we just have these four numbers so it does not make a lot of sense to the player, so I whipped some images to show the user what fences would be drawn depending on what grid cell was clicked.
Now we come back to the fence drawing thing to account for the orientations as well:
> **Note**
>
> In the handleGridClick() function, we want to implement the following functionality.
>
> If the outcome is 1 and the orientation is 0, then do the following when the user clicks on a grid cell.
>
> 1. let us say that a cell is valid if the top, left, and bottom borders of the grid have no visible borders.
> 2. if the cell is valid, then make its top, left, and bottom borders colored olivedrab.
>
>
> If the outcome is 1 and the orientation is 90, then do the following when the user clicks on a grid cell.
>
> 1. let us say that a cell is valid if the right, left, and bottom borders of the grid have no visible borders.
> 2. if the cell is valid, then make its right, left, and bottom borders colored olivedrab.
>
>
> If the outcome is 1 and the orientation is 180, then do the following when the user clicks on a grid cell.
>
> 1. let us say that a cell is valid if the right, top, and bottom borders of the grid have no visible borders.
> 2. if the cell is valid, then make its right, top, and bottom borders colored olivedrab.
>
>
> If the outcome is 1 and the orientation is 270, then do the following when the user clicks on a grid cell.
>
> 1. let us say that a cell is valid if the right, left, and top borders of the grid have no visible borders.
> 2. if the cell is valid, then make its right, left, and top borders colored olivedrab.
>
> Please remember to use the drawBorder function from before as you work out these cases. Also remember to update the grid visibility values, for the two relevant cells per border drawn. Thanks.
Getting this going for all the 20 different cases was really the bulk of the back and forth. While it got the overall functionality right, there would be small and frequent bugs in the details. For instance, if a cell's top border is being fenced, then the cell above it should have its bottom border's visibility updated: it knows this, but frequently got combinations wrong, and so I did have to read the code generated carefully. I either fixed it manually when the bugs were minor, or went back to requesting corrections by explaining the issue when it was off by a whole lot.
You can see that some of the prompts are longer than the corresponding code :D
> **Note**
>
> Looks great! Lets continue with our updates. Please remember to account for all the cases when updating the grid visibility values.
>
> If the outcome is 4 and the orientation is 0, then do the following when the user clicks on a grid cell.
>
> 1. let us say that a cell is valid if its bottom and left borders are not visible and the horizontally adjacent cell (i.e, the cell to the right of it) also does not have a bottom border. if a cell is on the right-most column, it is automatically not valid.
> 2. if the cell is valid, then make its bottom and left borders colored olivedrab. Also make the bottom border of the horizontally adjacent cell colored olivedrab. Update the grid visibility values as appropriate.
>
> If the outcome is 4 and the orientation is 180, then do the following when the user clicks on a grid cell.
>
> 1. let us say that a cell is valid if its top border is not visible and the horizontally adjacent cell (i.e, the cell to the right of it) also does not have a top border and the horizontally adjacent cell (i.e, the cell to the right of it) also does not have a right border. if a cell is on the right-most column, it is automatically not valid.
> 2. if the cell is valid, then make its top border colored olivedrab. Also make the top border of the horizontally adjacent cell colored olivedrab. Also make the right border of the horizontally adjacent cell colored olivedrab. Update the grid visibility values as appropriate.
>
> If the outcome is 4 and the orientation is 90, then do the following when the user clicks on a grid cell.
>
> 1. let us say that a cell is valid if its top and left borders are not visible and the vertically adjacent cell (i.e, the cell below it) also does not have a left border. if a cell is on the right-most column, it is automatically not valid.
> 2. if the cell is valid, then make its top and left borders colored olivedrab. Also make the left border of the vertically adjacent cell colored olivedrab. Update the grid visibility values as appropriate.
>
> If the outcome is 4 and the orientation is 270, then do the following when the user clicks on a grid cell.
>
> 1. let us say that a cell is valid if its bottom and right borders are not visible and the vertically adjacent cell (i.e, the cell to the top of it) also does not have a right border. if a cell is on the right-most column, it is automatically not valid.
> 2. if the cell is valid, then make its bottom and right borders colored olivedrab. Also make the right border of the vertically adjacent cell colored olivedrab. Update the grid visibility values as appropriate.
Maybe it'll soon be possible to just upload a picture of the game instruction booklet and let chatGPT do the rest of the heavy lifting. Until then, this was the best I could think of: maybe there's a shorter way? I did try using generic shape descriptions, but no luck on those.
Now the basic game was done, and there were three main features I'd have really liked to add at this point:
- Allow the user undo the previous fence placement.
- Count the number of protected sheep at the end.
- Make a version of this game where instead of rolling a dice, we let the user pick the fences they want: this can be useful for a multiplayer setting where we want the random choices to be the same for all players: so one player can roll the dice and the others can follow along.
I did try some of this: it's impressive that chatGPT gets the main ideas right the first two requirements (the use of an action stack for implementing undo, and recognizing that we need some kind of flood fill algorithm for the score). However, all the implementations ended up being somewhat buggy and after some wrestling I decided to push these extras to the roadmap. The deterministic version of the game should not be hard to make, even manually at this point, so I hope to come back to it soon.
After this I mainly asked for chatGPT to let the user customize the parameters of the game:
> **Note**
>
> Can you make it so that when the page loads we ask the user (via an alert) for a number between 7 and 32 and set the number of rounds to the number specified by the user?
It got this immediately right, and I wanted some styling:
> **Note**
>
> Can you add some css styling so that this prompt looks nice?
and it's response was:
> **Tip**
>
> Unfortunately, you cannot directly style the default JavaScript prompt function. Instead, you can create a custom modal using HTML, CSS, and JavaScript to achieve a more visually appealing and flexible solution.
>
> Here's an example of how you can create a custom modal to ask for the number of rounds:
>
> ...
Good to know! The modals worked out of the box, and it was easy to extend them so they asked for the number of sheep and bushes as well. The last thing I wanted to add was a sharing feature:
> **Note**
>
> Can you add code so that the user can share a screenshot of just the canvas once the game is over? So once the game is over, I want to show a link called "Share My Game!" The screenshot and options to share on social media should show up in a modal when the user clicks this link.
Now this it did remarkably well, except that when it tried to pass the entire image as a URL parameter, that didn't work out. When I conveyed this, the response was:
> **Tip**
>
> I apologize for the inconvenience. The reason for this issue is that sharing an image directly using a URL is not possible due to security reasons. To share your game image on social media platforms like Facebook and Twitter, you'll need to use their respective APIs.
>
> Here's a modified approach for sharing the image on Facebook and Twitter. You'll need to create Facebook and Twitter developer accounts and register your app to get the API keys.
Whoa... so ok, I don't have developer accounts and I was not going to follow through, but this was definitely interesting!
I did interleave responses from chatGPT with help from Ghostwriter, which is the intelligence built into repl.it out of the box. Ghostwriter's responses were usually not as sophisticated on comparable prompts, but on a couple of occassions chatGPT was completely lost on why something wasn't working, but Ghostwriter would figure it out when asked pointed questions about an error. There seems to be some potential that they will be a good team --- possibly also alongside Copilot, which I did not use at all here.
> **Caution**
>
> # The Final Product
> Anyway, long story short, I cleaned up a little further on my own, and finally: the game is [here](https://13sheep.netlify.app), the source is [here](https://github.com/neeldhara/13sheep/).
My experience with chatGPT and Ghostwriter as pair programmers was --- I daresay --- rewarding overall. When I first thought of doing this, perhaps partially [intoxicated by all the hype](https://twitter.com/ShriramKMurthi/status/1637058628187312134), I figured I could get this done in a couple of hours at the most: I estimated twenty minutes for functional code, and about a 100 minutes for making up my mind about colors and fonts. This was a vast underestimate: I think I spent close to a good twelve hours (including a couple of early throw-away prototypes, and all the failed attempts on the flood filling) altogether^[At least I'm [not the only one](https://twitter.com/ammaar/status/1637830530216390658?s=20) spending hours in the plural.]... at some point it did get a little addictive, and perhaps there was a sunk cost argument for not letting go halfway through.
As someone who does not know javascript, I found this to be a part empowering, part learning, and mostly amusing experience. It felt like picking up a natural language by directly talking to mostly fluent speakers who made random and small mistakes. My overall sentiments were very similar to the process described [in this thread](https://twitter.com/ammaar/status/1637592014446551040), where [Ammaar Reshi](https://twitter.com/ammaar) uses GPT-4, Replit, MidJourney, and Claude to create a 3D space runner from scratch with ZERO [sic] knowledge of Javascript or 3D game programming: you should check this out if you are interested in a much more sophisticated demonstration for deploying AI tools to make games!
In its current form I think this also has interesting implications for how programming is taught: I hesitate to elaborate any further on this given how likely it is that any commentary will be obsolete by tomorrow. But in the very near term, I can imagine that reading, analyzing, and even learning alongside chatGPT could make for interesting experiences in the classroom.

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

View file

@ -0,0 +1,540 @@
---
title: "Building Interactives"
description: "Background Interactions and visualizations have been useful for explaining concepts, although they are known to potentially mislead or confuse as often as they have been thought..."
pubDate: "2023-07-30"
authorName: "Neeldhara"
sourceCategories: ["exposition"]
sourcePath: "building-interactives/index.qmd"
---
## Background
Interactions and visualizations have been useful for explaining
concepts, although they are known to potentially mislead or confuse as
often as they have been thought of as tools that help clarify concepts.
[VisuAlgo](https://visualgo.net/en) is a very successful[^1] example of
interactive learning in CS education at an undergraduate level, which
brings the algorithms that one would typically encounter in an
introductory algorithms course to life: users can often provide their
own input, and the interface does the rest. On the bottom-right corner
one can typically see an implementation of the algorithm in code, which
is "run through" as elements get manipulated on a "main stage".
Other examples of deeply interactive experiences include:
1. [Brilliant](https://brilliant.org/home/)
2. [Mathigon](https://mathigon.org/)
3. [Seeing Theory](https://seeing-theory.brown.edu/)
4. [The Wisdom and/or Madness of the Crowds](https://ncase.me/crowds/)
5. [The Evolution of Trust](https://ncase.me/trust)
6. [Parable of the Polygons](https://ncase.me/polygons/)
7. [To Build a Better Ballot](https://ncase.me/ballot/)
8. [Visualizing Quaternions](https://eater.net/quaternions)
9. [Mechanical Watch](https://ciechanow.ski/mechanical-watch/)
...to name a few. These combine interactive workouts interleaved with text,
and usually encourage active participation from the reader. However,
while such tools can be invaluable, they are often tedious and
time-consuming to build, not to mention that they require fairly
specialized expertise. For instance, Ben Eater, the creator of the
quaternions visualization, says about the process of builiding the
visualization[^2]:
> *Since there wasn't really anything like this yet, we built it all
> ourselves from a variety of existing web tools: WebGL (using threejs
> plus some custom shaders) for 3d stuff, raw canvas for the 2d stuff,
> howlerjs for handling the audio playback, and lots of React for the UI
> and to glue it all together. It's very much a bespoke app. In the
> future, I hope we'll build more of these and as we do so, the tech
> will evolve to something more easily generalized.*
The availability of tools like chatGPT and its ilk, powered by large
language models, have been the subject of much heated debate, especially
in the context of their role in education. They have been viewed
(e.g, by [plagiairsm detectors](https://www.turnitin.com/blog/sneak-preview-of-turnitins-ai-writing-and-chatgpt-detection-capability),
where [challenges about false positives](https://www.k12dive.com/news/turnitin-false-positives-AI-detector/652221/)
persist)
as tools that can help students cheat, although there is also
much work arguing for their use in helping students learn.
Here, I want to focus on something perhaps more mundane, but
a theme that has been one of my favorite chatGPT use cases over the last few months:
it's utility in helping create materials
that are too tedious to bring to life otherwise.
It turns out that I often envision neat little interactive experiences
when I am thinking about how to describe something: it could just be
a thing that lets folks play with examples to build out some intuition
or it could be something that helps bring out a specific element of an
argument or an idea. However, the barrier of entry
to creating those experiences myself is _just a little out of reach_,
enough for me to not do it. But with the kind of help I have had from
chatGPT, I feel invested enough to mess around.
For a lot of standard topics, there are plenty of visualizations and
interactive experiences already available: so one might wonder if this
is worth it. I do think that leveraging existing content that's already
been done well is important, but: (a) not everything is already done, and
(b) experiences created from scratch allow for instructors to incorporate
their own variations on the textbook premise, and would also offer the
flexibility to be transformed into assessments --- both of these goals
are often hard to meet with off-the-shelf demonstrations.
Note: Although a lot of this discussion is about how instructors can
leverage chatGPT as a tool to efficiently create visualizations and
interactive experiences for their learners, none of the text in the
blog itself is generated with AI 😀 To make this distinction clear, all
text quoted verbatim from either books or chatGPT's output will be
placed in grey boxes. Prompts to chatGPT are not AI-generated either and
are shown in boxes with a green background.
## For Instructors
I'll describe two examples of visualizations of textbook topics that
may not be widely available otherwise. The entire chatlogs for the
specific demonstrations can be found as PDFs at the following links:
1. [Subtraction Game](chatGPT-subtraction-chatlog.pdf)
2. [File Storage 1](tape-drag-drop.pdf)
3. [File Storage 2](draggable-tape.pdf)
(The May 12 release of chatGPT was in use.)
### Exhibit A. The Subtraction Game
The subtraction game is the following.
> **Note**
>
> # The Game of Subtraction
> Subtraction is a game played on a heap of tokens. Each
> turn, the current player can remove either 1, 2, or 3 tokens from the
> pile, provided enough tokens exist. When the pile is empty there are no
> available moves. In this text, we will use a fancy number script to
> denote a subtraction position, e.g. S for a subtraction game with five
> tokens. Sample game: $$6 \rightarrow 5 \rightarrow 3 \rightarrow 0$$
> Starting from a pile of 6 , the first player takes one, then the second
> player takes two, then the first player takes all three to win the game.
>
> _--- from [Playing with Discrete Math](http://kyleburke.info/PlayingWithDiscreteMath.pdf)._
The text goes on to encourage the reader to play the game to develop a
feel for it, and uses the game as a running example to develop various
concepts in combinatorial game theory, including strategies, positions,
game trees, and so on.
The game of Subtraction can doubtless be played in a
low-tech environment using a whiteboard, pen and paper, or an actual
heap of tokens. However, an instructor may want to make an interactive
version of the game available as a part of instructional material such
as lecture notes. At this point, an instructor may look for an existing
implementations, although in this particular example this may turn out
to be a bit of a challenge: the internet is rife with so-called
"subtraction" games, most of which have nothing to do with the game at
hand. Besides, a custom implementation would provide a starting point
for the development of related concepts, customized quizzes, and so on.
As discussed earlier, creating a playable version of
Subtraction from scratch is arguably not a difficult
exercise, but for most people it would be time-consuming to the point
where the cost may outweigh the benefits. However, with a tool like
chatGPT at hand, the process becomes substantially easier.
> **Tip**
>
> # chatGPT Prompt
> We are going to code a simple HTML/JS/CSS game.
>
> Please create a game arena that is a 420 x 420 canvas with rounded corners. The background outside the canvas should be lightseagreen.
>
> All the elements below should be centered within the canvas.
>
> Inside the canvas, close to the top, draw a box with a random number between 15 and 50.
>
> Just below this box, draw three boxes labeled 1, 2, and 3.
>
> Just below these three boxes, display the text: "Latas turn to move." Let us call this string whoseTurn.
>
> Just below this text, add a link that says "Instructions". This should bring up a modal with the text "SUBTRACTION is a game played on a heap of tokens. Each turn, the current player can remove either 1, 2, or 3 tokens from the pile, provided enough tokens exist. When the pile is empty there are no available moves. The player with no valid moves left loses.".
>
> Finally, when the user clicks on either 1, 2, or 3, the number in the central box should reduce by 1, 2, or 3 respectively. If the subtraction results in a negative number, disregard the click and alert the user that "Only moves resulting in a positive result remaining."
>
> When a button is clicked, if whoseTurn is "Latas turn to move", then it should change to "Rajs turn to move", and vice versa.
>
> When the number hits 0, if whoseTurn is "Latas turn to move", then update whoseTurn to "Game over, Lata won", and "Game over, Raj won" otherwise. At this point, none of the buttons should be clickable.
The output of chatGPT on this prompt, with some minor modifications in
styling, leads to an interface that looks as shown below:
![An interactive version of Subtraction.](image001.png)
A natural extension to the game of subtraction is go beyond the numbers
1,2, and 3. One might then use a follow up prompt such as the one below.
> **Tip**
>
> # chatGPT Prompt
> Can you make it so that instead of 1, 2, 3, the buttons display three distinct random numbers between 1 and 9 (inclusive), and the rules are the same?
In this process we realize that the players may run out of moves even
before the number in question hits zero. An easy way to mitigate this is
to ensure that one of the numbers is always one, while the others are
randomly chosen. The output of chatGPT may have minor issues: for
instance, the documentation in the instructions modal would possibly not
adapted to the new set of numbers, the buttons may display the numbers
in non-ascending order, and so on. All of these "quirks" are easily
fixed with follow up prompts, and a working demonstration of the final
implementation can be found [here](https://subtraction.netlify.app/).
### Exhibit B. Storing Files on Tape
The problem of optimally storing files on a tape is a classic example of
an optimization problem that admits a greedy algorithm: the intuitive
approach to the solution turns out to be the correct one.
We reproduce the problem statement as given in [Algorithms](http://jeffe.cs.illinois.edu/teaching/algorithms/)
by [Jeff Erickson](http://jeffe.cs.illinois.edu/).
> **Note**
>
> # The Optimal File Storage Problem
> Suppose we have a set of $n$ files that we want to store on magnetic
> tape. ${ }^1$ In the future, users will want to read those files from
> the tape. Reading a file from tape isn't like reading a file from disk;
> first we have to fast-forward past all the other files, and that takes a
> significant amount of time. Let $L[1..n]$ be an array listing the
> lengths of each file; specifically, file $i$ has length $L[i]$. If the
> files are stored in order from 1 to $n$, then the cost of accessing the
> $k$ th file is $$\operatorname{cost}(k)=\sum_{i=1}^k L[i]$$
>
> The cost reflects the fact that before we read file $k$ we must first
> scan past all the earlier files on the tape. If we assume for the moment
> that each file is equally likely to be accessed, then the expected cost
> of searching for a random file is
> $$\mathrm{E}[\operatorname{cost}]=\sum_{k=1}^n \frac{\operatorname{cost}(k)}{n}=\frac{1}{n} \sum_{k=1}^n \sum_{i=1}^k L[i] .$$
> If we change the order of the files on the tape, we change the cost of
> accessing the files; some files become more expensive to read, but
> others become cheaper. Different file orders are likely to result in
> different expected costs. Specifically, let $\pi(i)$ denote the index of
> the file stored at position $i$ on the tape. Then the expected cost of
> the permutation $\pi$ is
> $$\mathrm{E}[\operatorname{cost}(\pi)]=\frac{1}{n} \sum_{k=1}^n \sum_{i=1}^k L[\pi(i)] .$$
> Which order should we use if we want this expected cost to be as small
> as possible? The answer seems intuitively clear: **Sort the files by
> increasing length.** But intuition is a tricky beast. **The only way to
> be sure that this order works is to** take off and nuke the entire site
> from-orbit **actually prove that it works!**
>
> _--- From [Algorithms](http://jeffe.cs.illinois.edu/teaching/algorithms/)._
Now the key to appreciating the proof of the greedy algorithm here is to
see that if we violate the "natural order" then we pay more in expected
cost. While the calculation is straightforward, an instructor may find
that it makes sense to motivate the main idea by allowing the learners
to play around with some examples.
There are two approaches to visualizing this problem. In both cases, the
stage consists of a tape represented as a long horizontal rectangle, and
the files are represented as rectangles whose height matches the height
of the tape, and whose lengths are proportional to their sizes. The
expected cost of access of whatever is on the tape is displayed at all
times, along with the optimal cost possible.
- A predefined set of files are given and are initially placed outside
the tape. The user can position them on the tape by, for example,
dragging and dropping them on the tape, or double clicking them: in
either case, the chosen file is appended to the end of the tape. We
may allow the user to reorder the files on the tape by drag and drop
actions or remove them off the tape entirely. The expected cost is
dynamically calculated and displayed.
- A set of files, say all equal in size, are already on the tape. The
learner can then drag the boundaries to change the file lengths, and
the change in costs update dynamically.
#### The First Approach
To create the first visualization, we started with the following prompt.
> **Tip**
>
> # chatGPT Prompt
> I want to help students understand the problem of "storing files on a tape". I am seeking your help in creating the following interface via HTML, JS, and CSS.
> What I want is for the user to be able to drag and drop several rectangular blocks (which I will refer to as pieces henceforth), whose total length is a fixed number of units, on to something that looks like a tape.
>
> So the interface should have a thin rectangular strip (which I will refer to as a tape henceforth) with a grey background at the center, and a collection of draggable pieces placed below it (none overlapping). When a piece is dropped on the tape, it should snap and align to the left without overlapping any of the strips that are already there. When a piece is dragged out of the tape, it should disappear from the tape and the pieces to the right of it should move leftward until the gap is filled.
>
> Please make the total length of the tape 420px wide, and the lengths of the pieces should be either 20px, 30px, 40px, or 50px wide; and they should be made of different colors from a neutral palette. Note that the piece lengths should be generated randomly from this set, they should add up to 420px.
>
> Let N be the number of pieces on the tape at any given point of time. There should be a display which shows the sum of the following quantities (and this should update as pieces are added or dropped on the top): the length of the first (i.e, leftmost) piece multiplied by N, the length of the second piece multiplied by (N-1), and so on, until the length of the last piece, multiplied by 1.
The first few outcomes on this and subsequent prompts had several
issues:
- the boxes were not stacked horizontally;
- the drag and drop behaviors were unpredictable;
- the pieces had spacing between them when pushed on the tape.
However, all of this was eventually fixed by describing the inaccuracies
in natural language. We also added some functionality allowing the
learner to see if their attempt was optimal:
> **Tip**
>
> # chatGPT Prompt
> Below average, can we add the following text: "Target: " followed by the sum of the following numbers, where X is the total number of pieces:
>
> the size of the smallest piece multiplied by X
> the size of the second smallest piece multiplied by X-1
> and so on up to
> the size of the second largest piece multiplied by 2
> the size of the largest piece multiplied by 1
>
> Below the target, display the text "Keep going until all pieces are on the tape", and if the tape has all the pieces but the average is not equal to the target, change the message to "Nice try, but you can do better!" and if the tape has all the pieces and the average is equal to the target, change the message to "Mission Accomplished!".
Eventually, we obtain an interface that looks as shown in with some
minor styling and updates in the desired widths.
Notice that one of the things that chatGPT had to do was randomly
generate a set of pieces from a given set of widths that added up the
exact width of the tape (as per our prompt). It did this using the
following loop:
> **Note**
>
> # chatGPT Output
> // Create pieces
> let totalWidth = 0;
> while(totalWidth < 420) {
>
> const size =
> sizes[Math.floor(Math.random()
> * sizes.length)];
>
> if(totalWidth + size <= 420) {
> totalWidth += size;
> // Code to create the pieces
> }
> }
Evidently, if the sizes array does not have an appropriate set of sizes,
this can loop forever. It turns out that chatGPT did not recognize this
issue on its own, and it is typical of the sort of bug that the user
would have to watch out for, either at the time of formulating
specifications or while working through the output.
You can play around with the implementation that I finally ended up with [here](https://filestorage1.netlify.app/).
#### The Second Approach {#the-second-approach .unnumbered}
For the second approach, we start off with the following prompt.[^3]
> **Tip**
>
> # chatGPT Prompt
> Please give me separate css, js, and html files for the following demonstration
>
> What I want initially is as follows
>
> - centered on the screen there is a 420px x 50px horizontal slab
>
> - there are three draggable dividers shown as black dotted lines inside the slab that divide the region equally into 4 parts of width 105 eac
>
> - the regions should initially display the number 105.
>
> If a divider is dragged, it changes the width of at most two regions that it is involved in. These regions should update their width. If any region becomes smaller than 20 px on drag, then any further drag should not be possible
>
> Then I want a text below the slab which says cost, followed by the sum of the following numbers
>
> - the width of the leftmost region * 4
>
> - the width of the region next to the leftmost region * 3
>
> - the width of the region to the left of the rightmost region * 2
>
> - the width of the rightmost region * 1
>
> divided by 4. This number should be dynamically updated as the regions change
>
> Below cost, compute the following quantity and display it, prepended with the text "Optimal Cost"
>
> - the width of the smallest region * 4
>
> - the width of the second-smallest region * 3
>
> - the width of the second-largest region * 2
>
> - the width of the largest region * 1
>
> divided by 4.
>
For visual clarity we also follow up with the following suggestion.
> **Tip**
>
> # chatGPT Prompt
> Can the background color be Mediumseagreen but with opacity proportional
> to the width (i.e, more opaque for wider regions and more transparent
> for smaller ones)?
<figure id="fig:003">
<figure>
<img src="image003-a.png" />
<figcaption>The initial configuration</figcaption>
</figure>
<figure>
<img src="image003-b.png" />
<figcaption>An example where the current cost is worse than the optimal
cost.</figcaption>
</figure>
<figure>
<img src="image003-c.png" />
<figcaption>An example where the current and optimal costs are the
same.</figcaption>
</figure>
</figure>
The current version of this implementation is [here](https://filestorage2.netlify.app/),
and it's still a little quirky in terms of the first couple of times you drag the slider,
but stabilizes soon after. I hope to fix this... eventually :)
## For Students
Sal Khan makes a compelling case for the use of AI to help with the
learning process [in a recent TED talk](https://www.ted.com/talks/sal_khan_how_ai_could_save_not_destroy_education?language=en).
In a computer programming
exercise available on Khan Academy, a student needs to modify an
existing snippet of code to "make two clouds drift apart". The
student attempts this by writing "leftX--", but notices that this only
affects the left cloud, and not the right one. The student then pulls up
Khanmigo to inquire why the attempt did not work out, and Khanmigo
recognized enough of the surrounding context to make a meaningful
suggestion.
![A typical exercise on Khan Academy, with the exercise material and the
student's attempt on the left; and the rendering on the right. The goal
is to modify the code so that the clouds drift
apart.](image005.png)
![Khanmigo trying to analyze the issue.](image004.png)
While [Khanmigo](https://www.khanacademy.org/khan-labs) is still under
development a the time of this writing,
this example already demonstrates the potential of a collaboration
between a well-intentioned learner and a well-intentioned AI. Just as
learning a language on a platform like Duolingo is an enhanced
experience when we attempt talking with native speakers, so is
programming language learning potentially enhanced by such transactions
between the learner and someone who has the advantage of expertise.
As a sample counterpoint to this thread of thought, in a [CACM blog](https://cacm.acm.org/blogs/blog-cacm/273577-ai-does-not-help-programmers/fulltext#comments),
Bertrand Meyer argues that chatGPT may not, in fact,
be helpful for (expert) programmers:
> Here is my experience so far. As a programmer, I know where to go to solve a problem. But I am fallible; I would love to have an assistant who keeps me in check, alerting me to pitfalls and correcting me when I err. A effective pair-programmer. But that is not what I get. Instead, I have the equivalent of a cocky graduate student, smart and widely read, also polite and quick to apologize, but thoroughly, invariably, sloppy and unreliable. I have little use for such supposed help.
Check out the blog to see where this is coming from: you can
eavesdrop on Meyer's conversation with chatGPT and decide for yourself :)
## What's Next?
For the interactives discussed here, there are several ways of extending
what has been cobbled together. For instance, for
the visualization of Subtraction, a natural next step is
to create an interactive process that allows the learner to visualize
the game tree, at least for small versions of the game.
For the visualization of the problem of storing files on a tape, there
are several possible enhancements:
(a) Show the cost breakdown more
explicitly in terms of the formula, with a color coding that relates the
numeric file sizes shown in the formula with the colors of the boxes on
the tape.
(b) Add an option to generate the optimal ordering in the
first approach.
(c) Gamify the problem where two users take turns to
position files on the tape, and one wants to minimize the expected cost,
while the other wants to maximize it: in particular, we establish a
target cost, and the first player wins if the final cost is smaller than
the target, the second player wins if the final cost is higher than the
target, and the game is a draw otherwise.
(d) Generalize the
visualization to the situation where we not only have files, but also
associated frequencies of access.
These were just a couple of examples to suggest that creating fun
and customized experiences for your classes may now just be a little
easier than before, and hopefully this encourages more of us to experiment
with the ideas we have.
On the theme of learners using chatGPT: there are several demonstrations that LLMs do well on the kind of
programming tasks that show up in introductory coursework; for instance
[here is a preprint](https://arxiv.org/abs/2210.15157) suggesting as much:
> We [...] evaluate the performance of Copilot on a publicly available dataset of 166 programming problems. We find that it successfully solves around half of these problems on its very first attempt, and that it solves 60% of the remaining problems using only natural language changes to the problem description. We argue that this type of prompt engineering, which we believe will become a standard interaction between human and Copilot when it initially fails, is a potentially useful learning activity that promotes computational thinking skills, and is likely to change the nature of code writing skill development.
Such illustrations simply reinforce my sense that class materials and exercises
should be adapted so that LLMs can be leveraged by students to
accelerate their learning processes, making the "cheat use case" implausible
almost by defintion. I realize this is
easier said than done, but it's already interesting to see all the ideas
that have come up to this effect.
Check out this [very cool thread](https://twitter.com/ShriramKMurthi/status/1683301415005855744)
on Porpoise, a tool meant to help learners articulate specs for a
given task: the first part of the exercise is reverse engineer
what the task in question based on some sample I/O that is given,
and the second part is to write it up so that chatGPT can produce
code to match the sample I/O + some hidden tests that extrapolate on
the samples.
Apart from writing code, chatGPT/Copilot/Ghostwriter can read code too,
and often provide [surprisingly relevant
insights](https://www.zdnet.com/article/okay-so-chatgpt-just-debugged-my-code-for-real/)
on why a piece of code does not work as expected.
One context in which I would like to leverage this is to look at failed
submissions on competitive coding platforms. Perhaps with some background
from the editorials, chatGPT and its ilk can provide meaningful
explanations of why something does not work, and if this turns out
to be reliable, then it potentially removes some of the frustration
from the learning process without short-circuiting it in bad ways.
I am aware that the release of chatGPT and friends has unleashed a
flurry of work in the teaching/learning space, so do let me know in the
comments if you have pointers to fun projects and ideas!
[^1]: The success of Visualgo is witnessed by its wide usage and several
anecdotal reports of positive feedback.
[^2]: At the time this writing, this comment is from five years ago, and
to the best of our knowledge, not much has moved along on the state
of the art in terms of tools for authors of interactive experiences.
[^3]: The conversation found in the supplementary material differs
slightly from what is shown below; we have consolidated some of the
prompts in the interest of brevity.

View file

@ -0,0 +1,46 @@
---
title: "Course Plan Generator"
description: "If you are a. teaching a course at IIT Gandhinagar next term (Jan-Apr 2024), b. working on your course plan, and c. need a list of dates on which you have classes, then you can..."
pubDate: "2023-12-25"
authorName: "Neeldhara"
sourceCategories: ["workflows"]
sourcePath: "course-plan/2024-fall/index.qmd"
---
If you are
a. teaching a course at IIT Gandhinagar next term (Jan-Apr 2024),
b. working on your course plan, and
c. need a list of dates on which you have classes,
then you can use the generator below to get a list, by checking your teaching days.
Dates during the mid-sem exam (Feb 19 24, 2024) and the mid-sem recess (Mar 23 - 31, 2024) are excluded. [Holidays](https://iitgn.ac.in/holiday/2024) are excluded too, but _restricted holidays are not_. If you need to view the holidays, you can indicate as much via the checkbox below.
For those outside IITGN: a standalone version is [here](https://classplan.neeldhara.repl.co/) and the source is [here](https://github.com/neeldhara/ClassPlan/tree/main), in case you'd like to adapt this to your own context.
<div>
<form>
<input type="checkbox" id="monday" name="day">&nbsp;Monday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="tuesday" name="day">&nbsp;Tuesday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="wednesday" name="day">&nbsp;Wednesday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="thursday" name="day">&nbsp;Thursday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="friday" name="day">&nbsp;Friday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="saturday" name="day">&nbsp; Saturday
</form></div>
<br>
<label><input type="checkbox" id="includeHolidays" name="includeHolidays"> Include Holidays</label>
<br>
<label><input type="checkbox" id="indicateRestrictedHolidays"> Indicate Restricted Holidays</label>
<br>
<br>
<button class="custom-button" onclick="generateDates()">
Generate Dates for Course Plan
</button>
<br><br>
<div class="sourceCode">
<pre class="sourceCode plaintext code-with-copy">
<code class="sourceCode plaintext" id="datesList">
</code>
</pre>
</div>

View file

@ -0,0 +1,94 @@
function isDateInRanges(date, ranges) {
return ranges.some(range => date >= range.start && date <= range.end);
}
function generateDates() {
const startDate = new Date(2024, 7, 2);
const endDate = new Date(2024, 10, 22);
const excludedRanges = [
{start: new Date(2024, 8, 27), end: new Date(2024, 9, 4)},
{start: new Date(2024, 9, 5), end: new Date(2024, 9, 13)}
];
const holidays = [
{date: new Date(2024, 7, 15), label: 'HOLIDAY: Independence Day'},
{date: new Date(2024, 7, 26), label: 'HOLIDAY: Janmashtami (Vaishnavi)'},
{date: new Date(2024, 8, 16), label: 'HOLIDAY: Milad-un-Nabi or Id-e-Milad'},
{date: new Date(2024, 9, 2), label: 'HOLIDAY: Mahatma Gandhi Birthday'},
{date: new Date(2024, 9, 12), label: 'HOLIDAY: Dussehra (Vijay Dashmi)'},
{date: new Date(2024, 9, 31), label: 'HOLIDAY: Diwali (Deepavali)'},
{date: new Date(2024, 10, 15), label: 'HOLIDAY: Guru Nanaks Birthday'}
];
const restrictedHolidays = [
{ date: new Date(2024,0,1), label: 'RH: New Years Day'},
{ date: new Date(2024,0,13), label: 'RH: Lohri'},
{ date: new Date(2024,0,14), label: 'RH: Makar Sankranti'},
{ date: new Date(2024,0,15), label: 'RH: Pongal'},
{ date: new Date(2024,0,17), label: 'RH: Guru Gobind Singh Birthday'},
{ date: new Date(2024,0,25), label: 'RH: Hazarat Ali Birthday'},
{ date: new Date(2024,1,14), label: 'RH: Basant Panchami'},
{ date: new Date(2024,1,19), label: 'RH: Shivaji Jayanti'},
{ date: new Date(2024,1,24), label: 'RH: Guru Ravi Das Birthday'},
{ date: new Date(2024,2,6), label: 'RH: Birthday of Swami Dayananda Saraswati'},
{ date: new Date(2024,2,24), label: 'RH: Holika Dahan'},
{ date: new Date(2024,2,25), label: 'RH: Dolyatra'},
{ date: new Date(2024,2,31), label: 'RH: Easter Sunday'},
{ date: new Date(2024,3,5), label: 'RH: Jamat-Ul-Vida'},
{ date: new Date(2024,3,9), label: 'RH: Ugadi'},
{ date: new Date(2024,3,13), label: 'RH: Vishu'},
{ date: new Date(2024,3,14), label: 'RH: Meshadi'},
{ date: new Date(2024,3,17), label: 'RH: Ram Navami'}
];
const weekdays = {
"monday": 1,
"tuesday": 2,
"wednesday": 3,
"thursday": 4,
"friday": 5,
"saturday": 6,
};
const selectedDays = Object.entries(weekdays)
.filter(([day, _]) => document.getElementById(day).checked)
.map(([_, dayNumber]) => dayNumber);
const includeHolidays = document.getElementById("includeHolidays").checked;
const indicateRestrictedHolidays = document.getElementById("indicateRestrictedHolidays").checked;
let currentDate = new Date(startDate);
const datesList = document.getElementById("datesList");
datesList.innerHTML = '';
while (currentDate <= endDate) {
let listItem = null;
let holiday = holidays.find(h => h.date.toDateString() === currentDate.toDateString());
let restrictedHoliday = restrictedHolidays.find(rh => rh.date.toDateString() === currentDate.toDateString());
if (selectedDays.includes(currentDate.getDay()) && !isDateInRanges(currentDate, excludedRanges)) {
listItem = document.createElement("li");
listItem.textContent = currentDate.toDateString();
if (holiday && includeHolidays) {
listItem.textContent += " " + holiday.label;
datesList.appendChild(listItem);
}
else if (!holiday){
datesList.appendChild(listItem);
if (restrictedHoliday && indicateRestrictedHolidays) {
listItem.textContent += " " + restrictedHoliday.label;
datesList.appendChild(listItem);
}
}
}
currentDate.setDate(currentDate.getDate() + 1);
}
}

View file

@ -0,0 +1,46 @@
---
title: "Course Plan Generator"
description: "If you are a. teaching a course at IIT Gandhinagar next term (Jan-Apr 2024), b. working on your course plan, and c. need a list of dates on which you have classes, then you can..."
pubDate: "2023-12-25"
authorName: "Neeldhara"
sourceCategories: ["workflows"]
sourcePath: "course-plan/2024-spring/index.qmd"
---
If you are
a. teaching a course at IIT Gandhinagar next term (Jan-Apr 2024),
b. working on your course plan, and
c. need a list of dates on which you have classes,
then you can use the generator below to get a list, by checking your teaching days.
Dates during the mid-sem exam (Feb 19 24, 2024) and the mid-sem recess (Mar 23 - 31, 2024) are excluded. [Holidays](https://iitgn.ac.in/holiday/2024) are excluded too, but _restricted holidays are not_. If you need to view the holidays, you can indicate as much via the checkbox below.
For those outside IITGN: a standalone version is [here](https://classplan.neeldhara.repl.co/) and the source is [here](https://github.com/neeldhara/ClassPlan/tree/main), in case you'd like to adapt this to your own context.
<div>
<form>
<input type="checkbox" id="monday" name="day">&nbsp;Monday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="tuesday" name="day">&nbsp;Tuesday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="wednesday" name="day">&nbsp;Wednesday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="thursday" name="day">&nbsp;Thursday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="friday" name="day">&nbsp;Friday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="saturday" name="day">&nbsp; Saturday
</form></div>
<br>
<label><input type="checkbox" id="includeHolidays" name="includeHolidays"> Include Holidays</label>
<br>
<label><input type="checkbox" id="indicateRestrictedHolidays"> Indicate Restricted Holidays</label>
<br>
<br>
<button class="custom-button" onclick="generateDates()">
Generate Dates for Course Plan
</button>
<br><br>
<div class="sourceCode">
<pre class="sourceCode plaintext code-with-copy">
<code class="sourceCode plaintext" id="datesList">
</code>
</pre>
</div>

View file

@ -0,0 +1,91 @@
function isDateInRanges(date, ranges) {
return ranges.some(range => date >= range.start && date <= range.end);
}
function generateDates() {
const startDate = new Date(2024, 0, 3);
const endDate = new Date(2024, 3, 24);
const excludedRanges = [
{start: new Date(2024, 2, 23), end: new Date(2024, 2, 31)},
{start: new Date(2024, 1, 19), end: new Date(2024, 1, 24)}
];
const holidays = [
{date: new Date(2024, 0, 26), label: 'HOLIDAY: Republic Day'},
{date: new Date(2024, 2, 8), label: 'HOLIDAY: Maha Shivratri'},
{date: new Date(2024, 2, 25), label: 'HOLIDAY: Holi'},
{date: new Date(2024, 2, 29), label: 'HOLIDAY: Good Friday'},
{date: new Date(2024, 3, 11), label: 'HOLIDAY: Idul Fitr'},
{date: new Date(2024, 3, 21), label: 'HOLIDAY: Mahavir Jayanti'}
];
const restrictedHolidays = [
{ date: new Date(2024,0,1), label: 'RH: New Years Day'},
{ date: new Date(2024,0,13), label: 'RH: Lohri'},
{ date: new Date(2024,0,14), label: 'RH: Makar Sankranti'},
{ date: new Date(2024,0,15), label: 'RH: Pongal'},
{ date: new Date(2024,0,17), label: 'RH: Guru Gobind Singh Birthday'},
{ date: new Date(2024,0,25), label: 'RH: Hazarat Ali Birthday'},
{ date: new Date(2024,1,14), label: 'RH: Basant Panchami'},
{ date: new Date(2024,1,19), label: 'RH: Shivaji Jayanti'},
{ date: new Date(2024,1,24), label: 'RH: Guru Ravi Das Birthday'},
{ date: new Date(2024,2,6), label: 'RH: Birthday of Swami Dayananda Saraswati'},
{ date: new Date(2024,2,24), label: 'RH: Holika Dahan'},
{ date: new Date(2024,2,25), label: 'RH: Dolyatra'},
{ date: new Date(2024,2,31), label: 'RH: Easter Sunday'},
{ date: new Date(2024,3,5), label: 'RH: Jamat-Ul-Vida'},
{ date: new Date(2024,3,9), label: 'RH: Ugadi'},
{ date: new Date(2024,3,13), label: 'RH: Vishu'},
{ date: new Date(2024,3,14), label: 'RH: Meshadi'},
{ date: new Date(2024,3,17), label: 'RH: Ram Navami'}
];
const weekdays = {
"monday": 1,
"tuesday": 2,
"wednesday": 3,
"thursday": 4,
"friday": 5,
"saturday": 6,
};
const selectedDays = Object.entries(weekdays)
.filter(([day, _]) => document.getElementById(day).checked)
.map(([_, dayNumber]) => dayNumber);
const includeHolidays = document.getElementById("includeHolidays").checked;
const indicateRestrictedHolidays = document.getElementById("indicateRestrictedHolidays").checked;
let currentDate = new Date(startDate);
const datesList = document.getElementById("datesList");
datesList.innerHTML = '';
while (currentDate <= endDate) {
let listItem = null;
let holiday = holidays.find(h => h.date.toDateString() === currentDate.toDateString());
let restrictedHoliday = restrictedHolidays.find(rh => rh.date.toDateString() === currentDate.toDateString());
if (selectedDays.includes(currentDate.getDay()) && !isDateInRanges(currentDate, excludedRanges)) {
listItem = document.createElement("li");
listItem.textContent = currentDate.toDateString();
if (holiday && includeHolidays) {
listItem.textContent += " " + holiday.label;
datesList.appendChild(listItem);
}
else if (!holiday){
datesList.appendChild(listItem);
if (restrictedHoliday && indicateRestrictedHolidays) {
listItem.textContent += " " + restrictedHoliday.label;
datesList.appendChild(listItem);
}
}
}
currentDate.setDate(currentDate.getDate() + 1);
}
}

View file

@ -0,0 +1,45 @@
---
title: "Course Plan Generator"
description: "If you are a. teaching a course at IIT Gandhinagar next term (Aug-Dec 2023), b. working on your course plan, and c. need a list of dates on which you have classes, then you can..."
pubDate: "2023-04-25"
authorName: "Neeldhara"
sourceCategories: ["workflows"]
sourcePath: "course-plan/index.qmd"
---
If you are
a. teaching a course at IIT Gandhinagar next term (Aug-Dec 2023),
b. working on your course plan, and
c. need a list of dates on which you have classes,
then you can use the generator below to get a list, by checking your teaching days.
Dates during Exam I (Sep 02 06, 2023), Exam II (Oct 11 15, 2023), and the mid-sem recess (Oct 21 - 29, 2023) are excluded. Holidays are excluded too, but _restricted holidays are not_. If you need to view the holidays, you can indicate as much via the checkbox below.
For those outside IITGN: a standalone version is [here](https://classplan.neeldhara.repl.co/) and the source is [here](https://github.com/neeldhara/ClassPlan/tree/main), in case you'd like to adapt this to your own context.
<div>
<form>
<input type="checkbox" id="monday" name="day">&nbsp;Monday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="tuesday" name="day">&nbsp;Tuesday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="wednesday" name="day">&nbsp;Wednesday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="thursday" name="day">&nbsp;Thursday &nbsp;&nbsp;&nbsp;
<input type="checkbox" id="friday" name="day">&nbsp;Friday
</form></div>
<br>
<label><input type="checkbox" id="includeHolidays" name="includeHolidays"> Include Holidays</label>
<br>
<label><input type="checkbox" id="indicateRestrictedHolidays"> Indicate Restricted Holidays</label>
<br>
<br>
<button class="custom-button" onclick="generateDates()">
Generate Dates for Course Plan
</button>
<br><br>
<div class="sourceCode">
<pre class="sourceCode plaintext code-with-copy">
<code class="sourceCode plaintext" id="datesList">
</code>
</pre>
</div>

View file

@ -0,0 +1,88 @@
function isDateInRanges(date, ranges) {
return ranges.some(range => date >= range.start && date <= range.end);
}
function generateDates() {
const startDate = new Date(2023, 7, 2);
const endDate = new Date(2023, 10, 24);
const excludedRanges = [
{start: new Date(2023, 8, 2), end: new Date(2023, 8, 6)},
{start: new Date(2023, 9, 11), end: new Date(2023, 9, 15)},
{start: new Date(2023, 9, 21), end: new Date(2023, 9, 29)}
];
const holidays = [
{date: new Date(2023, 7, 15), label: 'HOLIDAY: Independence Day'},
{date: new Date(2023, 8, 7), label: 'HOLIDAY: Janmashtami (Vaishnavi)'},
{date: new Date(2023, 8, 28), label: 'HOLIDAY: Milad-un-Nabi or Id-e-Milad'},
{date: new Date(2023, 9, 2), label: 'HOLIDAY: Mahatma Gandhis Birthday'},
{date: new Date(2023, 9, 24), label: 'HOLIDAY: Dussehra (Vijay Dashmi)'}
];
const restrictedHolidays = [
{date: new Date(2023, 7, 16), label: 'RH: Parsi New Years Day/ Nauraj'},
{date: new Date(2023, 7, 20), label: 'RH: Vinayaka Chaturthi'},
{date: new Date(2023, 7, 29), label: 'RH: Onam or Thiru Onam Day'},
{date: new Date(2023, 7, 30), label: 'RH: Raksha Bandhan'},
{date: new Date(2023, 8, 6), label: 'RH: Janmashtami (Smarta)'},
{date: new Date(2023, 8, 19), label: 'RH: Ganesh Chaturthi'},
{date: new Date(2023, 9, 21), label: 'RH: Dussehra (Saptami)'},
{date: new Date(2023, 9, 22), label: 'RH: Dussehra (Maha Ashtami)'},
{date: new Date(2023, 9, 23), label: 'RH: Dussehra (Maha Navmi)'},
{date: new Date(2023, 9, 28), label: 'RH: Maharishi Valmikis Birthday'},
{date: new Date(2023, 10, 1), label: 'RH: Karaka Chaturthi (Karwa Chouth)'},
{date: new Date(2023, 10, 12), label: 'RH: Naraka Chaturdasi'},
{date: new Date(2023, 10, 13), label: 'RH: Govardhan Puja'},
{date: new Date(2023, 10, 15), label: 'RH: Bhai Duj'},
{date: new Date(2023, 10, 19), label: 'RH: Pratihar Shashthi or Surya Shashthi (Chhat Puja)'},
{date: new Date(2023, 10, 24), label: 'RH: Guru Tegh Bahadur\'s Martyrdom Day'}
];
const weekdays = {
"monday": 1,
"tuesday": 2,
"wednesday": 3,
"thursday": 4,
"friday": 5
};
const selectedDays = Object.entries(weekdays)
.filter(([day, _]) => document.getElementById(day).checked)
.map(([_, dayNumber]) => dayNumber);
const includeHolidays = document.getElementById("includeHolidays").checked;
const indicateRestrictedHolidays = document.getElementById("indicateRestrictedHolidays").checked;
let currentDate = new Date(startDate);
const datesList = document.getElementById("datesList");
datesList.innerHTML = '';
while (currentDate <= endDate) {
let listItem = null;
let holiday = holidays.find(h => h.date.toDateString() === currentDate.toDateString());
let restrictedHoliday = restrictedHolidays.find(rh => rh.date.toDateString() === currentDate.toDateString());
if (selectedDays.includes(currentDate.getDay()) && !isDateInRanges(currentDate, excludedRanges)) {
listItem = document.createElement("li");
listItem.textContent = currentDate.toDateString();
if (holiday && includeHolidays) {
listItem.textContent += " " + holiday.label;
datesList.appendChild(listItem);
}
else if (!holiday){
datesList.appendChild(listItem);
if (restrictedHoliday && indicateRestrictedHolidays) {
listItem.textContent += " " + restrictedHoliday.label;
datesList.appendChild(listItem);
}
}
}
currentDate.setDate(currentDate.getDate() + 1);
}
}

View file

@ -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.

View file

@ -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.

View file

@ -9,7 +9,7 @@ import { SITE_TITLE } from '@/consts';
export async function getStaticPaths() {
const posts = await getCollection(ACTIVE_BLOG_SITE.key);
return posts.map((post) => ({
params: { slug: post.id },
params: { slug: post.id.replace(/\/index$/, '') },
props: post,
}));
}

View file

@ -14,7 +14,7 @@ export async function GET(context) {
site: context.site,
items: posts.map((post) => ({
...post.data,
link: `/${post.id}/`,
link: `/${post.id.replace(/\/index$/, "")}/`,
})),
});
}