Here is the code for it below here. Anyone reading this is more than welcome to use it.
Simple instructions
Copy the entire code below except for [code] and [/code] at the top and bottom, into Notepad or similar, and save it as: pick-3-reduction-tool.html
Then -> double-click the saved file to use it.
No internet needed. :-)
[code]<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pick 3 Reduction Tool</title>
<style>
:root {
color-scheme: light;
--blue:#124f86;
--blue2:#eaf4ff;
--green:#16833a;
--line:#cbd9e6;
--ink:#17212b;
}
* { box-sizing: border-box; }
body {
margin:0;
background:#edf3f8;
color:var(--ink);
font:16px/1.45 Arial,Helvetica,sans-serif;
}
.app {
width:min(920px,calc(100% - 24px));
margin:24px auto;
background:white;
border:1px solid var(--line);
border-radius:14px;
box-shadow:0 8px 28px #284a6818;
overflow:hidden;
}
header { padding:22px 24px; color:white; background:linear-gradient(135deg,#0f4777,#1970ad); }
h1 { margin:0 0 4px; font-size:clamp(24px,4vw,34px); }
header p { margin:0; opacity:.93; }
main { padding:22px; }
.positions { display:grid; grid-template-columns:repeat(3,1fr); gap:14px; }
fieldset {
min-width:0;
margin:0;
padding:14px;
border:1px solid var(--line);
border-radius:10px;
background:#fbfdff;
}
legend { padding:0 7px; font-weight:700; color:var(--blue); }
.mini { display:flex; gap:7px; margin-bottom:10px; }
button { border:0; border-radius:7px; padding:9px 13px; font-weight:700; cursor:pointer; }
.mini button {
flex:1;
padding:7px 8px;
color:var(--blue);
background:var(--blue2);
border:1px solid #b9d4ec;
}
.digits { display:grid; grid-template-columns:repeat(2,minmax(50px,1fr)); gap:5px; }
label {
display:flex;
align-items:center;
gap:8px;
padding:5px 7px;
border-radius:6px;
cursor:pointer;
}
label:hover { background:var(--blue2); }
input[type=checkbox] { width:19px; height:19px; accent-color:var(--green); }
.note { margin:16px 0 0; padding:11px 13px; border-left:4px solid #edae25; background:#fff8e6; }
.actions { display:flex; flex-wrap:wrap; gap:9px; margin:18px 0; }
.primary { color:white; background:var(--blue); }
.copy { color:white; background:var(--green); }
.secondary { color:#263645; background:#e7edf2; }
.summary {
display:flex;
justify-content:space-between;
gap:12px;
align-items:center;
padding:12px 14px;
border:1px solid var(--line);
border-radius:9px 9px 0 0;
background:#f5f9fc;
font-weight:700;
}
#results {
min-height:100px;
max-height:360px;
overflow:auto;
padding:15px;
border:1px solid var(--line);
border-top:0;
border-radius:0 0 9px 9px;
background:white;
font:17px/1.75 Consolas,"Courier New",monospace;
word-spacing:7px;
overflow-wrap:anywhere;
}
.empty { color:#697887; font-family:Arial,Helvetica,sans-serif; word-spacing:normal; }
footer {
padding:14px 22px;
text-align:center;
color:#5c6872;
background:#f4f7fa;
border-top:1px solid var(--line);
font-size:14px;
}
@media (max-width:650px) {
.positions { grid-template-columns:1fr; }
.digits { grid-template-columns:repeat(5,1fr); }
main { padding:15px; }
}
</style>
</head>
<body>
<div class="app">
<header>
<h1>Pick 3 Reduction Tool</h1>
<p>Select the digits allowed in each position. An empty position is treated as 0–9.</p>
</header>
<main>
<div class="positions" id="positions"></div>
<div class="note">
<strong>Example:</strong> Select 1 in Position 1 and 5 in
Position 2, leaving Position 3 empty, to produce 150 through 159.
</div>
<div class="actions">
<button class="primary" id="generate" type="button">Generate Numbers</button>
<button class="copy" id="copy" type="button">Copy Results</button>
<button class="secondary" id="clear" type="button">Clear All</button>
<button class="secondary" id="all" type="button">Select All Digits</button>
</div>
<div class="summary"><span>Number Pool</span><span id="count">1,000 numbers</span></div>
<div id="results" aria-live="polite"></div>
</main>
<footer>
Runs entirely on your computer. No internet connection or
installation is required.
</footer>
</div>
<script>
const positions = document.getElementById('positions');
const results = document.getElementById('results');
const count = document.getElementById('count');
for (let p = 0; p < 3; p++) {
const box = document.createElement('fieldset');
box.innerHTML = `<legend>Position ${p + 1}</legend>
<div class="mini">
<button type="button" data-action="all">All</button>
<button type="button" data-action="none">None</button>
</div>
<div class="digits">${Array.from(
{length:10},
(_,d) => `<label><input type="checkbox"
data-position="${p}" value="${d}" checked> ${d}</label>`
).join('')}</div>`;
positions.appendChild(box);
}
function selected(position) {
const query = `input[data-position="${position}"]:checked`;
const values = [...document.querySelectorAll(query)]
.map(x => x.value);
return values.length ? values : ['0','1','2','3','4','5','6','7','8','9'];
}
function generate() {
const a = selected(0), b = selected(1), c = selected(2), pool = [];
for (const x of a) for (const y of b) for (const z of c) pool.push(x + y + z);
results.textContent = pool.join(' ');
results.classList.remove('empty');
const word = pool.length === 1 ? 'number' : 'numbers';
count.textContent = `${pool.length.toLocaleString()} ${word}`;
}
positions.addEventListener('click', event => {
const button = event.target.closest('button[data-action]');
if (!button) return;
const checked = button.dataset.action === 'all';
button.closest('fieldset').querySelectorAll('input')
.forEach(box => box.checked = checked);
generate();
});
positions.addEventListener('change', generate);
document.getElementById('generate').addEventListener('click', generate);
document.getElementById('clear').addEventListener('click', () => {
document.querySelectorAll('input[type=checkbox]').forEach(box => box.checked = false);
results.innerHTML = `<span class="empty">
All positions are empty, so each position currently acts as
0–9. Select one or more digits to reduce the pool.
</span>`;
count.textContent = '1,000 numbers';
});
document.getElementById('all').addEventListener('click', () => {
document.querySelectorAll('input[type=checkbox]').forEach(box => box.checked = true);
generate();
});
document.getElementById('copy').addEventListener('click', async event => {
const text = results.textContent.trim();
try {
await navigator.clipboard.writeText(text);
} catch (_) {
const area = document.createElement('textarea');
area.value = text;
document.body.appendChild(area);
area.select();
document.execCommand('copy');
area.remove();
}
const button = event.currentTarget, old = button.textContent;
button.textContent = 'Copied!'; setTimeout(() => button.textContent = old, 1200);
});
generate();
</script>
</body>
</html>
[/code]