λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
IT/JavaScript

λ°°μ—΄μ˜ μš”μ†Œλ₯Ό λ¬΄μž‘μœ„λ‘œ μ„žκΈ°

by λ¬΄λ…ˆ 2022. 4. 1.

πŸ“Œ λ°°μ—΄μ˜ μš”μ†Œλ₯Ό λ¬΄μž‘μœ„λ‘œ μ„žκΈ°

둜또 ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λ©΄μ„œ ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄ λ°°μ—΄μ˜ μš”μ†Œλ₯Ό 랜덀으둜 μž…λ ₯λ°›λŠ” μ½”λ“œλ₯Ό κ΅¬ν˜„ν•˜κ³ μž ν–ˆλ‹€. 

ν•˜μ§€λ§Œ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 파이썬의 random λͺ¨λ“ˆκ³Ό 같은 λ°°μ—΄μ˜ μš”μ†Œλ₯Ό 랜덀 ν•œ λ°©λ²•μœΌλ‘œ λ°”κΎΈλŠ” κΈ°λŠ₯을 μ œκ³΅ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ λ°°μ—΄μ˜ μš”μ†Œλ₯Ό μ„žκΈ° μœ„ν•΄μ„œλŠ” κΈ°λŠ₯을 직접 κ΅¬ν˜„ν•΄μ„œ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€λŠ” 것을 μ•Œκ²Œ λ˜μ—ˆλ‹€. 이λ₯Ό 직접 κ΅¬ν˜„ν•΄λ³΄λ„λ‘ ν•˜μž!

✏️ μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ λ°°μ—΄μ˜ μš”μ†Œλ₯Ό λ¬΄μž‘μœ„λ‘œ μ„žμ–΄λ³΄μž

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ 배열을 λ¬΄μž‘μœ„λ‘œ μ„žλŠ” 방법은 sort() λ©”μ„œλ“œμ™€ Math.random() λ©”μ„œλ“œλ₯Ό μ΄μš©ν•˜μ—¬ κ΅¬ν˜„ν•  수 μžˆλ‹€.

function shuffle(array) {
  array.sort(() => Math.random() - 0.5);
}

let arr = [1, 2, 3];
shuffle(arr);

sort와 random을 ν™œμš©ν•œ λ¬΄μž‘μœ„ μ •λ ¬ κ²°κ³Ό

μœ„ μ½”λ“œλ₯Ό 톡해 κ°„λ‹¨ν•˜κ²Œ λ¬΄μž‘μœ„ ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€.

arr 배열은 μ•„λž˜μ™€ 같이 [1, 3, 2]둜 λ¬΄μž‘μœ„λ‘œ μˆœμ„œκ°€ λ³€κ²½λœ 것을 확인할 수 μžˆλ‹€.

μ΄λ•Œ Math.random() - 0.5 의 계산 κ²°κ³ΌλŠ” μ–‘μˆ˜λ‚˜ 음 수 λ‘˜ 쀑 ν•˜λ‚˜μ΄κΈ° λ•Œλ¬Έμ— μ •λ ¬ ν•¨μˆ˜λŠ” μš”μ†Œλ₯Ό λ¬΄μž‘μœ„λ‘œ 재 μ •λ ¬ν•  수 있게 ν•œλ‹€.

ν•˜μ§€λ§Œ sortλŠ” 이런 μš©λ„λ‘œ λ§Œλ“€μ–΄μ§„ λ©”μ„œλ“œκ°€ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— 숫자 1, 2, 3으둜 λ§Œλ“€ 수 μžˆλŠ” μˆœμ—΄μ΄ 같은 λΉˆλ„λ‘œ λ°œμƒν•˜μ§€ μ•Šμ„ 수 도 μžˆλ‹€.

μ˜ˆμ‹œλ₯Ό 톡해 μ‹€μ œ λΉˆλ„μˆ˜λ₯Ό 확인해보도둝 ν•˜μž.

function shuffle(array) {
  array.sort(() => Math.random() - 0.5);
}

// 1, 2, 3으둜 λ§Œλ“€ 수 μžˆλŠ” λͺ¨λ“  μˆœμ—΄μ˜ λΉˆλ„λ₯Ό μΈ‘μ •ν•˜κΈ° μœ„ν•œ 객체
let count = {
  '123': 0,
  '132': 0,
  '213': 0,
  '231': 0,
  '321': 0,
  '312': 0
};
for (let i = 0; i < 1000000; i++) {
  let array = [1, 2, 3];
  shuffle(array);
  count[array.join('')]++;
}

shuffle λ©”μ„œλ“œλ₯Ό 백만번 μ‹€ν–‰μ‹œμΌœ κ°€λŠ₯ν•œ ν•œ λͺ¨λ“  결과의 λΉˆλ„λ₯Ό μΈ‘μ •ν•΄λ³΄μž.

// λ§Œλ“€ 수 μžˆλŠ” λͺ¨λ“  μˆœμ—΄μ˜ 생성 λΉˆλ„ 좜λ ₯
for (let key in count) {
	console.log(`${key}: ${count[key]}`);
}

μ‹€ν–‰ κ²°κ³ΌλŠ” μœ„μ™€ κ°™λ‹€. (μžλ°”μŠ€ν¬λ¦½νŠΈ μ—”μ§„λ§ˆλ‹€ λ‹€λ₯Ό 수 있음)

μ‹€ν–‰ κ²°κ³Ό λΉˆλ„κ°€ ν•œμͺ½μœΌλ‘œ μ§€λ‚˜μΉ˜κ²Œ 편ν–₯될 수 μžˆλ‹€λŠ” 것을 μ•Œκ²Œ λ˜μ—ˆλ‹€.

μ‹€ν–‰ κ²°κ³ΌλŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ μ—”μ§„λ§ˆλ‹€ λ‹€λ₯Ό 수 μžˆμ§€λ§Œ, 기쑴의 μ½”λ“œλŠ” λΉˆλ„κ°€ λ‹€λ₯Έ λ¬Έμ œμ μ„ 가지고 μžˆλ‹€.

ν•΄λ‹Ή 결과의 λ°œμƒ 원인은, sortλ₯Ό μ‹€ν–‰ν–ˆμ„ λ•Œ λ‚΄λΆ€ 둜직으둜 인해 λ°œμƒν•˜λŠ” 문제둜, 좔가적인 방식을 톡해 λΉˆλ„λ₯Ό κ°™κ²Œλ” μœ λ„ν•˜λ„λ‘ ν•˜μž.

✏️ ν”Όμ…”-예이츠 μ…”ν”Œ(Fishcer-Yates shuffle) μ•Œκ³ λ¦¬μ¦˜ ν™œμš©

ν”Όμ…”-예이츠 μ…”ν”Œ μ•Œκ³ λ¦¬μ¦˜μ€ λ°°μ—΄ 끝 μš”μ†ŒλΆ€ν„° μ‹œμž‘ν•΄ μ•žμœΌλ‘œ ν•˜λ‚˜μ”© λ‚˜μ•„κ°€λ©΄μ„œ ν•΄λ‹Ή μš”μ†Œ μ•žμ— μžˆλŠ” μž„μ˜μ˜ μš”μ†Œμ™€ ν•΄λ‹Ή μš”μ†Œλ₯Ό λ°”κΏ”μΉ˜κΈ°ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€.

// "ꡬ쑰 λΆ„ν•΄ ν• λ‹Ή(destructuring assignment)" ver
function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
		// λ¬΄μž‘μœ„λ‘œ index κ°’ 생성 (0 이상 i 미만)
    let j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
}
// ꡬ쑰 λΆ„ν•΄ 할당을 μ‚¬μš©ν•˜μ§€ μ•Šμ€ μ½”λ“œ
function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    let j = Math.floor(Math.random() * (i + 1)); 

		// μž„μ‹œ λ³€μˆ˜μ— 원본 값을 μ €μž₯ν•˜κ³ , 랜덀 κ°’ jλ₯Ό μ‚¬μš©ν•΄ λ°°μ—¬
    let t = array[i]; 
		array[i] = array[j]; 
		array[j] = t
  }
}

μƒˆλ‘œ μž‘μ„±ν•œ ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•΄μ„œ λΉˆλ„λ₯Ό μΈ‘μ •ν•΄λ³΄μž.

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

// 1, 2, 3으둜 λ§Œλ“€ 수 μžˆλŠ” λͺ¨λ“  μˆœμ—΄μ˜ λΉˆλ„ μΈ‘μ •
let count = {
  '123': 0,
  '132': 0,
  '213': 0,
  '231': 0,
  '321': 0,
  '312': 0
};

for (let i = 0; i < 1000000; i++) {
  let array = [1, 2, 3];
  shuffle(array);
  count[array.join('')]++;
}

// λ§Œλ“€ 수 μžˆλŠ” λͺ¨λ“  μˆœμ—΄μ˜ 생성 λΉˆλ„ 좜λ ₯
for (let key in count) {
	console.log(`${key}: ${count[key]}`);
}

ν”Όμ…”-예이츠 μ•Œκ³ λ¦¬μ¦˜ λ°©μ‹μ˜ μ •λ ¬ κ²°κ³Ό

μ‹€ν–‰ κ²°κ³Ό λͺ¨λ“  μˆœμ—΄μ΄ 거의 μœ μ‚¬ν•œ λΉˆλ„λ‘œ λ§Œλ“€μ–΄ 진것을 확인할 수 μžˆλ‹€.

이둜써 기쑴의 ν•¨μˆ˜λ³΄λ‹€ λ”μš± κ³ λ₯Έ 결과값을 νšλ“ν•  수 μžˆμ„ 뿐만 μ•„λ‹ˆλΌ ν”Όμ…”-예이츠 μ•Œκ³ λ¦¬μ¦˜μ€ ‘μ •λ ¬' 연산도 μ—†κΈ° λ•Œλ¬Έμ— μ„±λŠ₯상 이점 λ˜ν•œ 가지고 μžˆλ‹€.

 


μ°Έκ³ 

 

λ°°μ—΄ μš”μ†Œ λ¬΄μž‘μœ„λ‘œ μ„žκΈ°

λ°°μ—΄μ˜ μš”μ†Œλ₯Ό λ¬΄μž‘μœ„λ‘œ μ„žμ–΄μ£ΌλŠ” ν•¨μˆ˜ shuffle(array)을 μž‘μ„±ν•΄ λ³΄μ„Έμš”. shuffle을 μ—¬λŸ¬ 번 μ‹€ν–‰ν•˜λ©΄ μš”μ†Œμ˜ μ •λ ¬ μˆœμ„œκ°€ 달라야 ν•©λ‹ˆλ‹€. μ˜ˆμ‹œλ₯Ό μ‚΄νŽ΄λ΄…μ‹œλ‹€. let arr = [1, 2, 3]; shuffle(arr); // arr = [3, 2, 1]

ko.javascript.info

 

Fisher–Yates shuffle - Wikipedia

From Wikipedia, the free encyclopedia Jump to navigation Jump to search Algorithm for generating a random permutation of a finite set Example of shuffling five letters using Durstenfeld's in-place version of the Fisher–Yates shuffle The Fisher–Yates sh

en.wikipedia.org

 

λ°˜μ‘ν˜•

'IT > JavaScript' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

requestAnimationFrame vs setTimeout  (0) 2022.04.08
DOMContentLoaded 이벀트 핸듀링  (0) 2022.04.01
λ¬Έμžμ—΄ μΉ˜ν™˜ (replace, RexExp, match)  (0) 2022.03.13
TypeScript vs PropTypes  (0) 2022.03.09
[JavaScript] nullκ³Ό undefined  (0) 2022.01.19

λŒ“κΈ€