Community코딩 & 개발github.com

Chibuchibs/free-claude-skills

셔플, 무작위 선택, 확률이 공정해 보이지 않을 때 제대로 검사하고 분포를 테스트합니다. 코드가 배열을 섞거나, 퀴즈 답변을 무작위로 배치하거나, 하위 집합을 선택하거나, 확률을 할당하거나, 전리품이나 보상을 생성할 때, 또는 누군가 결과가 "조작된 것 같다", "항상 같은 것만 뽑힌다"고 말하거나 무언가를 섞거나 무작위화하는 방법을 물을 때 사용하세요.

free-claude-skills란 무엇인가요?

이 스킬은 JavaScript에서 흔히 발생하는 무작위화 버그, 특히 `Array.prototype.sort`에 `Math.random() - 0.5` 비교 함수를 전달하는 잘못된 셔플 패턴을 집중적으로 탐지하고 수정합니다. 이 패턴은 정렬 비교자의 일관성 요구 조건을 위반하여 결과 분포에 심각한 편향을 초래하며, 실제 측정 결과 퀴즈 보기 4개 중 첫 번째 위치에 정답이 28.3% 확률로 배치되는 등 균등(25%)에서 크게 벗어납니다. 이 스킬은 Fisher-Yates 셔플을 올바른 해결책으로 제시하며, 패턴 매칭만으로 무분별하게 대체하지 말고 실제로 정렬 비교자로 사용된 경우만 교체하도록 주의합니다. 또한 분포를 눈으로 확인하지 말고 실제로 계수하여 검증할 것, 표시된 확률이 실제 코드가 굴리는 확률과 일치하는지 시뮬레이션으로 확인할 것, 그리고 표시된 목표(예: "5개 중 3개")가 실제로 도달 가능한 확률인지 검증할 것을 권장합니다. 다양한 개발 환경과 CI/CD 파이프라인에서 사용할 수 있는 범용적인 코드 리뷰 및 디버깅 기법을 제공합니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Chibuchibs/free-claude-skills/tree/HEAD/skills/randomness-correctness

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

공정하지 않은 셔플

JavaScript에서 가장 흔한 무작위화 버그:

const shuffled = items.sort(() => Math.random() - 0.5);   // 틀렸음

얼핏 보기엔 괜찮아 보이고 어디서나 볼 수 있습니다. 이것은 셔플이 아닙니다. 정렬 비교자는 일관성이 있어야 하는데, 이 비교자는 그렇지 않으므로 엔진의 정렬이 왜곡된 순열을 생성합니다.

퀴즈 보기 4개를 대상으로 측정:

위치정답이 그 위치에 들어갈 확률
028.3%
128.2%
224.7%
318.8%

균등하다면 각각 25%여야 합니다. 실제로, 항상 첫 번째 보기를 고르는 것이 무작위로 고르는 것보다 더 나았습니다. 이를 알아챈 플레이어는 유리한 고지를 점하게 되며, 그 퀴즈는 조용히 공정하지 않았습니다.

수정 방법

Fisher–Yates, 딱 한 번, 헬퍼 함수로:

function shuffle(a) {
  const out = [...a];
  for (let i = out.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [out[i], out[j]] = [out[j], out[i]];
  }
  return out;
}

그런 다음 모든 곳에서 교체하세요. 이 버그는 보통 한 번 이상 나타납니다. 어떤 코드베이스에서는 열한 군데에서 발견되었습니다. 퀴즈 보기 섞기, 어떤 질문을 보여줄지 고르기, 어떤 항목을 제공할지 선택하기, 메뉴 순서 정하기 등이었고 각각 약간씩 분포를 왜곡했습니다.

패턴 매칭만으로 무분별하게 대체하지 마십시오. (Math.random() - 0.5)는 물리 시뮬레이션의 노이즈나 지터(jitter) 등 합법적인 용도로도 사용됩니다:

velocity += (Math.random() - 0.5) * 0.012;   // 이건 건드리지 마세요

일치하는 각 부분이 실제로 정렬 비교자인지 확인하세요.

분포 테스트

무작위성을 눈으로 확인하지 마십시오. 직접 세어 보세요:

const pos = [0,0,0,0], N = 200000;
for (let i = 0; i < N; i++) {
  const order = shuffle(['a','b','c','d'].map((t,i) => [t,i]));
  pos[order.findIndex(o => o[1] === 0)]++;
}
pos.forEach((c,i) => console.log(i, (c/N*100).toFixed(1) + '%'));

위치 간 퍼짐(Spread)이 약 3% 포인트 이상이면 무언가 편향되어 있다는 의미입니다.

테스트에는 적절한 생성기를 사용하십시오. 직접 만든 선형 합동 생성기는 1–2 포인트의 "오차"를 만들어내어 실제 버그처럼 보이지만 실제로는 테스트 자체의 문제였습니다. Math.random()은 분포 검사에 충분히 균일합니다. 사용자 정의 생성기는 재현 가능한 시드가 필요할 때 사용하고, 별도로 검증하십시오.

사용자에게 보여주는 확률 확인

어디에나 확률(백분율, 진행률 표시줄, 성공 확률)을 표시한다면, 그것이 코드가 실제로 굴리는 값과 일치하는지 확인하십시오. 실제 굴림을 수십만 번 시뮬레이션하여 비교하세요:

cred   0  표시 5.0%/40.0%/55.0%   실제 5.0%/40.0%/55.0%
cred 100  표시 40.0%/40.0%/20.0%  실제 40.0%/40.1%/20.0%

최대 오차가 0.5% 포인트 미만이면 표시가 거짓말을 하고 있지 않다는 의미입니다. 결과가 실제로 지켜지지 않는 확률을 표시하는 것은 아무것도 표시하지 않는 것보다 더 나쁩니다. 사람들이 그 정보를 바탕으로 결정을 내리기 때문입니다.

추가 확인 사항

명시된 목표가 실제로 도달 가능한지 확인하십시오. "5개 중 3개"라고 읽히는 카운터는 플레이어에게 5가 목표라고 알려줍니다. 만약 5가 0.17%의 확률로만 발생한다면, 인터페이스는 사실상 절대 일어나지 않는 일을 약속하는 것입니다. 표시하는 모든 이정표의 실제 확률을 계산해 보십시오.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

관련 스킬