๐ shuffle ํจ์๋ฅผ ๋ง๋ค์ด๋ณด์
JS
๋ก shuffle
ํจ์๋ฅผ ๋ง๋ค ๋ ๊ฐ์ฅ ๋จผ์ ์๊ฐ๋๋ ๋ฉ์๋๋ sort()
์ผ ๊ฒ์ด๋ค. ์๋ง๋ ๋ค์ ์ฝ๋์ฒ๋ผ ๊ตฌ์ฑํ์ง ์์์๊น??
// sort shuffle
const arr = [1, 2, 3, 4, 5];
const shuffle = arr.sort(() => Math.random() - 0.5)
console.log(shuffle);
๐๐พ [ 5, 3, 2, 1, 4 ]
๊ตฌํ ๋ก์ง์ ์ดํด๋ณด๋ฉด ๋ฐฐ์ด์ ์ํํ๋ฉด์ Math.random()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋์จ ๋๋ค ํ ๊ฐ์ -0.5
๋ฅผ ํ์ฌ sort()
๋ฉ์๋๋ฅผ ๊ฑฐ์น๊ฒ ๋๋ค. ๋ง์ฝ, Math.random() - 0.5
๋ฅผ ํ ๊ฐ์ด ์์๋ผ๋ฉด ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌ๋๊ณ , ์์๋ฅผ ๋ฆฌํดํ๋ฉด ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌ๋๋ค. arr
๋ฐฐ์ด์ ๋ชจ๋ ์ํํ๊ฒ ๋๋ฉด ์๋จ ์ฝ๋ ๋ธ๋ก 6๋ฒ Line์ฒ๋ผ ๋ฐฐ์ด์ด shuffle
๋ ๊ฒ์ ์ ์ ์๋ค.
sort
ํจ์๋ก ๊ตฌํํ์ ๋์ ์ฅ์ ์ ์ฝ๋๊ฐ ๊ฐ๋จํด์ง๋ ๋ฐ๋ฉด, ๋จ์ ์ ๋ชจ๋ ํ๋ฅ ์ด ๊ท ์ผํ๊ฒ ์ผ์ด๋์ง ์๋๋ค. (JS ์์ง๋ง๋ค ๊ฒฐ๊ณผ๊ฐ ๋ค๋ฅผ ์ ์๋ค.) ๊ทธ ์ด์ ๋ sort
๋ ์ด๋ฐ ์ฉ๋๋ก ๋ง๋ค์ด์ง ๋ฉ์๋๊ฐ ์๋๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ฅผ ์ฆ๋ช
ํ๊ธฐ ์ํด ๋ค์ ์ฝ๋๋ฅผ ์ดํด๋ณด์. sort
๋ฉ์๋๋ฅผ ์ด์ฉํด ๋ฐฐ์ด [1, 2, 3]
์ ๋ฐฑ๋ง ๋ฒ shuffle
ํด๋ดค๋ค.
const arr = [1, 2, 3];
function shuffle(array) {
array.sort(() => Math.random() - 0.5);
}
let count = {
'123': 0,
'132': 0,
'213': 0,
'231': 0,
'321': 0,
'312': 0
};
for (let i = 0; i < 1_000_000; i++) {
let array = [1, 2, 3];
shuffle(array);
count[array.join('')]++;
}
๐๐พ
123: 375285,
132: 62554,
213: 125270,
231: 62429,
312: 62557,
321: 311905
count
๋ฅผ ์ดํด๋ณด๋ฉด ๋น๋๊ฐ ์ฒ์, ์ค๊ฐ, ๋์ ์ ๋ ค์๋ ๊ฒ์ ์ ์ ์๋ค. ๊ทธ ์ด์ ๋ sort
๋ฉ์๋ ๋๋ฌธ์ธ๋ฐ, sort
๋ฅผ ์คํํ๋ฉด ์ธ์๋ก ๋๊ธด ์ ๋ ฌ ํจ์๊ฐ ๋ฐฐ์ด์ ์ ๋ฆฌํด์ฃผ๋๋ฐ, ์ด ๊ณผ์ ์์ element
๋น๊ต๊ฐ ์์ ๋ฌด์์๋ก ์ด๋ฃจ์ด์ง๊ธฐ ๋๋ฌธ์ด๋ค. JS ์์ง๋ง๋ค ๋ด๋ถ ๊ตฌํ ๋ฐฉ์๋ ๋ฌ๋ผ ์ด๋ฐ ํผ๋์ ๋ ์ปค์ง๊ฒ ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํผ์
-์์ด์ธ (Fisher-Yates)
์
ํ์ ์ด์ฉํ๋ฉด ํธํฅ๋์ง ์์ ๋น๋๋ก shuffle
์ ํ ์ ์๊ณ , ์๊ฐ๋ณต์ก๋๋ sort
๋ฉ์๋๋ณด๋ค ์ด์ ์ด ์๋ค. Tim sort๋ฅผ ์ฌ์ฉํ sort
๋ฉ์๋๋ ํ๊ท O(nlogn)
์ ๋ง์กฑํ์ง๋ง, ํผ์
-์์ด์ธ ๋ O(N)
์ ๋ง์กฑํ๊ธฐ ๋๋ฌธ์ด๋ค. ํผ์
-์์ด์ธ (Fisher-Yates)
์ ๊ตฌํ์์๋ ๋ค์๊ณผ ๊ฐ๋ค.
- 1๋ถํฐ N๊น์ง์ ์ ์ค ์์์ ์ซ์๋ฅผ ์ ํํ๋ค.
- 1๊ณผ ์ ํ๋์ง ์๊ณ ๋จ์ ์๋ ์ ์ฌ์ด์ ์์์ ์ k๋ฅผ ์ ํํ๋ค.
- k๋ฅผ ์ ํ๋์ง ์์ ๋ง์ง๋ง ์ซ์์ ์๋ฆฌ๋ฅผ ๋ฐ๊พผ๋ค.
- 1๋ถํฐ N-1๊น์ง์ ์ ์ค ์์์ ์ซ์๋ฅผ ์ ํํ๋ค.
- ๋ ์ด์ ์ ํํ ์ซ์๊ฐ ์์ ๋๊น์ง 2~4๋ฒ์ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
์ด๋ฅผ JS์ฝ๋๋ก ์์ฑํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
// Fisher-Yates shuffle
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) { // ๋ฐฐ์ด์ ๋ง์ง๋ง๋ถํฐ ์์ํ๋ค. i๊ฐ 0์ด๋๋ฉด ๋ฐ๋ณต๋ฌธ์ ์ข
๋ฃํ๋ค.
let j = Math.floor(Math.random() * (i + 1)); // ๋๋คํ ๊ฐ๊ณผ ํ์ฌ ์ธ๋ฑ์ค ์์น + 1์ ๊ณฑํ๊ณ ์์์ ์ ์ ๊ฑฐํ๋ค.
[array[i], array[j]] = [array[j], array[i]]; // ํ์ฌ ์ธ๋ฑ์ค์ ๋๋คํ๊ฐ์ ์ธ๋ฑ์ค ์์น + 1์ ๊ณฑํ๊ณ ์์์ ์ ์ ๊ฑฐํ ๊ฐ๊ณผ ์๋ฆฌ๋ฅผ ๋ฐ๊พผ๋ค.
}
}
ํ์
์คํฌ๋ฆฝํธ๋ก ์ฝ๋๋ฅผ ๊ฐ๋
์ฑ ์๊ฒ ์์ฑํด๋ดค๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฐฑ๋ง ๋ฒ shuffle
ํด๋ดค๊ณ ๊ฒฐ๋ก ์ ์ผ๋ก ํ๋ฅ ์ด ๊ท ์ผํ๊ฒ ๋์ค๋ ๊ฒ์ ์ ์ ์๋ค.
function shuffle<T>(array: T[]) {
for (let index = array.length - 1; index > 0; index--) {
const randomIndex = Math.floor(Math.random() * (index + 1))
[array[index], array[randomIndex]] = [array[randomIndex], array[index]]
}
return array
}
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('')]++;
}
๐๐พ
123: 166693
132: 166647
213: 166628
231: 167517
312: 166199
321: 166316
์ด๋ ๊ฒ shuffle
ํจ์๋ฅผ ์์๋ดค๋๋ฐ, ๋ฐ์ดํฐ์ ํฌ๊ธฐ๊ฐ ์๊ณ ๋น๋์ ์๊ด์์ด ๊ฐํธํ๊ฒ shuffle
์ ๊ตฌํํ๋ ค๋ฉด sort
๋ฅผ ์ฌ์ฉํด๋ ๋์ง๋ง, ๋ฐ์ดํฐ์ ํฌ๊ธฐ๊ฐ ํฌ๊ณ ๋ฐ์ ๋น๋๊ฐ ๊ท ์ผํ๊ฒ ์ผ์ด๋์ผ ํ๋ค๋ฉด ํผ์
-์์ด์ธ ์ ๋ก์ง์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ด๋จ๊น?๋ผ๊ณ ์๊ฐํ๋ฉด์ ๊ธ์ ๋ง์น๋ค.
Reference
๋๊ธ