Skip to content

Repository files navigation

NeetCode Cycle Randomizer

A polished, standalone web app for practicing the NeetCode 150 — without ever repeating a problem until you've seen them all.

🌐 Live demo: https://aadityajo.github.io/neetcode-cycle-randomizer/


Setup

# 1. Install dependencies
npm install

# 2. Start the dev server
npm run dev

# 3. Open http://localhost:5173/neetcode-cycle-randomizer/

Deploy to GitHub Pages

npm run deploy

This builds the app and pushes to the gh-pages branch. Make sure your repo has GitHub Pages enabled pointing to that branch.


Project Structure

src/
├── data/
│   └── problems.ts          ← 🔑 NeetCode 150 dataset (swap here!)
├── types/
│   └── index.ts             ← All TypeScript interfaces
├── lib/
│   ├── storage.ts           ← LocalStorage read/write helpers
│   ├── cycle.ts             ← Core random-cycle algorithm
│   ├── filters.ts           ← Filter/sort utilities
│   └── progress.ts          ← Progress calculation
├── hooks/
│   └── useAppState.ts       ← Central state + all actions
├── components/
│   ├── Header.tsx           ← Sticky header + dark mode toggle
│   ├── StatsRow.tsx         ← Four stat cards
│   ├── CurrentProblemPanel.tsx ← Problem card + pick button
│   ├── ProblemList.tsx      ← Filterable/sortable table
│   ├── ResetControls.tsx    ← Reset, export, import, settings
│   ├── ProgressBar.tsx      ← Reusable progress bar
│   └── Toast.tsx            ← Toast notification system
├── App.tsx                  ← Root layout
└── main.tsx                 ← React entry point

How the Cycle Logic Works

Algorithm

pickNext():
  1. Build pool = allProblems − seenThisCycle
     (optionally filter out completedProblemIds if excludeCompleted = true)
  2. If pool is empty → mark cycleComplete = true, show celebration
  3. Otherwise → pick pool[random index]
  4. Add chosen.id to seenThisCycle
  5. Set currentProblemId = chosen.id
  6. Persist to localStorage

The key invariant is: once a problem enters seenThisCycle, it cannot be picked again until a new cycle begins.

Explicit state fields (per spec)

Field Purpose
allProblems Full problem list (from data/problems.ts)
seenThisCycle Set of IDs seen in the active cycle
completedProblemIds IDs marked ✅ (persists across cycles)
needsReviewProblemIds IDs marked 🔖
skippedProblemIds IDs marked ⏭️
currentCycleNumber 1-indexed cycle count
currentProblemId Currently displayed problem
cycleComplete True after all problems are seen
excludeCompleted When true, completed problems skip future cycles

How to Replace the Dataset

Open src/data/problems.ts — there is a single PROBLEMS array at the top of the file. Replace or extend it with your own dataset. Each entry must match:

interface Problem {
  id: string       // unique, any string
  title: string
  category: string // e.g. "Arrays & Hashing"
  difficulty: 'Easy' | 'Medium' | 'Hard'
  url: string      // LeetCode or NeetCode URL
}

The file already contains all 150 NeetCode 150 problems seeded and ready to use. The categories match NeetCode's official groupings.


Features

  • 🎲 Random non-repeating cycle — guaranteed no repeats until all seen
  • 📊 Progress tracking — cycle number, seen/total, completed overall
  • Problem actions — mark completed, needs review, skipped
  • 🔍 Filterable list — search, category, difficulty, status
  • 🎯 Surprise mode — pick from a specific category only
  • 📦 Export / Import — save progress as JSON
  • 🎉 Confetti on cycle completion
  • 💾 LocalStorage persistence — refresh-proof
  • 🌙 Dark mode (default) with toggle
  • 📱 Responsive layout

Tech Stack

  • React 18 + TypeScript
  • Vite — dev server and bundler
  • Tailwind CSS — utility-first styling
  • canvas-confetti — cycle completion celebration
  • lucide-react — icons
  • LocalStorage — all persistence, no backend

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages