Skip to content

Instantly share code, notes, and snippets.

@ia7ck
Last active December 20, 2018 23:05
Show Gist options
  • Save ia7ck/a0de99587e4d57cee8fc1c9d85b4c59f to your computer and use it in GitHub Desktop.
Save ia7ck/a0de99587e4d57cee8fc1c9d85b4c59f to your computer and use it in GitHub Desktop.
<!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>
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