Nested WHILE loops not acting as expected - Javascript / Google Apps Script - javascript

I've got a function that isn't acting as intended. Before I continue, I'd like preface this with the fact that I normally program in Mathematica and have been tasked with porting over a Mathematica function (that I wrote) to JavaScript so that it can be used in a Google Docs spreadsheet. I have about 3 hours of JavaScript experience...
The entire (small) project is calculating the Gross Die per Wafer, given a wafer and die size (among other inputs). The part that isn't working is where I check to see if any corner of the die is outside of the effective radius, Reff.
The function takes a list of X and Y coordinates which, when combined, create the individual XY coord of the center of the die. That is then put into a separate function "maxDistance" that calculates the distance of each of the 4 corners and returns the max. This max value is checked against Reff. If the max is inside the radius, 1 is added to the die count.
// Take a list of X and Y values and calculate the Gross Die per Wafer
function CoordsToGDW(Reff,xSize,ySize,xCoords,yCoords) {
// Initialize Variables
var count = 0;
// Nested loops create all the x,y coords of the die centers
for (var i = 0; i < xCoords.length; i++) {
for (var j = 0; j < yCoords.length, j++) {
// Add 1 to the die count if the distance is within the effective radius
if (maxDistance(xCoords[i],yCoords[j],xSize,ySize) <= Reff) {count = count + 1}
}
}
return count;
}
Here are some examples of what I'm getting:
xArray={-52.25, -42.75, -33.25, -23.75, -14.25, -4.75, 4.75, 14.25, 23.75, 33.25, 42.75, 52.25, 61.75}
yArray={-52.5, -45.5, -38.5, -31.5, -24.5, -17.5, -10.5, -3.5, 3.5, 10.5, 17.5, 24.5, 31.5, 38.5, 45.5, 52.5, 59.5}
CoordsToGDW(45,9.5,7.0,xArray,yArray)
returns: 49 (should be 72)
xArray={-36, -28, -20, -12, -4, 4, 12, 20, 28, 36, 44}
yArray={-39, -33, -27, -21, -15, -9, -3, 3, 9, 15, 21, 27, 33, 39, 45}
CoordsToGDW(32.5,8,6,xArray,yArray)
returns: 39 (should be 48)
I know that maxDistance() is returning the correct values. So, where's my simple mistake?
Also, please forgive me writing some things in Mathematica notation...
Edit #1: A little bit of formatting.
Edit #2: Per showi, I've changed WHILE loops to FOR loops and replaced <= with <. Still not the right answer. It did clean things up a bit though...
Edit #3: What I'm essentially trying to do is take [a,b] and [a,b,c] and return [[a,a],[a,b],[a,c],[b,a],[b,b],[b,c]]
Edit #4:
So it turns out my nested loops are working correctly: when I remove the maxDistance function and replace it with 1 (so that 1 <= Reff is always true), I find that the total number of loop executions is correct.
How I found it: I added some code that just prints out what the function is doing on each loop iteration and saw that X and Y were correct, but the maxDistance function was returning NaN or a very large value when X || Y were positive. I'll look into this function.
Thanks for the help everyone!

If i'm not wrong you're taking one element more than the actually array size when you're doing
while (i <= xCoords.length) {
It should be
while(i < xCoords.length) {
but i prefer
for (var i = 0; i < xCoords.length; i++)
Dunno if it can help :)
And when you're doing var a = {10, 9, 8, 7} it's not an array but a Object, you probly mean var a = []; or it's mathematica thing :)

while (i < xCoords.length) {
j = 0;
while (j < yCoords.length) {
try this

So it turns out my nested loops are working correctly: when I remove the maxDistance function and replace it with 1 (so that 1 <= Reff is always true), I find that the total number of loop executions is correct.
How I found it: I added some code that just prints out what the function is doing on each loop iteration and saw that X and Y were correct, but the maxDistance function was returning NaN or a very large value when X || Y were positive. I'll look into this function.

Related

Codility - Stonewall problem: 100% on correctness but 0% on performance

I'm working on the stonewall exercise of codility. Getting 100% on the correctness tests, but failing all of the performance tests. I'm having trouble envisiging why my solution may be fine for smaller inputs but is going so wrong for larger inputs. Is anyone able to offer feedback about what might be wrong with my solution? I've found this one quite challenging. Taken me a few days of revisiting just to get to this stage! Thanks in advance.
The problem
You are going to build a stone wall. The wall should be straight and N
meters long, and its thickness should be constant; however, it should
have different heights in different places. The height of the wall is
specified by an array H of N positive integers. H[I] is the height of
the wall from I to I+1 meters to the right of its left end. In
particular, H[0] is the height of the wall's left end and H[N−1] is
the height of the wall's right end.
The wall should be built of cuboid stone blocks (that is, all sides of
such blocks are rectangular). Your task is to compute the minimum
number of blocks needed to build the wall.
Write a function:
function solution(H);
that, given an array H of N positive integers specifying the height of
the wall, returns the minimum number of blocks needed to build it.
For example, given array H containing N = 9 integers: H[0] = 8
H[1] = 8 H[2] = 5 H[3] = 7 H[4] = 9 H[5] = 8 H[6] = 7
H[7] = 4 H[8] = 8
the function should return 7. The figure shows one possible
arrangement of seven blocks.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array H is an integer within the range [1..1,000,000,000].
My solution
function solution(H) {
let stones = 0
let absoluteMinimum = Infinity;
let prevStones = []
for (let i = 0; i < H.length; i++) {
if (H[i] < absoluteMinimum) {
stones ++
absoluteMinimum = H[i]
prevStones = [H[i]]
} else if (prevStones.includes(H[i])) {
while (prevStones.includes(H[i])) {
prevStones.pop()
}
prevStones.push(H[i])
} else if (H[i] != H[i-1]) {
prevStones.push(H[i])
stones ++
}
}
return stones
}
Here is the summary of my attempt including test results.
https://app.codility.com/demo/results/training2V8Y42-AUQ/
Following #Teemu's comment, and noting that the code simply is searching prevStones for the existence of a specific height, suggest creating another array that holds the counts of the heights in prevStonesCount.
Eg, if setting prevStones = [ 8 ] then set prevStonesCount[ 8 ] = 1, as there is one stone in the prevStones array of height 8.
Now, rather than having to perform prevStones.includes( 8 ), simply check if 0 < prevStonesCount[ 8 ]. (That is, .includes() searches the entire prevStones array for a height of 8, whereas prevStonesCount[ 8 ] in one step indicates whether any stones of height 8 are in the prevStones array.)
Thus, anytime performing a prevStones.push( x ) or prevStones.pop( x ), make the corresponding adjustment of prevStonesCount[ x ] += 1 or prevStonesCount[ x ] -= 1, respectively.
Note also that within the first if where prevStones = [H[i]], that the prevStones array is essentially cleared and set to an initial value. This means that the prevStonesCount array will also need to be cleared, and then set prevStonesCount[ H[i] ] = 1.

how to return to start when iterating over array and iterator become larger than length (in a graphics render loop)

I'm trying to make an animation recorder that records x,y positions into an array and allow the animation to be recalled. I specifically have p5.js in mind as the graphics lib, but any should work. since this is just array work.
in p5.js to return the value of Sin() or Cos() you can pass them an angle, that angle can be ever incrementing since 2PI == 4PI (in terms of the direction the rotation is facing) etc. I'm looking to replicate this kind of function but to return the data stored in an array.
so for example you've got an array like the following
let demo = ['297', '298', '299', '300']
It would be easy to loop over the array once since it has 4 items, but I'd like to write a function where if we passed in 4, it would return index 0, '297' or if we fed in 11, it would return '300' or if we fed in 22 it would return '299'
this way the function could continually be fed in an ever increasing value that moves up each frame we could return the values of the array in a loop.
let survey = 0;
let demo = ['297', '298', '299', '300']
//a rendering loop
function draw(){
survey ++
let xPos = getPosition(survey) //this getPosition function is the one in question
ellipse(xPos,100,50)
}
I feel like this is some modulo math, but I cant quite get it sorted.
thanks for taking a look!
The solution to your problem is the modulus (%) operator. This operator will return the remainder of the division.
E.g. 11 % 4 = 3
const positions = [297, 298, 299, 300];
function getPosition(positions, i) {
return positions[i % positions.length];
}
console.log(getPosition(positions, 4)); // 297
console.log(getPosition(positions, 11)); // 300
console.log(getPosition(positions, 22)); // 299

Finding the position of the lowest value in a Von Neumann Neighborhood

I have a 2 dimensonal array in Javascript with floats inside. I have to iterate over every item in the array and find the position of the lowest float in a Von Neumann Neighborhood. The problem is I know how I find the lowest value, but not how to find the position of this value in the array.
I think there has to be a simple solution for that, but I just can't get my head around it. I think I have a "programmer's block" :D I hope you understand my problem, english is not my first language.
Background
I tried implementing a hydraulic erosion algorithm to my terrain generator, which I wrote in JavaScript and WebGL. The algorithm I'm trying to use is the optimized hydraulic erosion algorithm described in "Realtime Procedural Terrain Generation" from Jacob Olsen, 2004
If you know how to know the right, you just to do a double loop
function findStuff(array2D){
for(var x = 0, max = array2D.length; x < max; x++){// parse each row
var row = array2D[x];
for(var y = 0, maxY = row.length; y < maxY; y++){// parse each col
// do stuff here
if(anyConditionFilled){
return [x,y];// will return an array with x at index 0, and y at index 1
}
}
}
}
var res = findStuff(myArray2D);
console.log('res : ', res);

How to get proper stack labels with 'datetime' axis?

First off, the fiddle to my question is here: http://jsfiddle.net/pfifas/aTh7F/
The problem
I want to display the sum of the values of all series at each point on the horizontal axis as stack labels above each stack. Because I have negative stacks and I do not want to display positive and negative totals above and beneath separately, I set up a formatter function manually (lines 42 through 50 in the fiddle). The stack labels that I want should be the sum over all values at a given point, i.e. the sum of the positive stacks minus the sum of all negative stacks. E.g. if the data series at the first point is
data: [1,-2,3,4]
I would like the stack label to display a "6" above the stacked bar. My formatter function works fine with data series of the sort
data: [1,-2,3,4]
But once I add a date variable to each series like
data: [
[Date.UTC(2010, 0, 1), 4],
[Date.UTC(2010, 3, 1), 15],
[Date.UTC(2010, 6, 1), 17],
[Date.UTC(2010, 9, 1), 10]
]
the stack labels are not displayed anymore. I think I am making a mistake with the indexing of the array in the formatter function. How do I have to change the indexing to achieve the correct result?
On a different note, where can I learn more about which variables are available inside the formatter environment and how to handle them in highcharts?
Edit:
In response to Onkloss answer, I should highlight that this issue is related to setting the axis to type 'datetime', not to whether the array of data is multidimensional (as the previous question title was suggesting).
The issue is the use of this.x here:
for (i = 0; i < 4; i++) {
sum += series[i].yData[this.x];
}
For "normal" x-axis types this works well since you can open the yData by index. In your case it will end up trying to find something like series[0].yData[1262304000000], which won't work.
I'm not aware of any easy way to find the relationship between the timestamp this.x and which index that has on the x-axis. My solution uses another for loop to compare the timestamp from this.x with the xData array, and if it matches we use the data in the sum, as shown in this updated formatter:
formatter: function () {
// If doing negative, ignore
if(this.total <= 0)
return;
var sum = 0;
var series = this.axis.series;
for (var i = 0; i < series.length; i++){
for(var j = 0; j < series[i].xData.length; j++) {
if(series[i].options.type == 'column' && series[i].xData[j] == this.x) {
sum += series[i].yData[j];
break;
}
}
}
return sum;
}
This updated JSFiddle shows it in action.
If I understand what you're asking for correctly, the following formatter function should work:
formatter: function () {
return this.total >= 0 ?this.total : null ;
},
http://jsfiddle.net/aTh7F/1/
As to the available options in the formatter function, http://api.highcharts.com/highcharts#plotOptions.column.dataLabels.formatter should help. But, I tend to just put a breakpoint in the function and inspect what this is. :)

Javascript points calculating system

I trying to create a points calculating system with javascript, but the problem is with the mathematical part. I have saved on the server the points number, and based on that number I want to decide the level. Sorry for my bad english, I cant explain very well :D. I want something like: level 1 need 0 points
level 2 needs 100 points
level 3 needs 240 points
level 4 needs 420 points
level 5 needs 640 points
and so on....
I need a mathematical function to calculate each level with it. Something that if I know the level to calculate the points needed, and if I know only the points to calculate the level.
To generate the series you've provided use:
function getPoints(level)
{
return 20*(level-1)*(level+3);
}
To get the level from the points is a bit more tricky, you need to invert the above formula using the quadratic formula and then take the positive solution:
function getLevel(points)
{
var level = -1 + Math.sqrt(4 + points/20);
// Round down to nearest level
return Math.floor(level);
}
Also, in the future try and make your questions clearer. As you can see three people (at least) misunderstood your question - it wasn't clear that you set of levels was a mathematical series.
var levels = {
1: 0,
2: 100,
3: 240,
4: 420,
5: 640}
function get_level(points){
for (level in levels){
if (points < levels[level]){
return level - 1;
}
}
}
This simply takes the levels hash and itenerates through the levels, until the points is higher than the level's minimum, returning the last level.
ummm, I have a vague idea of what you're going for
var levels = [0, 100, 240, 420, 640];
function GetLevel(points)
{
for(i == levels.length - 1; i >= 0; i--)
{
if (points >= levels[i]) return i + 1;
}
}
points to next level
function PointsToNextLevel(currentPoints)
{
var level = GetLevel(currentPoints);
if (level == levels.length) return 0;
return levels[level - 1] - currentPoints;
}
this function should solve your problem and, to me, seems very easy to understand:
function getLevel(points)
{
var levels = [0,100, 240, 420, 640];
var maxLevel = levels.length;
var i;
for (i=0;i<maxLevel;i++) {
if (levels[i]>points) return i;
}
return maxLevel;
}

Categories

Resources