Editing Highcharts.js donut data programmatically va JS - javascript

I am trying to do the same for donut (editing the donut data programmatically), but the code just wouldn't work for me, although the syntax seems to be straghtforward here.
My goal is to find the data point in the donut which corresponds to the given x-axis value and set the value to 10. Any ideas on this ?
Here's the JSFIddle
btnEdit.click(function() {
// chart.series[0].data[0].update(x += 10); - this code doesn't work
var x = prompt("Please enter your name");
// find the data point that corresponds to x
// Set it to 10
});

Actually, you are looking for a point by its name, not its x value, because x value is a number, name is a string (for categorized data there is natural mapping between those two).
btnEdit.click(function() {
// chart.series[0].data[0].update(x += 10); - this code doesn't work
var i = 0,
points = chart.series[0].data,
len = points.length,
x = prompt("Please enter your name"),
point;
for (; i < len; i++) {
point = points[i];
if (point.name === x) {
point.update({
y: 10
});
break;
}
}
// find the data point that corresponds to x
// Set it to 10
});
Example: http://jsfiddle.net/caLv5d6x/3/
The above solution assumes that you have points which their name are unique - but it doesn't have to be like that.
A small adjustment is enough:
btnEdit.click(function() {
// chart.series[0].data[0].update(x += 10); - this code doesn't work
var x = prompt("Please enter your name");
chart.series[0].data.forEach(function (point) {
if (point.name === x) {
point.update({
y: 10
}, false, false);
}
});
chart.redraw();
// find the data point that corresponds to x
// Set it to 10
});
Example: http://jsfiddle.net/caLv5d6x/4/

Related

Paper Cut into Minimum Number of Squares in JS

I'm trying to convert the algorithme from https://www.geeksforgeeks.org/paper-cut-minimum-number-squares-set-2/
in javascript.
I was able to translate the first algo in js (https://www.geeksforgeeks.org/paper-cut-minimum-number-squares/) easily, but the greedy approach isn't precise enough.
I'm having some issues with js and recursive programming, on my first attempts, I got the Maximum call stack size exceeded error, so I tried to raise it with node --stack-size=10000 <app>, but in this case the script doesn't output anything.
This is what I have right now :
// JS program to find minimum
// number of squares
// to cut a paper using Dynamic Programming
const MAX = 300
let dp = new Array(MAX);
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(MAX).fill(0);
}
// Returns min number of squares needed
function minimumSquare(m, n) {
// Initializing max values to
// vertical_min
// and horizontal_min
let vertical_min = 10000000000
let horizontal_min = 10000000000
// If the given rectangle is
// already a square
if (m === n) {
return 1
}
// If the answer for the given rectangle is
// previously calculated return that answer
if (dp[m][n] !== 0) {
return dp[m][n]
}
// The rectangle is cut horizontally and
// vertically into two parts and the cut
// with minimum value is found for every
// recursive call.
for (let i=1; i<m/2+1; i++) {
// Calculating the minimum answer for the
// rectangles with width equal to n and length
// less than m for finding the cut point for
// the minimum answer
horizontal_min = Math.min(minimumSquare(i, n) + minimumSquare(m-i, n), horizontal_min)
}
for (let j=1; j<n/2+1; j++) {
// Calculating the minimum answer for the
// rectangles with width equal to n and length
// less than m for finding the cut point for
// the minimum answer
vertical_min = Math.min(minimumSquare(m, j) + minimumSquare(m, n-j), vertical_min)
}
// Minimum of the vertical cut or horizontal
// cut to form a square is the answer
dp[m][n] = Math.min(vertical_min, horizontal_min)
return dp[m][n]
}
// Driver code
let m = 30
let n = 35
console.log(minimumSquare(m, n))
//This code is contributed by sahilshelangia
Expected Result would be the minimal number of squares possible in a rectangle of m, n dimensions.
For example, for 30x15 rectangle, the script would output 2.
I have added 2 new conditions to fix the issue. those are
If m is exactly divisible by n then return value m/n
If n is exactly divisible by m then return value n/m
const MAX = 300
let dp = new Array(MAX);
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(MAX).fill(0);
}
// Returns min number of squares needed
function minimumSquare(m, n) {
// Initializing max values to
// vertical_min
// and horizontal_min
let vertical_min = 10000000000
let horizontal_min = 10000000000
// If the given rectangle is
// already a square
if (m === n) {
return 1
}
// If the answer for the given rectangle is
// previously calculated return that answer
if (dp[m][n] !== 0) {
return dp[m][n]
}
if(m%n==0){//if m is exactly divisible by n
dp[m][n] = m/n
return m/n;
}
if(n%m==0){//if n is exactly divisible by m
dp[m][n] = n/m
return n/m;
}
// The rectangle is cut horizontally and
// vertically into two parts and the cut
// with minimum value is found for every
// recursive call.
for (let i=1; i<m/2+1; i++) {
// Calculating the minimum answer for the
// rectangles with width equal to n and length
// less than m for finding the cut point for
// the minimum answer
horizontal_min = Math.min(minimumSquare(i, n) + minimumSquare(m-i, n), horizontal_min)
}
for (let j=1; j<n/2+1; j++) {
// Calculating the minimum answer for the
// rectangles with width equal to n and length
// less than m for finding the cut point for
// the minimum answer
vertical_min = Math.min(minimumSquare(m, j) + minimumSquare(m, n-j), vertical_min)
}
// Minimum of the vertical cut or horizontal
// cut to form a square is the answer
dp[m][n] = Math.min(vertical_min, horizontal_min)
return dp[m][n]
}
// Driver code
let m = 30
let n = 35
console.log(minimumSquare(m, n))

Javascript - Flood-Fill and scanLine algorithms are line-based floods but I want square based floods

I have a flood-fill algorithm (Flood-fill) to fill a 24x24 matrix. I would like to draw a shape as similar to a square using exactly cspots spots for each group as cspots can contain any number. The total of all groups cspots value will equal (24*24) so as the drawing progresses, the areas will become less and less square-like but I would like to keep the semblance of a square. In this example, there are 10 groups of varying cspots values and they need to be all drawn within the 24*24 matrix as square-like as possible. Matrix is 24x24 here but will be bigger with more groups in production. Code:
Main code:
var cspots, // number of spots per group
gArr=[]; // global array which contains all group spots
var tArr = new Array(gArr.length); // touch array for flood-fill
for(var spot in inArr) {
for (var tspot in tArr) // initialise touch array
tArr[tspot]=0;
for(gspot in gArr) { // find lowest open y*24+x ordinal
if (gArr[gspot][0] == 0)
break;
tArr[gspot]=1;
}
cspots = inArr[spot].GD;
userFill(gArr[gspot][1],gArr[gspot][2],inArr[spot].KY,tArr);
}
function userFill(x,y,elem,tArr) {
var gord, qt=0;
if (!cspots) return;
if ((x >= 0) && (x <= 23) && (y >= 0) && (y <= 23)) {
gord = y*24 + x;
if (gArr[gord][0] != 0 || tArr[gord])
return;
gArr[gord][0] = elem;
tArr[gord] = 1;
--cspots;
userFill(x+1,y,elem,tArr);
userFill(x-1,y,elem,tArr);
// before the y-change we need to see if there are any open spots on this line
for(gord=y*24; gord<=(y*24)+23; gord++) {
if (gArr[gord][0] == 0) {
qt=1;
break;
}
}
if (!qt) {
userFill(x,y+1,elem,tArr);
userFill(x,y-1,elem,tArr);
}
}
};
This is a standard flood-fill recursive algorithm (with an accompanying touch array to mark any touches) with the additional code that I check if all x-values are set to non-zero on each x-plane before changing the y-value. This produces a matrix like this:
The problem is that it doesn't look very good (imo) as most of the areas are strung-out along the x-plane. What I want is each different group area to be in the shape of a square as much as I can. Sort-of like this example (using letters to indicate the different group areas):
V V V W W W W X X X X X
V V Y W W W W X X X X Z
Y Y Y W W W W Z Z Z Z Z
Y Y W W W W Z Z Z Z Z
... and so on
So I have changed the userFill to look at a boxX variable which is just the (sqrt of each area)+1, which hopefully I can use to limit each area to make a square-shape. And a preX variable to store the anchor point from each group area so I know how many spots have been added. Here's the new userFill:
Main code:
var tArr = new Array(gArr.length);
for(var spot in inArr) {
for (var tspot in tArr) // initialise touch array
tArr[tspot]=0;
for(gspot in gArr) { // find lowest open y*24+x ordinal
if (gArr[gspot][0] == 0)
break;
tArr[gspot]=1;
}
cspots = inArr[spot].GD;
boxX = Math.ceil(Math.sqrt(cspots));
preX = gArr[gspot][1];
userFill(gArr[gspot][1],gArr[gspot][2],inArr[spot].KY,tArr);
}
function userFill(x,y,elem,tArr) {
var gord, qt=0;
if (!cspots) return;
if ((x >= 0) && (x <= 23) && (y >= 0) && (y <= 23)) {
gord = y*24 + x;
if (gArr[gord][0] != 0 || tArr[gord])
return;
gArr[gord][0] = elem;
tArr[gord] = 1;
--cspots;
// before the x-change we need to see if we have done a boxX number of changes to maintain square-shape
if (Math.abs(x-preX) == boxX) {
userFill(preX,y+1,elem,tArr);
userFill(preX,y-1,elem,tArr);
return;
}
userFill(x+1,y,elem,tArr);
userFill(x-1,y,elem,tArr);
// before the y-change we need to see if there are any open spots on this line
for(gord=y*24; gord<=(y*24)+boxX; gord++) {
if (gArr[gord][0] == 0) {
qt=1;
break;
}
}
if (!qt) {
userFill(x,y+1,elem,tArr);
userFill(x,y-1,elem,tArr);
}
}
};
The only difference is that I check if boxX spots have been added and then call userFill recursively to change the y-plane.
Here's the output and it looks better as most areas are square-like but obviously it needs work (missing most of the spots, pale-blue group area is very oddly-shaped and not square-like at all), but I wonder if there is a better algorithm out there that changes a flood-fill from line-based to square based.
FIXED:
I used a Breadth-First Search which created square-like structures for each group area. The code is:
function bfsFill(x,y,elem,tArr) {
var gord, i=0, pt, queue=[], cnt=0;
if (!cspots) return;
if (isOutOfBounds(x,y)) return;
queue.push([x,y]);
while(cspots>0 && queue.length>0) {
pt = queue.shift();
gord = pt[1]*24 + pt[0];
tArr[gord] = 1;
gArr[gord][0] = elem;
--cspots;
var rArr = neighbours(pt);
async.eachSeries(rArr, function(el, cb2) {
if (!isOutOfBounds(el[0],el[1])) {
gord = el[1]*24 + el[0];
if (tArr[gord] == 0 && gArr[gord][0] == 0) {
for(var qi in queue) {
if (queue[qi][0] == el[0] && queue[qi][1]==el[1]) {
cb2();
return;
}
}
queue.push(el);
}
}
cb2();
}, function(err) {
});
}
};

Swapping imputed values. Z axis optimization. Making smallest value the Z axis

I am making a simple cost estimator. It takes 3 imputed values X,Y,Z and displays a price which is a simple calculation of a value by the z axis (the third of 3 collected values).
You can view the estimator here: http://codepen.io/FredHair/pen/FgJAd
What I would like to add is a checkbox that when clicked would check that the smallest value is stored as the Z axis. So if the user imputed 3 values and the X or Y value was the smallest then that value would be swapped with with the z axis value.
How would I go about writing a function for this?
Any help would be greatly appreciated even in pseudo code, which I could then write myself.
I have made a checkbox:
<input type="checkbox" id="zAxis">Z Axis Optimization<br>
This is my function for the Estimator:
//Calc with Switch//
function calculator(){
var x = Number(document.getElementById("x").value);
var y = Number(document.getElementById("y").value);
var z = Number(document.getElementById("z").value);
var p = Number(3);
var result;
var calc = document.getElementById("choice").value
switch(calc){
case"1" : result = z * p;
break;
case"2" : result = (z * p) + 50;
break;
case"3" : result = (z * p) + 30;
break;
}
//Display Result//
document.getElementById("result").innerHTML = " = £ " + result;
I know I will need to write a function like:
IF (x<=y && <=z) then do something
OR (y<=y && <=x) then do something
But any help will be greatly appreciated.
Here is Codepen again: http://codepen.io/FredHair/pen/FgJAd
Thanks in advance.

Use jquery to dynamically number table columns diagonally

Hi there fellow coders,
I'm looking to find a way to fill a pre-built dynamic blank table with numbering (and colouring if possible) like so:
As you can see the numbering is ascending order diagonally. I know there's probably some way to calculate the number based on the tables td index but can't quite figure out how to do that for every column diagonally. Any help would be appreciated.
Update: Ok back from my Holidays. Thanks to all you clever people for your replies. As I'm sure you've all had to experience the pain in the neck clients can be, I've been told the spec has changed(again). This being the case I've had to put the grid/matrix into a database and output using a pivot table. Every square has to be customizable color-wise.
Nothing is going to waste though I have learnt quite a few nifty new javascript/jquery tricks from your responses I didn't know about before, so thanks, and I'll be sure to pay it forward :)
Here's what I came up with in the end.
Given you said "colouring if possible" I'll provide an example solution that doesn't do colours quite the way you want (it does it in a way that I found easier to code and more attractive to look at) but which does handle all the numbering correctly for varying table sizes.
The function below assumes the table already exists; in this demo I've included code that generates a table to whatever size you specify and then calls the function below to do the numbering and colours.
function numberDiagonally(tableId) {
var rows = document.getElementById(tableId).rows,
numRows = rows.length,
numCols = rows[0].cells.length,
sq = numRows + numCols - 1,
d, x, y,
i = 1,
dc,
c = -1,
colors = ["green","yellow","orange","red"];
diagonalLoop:
for (d = 0; d < sq; d++) {
dc = "diagonal" + d;
for (y = d, x = 0; y >= 0; y--, x++) {
if (x === numCols)
continue diagonalLoop;
if (y < numRows)
$(rows[y].cells[x]).html(i++).addClass(dc);
}
}
for (d = 0; d < sq; d++)
$(".diagonal" + d).css("background-color", colors[c=(c+1)%colors.length]);
}
Demo: http://jsfiddle.net/7NZt3/2
The general idea I came up with was to imagine a square twice as big as whichever of the x and y dimensions is bigger and then use a loop to create diagonals from the left edge of that bounding square going up and to the right - i.e., in the order you want the numbers. EDIT: Why twice as big as longer side? Because that's the first thing that came into my head when I started coding it and it worked (note that the variable i that holds the numbers that get displayed is not incremented for the imaginary cells). Now that I've had time to think, I realise that my sq variable can be set precisely to one less than the number of rows plus the columns - a number that ends up rather smaller for non-square tables. Code above and fiddle updated accordingly.
Note that the background colours could be set directly in the first loop, but instead I opted to assign classes and set the loops for each class later. Seemed like a good idea at the time because it meant individual diagonals could be easily selected in jQuery with a single class selector.
Explaining exactly how the rest works is left as an exercise for the reader...
UPDATE - this version does the colouring more like you asked for: http://jsfiddle.net/7NZt3/1/ (in my opinion not as pretty, but each to his own).
This fiddle populates an existing table with numbers and colors. It is not limited to being a 5x5 table. I didn't understand the logic of 15 being orange rather than yellow, so I simply grouped the diagonal cells into color regions.
// we're assuming the table exists
var $table = $('table'),
// cache the rows for quicker access
$rows = $table.find('tr'),
// determine number of rows
_rows = $rows.length,
// determine number of cells per row
_cols = $rows.first().children().length,
// determine total number of cells
max = _rows * _cols,
// current diagonal offset (for coloring)
d = 1,
// current row
r = 0,
// current cell
c = 0;
for (var i=1; i <= max; i++) {
// identify and fill the cell we're targeting
$rows.eq(r).children().eq(c)
.addClass('d' + d)
.text(i);
if (i < max/2) {
// in the first half we make a "line-break" by
// moving one row down and resetting to first cell
if (!r) {
r = c + 1;
c = 0;
d++;
continue;
}
} else {
// in the second half our "line-break" changes to
// moving to the last row and one cell to the right
if (c + 1 == _cols) {
c = 1 + r;
r = _rows -1;
d++;
continue;
}
}
r--;
c++;
}
Here's a jsFiddle that does what you asked for - http://jsfiddle.net/jaspermogg/MzNr8/8/
I took the liberty of making it a little bit user-customisable; it's interesting to see how long it takes the browser to render a 1000x1000 table using this method :-D
Assuming that each cell has an id of [column]x[row], here are teh codez for how to fill in the numbers of a square table of side length sidelength.
//populate the cells with numbers according to the spec
function nums(){
var xpos = 0
var ypos = 0
var cellval = 1
for(i=0;i<2*sidelength;i++){
if(i >= sidelength){
ypos = sidelength - 1
xpos = 1 + i - sidelength
$('td#' + xpos + 'x' + ypos).text(cellval)
cellval = cellval + 1
while(xpos + 1 < sidelength){
ypos = ypos-1
xpos = xpos+1
$('td#' + xpos + 'x' + ypos).text(cellval)
cellval = cellval + 1
}
} else {
ypos = i
xpos = 0
$('td#' + xpos + 'x' + ypos).text(cellval)
cellval = cellval + 1
while(!(ypos-1 < 0)){
ypos = ypos-1
xpos = xpos+1
$('td#' + xpos + 'x' + ypos).text(cellval)
cellval = cellval + 1
}
}
}
}
And here they are for how to colour the bugger.
// color the cells according to the spec
function cols(){
if(+$('td#0x0').text() === 99){
return false
} else {
$('td').each(function(index, element){
if(+$(this).text() > 22)
{
$(this).attr("bgcolor", "red")
}
if(+$(this).text() <= 22)
{
$(this).attr("bgcolor", "orange")
}
if(+$(this).text() <= 14)
{
$(this).attr("bgcolor", "yellow")
}
if(+$(this).text() <= 6)
{
$(this).attr("bgcolor", "green")
}
})
}
}
Enjoy, eh? :-)

Difficulties in converting an recursive algorithm into an iterative one

I've been trying to implement a recursive backtracking maze generation algorithm in javascript. These were done after reading a great series of posts on the topic here
While the recursive version of the algorithm was a no brainer, the iterative equivalent has got me stumped.
I thought I understood the concept, but my implementation clearly produces incorrect results. I've been trying to pin down a bug that might be causing it, but I am beginning to believe that my problems are being caused by a failure in logic, but of course I am not seeing where.
My understanding of the iterative algorithm is as follows:
A stack is created holding representations of cell states.
Each representation holds the coordinates of that particular cell, and a list of directions to access adjacent cells.
While the stack isn't empty iterate through the directions on the top of the stack, testing adjacent cells.
If a valid cell is found place it at the top of the stack and continue with that cell.
Here is my recursive implementation ( note: keydown to step forward ): http://jsbin.com/urilan/14
And here is my iterative implementation ( once again, keydown to step forward ): http://jsbin.com/eyosij/2
Thanks for the help.
edit: I apologize if my question wasn't clear. I will try to further explain my problem.
When running the iterative solution various unexpected behaviors occur. First and foremost, the algorithm doesn't exhaust all available options before backtracking. Rather, it appears to be selecting cells at a random when there is one valid cell left. Overall however, the movement doesn't appear to be random.
var dirs = [ 'N', 'W', 'E', 'S' ];
var XD = { 'N': 0, 'S':0, 'E':1, 'W':-1 };
var YD = { 'N':-1, 'S':1, 'E':0, 'W': 0 };
function genMaze(){
var dirtemp = dirs.slice().slice(); //copies 'dirs' so its not overwritten or altered
var path = []; // stores path traveled.
var stack = [[0,0, shuffle(dirtemp)]]; //Stack of instances. Each subarray in 'stacks' represents a cell
//and its current state. That is, its coordinates, and which adjacent cells have been
//checked. Each time it checks an adjacent cell a direction value is popped from
//from the list
while ( stack.length > 0 ) {
var current = stack[stack.length-1]; // With each iteration focus is to be placed on the newest cell.
var x = current[0], y = current[1], d = current[2];
var sLen = stack.length; // For testing whether there is a newer cell in the stack than the current.
path.push([x,y]); // Store current coordinates in the path
while ( d.length > 0 ) {
if( stack.length != sLen ){ break;}// If there is a newer cell in stack, break and then continue with that cell
else {
var cd = d.pop();
var nx = x + XD[ cd ];
var ny = y + YD[ cd ];
if ( nx >= 0 && ny >= 0 && nx < w && ny < h && !cells[nx][ny] ){
dtemp = dirs.slice().slice();
cells[nx][ny] = 1;
stack.push( [ nx, ny, shuffle(dtemp) ] ); //add new cell to the stack with new list of directions.
// from here the code should break from the loop and start again with this latest addition being considered.
}
}
}
if (current[2].length === 0){stack.pop(); } //if all available directions have been tested, remove from stack
}
return path;
}
I hope that helps clear up the question for you. If it is still missing any substance please let me know.
Thanks again.
I'm not very good in javascript, but I try to implement your recursive code to iterative. You need to store For index on stack also. So code look like:
function genMaze(cx,cy) {
var dirtemp = dirs; //copies 'dirs' so its not overwritten
var path = []; // stores path traveled.
var stack = [[cx, cy, shuffle(dirtemp), 0]]; // we also need to store `for` indexer
while (stack.length > 0) {
var current = stack[stack.length - 1]; // With each iteration focus is to be placed on the newest cell.
var x = current[0], y = current[1], d = current[2], i = current[3];
if (i > d.length) {
stack.pop();
continue;
}
stack[stack.length - 1][3] = i + 1; // for next iteration
path.push([x, y]); // Store current coordinates in the path
cells[x][y] = 1;
var cd = d[i];
var nx = x + XD[cd];
var ny = y + YD[cd];
if (nx >= 0 && ny >= 0 && nx < w && ny < h && !cells[nx][ny]) {
dtemp = dirs;
stack.push([nx, ny, shuffle(dtemp), 0]);
}
}
return path;
}
Does this little code could also help ?
/**
Examples
var sum = tco(function(x, y) {
return y > 0 ? sum(x + 1, y - 1) :
y < 0 ? sum(x - 1, y + 1) :
x
})
sum(20, 100000) // => 100020
**/
function tco(f) {
var value, active = false, accumulated = []
return function accumulator() {
accumulated.push(arguments)
if (!active) {
active = true
while (accumulated.length) value = f.apply(this, accumulated.shift())
active = false
return value
}
}
}
Credits, explanations ans more infos are on github https://gist.github.com/1697037
Is has the benefit to not modifying your code, so it could be applied in other situations too. Hope that helps :)

Categories