Last active
December 20, 2018 23:05
-
-
Save ia7ck/a0de99587e4d57cee8fc1c9d85b4c59f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Zeta</title> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css"> | |
<link href="https://fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet"> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/qs/6.6.0/qs.min.js"></script> | |
</head> | |
<body> | |
<div id="main" style="width: 500px; height: 500px; border: solid 0.5px"> | |
</div> | |
<script defer src="./index.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let n = 4; | |
let BASE_TIMEOUT = 1000; | |
const qs = Qs.parse(document.location.search.slice(1)); | |
if (qs["n"]) { | |
const _n = parseInt(qs["n"]); | |
if (_n === 3 || _n === 4) { | |
n = _n; | |
} | |
} | |
if (qs["speed"]) { | |
const _s = parseInt(qs["speed"]); | |
if (1 <= _s && _s <= 10) { | |
BASE_TIMEOUT /= _s; | |
} | |
} | |
// init | |
let nodes = new vis.DataSet(); | |
let edges = new vis.DataSet(); | |
for (let bit = 0; bit < (1 << n); bit++) { | |
nodes.add({ id: bit, label: toBin(bit) }); | |
} | |
let seen = [], in_deg = []; | |
function rec(bit) { | |
if (!seen[bit]) { | |
seen[bit] = true; | |
in_deg[bit] = 0; | |
for (let i = 0; i < n; i++) { | |
if (bit & (1 << i)) { | |
rec(bit ^ (1 << i)); | |
const from = bit ^ (1 << i), to = bit; | |
edges.add({ from, to }); | |
in_deg[to]++; | |
} | |
} | |
} | |
} | |
rec((1 << n) - 1); | |
let data = { nodes, edges }; | |
const blue = "#B3D4F5", red = "#F5B3B3", selected = "#F59393", green = "#B3F5D4"; | |
const options = { | |
nodes: { | |
color: blue, | |
font: { | |
face: "Lato Regular", | |
bold: { | |
face: "Lato Bold", | |
}, | |
multi: true, | |
}, | |
chosen: false, | |
}, | |
edges: { | |
color: { | |
inherit: false, | |
color: blue, | |
}, | |
arrows: "to", | |
chosen: false, | |
}, | |
layout: { | |
hierarchical: { | |
enabled: true, | |
direction: "DU", | |
sortMethod: "directed", | |
} | |
}, | |
}; | |
const container = document.getElementById("main"); | |
const network = new vis.Network(container, data, options); | |
function toBin(num) { | |
return ("0".repeat(n) + num.toString(2)).slice(-n); | |
} | |
const sleep = (ms) => (new Promise(resolve => setTimeout(resolve, ms))); | |
(async () => { | |
for (let i = 0; i < n; i++) { | |
let edgeIDs = []; | |
for (let bit = 0; bit < (1 << n); bit++) { | |
if ((bit & (1 << i)) == 0) { | |
const from = bit, to = bit ^ (1 << i); | |
edgeIDs.push(getEdgeID(from, to)); | |
} | |
} | |
edges.update(edgeIDs.map((id) => ({ id, color: { color: "#499FF5" } }))) | |
await sleep(BASE_TIMEOUT * 1.5); | |
for (let id of edgeIDs) { | |
const edge = edges.get(id); | |
const from = edge.from, to = edge.to; | |
nodes.update({ | |
id: from, | |
color: selected, | |
label: emph(from, i), | |
}); | |
await sleep(BASE_TIMEOUT); | |
edges.update({ | |
id: id, | |
color: { color: "#F57A7A" }, | |
}); | |
await sleep(BASE_TIMEOUT); | |
nodes.update({ | |
id: to, | |
color: selected, | |
label: emph(to, i), | |
}); | |
await sleep(BASE_TIMEOUT); | |
nodes.update({ | |
id: from, | |
color: red, | |
label: toBin(from), | |
}); | |
if (in_deg[from] > 0) {// 未確定なら青色 | |
nodes.update({ | |
id: from, | |
color: blue, | |
}); | |
} | |
edges.update({ | |
id: id, | |
color: { color: red }, | |
}); | |
nodes.update({ | |
id: to, | |
color: red, | |
label: toBin(to), | |
}); | |
if ((--in_deg[to]) > 0) { // 未確定なら青色 | |
nodes.update({ | |
id: to, | |
color: blue, | |
}); | |
} | |
await sleep(BASE_TIMEOUT); | |
}; | |
} | |
network.on("selectNode", (props) => { | |
if (props.nodes.length > 0) { | |
const nID = props.nodes[0]; | |
let edgeIDs = [], nodeIDs = []; | |
function traverse(i, bit) { | |
nodeIDs.push(bit); | |
for (let j = 0; j < i; j++) { | |
if (bit & (1 << j)) { | |
edgeIDs.push(getEdgeID(bit ^ (1 << j), bit)); | |
traverse(j, bit ^ (1 << j)); | |
} | |
} | |
} | |
traverse(n, nID); | |
nodes.update(nodeIDs.map((id) => ({ id, color: green, borderWidth: 2 }))); | |
edges.update(edgeIDs.map((id) => ({ id, color: { color: green }, width: 2 }))); | |
} | |
}); | |
network.on("deselectNode", (props) => { | |
nodes.update(nodes.getIds().map((id) => ({ id, color: red, borderWidth: 1 }))); | |
edges.update(edges.getIds().map((id) => ({ id, color: { color: red }, width: 1 }))); | |
}); | |
})(); | |
function getEdgeID(from, to) { // あ... | |
const edge = edges.get({ | |
filter: (e) => (e.from === from && e.to === to), | |
}); | |
return edge[0].id; | |
} | |
function emph(bit, i) { // 下からi-bit目を強調 | |
const s = toBin(bit); | |
return s.slice(0, -i - 1) + `<b>${s[s.length - i - 1]}</b>` + s.slice(n - i); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment