Color the edges of the graph below using the two buttons. Try to avoid creating any triangle where all three edges share a color. With 5 vertices you can sometimes succeed — but with 6, Ramsey theory says it is impossible.
<p class="hint">Color the edges of the complete graph. Two colors: <b style="color:#c92f3c">Red</b> and <b style="color:#1d7abd">Blue</b>. Try to avoid any triangle where all three edges share a color. Select a color, then click edges to paint them.</p>
<div class="controls">
<button id="btn-red" class="color-btn red active" type="button">● Red</button>
<button id="btn-blue" class="color-btn blue" type="button">● Blue</button>
<span id="size-label">Vertices: <b id="nval">6</b></span>
<button id="btn-less" type="button" class="ghost sm">−</button>
<button id="btn-more" type="button" class="ghost sm">+</button>
</div>
<svg id="graph" width="300" height="300" viewBox="0 0 300 300"></svg>
<div class="status" id="status">Color edges, then press Check.</div>
<div class="btns">
<button id="btn-check" type="button">Check for triangles</button>
<button id="btn-random" type="button">Random coloring</button>
<button id="btn-reset" type="button" class="ghost">Clear</button>
</div>
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .6rem; line-height: 1.45; }
.controls { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .5rem; }
.color-btn { font: 600 13px system-ui; padding: .3rem .75rem; border-radius: 20px; cursor: pointer; border: 2px solid transparent; background: #e8eef3; color: #444; }
.color-btn.red { border-color: #e63946; }
.color-btn.blue { border-color: #1d7abd; }
.color-btn.active.red { background: #e63946; color: #fff; }
.color-btn.active.blue { background: #1d7abd; color: #fff; }
#size-label { font-size: .88rem; margin-left: .4rem; color: #555; }
svg { display: block; margin: 0 auto .3rem; }
line.edge { stroke: #ccc; stroke-width: 3; cursor: pointer; transition: stroke .12s; }
line.edge:hover { stroke-width: 5; }
line.edge.red { stroke: #e63946; }
line.edge.blue { stroke: #1d7abd; }
line.edge.highlight { stroke-width: 6; opacity: 1; }
circle.vertex { fill: #1d3557; }
text.label { font: 700 11px system-ui; fill: #fff; text-anchor: middle; dominant-baseline: central; pointer-events: none; }
.status { font-size: .95rem; font-weight: 600; margin: .4rem 0; min-height: 1.4em; }
.status.ok { color: #0a7d33; }
.status.bad { color: #c92f3c; }
.status.info { color: #1d3557; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
button { font: 600 13px system-ui; padding: .4rem .85rem; border: 1px solid #1d3557; background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
button.sm { padding: .3rem .6rem; font-size: 14px; }
const fmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// Ramsey theory demo: 2-color edges of a complete graph.
// R(3,3)=6 guarantees a monochromatic triangle exists in any 2-coloring of K6.
// We let the user try to avoid one; with n>=6 it's provably impossible.
let n = 6;
let currentColor = 'red';
const edgeColor = {}; // "i,j" -> 'red'|'blue'|null
const svg = document.getElementById('graph');
const W = 300, H = 300, R = 115, CX = 150, CY = 150;
function edgeKey(i, j) { return i < j ? i+','+j : j+','+i; }
function vertexPos(i) {
const angle = (2 * Math.PI * i / n) - Math.PI / 2;
return { x: CX + R * Math.cos(angle), y: CY + R * Math.sin(angle) };
}
function buildGraph() {
svg.innerHTML = '';
// Draw edges first (behind vertices)
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
const k = edgeKey(i, j);
const pi = vertexPos(i), pj = vertexPos(j);
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', pi.x); line.setAttribute('y1', pi.y);
line.setAttribute('x2', pj.x); line.setAttribute('y2', pj.y);
line.setAttribute('class', 'edge' + (edgeColor[k] ? ' ' + edgeColor[k] : ''));
line.dataset.key = k;
line.addEventListener('click', () => {
edgeColor[k] = currentColor;
buildGraph();
document.getElementById('status').textContent = 'Color edges, then press Check.';
document.getElementById('status').className = 'status';
});
svg.appendChild(line);
}
}
// Draw vertices on top
for (let i = 0; i < n; i++) {
const p = vertexPos(i);
const c = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
c.setAttribute('cx', p.x); c.setAttribute('cy', p.y); c.setAttribute('r', 13);
c.setAttribute('class', 'vertex');
svg.appendChild(c);
const t = document.createElementNS('http://www.w3.org/2000/svg', 'text');
t.setAttribute('x', p.x); t.setAttribute('y', p.y);
t.setAttribute('class', 'label');
t.textContent = i + 1;
svg.appendChild(t);
}
}
function findMonochromaticTriangle(color) {
for (let i = 0; i < n; i++)
for (let j = i + 1; j < n; j++)
for (let k = j + 1; k < n; k++) {
if (edgeColor[edgeKey(i,j)] === color &&
edgeColor[edgeKey(i,k)] === color &&
edgeColor[edgeKey(j,k)] === color) {
return [i, j, k];
}
}
return null;
}
function highlightTriangle(tri, color) {
const [a, b, c] = tri;
const pairs = [[a,b],[a,c],[b,c]];
svg.querySelectorAll('line.edge').forEach(line => {
const k = line.dataset.key;
if (pairs.some(([x,y]) => edgeKey(x,y) === k)) {
line.classList.add('highlight');
}
});
}
function check() {
const uncolored = [];
for (let i = 0; i < n; i++)
for (let j = i+1; j < n; j++)
if (!edgeColor[edgeKey(i,j)]) uncolored.push(edgeKey(i,j));
if (uncolored.length > 0) {
setStatus(fmt('Color all %v% edges first (%length% remaining).', { v: n*(n-1)/2, length: uncolored.length }), 'info');
return;
}
const redTri = findMonochromaticTriangle('red');
const blueTri = findMonochromaticTriangle('blue');
if (redTri) {
highlightTriangle(redTri, 'red');
setStatus(fmt('Red triangle found: vertices %map%. Order is unavoidable!', { map: redTri.map(x=>x+1).join('–') }), 'bad');
console.log('Red triangle:', redTri);
} else if (blueTri) {
highlightTriangle(blueTri, 'blue');
setStatus(fmt('Blue triangle found: vertices %map%. Order is unavoidable!', { map: blueTri.map(x=>x+1).join('–') }), 'bad');
console.log('Blue triangle:', blueTri);
} else {
if (n >= 6) {
setStatus(fmt('No monochromatic triangle yet — but with %n% vertices Ramsey theory says one must exist! Check all edges.', { n: n }), 'info');
} else {
setStatus(fmt('✓ No monochromatic triangle! With only %n% vertices it can be avoided.', { n: n }), 'ok');
}
}
}
function randomColoring() {
for (let i = 0; i < n; i++)
for (let j = i+1; j < n; j++)
edgeColor[edgeKey(i,j)] = Math.random() < 0.5 ? 'red' : 'blue';
buildGraph();
setStatus('Random coloring applied. Press Check to find the triangle.', 'info');
}
function setStatus(t, cls) {
const s = document.getElementById('status');
s.textContent = t;
s.className = 'status ' + (cls || '');
}
document.getElementById('btn-red').addEventListener('click', () => {
currentColor = 'red';
document.getElementById('btn-red').classList.add('active');
document.getElementById('btn-blue').classList.remove('active');
});
document.getElementById('btn-blue').addEventListener('click', () => {
currentColor = 'blue';
document.getElementById('btn-blue').classList.add('active');
document.getElementById('btn-red').classList.remove('active');
});
document.getElementById('btn-check').addEventListener('click', check);
document.getElementById('btn-random').addEventListener('click', randomColoring);
document.getElementById('btn-reset').addEventListener('click', () => {
Object.keys(edgeColor).forEach(k => delete edgeColor[k]);
buildGraph();
setStatus('Color edges, then press Check.', '');
});
document.getElementById('btn-less').addEventListener('click', () => {
if (n > 3) { n--; Object.keys(edgeColor).forEach(k => delete edgeColor[k]); document.getElementById('nval').textContent = n; buildGraph(); setStatus('Color edges, then press Check.',''); }
});
document.getElementById('btn-more').addEventListener('click', () => {
if (n < 8) { n++; Object.keys(edgeColor).forEach(k => delete edgeColor[k]); document.getElementById('nval').textContent = n; buildGraph(); setStatus('Color edges, then press Check.',''); }
});
buildGraph();
<p class="hint">Color the edges of the complete graph. Two colors: <b style="color:#c92f3c">Red</b> and <b style="color:#1d7abd">Blue</b>. Try to avoid any triangle where all three edges share a color. Select a color, then click edges to paint them.</p>
<div class="controls">
<button id="btn-red" class="color-btn red active" type="button">● Red</button>
<button id="btn-blue" class="color-btn blue" type="button">● Blue</button>
<span id="size-label">Vertices: <b id="nval">6</b></span>
<button id="btn-less" type="button" class="ghost sm">−</button>
<button id="btn-more" type="button" class="ghost sm">+</button>
</div>
<svg id="graph" width="300" height="300" viewBox="0 0 300 300"></svg>
<div class="status" id="status">Color edges, then press Check.</div>
<div class="btns">
<button id="btn-check" type="button">Check for triangles</button>
<button id="btn-random" type="button">Random coloring</button>
<button id="btn-reset" type="button" class="ghost">Clear</button>
</div>
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .6rem; line-height: 1.45; }
.controls { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .5rem; }
.color-btn { font: 600 13px system-ui; padding: .3rem .75rem; border-radius: 20px; cursor: pointer; border: 2px solid transparent; background: #e8eef3; color: #444; }
.color-btn.red { border-color: #e63946; }
.color-btn.blue { border-color: #1d7abd; }
.color-btn.active.red { background: #e63946; color: #fff; }
.color-btn.active.blue { background: #1d7abd; color: #fff; }
#size-label { font-size: .88rem; margin-left: .4rem; color: #555; }
svg { display: block; margin: 0 auto .3rem; }
line.edge { stroke: #ccc; stroke-width: 3; cursor: pointer; transition: stroke .12s; }
line.edge:hover { stroke-width: 5; }
line.edge.red { stroke: #e63946; }
line.edge.blue { stroke: #1d7abd; }
line.edge.highlight { stroke-width: 6; opacity: 1; }
circle.vertex { fill: #1d3557; }
text.label { font: 700 11px system-ui; fill: #fff; text-anchor: middle; dominant-baseline: central; pointer-events: none; }
.status { font-size: .95rem; font-weight: 600; margin: .4rem 0; min-height: 1.4em; }
.status.ok { color: #0a7d33; }
.status.bad { color: #c92f3c; }
.status.info { color: #1d3557; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
button { font: 600 13px system-ui; padding: .4rem .85rem; border: 1px solid #1d3557; background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
button.sm { padding: .3rem .6rem; font-size: 14px; }
const fmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// Ramsey theory demo: 2-color edges of a complete graph.
// R(3,3)=6 guarantees a monochromatic triangle exists in any 2-coloring of K6.
// We let the user try to avoid one; with n>=6 it's provably impossible.
let n = 6;
let currentColor = 'red';
const edgeColor = {}; // "i,j" -> 'red'|'blue'|null
const svg = document.getElementById('graph');
const W = 300, H = 300, R = 115, CX = 150, CY = 150;
function edgeKey(i, j) { return i < j ? i+','+j : j+','+i; }
function vertexPos(i) {
const angle = (2 * Math.PI * i / n) - Math.PI / 2;
return { x: CX + R * Math.cos(angle), y: CY + R * Math.sin(angle) };
}
function buildGraph() {
svg.innerHTML = '';
// Draw edges first (behind vertices)
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
const k = edgeKey(i, j);
const pi = vertexPos(i), pj = vertexPos(j);
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', pi.x); line.setAttribute('y1', pi.y);
line.setAttribute('x2', pj.x); line.setAttribute('y2', pj.y);
line.setAttribute('class', 'edge' + (edgeColor[k] ? ' ' + edgeColor[k] : ''));
line.dataset.key = k;
line.addEventListener('click', () => {
edgeColor[k] = currentColor;
buildGraph();
document.getElementById('status').textContent = 'Color edges, then press Check.';
document.getElementById('status').className = 'status';
});
svg.appendChild(line);
}
}
// Draw vertices on top
for (let i = 0; i < n; i++) {
const p = vertexPos(i);
const c = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
c.setAttribute('cx', p.x); c.setAttribute('cy', p.y); c.setAttribute('r', 13);
c.setAttribute('class', 'vertex');
svg.appendChild(c);
const t = document.createElementNS('http://www.w3.org/2000/svg', 'text');
t.setAttribute('x', p.x); t.setAttribute('y', p.y);
t.setAttribute('class', 'label');
t.textContent = i + 1;
svg.appendChild(t);
}
}
function findMonochromaticTriangle(color) {
for (let i = 0; i < n; i++)
for (let j = i + 1; j < n; j++)
for (let k = j + 1; k < n; k++) {
if (edgeColor[edgeKey(i,j)] === color &&
edgeColor[edgeKey(i,k)] === color &&
edgeColor[edgeKey(j,k)] === color) {
return [i, j, k];
}
}
return null;
}
function highlightTriangle(tri, color) {
const [a, b, c] = tri;
const pairs = [[a,b],[a,c],[b,c]];
svg.querySelectorAll('line.edge').forEach(line => {
const k = line.dataset.key;
if (pairs.some(([x,y]) => edgeKey(x,y) === k)) {
line.classList.add('highlight');
}
});
}
function check() {
const uncolored = [];
for (let i = 0; i < n; i++)
for (let j = i+1; j < n; j++)
if (!edgeColor[edgeKey(i,j)]) uncolored.push(edgeKey(i,j));
if (uncolored.length > 0) {
setStatus(fmt('Color all %v% edges first (%length% remaining).', { v: n*(n-1)/2, length: uncolored.length }), 'info');
return;
}
const redTri = findMonochromaticTriangle('red');
const blueTri = findMonochromaticTriangle('blue');
if (redTri) {
highlightTriangle(redTri, 'red');
setStatus(fmt('Red triangle found: vertices %map%. Order is unavoidable!', { map: redTri.map(x=>x+1).join('–') }), 'bad');
console.log('Red triangle:', redTri);
} else if (blueTri) {
highlightTriangle(blueTri, 'blue');
setStatus(fmt('Blue triangle found: vertices %map%. Order is unavoidable!', { map: blueTri.map(x=>x+1).join('–') }), 'bad');
console.log('Blue triangle:', blueTri);
} else {
if (n >= 6) {
setStatus(fmt('No monochromatic triangle yet — but with %n% vertices Ramsey theory says one must exist! Check all edges.', { n: n }), 'info');
} else {
setStatus(fmt('✓ No monochromatic triangle! With only %n% vertices it can be avoided.', { n: n }), 'ok');
}
}
}
function randomColoring() {
for (let i = 0; i < n; i++)
for (let j = i+1; j < n; j++)
edgeColor[edgeKey(i,j)] = Math.random() < 0.5 ? 'red' : 'blue';
buildGraph();
setStatus('Random coloring applied. Press Check to find the triangle.', 'info');
}
function setStatus(t, cls) {
const s = document.getElementById('status');
s.textContent = t;
s.className = 'status ' + (cls || '');
}
document.getElementById('btn-red').addEventListener('click', () => {
currentColor = 'red';
document.getElementById('btn-red').classList.add('active');
document.getElementById('btn-blue').classList.remove('active');
});
document.getElementById('btn-blue').addEventListener('click', () => {
currentColor = 'blue';
document.getElementById('btn-blue').classList.add('active');
document.getElementById('btn-red').classList.remove('active');
});
document.getElementById('btn-check').addEventListener('click', check);
document.getElementById('btn-random').addEventListener('click', randomColoring);
document.getElementById('btn-reset').addEventListener('click', () => {
Object.keys(edgeColor).forEach(k => delete edgeColor[k]);
buildGraph();
setStatus('Color edges, then press Check.', '');
});
document.getElementById('btn-less').addEventListener('click', () => {
if (n > 3) { n--; Object.keys(edgeColor).forEach(k => delete edgeColor[k]); document.getElementById('nval').textContent = n; buildGraph(); setStatus('Color edges, then press Check.',''); }
});
document.getElementById('btn-more').addEventListener('click', () => {
if (n < 8) { n++; Object.keys(edgeColor).forEach(k => delete edgeColor[k]); document.getElementById('nval').textContent = n; buildGraph(); setStatus('Color edges, then press Check.',''); }
});
buildGraph();
No matter what coloring you try on 6 vertices, the demo will find a monochromatic triangle. The proof of R(3,3) = 6 is elegant: fix any vertex — it has 5 edges. By the pigeonhole principle, at least 3 must share a color. Among those 3 neighbors, any edge between them creates a triangle; if there is none, those 3 form a triangle in the opposite color.
Comments
Loading comments...