Skip to content

fix(ui): replace biased array shuffle with Fisher-Yates algorithm#846

Merged
koala73 merged 1 commit intokoala73:mainfrom
NewCoder3294:fix/biased-shuffle-algorithm
Mar 19, 2026
Merged

fix(ui): replace biased array shuffle with Fisher-Yates algorithm#846
koala73 merged 1 commit intokoala73:mainfrom
NewCoder3294:fix/biased-shuffle-algorithm

Conversation

@NewCoder3294
Copy link
Copy Markdown
Collaborator

Summary

  • Replace biased array.sort(() => Math.random() - 0.5) with a proper Fisher-Yates (Knuth) shuffle in the search modal's tip randomization (SearchModal.ts line 301).
  • Add a reusable shuffle<T>() utility to src/utils/index.ts that returns a new array without mutating the original.
  • No other instances of the biased sort pattern were found elsewhere in the codebase.

Why this matters

Using sort() with a random comparator produces statistically biased results. The ECMAScript spec does not define a particular sorting algorithm, so the distribution of permutations depends on the engine's implementation (e.g., V8 uses TimSort). A random comparator violates the requirement that the comparator be consistent and transitive, meaning some orderings appear significantly more often than others.

The Fisher-Yates shuffle (also known as the Knuth shuffle) guarantees a uniformly random permutation in O(n) time by iterating backwards through the array and swapping each element with a randomly chosen element from the remaining unprocessed portion.

Changes

File Change
src/utils/index.ts Add generic shuffle<T>(arr: T[]): T[] utility function
src/components/SearchModal.ts Import shuffle from utils; replace tips.sort(() => Math.random() - 0.5) with shuffle(tips)

Test plan

  • TypeScript compiles cleanly (tsc --noEmit)
  • Verify search modal empty state still shows 4 randomized tips when opened
  • Confirm tips appear in varying order across multiple opens

🤖 Generated with Claude Code

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 2, 2026

@NewCoder3294 is attempting to deploy a commit to the Elie Team on Vercel.

A member of the Team first needs to authorize it.

@koala73 koala73 added Ready to Merge PR is mergeable, passes checks, and adds value Low Value Trivial, unnecessary, or not aligned with project needs labels Mar 3, 2026
The search modal tip randomization used `array.sort(() => Math.random() - 0.5)`
which produces statistically biased results because comparison-based sorting
algorithms require a consistent comparator to work correctly. A random comparator
violates this contract, causing some permutations to appear more frequently than
others depending on the underlying sort implementation.

Replace with a proper Fisher-Yates (Knuth) shuffle that guarantees a uniform
distribution of all possible permutations in O(n) time. The new `shuffle()`
utility is added to `src/utils/index.ts` for reuse across the codebase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@koala73 koala73 force-pushed the fix/biased-shuffle-algorithm branch from 347d46d to f6cd0a1 Compare March 19, 2026 13:25
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
worldmonitor Ready Ready Preview, Comment Mar 19, 2026 1:28pm

Request Review

@koala73 koala73 merged commit 391b922 into koala73:main Mar 19, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Low Value Trivial, unnecessary, or not aligned with project needs Ready to Merge PR is mergeable, passes checks, and adds value

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants