Skip to content

Commit 670aa4c

Browse files
author
snie
committed
init
0 parents  commit 670aa4c

File tree

3 files changed

+322
-0
lines changed

3 files changed

+322
-0
lines changed

css/main.css

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
body {
2+
background: white;
3+
}
4+
5+
#doc {
6+
text-align: center;
7+
}
8+
9+
#vis {
10+
border: solid;
11+
border-width: 0.5;
12+
border-radius: 15px;
13+
}
14+
15+
#svg {
16+
overflow: visible;
17+
width: 1200px;
18+
height: 1000px;
19+
20+
margin-left: 10;
21+
}
22+
23+
24+
#inputValue {
25+
margin: 15px;
26+
margin-top: 20px;
27+
position: absolute;
28+
}
29+
30+
#tooltip {
31+
position: absolute;
32+
display: none;
33+
padding: 10px;
34+
background-color: lightblue;
35+
-webkit-border-radius: 10px;
36+
-moz-border-radius: 10px;
37+
border-radius: 10px;
38+
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
39+
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
40+
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
41+
pointer-events: none;
42+
}

js/main.js

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
/*
2+
Giiven a certain number, calculate the whole tree layout:
3+
- number of nodes at each level
4+
- value of each node
5+
- how many levels (when to stop)
6+
- calculate the node position based on the node number
7+
- calculate the line position based on node position
8+
*/
9+
10+
function fullBfs(node) {
11+
if (input == 0) return;
12+
13+
var tmp = Math.floor(Math.sqrt(node.value));
14+
node.children = [];
15+
for (var i = 1; i <= tmp; i++) {
16+
var child = {
17+
'value': node.value - Math.pow(i, 2),
18+
'parent': node
19+
};
20+
node.children.push(child);
21+
}
22+
23+
for (var i = 0; i < node.children.length; i++) {
24+
fullBfs(node.children[i]);
25+
}
26+
}
27+
28+
function partialBfs(root) {
29+
var calBfs = function() {
30+
if (flag == true) return;
31+
32+
var node = queue.shift();
33+
34+
var tmp = Math.floor(Math.sqrt(node.value));
35+
node.children = [];
36+
for (var i = 1; i <= tmp; i++) {
37+
var child = {
38+
'id': 'circle' + id.toString(),
39+
'value': node.value - Math.pow(i, 2),
40+
'sqrt': i,
41+
'parent': node
42+
};
43+
id++;
44+
node.children.push(child);
45+
}
46+
47+
for (var i = 0; i < node.children.length; i++) {
48+
queue.push(node.children[i]);
49+
if (node.children[i].value == 0) flag = true;
50+
}
51+
52+
calBfs();
53+
}
54+
55+
var id = 1;
56+
var flag = false;
57+
var queue = [];
58+
queue.push(root);
59+
60+
calBfs();
61+
}
62+
63+
64+
65+
function layout(nodeList, levelWidth, levelHeight) {
66+
var calLevelLayout = function(nodeList) {
67+
var nextLevel = [];
68+
69+
var span = levelWidth / nodeList.length;
70+
for (var i = 0; i < nodeList.length; i++) {
71+
nodeList[i].cx = span / 2 + span * i;
72+
nodeList[i].cy = (depth + 1) * levelHeight;
73+
nodeList[i].r = 8;
74+
if (nodeList[i].children) {
75+
for (var j = 0; j < nodeList[i].children.length; j++) {
76+
nextLevel.push(nodeList[i].children[j]);
77+
}
78+
}
79+
}
80+
81+
if (nextLevel.length > 0) {
82+
depth++;
83+
calLevelLayout(nextLevel);
84+
} else {
85+
return;
86+
}
87+
}
88+
89+
var depth = 0;
90+
calLevelLayout(nodeList);
91+
}
92+
93+
94+
function draw(canvas, root) {
95+
var mouseOver = function(node) {
96+
colorList = [];
97+
var tmpNode = node;
98+
var tooltipHtml = root.value.toString() + '=' + node.value.toString() + '+';
99+
100+
while(tmpNode) {
101+
var circle = d3.select('#' + tmpNode.id);
102+
var highlightColor = '#ff4000';
103+
colorList.push(circle.attr('fill'));
104+
circle.attr('fill', highlightColor)
105+
.attr('stroke', highlightColor);
106+
if(tmpNode.parent) {
107+
d3.select('#' + tmpNode.parent.id + '-' + tmpNode.id)
108+
.attr('stroke', highlightColor)
109+
.attr('stroke-width', 2);
110+
tooltipHtml += tmpNode.sqrt.toString() + '<sup>2</sup>' + '+';
111+
}
112+
tmpNode = tmpNode.parent;
113+
}
114+
115+
var xPosition = d3.event.pageX + 8;
116+
var yPosition = d3.event.pageY + 12;
117+
118+
var widthSpace = 150;
119+
var heightSpace = 100;
120+
if (xPosition > window.innerWidth - 100) {
121+
xPosition = d3.event.pageX - widthSpace;
122+
}
123+
124+
if (yPosition > window.innerHeight - 50) {
125+
yPosition = d3.event.pageY - heightSpace;
126+
}
127+
128+
d3.select("#tooltip")
129+
.style("left", xPosition + "px")
130+
.style("top", yPosition + "px")
131+
.style("display", "block")
132+
.select("#tooltip-text")
133+
.html(tooltipHtml.substr(0, tooltipHtml.length-1));
134+
}
135+
136+
var mouseOut = function(node) {
137+
var tmpNode = node;
138+
while(tmpNode) {
139+
d3.select('#' + tmpNode.id)
140+
.attr('fill', colorList.shift())
141+
.attr('stroke', 'black');;
142+
if(tmpNode.parent) {
143+
d3.select('#' + tmpNode.parent.id + '-' + tmpNode.id)
144+
.attr('stroke', 'black')
145+
.attr('stroke-width', 1);
146+
}
147+
tmpNode = tmpNode.parent;
148+
}
149+
d3.select("#tooltip").style("display", "none");
150+
}
151+
152+
153+
var drawNode = function() {
154+
if (queue.length == 0) return;
155+
156+
var node = queue.shift();
157+
158+
if (node.parent) {
159+
d3.select('#' + node.parent.id)
160+
.attr('fill', 'white');
161+
162+
canvas.append('line')
163+
.attr('id', node.parent.id + '-' + node.id)
164+
.attr('x1', node.cx)
165+
.attr('y1', node.cy - node.r)
166+
.attr('x2', node.parent.cx)
167+
.attr('y2', node.parent.cy + node.parent.r)
168+
.attr('stroke', 'black')
169+
.attr('stroke-width', 1);
170+
}
171+
172+
canvas.append('circle')
173+
.attr('id', node.id)
174+
.attr('cx', node.cx)
175+
.attr('cy', node.cy)
176+
.attr('r', node.r)
177+
.attr('fill', 'white')
178+
.attr('stroke', 'black')
179+
.attr('stroke-width', 1)
180+
.attr('fill', function(){
181+
return node.value == 0 ? 'orange' : 'lightgreen';
182+
})
183+
.on('mouseover', function(){
184+
mouseOver(node);
185+
})
186+
.on('mouseout', function(){
187+
mouseOut(node);
188+
});
189+
190+
canvas.append('text')
191+
.attr('x', node.cx - node.r / 3)
192+
.attr('y', node.cy + node.r / 3)
193+
.text(node.value.toString())
194+
.attr('text-anchor', "middle")
195+
.attr('font-size', 8)
196+
.on('mouseover', function(){
197+
mouseOver(node);
198+
})
199+
.on('mouseout', function(){
200+
mouseOut(node);
201+
});
202+
203+
if (node.children) {
204+
for (var i = 0; i < node.children.length; i++) {
205+
queue.push(node.children[i]);
206+
}
207+
}
208+
209+
setTimeout(drawNode, 30);
210+
}
211+
212+
var queue = [];
213+
var colorList;
214+
queue.push(root);
215+
drawNode();
216+
}
217+
218+
function init() {
219+
canvasSize = {
220+
'width': window.innerWidth - 35,
221+
'height': window.innerHeight
222+
};
223+
224+
svgGroup = d3.select('#svg').append('g');
225+
}
226+
227+
function start(value) {
228+
var treeRoot = {};
229+
treeRoot.value = value;
230+
treeRoot.id = 'circle0';
231+
partialBfs(treeRoot);
232+
233+
var nodeList = [];
234+
nodeList.push(treeRoot);
235+
layout(nodeList, canvasSize.width, 120);
236+
237+
if (svgGroup) {
238+
svgGroup.remove();
239+
}
240+
241+
svgGroup = d3.select('#svg').append('g');
242+
243+
draw(svgGroup, treeRoot);
244+
}
245+
246+
var canvasSize;
247+
var svgGroup;
248+
init();
249+
250+
251+
252+
253+
254+
255+

perfect_squares.html

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
</head>
2+
<link rel="stylesheet" type="text/css" href="css/main.css">
3+
</head>
4+
<body>
5+
<div id='doc'>
6+
<p>This is a visualization intended to illustrate a BFS solution of the perfect square problem on Leetcode. Following is the link to the problem and the BFS solution.</p>
7+
<a href="https://leetcode.com/problems/perfect-squares/" target="_blank">Perfect Squares Problem</a>
8+
<br>
9+
<a href="https://discuss.leetcode.com/topic/24255/summary-of-4-different-solutions-bfs-dp-static-dp-and-mathematics" target="_blank">BFS Solution</a>
10+
</div>
11+
12+
<br>
13+
14+
<div id="vis">
15+
<input id='inputValue' type="text" placeholder="input number" onchange="start(this.value)">
16+
<svg id='svg'></svg>
17+
</div>
18+
19+
<div id="tooltip" class="hidden">
20+
<p><span id="tooltip-text"></span></p>
21+
</div>
22+
23+
<script src="https://d3js.org/d3.v3.min.js"></script>
24+
<script src="js/main.js"></script>
25+
</body>

0 commit comments

Comments
 (0)