Skip to content

Instantly share code, notes, and snippets.

@brookjordan
Last active March 31, 2026 12:58
Show Gist options
  • Select an option

  • Save brookjordan/f0cb0c01278e78d18f4ba0841df11d3c to your computer and use it in GitHub Desktop.

Select an option

Save brookjordan/f0cb0c01278e78d18f4ba0841df11d3c to your computer and use it in GitHub Desktop.
/**
* Outputs something like:
*
* Top 5:
* 1. 96282600 (36.5) — pair 00, palindrome 62826, ends-00, touches: pair 00 + palindrome 62826
* 2. 97557734 (32.3) — near-run 975, pair 55, pair 77, palindrome 7557, overlaps: near-run 975 ∩ pair 55, overlaps: near-run 975 ∩ palindrome 7557, touches: pair 55 + pair 77, overlaps: pair 77 ∩ palindrome 7557
* 3. 96699348 (31.6) — pair 66, pair 99, palindrome 9669, touches: pair 66 + pair 99, overlaps: pair 99 ∩ palindrome 9669
* 4. 96644427 (31.4) — triple 444, pair 66, touches: triple 444 + pair 66
* 5. 96332109 (27.9) — run4 3210, pair 33, start=end, overlaps: run4 3210 ∩ pair 33
*
**/
/** export const numbers = [
* '96282600',
* '97557734',
* '96699348',
* '96644427',
* '96332109',
* ]
**/
import { numbers } from './numbers.ts';
type Pattern = { start: number; end: number; score: number; label: string };
function overlaps(a: Pattern, b: Pattern): boolean {
return a.start < b.end && b.start < a.end;
}
function touches(a: Pattern, b: Pattern): boolean {
return a.end === b.start || b.end === a.start;
}
// quadratic run scoring: 3→4, 4→10, 5→18, 6→28
const runScore = (len: number) => len < 3 ? 0 : len * len - len * 2;
const nearRunScore = (len: number) => Math.round(runScore(len) * 0.4);
function getPatterns(n: string): Pattern[] {
const d = n.split('').map(Number);
const h = n.length / 2;
const patterns: Pattern[] = [];
const coveredByRun = new Set<number>();
const add = (start: number, end: number, score: number, label: string) => {
const containsZero = d.slice(start, end).includes(0);
patterns.push({ start, end, score: containsZero ? score * 1.4 : score, label });
};
// --- Runs (strictly monotonic, quadratic scoring, no double-counting) ---
for (let i = 0; i < d.length; i++) {
for (const dir of ['asc', 'desc'] as const) {
let len = 1;
while (i + len < d.length && (dir === 'asc' ? d[i+len] === d[i+len-1]+1 : d[i+len] === d[i+len-1]-1)) len++;
if (len >= 3 && !coveredByRun.has(i)) {
add(i, i+len, runScore(len), `run${len} ${d.slice(i,i+len).join('')}`);
for (let k = i; k < i+len; k++) coveredByRun.add(k);
}
}
}
// --- Near-runs (step of 2, asc or desc) ---
const coveredByNearRun = new Set<number>();
for (let i = 0; i < d.length; i++) {
for (const dir of ['asc', 'desc'] as const) {
let len = 1;
while (i + len < d.length && (dir === 'asc' ? d[i+len] - d[i+len-1] === 2 : d[i+len-1] - d[i+len] === 2)) len++;
if (len >= 3 && !coveredByNearRun.has(i)) {
add(i, i+len, nearRunScore(len), `near-run ${d.slice(i,i+len).join('')}`);
for (let k = i; k < i+len; k++) coveredByNearRun.add(k);
}
}
}
// --- Triplets first, then pairs not inside a triple ---
const coveredByTriple = new Array(d.length).fill(false);
for (let i = 0; i < d.length - 2; i++)
if (d[i] === d[i+1] && d[i+1] === d[i+2]) {
add(i, i+3, 15, `triple ${d[i]}${d[i+1]}${d[i+2]}`);
coveredByTriple[i] = coveredByTriple[i+1] = coveredByTriple[i+2] = true;
}
for (let i = 0; i < d.length - 1; i++)
if (d[i] === d[i+1] && !coveredByTriple[i] && !coveredByTriple[i+1])
add(i, i+2, 6, `pair ${d[i]}${d[i+1]}`);
// --- Substring palindromes (longest only per position, even=odd-1 except 8) ---
const coveredByPalindrome = new Array(d.length).fill(false);
for (let len = d.length; len >= 4; len--) {
for (let i = 0; i <= d.length - len; i++) {
const sub = n.slice(i, i+len);
if (sub === sub.split('').reverse().join('')) {
const alreadyCovered = Array.from({length: len}, (_, k) => coveredByPalindrome[i+k]).every(Boolean);
if (!alreadyCovered) {
const effectiveLen = len % 2 === 0 && len < 8 ? len - 1 : len;
add(i, i+len, Math.round(4 + (effectiveLen - 1) * 1.5), `palindrome ${sub}`);
for (let k = i; k < i+len; k++) coveredByPalindrome[k] = true;
}
}
}
}
// --- Repeated units (2-3 digit substrings appearing 2+ times) ---
// Leading echoes (unit starts at pos 0 or 1) score higher
const coveredByUnit = new Set<number>();
for (let unitLen = 3; unitLen >= 2; unitLen--) {
for (let i = 0; i <= n.length - unitLen * 2; i++) {
const unit = n.slice(i, i + unitLen);
const positions = [i];
let search = i + unitLen;
while (search <= n.length - unitLen) {
const idx = n.indexOf(unit, search);
if (idx === -1) break;
positions.push(idx);
search = idx + unitLen;
}
if (positions.length < 2) continue;
if (positions.some(p => coveredByUnit.has(p))) continue;
const first = positions[0], last = positions[positions.length - 1];
const gap = last - first - unitLen;
// 2-digit echoes: gap <= 2 and gap must be consistent (same spacing throughout)
if (unitLen === 2 && gap > 2) continue;
if (unitLen === 2) {
// check the offset before first unit matches the gap
const offsetBefore = first;
const offsetAfter = n.length - (last + unitLen);
// allow start/end of number to be 0, otherwise spacing must match gap
const validSpacing = offsetBefore === offsetAfter ||
offsetBefore === 0 || offsetAfter === 0;
if (!validSpacing) continue;
}
const baseScore = unitLen === 3 ? 11 : 4;
const gapPenalty = Math.min(gap * 0.5, 3);
const countBonus = (positions.length - 2) * 2;
const leadingBonus = unitLen === 3 ? (first === 0 ? 5 : first === 1 ? 2.5 : 0) : 0;
const pts = baseScore - gapPenalty + countBonus + leadingBonus;
if (pts > 0) {
add(first, last + unitLen, pts, `repeat${unitLen} ${unit}`);
positions.forEach(p => { for (let k = p; k < p + unitLen; k++) coveredByUnit.add(k); });
}
}
}
const repeatUnits = new Set(patterns.filter(p => p.label.startsWith('repeat')).map(p => p.label.split(' ')[1]));
for (let rhymeLen = h; rhymeLen >= 2; rhymeLen--) {
if (n.slice(h - rhymeLen, h) === n.slice(n.length - rhymeLen)) {
const unit = n.slice(h - rhymeLen, h);
if (repeatUnits.has(unit)) break;
const pts = rhymeLen === h ? 6 + rhymeLen * 5 : rhymeLen === 2 ? 6 : 2 + rhymeLen * 4;
add(h - rhymeLen, n.length, pts, `rhyme${rhymeLen} ...${unit}`);
break;
}
}
// --- End anchors ---
if (n.endsWith('000')) add(n.length-3, n.length, 10, 'ends-000');
else if (n.endsWith('00')) add(n.length-2, n.length, 6, 'ends-00');
else if (n.endsWith('0')) add(n.length-1, n.length, 2, 'ends-0');
// --- Start/end same digit — flat bonus, no range so it can't stack overlaps ---
if (d[0] === d[d.length-1]) patterns.push({ start: -1, end: -1, score: 3, label: 'start=end' });
return patterns;
}
function score(n: string): number {
const d = n.split('').map(Number);
const patterns = getPatterns(n);
let s = patterns.reduce((acc, p) => acc + p.score, 0);
for (let i = 0; i < patterns.length; i++)
for (let j = i+1; j < patterns.length; j++) {
const a = patterns[i], b = patterns[j];
const aInsideB = a.start >= b.start && a.end <= b.end;
const bInsideA = b.start >= a.start && b.end <= a.end;
const aPalin = a.label.startsWith('palindrome');
const bPalin = b.label.startsWith('palindrome');
if (overlaps(a, b) || (a.start === b.start && a.end === b.end)) {
if ((aInsideB && bPalin) || (bInsideA && aPalin)) continue;
if ((a.label.startsWith('ends-0') && b.label === 'pair 00') ||
(b.label.startsWith('ends-0') && a.label === 'pair 00')) continue;
if (a.start < 0 || b.start < 0) continue;
// rhyme/repeat are meta-patterns, exclude from overlap bonuses
const isRhymeOrRepeat = (p: Pattern) => p.label.startsWith('rhyme') || p.label.startsWith('repeat');
if (isRhymeOrRepeat(a) || isRhymeOrRepeat(b)) continue;
s += Math.min(a.score, b.score);
} else if (touches(a, b)) {
if (a.start < 0 || b.start < 0) continue;
if ((a.label.startsWith('ends-0') && b.label === 'pair 00') ||
(b.label.startsWith('ends-0') && a.label === 'pair 00')) continue;
const isAnchor = (p: Pattern) => p.label.startsWith('ends-');
const isRhymeOrRepeat = (p: Pattern) => p.label.startsWith('rhyme') || p.label.startsWith('repeat');
if (isRhymeOrRepeat(a) || isRhymeOrRepeat(b)) continue;
if (isAnchor(a) || isAnchor(b)) { s += 1; continue; }
const la = a.end - a.start, lb = b.end - b.start;
const lens = [la, lb].sort((x, y) => x - y);
s += (lens[0] === 2 && lens[1] >= 3) ? 7 : 1;
}
}
// --- Red flag: 4 unique digits in a window with no pattern covering it ---
for (let i = 0; i <= d.length - 4; i++) {
const window = d.slice(i, i+4);
// a pattern covers this window if it overlaps any part of it
const hasPattern = patterns.some(p => p.start < i+4 && p.end > i);
if (new Set(window).size >= 4 && !hasPattern) s -= 3;
}
// prefix
if (n.startsWith('96')) s += 3;
else if (n.startsWith('97')) s += 2;
else if (n.startsWith('98')) s += 1;
// high average digit
const avg = d.reduce((a, b) => a + b, 0) / d.length;
s += (avg - 5) * 1.5;
// low unique digit count
const unique = new Set(d).size;
s += Math.max(0, (5 - unique) * 2);
// all digits >= 5
if (d.every(x => x >= 5)) s += 4;
return s;
}
function explain(n: string): string[] {
const d = n.split('').map(Number);
const patterns = getPatterns(n);
const labels = patterns.map(p => p.label);
for (let i = 0; i < patterns.length; i++)
for (let j = i+1; j < patterns.length; j++) {
const a = patterns[i], b = patterns[j];
const aInsideB = a.start >= b.start && a.end <= b.end;
const bInsideA = b.start >= a.start && b.end <= a.end;
const aPalin = a.label.startsWith('palindrome');
const bPalin = b.label.startsWith('palindrome');
const sameDigits = (a.label.startsWith('ends-0') && b.label === 'pair 00') ||
(b.label.startsWith('ends-0') && a.label === 'pair 00');
if (overlaps(a, b) || (a.start === b.start && a.end === b.end)) {
if ((aInsideB && bPalin) || (bInsideA && aPalin) || sameDigits || a.start < 0 || b.start < 0) continue;
const isRhymeOrRepeatE = (p: Pattern) => p.label.startsWith('rhyme') || p.label.startsWith('repeat');
if (isRhymeOrRepeatE(a) || isRhymeOrRepeatE(b)) continue;
labels.push(`overlaps: ${a.label} ∩ ${b.label}`);
} else if (touches(a, b)) {
if (a.start < 0 || b.start < 0 || sameDigits) continue;
const isAnchor = (p: Pattern) => p.label.startsWith('ends-');
const isRhymeOrRepeatE = (p: Pattern) => p.label.startsWith('rhyme') || p.label.startsWith('repeat');
if (isRhymeOrRepeatE(a) || isRhymeOrRepeatE(b)) continue;
if (!(isAnchor(a) || isAnchor(b)))
labels.push(`touches: ${a.label} + ${b.label}`);
}
}
for (let i = 0; i <= d.length - 4; i++) {
const window = d.slice(i, i+4);
const hasPattern = patterns.some(p => p.start < i+4 && p.end > i);
if (new Set(window).size >= 4 && !hasPattern)
labels.push(`red-flag ${window.join('')}`);
}
return labels;
}
const rankedNums = numbers
.map((n) => ({ n, s: score(n) }))
.sort((a, b) => b.s - a.s);
console.log('Top 100:');
rankedNums
.slice(0, 100)
.forEach(({ n, s }, i) => {
const why = explain(n).join(', ');
console.log(`${String(i+1).padStart(2)}. ${n} (${s.toFixed(1)}) — ${why}`);
});
@brookjordan
Copy link
Copy Markdown
Author

Yes, it’s vibe coded.

I’m organising numbers.

Sue me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment