Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2025-05-15 - Hybrid Unique Sampling in random.html
**Learning:** Rejection sampling for unique random numbers (using a Set) collapses in performance (O(N²)) when the requested count approach the total range size (Coupon Collector's Problem).
**Action:** Use a hybrid approach: rejection sampling for densities < 50% and Sparse Fisher-Yates (Map-based) for densities >= 50% to maintain O(count) complexity regardless of range.
74 changes: 62 additions & 12 deletions random.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,41 @@
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
min-height: 100vh;
margin: 0;
padding: 20px;
background-color: #f0f0f0;
font-family: Arial, sans-serif;
box-sizing: border-box;
}
.button {
padding: 20px 40px;
font-size: 24px;
margin-top: 10px;
margin-bottom: 20px;
cursor: pointer;
border: none;
background-color: #4CAF50;
color: white;
border-radius: 10px;
transition: transform 0.1s;
}
.button:active {
transform: scale(0.98);
}
.number {
font-size: 36px;
font-size: 24px;
color: #333;
margin-top: 10px;
max-width: 800px;
max-height: 50vh;
overflow-y: auto;
word-break: break-all;
background: #fff;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
text-align: center;
}
.input-field {
margin: 10px 0;
Expand All @@ -48,23 +65,56 @@
<div class="number" id="randomNumbers"></div>

<script>
/**
* ⚡ BOLT OPTIMIZATION:
* 1. Hybrid Sampling: Rejection sampling for low density (<50%),
* Sparse Fisher-Yates (Map-based) for high density (>=50%).
* This avoids the O(N^2) "Coupon Collector's" performance collapse.
* 2. textContent: Faster DOM updates than innerText/innerHTML.
* 3. Bug Fix: Allow single-value ranges (minValue === maxValue).
*/
function generateRandomNumbers() {
let minValue = parseInt(document.getElementById('minValue').value);
let maxValue = parseInt(document.getElementById('maxValue').value);
let count = parseInt(document.getElementById('count').value);
let randomNumbers = new Set();
const minInput = document.getElementById('minValue');
const maxInput = document.getElementById('maxValue');
const countInput = document.getElementById('count');
const resultDisplay = document.getElementById('randomNumbers');

if (isNaN(minValue) || isNaN(maxValue) || isNaN(count) || minValue >= maxValue || count <= 0 || count > (maxValue - minValue + 1)) {
document.getElementById('randomNumbers').innerText = '請確保輸入正確的數值範圍和數量';
const minValue = parseInt(minInput.value);
const maxValue = parseInt(maxInput.value);
const count = parseInt(countInput.value);

if (isNaN(minValue) || isNaN(maxValue) || isNaN(count) || minValue > maxValue || count <= 0 || count > (maxValue - minValue + 1)) {
resultDisplay.textContent = '請確保輸入正確的數值範圍和數量';
return;
}

while (randomNumbers.size < count) {
let randomNumber = Math.floor(Math.random() * (maxValue - minValue + 1)) + minValue;
randomNumbers.add(randomNumber);
const range = maxValue - minValue + 1;
let result = [];

// Performance threshold: 50% density
if (count < range / 2) {
// Low density: Rejection sampling (O(count) on average)
const randomSet = new Set();
while (randomSet.size < count) {
const num = Math.floor(Math.random() * range) + minValue;
randomSet.add(num);
}
result = Array.from(randomSet);
} else {
// High density: Sparse Fisher-Yates (O(count) guaranteed)
// This Map maps 'original index' to 'swapped value'
const map = new Map();
for (let i = 0; i < count; i++) {
const r = Math.floor(Math.random() * (range - i)) + i;
const valI = map.has(i) ? map.get(i) : i;
const valR = map.has(r) ? map.get(r) : r;

result.push(valR + minValue);
map.set(r, valI);
}
}

document.getElementById('randomNumbers').innerText = Array.from(randomNumbers).join(', ');
resultDisplay.textContent = result.join(', ');
}
</script>
</body>
Expand Down