i need help in that
You are again the owner of a coworking space like WeWork and your office building is rectangular. You team just created many wall partitions to create mini offices for startups. Your office campus is represented by a 2D array of 1s (floor spaces) and 0s (walls). Each point on this array is a one foot by one foot square. Before renting to tenants, you want to reserve an office for yourself. You wish to fit the largest possible rectangular table in your office, and you will select the office that fits this table. The table sides will always be parallel to the boundaries of the office building. What is the area of the biggest table that can fit in your office?
Functions
biggestTable() has one parameter:
grid: a 2D grid/array of 1s and 0s
Input Format
For some of our templates, we have handled parsing for you. If we do not provide you a parsing function, you will need to parse the input directly. In this problem, our input format is as follows:
The first line is the number of rows in the 2D array
The second line is the number of columns in the 2D array
The rest of the input contains the data to be processed
Here is an example of the raw input:
4
5
11110
11010
11000
00000
Expected Output
Return the area of the biggest area made of 1s in the grid. Assume the grid is surrounded by 0s (walls).
Constraints
Assume that the bounds of the array are the following:
The total amount of elements in the array: width x height <= 10^6
Example
Example biggestTable() Input
grid:
[[1, 0, 1, 1, 1],
[1, 0, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 0, 0, 1, 0]]
Example Output
9
Solution
The top right of the grid consists of a rectangle with nine 1s in it, the biggest possible space for our table.
The problem can be approached in a logical way where you loop through the building and check for potential space where tables can be placed, then just return the biggest table found:
function biggestTable(grid) {
const tableExist = (x, y, w, h) => {
let exist = 1;
for(let i = 0; i < w ; i++) {
for(let j = 0; j < h ; j++) {
exist &= grid[j + y] !== undefined && grid[j + y][i + x] == 1;
}
}
return exist;
};
const biggestTableAt = (x, y) => {
let max = 0;
for(let w = 1; w <= grid[0].length; w++) {
for(let h = 1; h <= grid.length; h++) {
const table_size = w * h;
if (tableExist(x, y, w, h) && table_size>max) {
max = table_size;
}
}
}
return max;
};
let max = 0;
for(let x = 0; x < grid[0].length; x++) {
for(let y= 0; y < grid.length; y++) {
const table_size = biggestTableAt(x, y);
if (table_size > max) {
max = table_size;
}
}
}
return max;
}
Related
I'm doing this problem on leetcode:
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
My logic is to find the minimum number in each array and add that to the sum.
This is my code in javascript:
var minimumTotal = function(triangle) {
let sum = 0;
for (let i = 0; i < triangle.length; i++) {
sum += Math.min.apply(null, triangle[i])
}
return sum;
};
But it doesn't work for this test case: [[-1],[2,3],[1,-1,-3]].
The expected output is -1. I'm confused how it should equal -1, because -1 + 2 = 1 and none of the numbers in third array equal -1 when summed with 1.
I looked at the discussion answers and they all used some sort of dynamic programming solution.
What am I doing wrong?
There is a path where the output should be -1.
[
[ -1 ],
[ 2, 3 ],
[ 1, -1, -3 ],
]
-1 + 3 - 3 = -1
The problem is that you only have 2 possible branches at each fork, whereas it appears you're taking the lowest number from the entire row.
Under the rules of the challenge, you shouldn't be able to go from 2 in the second row to -3 in the third row, which would be the most efficient path under your approach.
What you are doing does not seem to follow the desired data structure of the problem. You are generating an int, while the desired output should be an array.
The correct answers are already posted in the discussion board:
This solution is an accepted one (just tested it):
JavaScript
var minimumTotal = function(triangle) {
for (let row = triangle.length - 2; row > -1; row--)
for (let col = 0; col < triangle[row].length; col++)
triangle[row][col] += Math.min(triangle[-~row][col], triangle[-~row][-~col])
return triangle[0][0]
}
-~row is the same as row + 1 (bitwise version).
Reference
Explains it here
If you might be interested in Python and Java, these are "accepted" solutions:
Python
class Solution:
def minimumTotal(self, triangle):
if not triangle:
return
dp = triangle[-1]
for row in range(len(triangle) - 2, -1, -1):
for col in range(len(triangle[row])):
dp[col] = min(dp[col], dp[-~col]) + triangle[row][col]
return dp[0]
Java
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int[] dp = new int[-~triangle.size()];
for (int row = triangle.size() - 1; row > -1; row--)
for (int col = 0; col < triangle.get(row).size(); col++)
dp[col] = Math.min(dp[col], dp[-~col]) + triangle.get(row).get(col);
return dp[0];
}
}
For each step, you may move to an adjacent number of the row below. More formally, if you are on index i on the current row, you may move to either index i or index i + 1 on the next row.
The above statement is part of the question and it helps to create a graph like this.
Dynamic programming is used where we have problems, which can be divided into similar sub-problems, so that their results can be re-used. We start from the bottom and determine which minimum value we take and then we are going to be using that minimum value above. That is why we use dynamic programming here. Now each row gets 1 size bigger, so you can imagine under the last row, we have 4 0's.
that is why in dynamic programming we always create an array whose size is always 1 greater than the original array. We fill the array with default values. I will be explaining in python but later on I will challenge myself to write in javascript. first, initialize the dp array
dp=[0]*(len(triangle)+1) #[[0],[0],[0],[0]]
Now, we are starting from the level=[1,-1,3]. For this level, since the bottom is full of 0's, our dp array will be
dp=[1,-1,-3,0]
now we are moving above level, level=[2,3], but we are using the data from the bottom. (That is why we are using dynamic programming). From 2, its index is 0, so I ask myself what is the minimum between 0'th and 1'st value of the dp array. Whichever is minimum we add it to 2? Obviously, -1 is minimum, 2+(-1)=1 and dp gets updated.
dp=[1, -1, -3, 0]
We do the same for 3. its index is 1, and we ask what is the min(-1,3), because 3 is pointing to -1 and 3 and then we add -1 to 3 which is 2. new dp
dp=[1,0,-3,0]
Now we are at the root level. -1 and its index is 0. We ask what is min value of index 0'th and index 1'st of the dp array. min(1,0)=0 and we add it to -1. dp gets updated
dp=[-1,0,3,0]
and finally, we return dp[0]=0
Here is the code in python:
from typing import List
class Solution:
def min_total(self,triangle:List[List[int]])->int:
# dp[] is the bottom row
dp=[0]*(len(triangle)+1)
// triangle[::-1] says start from the last element of triangle
for row in triangle[::-1]:
for i,n in enumerate(row):
dp[i]=n+min(dp[i],dp[i+1])
return dp[0]
Here is javascript code:
function minPath(triangle) {
let dp = new Array(triangle.length + 1).fill(0);
for (let row = triangle.length - 1; row >= 0; row--) {
for (let i = 0; i <= triangle[row].length - 1; i++) {
dp[i] = triangle[row][i] + Math.min(dp[i], dp[i + 1]);
}
}
console.log(dp);
return dp[0];
}
const triangle = [[-1], [2, 3], [1, -1, -3]];
console.log(minPath(triangle));
As this was brought back up, it's worth pointing out that the dynamic programming technique discussed in answers and comments can be done very simply with a reduceRight:
const minSum = (triangle) =>
triangle .reduceRight ((ms, ns) => ns .map (
(n, i) => n + (i > ms.length ? ms[i] : Math .min (ms [i], ms [i + 1]))
)) [0]
console .log (minSum ([[-1], [2, 3], [1, -1, -3]])) //=> -1
console .log (minSum ([[2], [3, 4], [6, 5, 7], [4, 1, 8, 3]])) //=> 11
console .log (minSum ([[-10]])) //=> -10
At each step we calculate the minimum paths through all the elements in a row. ms is the minimum paths through the row below (and on the initial pass will just be the bottom row) and for each n in our row ns, if we're at the rightmost element, we just copy the value from the corresponding row below, otherwise we take the minimum of the element right below and the one to its right.
Since this is called a triangle, I think we can assume that the first row has only one element. But if that's not the case, we could simply take the minimum of the results rather than taking the first element in the final value. That is, we could replace triangle .reduceRight ( ... ) [0] with Math .min (... triangle .reduceRight ( ... )).
/*
[120] Triangle
https://leetcode.com/problems/triangle/description/
*/
import java.util.List;
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
if (triangle.size() == 0)
return 0;
int rows = triangle.size();
int cols = triangle.get(rows - 1).size();
int[] tmp = new int[cols];
int index = 0;
for (int var : triangle.get(rows - 1)) {
tmp[index++] = var;
}
for (int i = rows - 2; i >= 0; i--) {
for (int j = 0; j <= triangle.get(i).size() - 1; j++) {
tmp[j] = triangle.get(i).get(j) + Math.min(tmp[j], tmp[j + 1]);
}
}
return tmp[0];
}
}
I've just implemented a topological sort algorithm on my isometric game using this guide: https://mazebert.com/2013/04/18/isometric-depth-sorting/
The issue
Here's a little example (this is just a drawing to illustrate my problem because as we say, a picture is worth a thousand words), what I'm expecting is in left and the result of the topological sorting algorithm is in right
So in the right image, the problem is that the box is drawn BEFORE the character and I'm expecting it to be drawn AFTER like in the left image.
Code of the topological sorting algorithm (Typescript)
private TopologicalSort2() {
// https://mazebert.com/2013/04/18/isometric-depth-sorting/
for(var i = 0; i < this.Stage.children.length; i++) {
var a = this.Stage.children[i];
var behindIndex = 0;
for(var j = 0; j < this.Stage.children.length; j++) {
if(i == j) {
continue;
}
var b = this.Stage.children[j];
if(!a.isoSpritesBehind) {
a.isoSpritesBehind = [];
}
if(!b.isoSpritesBehind) {
b.isoSpritesBehind = [];
}
if(b.posX < a.posX + a.sizeX && b.posY < a.posY + a.sizeY && b.posZ < a.posZ + a.sizeZ) {
a.isoSpritesBehind[behindIndex++] = b;
}
}
a.isoVisitedFlag = 0;
}
var _sortDepth = 0;
for(var i = 0; i < this.Stage.children.length; ++i) {
visitNode(this.Stage.children[i]);
}
function visitNode(n: PIXI.DisplayObject) {
if(n.isoVisitedFlag == 0) {
n.isoVisitedFlag = 1;
if(!n.isoSpritesBehind) {
return;
}
for(var i = 0; i < n.isoSpritesBehind.length; i++) {
if(n.isoSpritesBehind[i] == null) {
break;
} else {
visitNode(n.isoSpritesBehind[i]);
n.isoSpritesBehind[i] = null;
}
}
n.isoDepth = _sortDepth++;
}
}
this.Stage.children.sort((a, b) => {
if(a.isoDepth - b.isoDepth != 0) {
return a.isoDepth - b.isoDepth;
}
return 0;
});
}
Informations
Player:
posX: [the x coordinate of the player]
posY: [the y coordinate of the player]
posZ: 0
sizeX: 1
sizeY: 1
sizeZ: 1
Box:
posX: [the x coordinate of the box]
posY: [the y coordinate of the box]
posZ: 0
sizeX: 3
sizeY: 1
sizeZ: 1
X and Y axis
Do you have any idea of the source of this problem? and maybe how to solve it?
The way to determine whether one object is before the other requires a bit more linear algebra.
First of all, I would suggest to translate the coordinates from the "world" coordinates to the "view" 2D coordinates, i.e. to the rows and columns of the display.
Note also that the original Z coordinate does not influence the sort order (imagine that an object would be lifted up along the Z axis: we can find a sort order where this move would not have any impact). So the above-mentioned translation could assume all points are at Z=0.
Let's take this set-up, but depicted from "above", so when looking along the Z axis down to the game floor:
In the picture there are 7 objects, numbered from 0 to 6. The line of view in the game would be from the bottom-left of this picture. The coordinate system in which I would suggest to translate some points is depicted with the red row/col axis.
The white diagonals in each object link the two points that would be translated and used in the algorithm. The assumption is that when one object is in front of another, their diagonal lines will not intersect. If they would, it would mean that objects are overlapping each other in the game world, which would mean they are like gasses, not solids :) I will assume this is not the case.
One object A could be in front of another object B when in the new coordinate system, the left-most column coordinate of B falls between the two column coordinates of A (or vice versa). There might not really be such an overlap when their Z coordinates differ enough, but we can ignore that, because when there is no overlap we can do no harm in specifying a certain order anyway.
Now, when the coordinates indicate an overlap, the coordinates of diagonals (of A and B) must be compared with some linear algebra formula, which will determine which one is in front of the other.
Here is your adapted function that does that:
topologicalSort() {
// Exit if sorting is a non-operation
if (this.Stage.children.length < 2) return;
// Add two translated coordinates, where each of the resulting
// coordinates has a row (top to bottom) and column
// (left to right) part. They represent a position in the final
// rendered view (the screen).
// The two pairs of coordinates are translations of the
// points (posX + sizeX, Y, 0) and (posX, posY + sizeY, 0).
// Z is ignored (0), since it does not influence the order.
for (let obj of this.Stage.children) {
obj.leftCol = obj.posY - obj.posX - obj.sizeX;
obj.rightCol = obj.posY - obj.posX + obj.sizeY;
obj.leftRow = obj.posY + obj.posX + obj.sizeX;
obj.rightRow = obj.posY + obj.posX + obj.sizeY;
obj.isoSpritesBehind = [];
}
for(let i = 0; i < this.Stage.children.length; i++) {
let a = this.Stage.children[i];
// Only loop over the next objects
for(let j = i + 1; j < this.Stage.children.length; j++) {
let b = this.Stage.children[j];
// Get the two objects in order of left column:
let c = b.leftCol < a.leftCol ? b : a;
let d = b.leftCol < a.leftCol ? a : b;
// See if they overlap in the view (ignoring Z):
if (d.leftCol < c.rightCol) {
// Determine which is behind: some linear algebra
if (d.leftRow <
(d.leftCol - c.leftCol)/(c.rightCol - c.leftCol)
* (c.rightRow - c.leftRow) + c.leftRow) {
// c is in front of d
c.isoSpritesBehind.push(d);
} else { // d is in front of c
d.isoSpritesBehind.push(c);
}
} // in the else-case it does not matter which one comes first
}
}
// This replaces your visitNode function and call:
this.Stage.children.forEach(function getDepth(obj) {
// If depth was already assigned, this node was already visited
if (!obj.isoDepth) {
// Get depths recursively, and retain the maximum of those.
// Add one more to get the depth for the current object
obj.isoDepth = obj.isoSpritesBehind.length
? 1+Math.max(...obj.isoSpritesBehind.map(getDepth))
: 1; // Depth when there is nothing behind it
}
return obj.isoDepth; // Return it for easier recursion
});
// Sort like you did, but in shorter syntax
this.Stage.children.sort((a, b) => a.isoDepth - b.isoDepth);
}
I add a snippet where I completed the class with a minimum of code, enough to make it run and output the final order in terms of object index numbers (as they were originally inserted):
class Game {
constructor() {
this.Stage = { children: [] };
}
addObject(posX, posY, posZ, sizeX, sizeY, sizeZ) {
this.Stage.children.push({posX, posY, posZ, sizeX, sizeY, sizeZ,
id: this.Stage.children.length}); // add a unique id
}
topologicalSort() {
// Exit if sorting is a non-operation
if (this.Stage.children.length < 2) return;
// Add two translated coordinates, where each of the resulting
// coordinates has a row (top to bottom) and column
// (left to right) part. They represent a position in the final
// rendered view (the screen).
// The two pairs of coordinates are translations of the
// points (posX + sizeX, Y, 0) and (posX, posY + sizeY, 0).
// Z is ignored (0), since it does not influence the order.
for (let obj of this.Stage.children) {
obj.leftCol = obj.posY - obj.posX - obj.sizeX;
obj.rightCol = obj.posY - obj.posX + obj.sizeY;
obj.leftRow = obj.posY + obj.posX + obj.sizeX;
obj.rightRow = obj.posY + obj.posX + obj.sizeY;
obj.isoSpritesBehind = [];
}
for(let i = 0; i < this.Stage.children.length; i++) {
let a = this.Stage.children[i];
// Only loop over the next objects
for(let j = i + 1; j < this.Stage.children.length; j++) {
let b = this.Stage.children[j];
// Get the two objects in order of left column:
let c = b.leftCol < a.leftCol ? b : a;
let d = b.leftCol < a.leftCol ? a : b;
// See if they overlap in the view (ignoring Z):
if (d.leftCol < c.rightCol) {
// Determine which is behind: some linear algebra
if (d.leftRow <
(d.leftCol - c.leftCol)/(c.rightCol - c.leftCol)
* (c.rightRow - c.leftRow) + c.leftRow) {
// c is in front of d
c.isoSpritesBehind.push(d);
} else { // d is in front of c
d.isoSpritesBehind.push(c);
}
} // in the else-case it does not matter which one comes first
}
}
// This replaces your visitNode function and call:
this.Stage.children.forEach(function getDepth(obj) {
// If depth was already assigned, this node was already visited
if (!obj.isoDepth) {
// Get depths recursively, and retain the maximum of those.
// Add one more to get the depth for the current object
obj.isoDepth = obj.isoSpritesBehind.length
? 1+Math.max(...obj.isoSpritesBehind.map(getDepth))
: 1; // Depth when there is nothing behind it
}
return obj.isoDepth; // Return it for easier recursion
});
// Sort like you did, but in shorter syntax
this.Stage.children.sort((a, b) => a.isoDepth - b.isoDepth);
}
toString() { // Just print the ids of the children
return JSON.stringify(this.Stage.children.map( x => x.id ));
}
}
const game = new Game();
game.addObject( 2, 2, 0, 1, 1, 1 );
game.addObject( 1, 3, 0, 3, 1, 1 );
game.addObject( 6, 1, 0, 1, 3, 1 );
game.addObject( 9, 3, 0, 1, 1, 1 );
game.addObject( 5, 3, 0, 1, 3, 1 );
game.addObject( 7, 2, 0, 1, 1, 1 );
game.addObject( 8, 2, 0, 3, 1, 1 );
game.topologicalSort();
console.log(game + '');
The objects in the snippet are the same as in the picture with the same numbers. The output order is [0,1,4,2,5,6,3] which is the valid sequence for drawing the objects.
As a learning project, I'm writing a simple logical game where the user has html canvas grid where he needs to connect same-colored squares.
I'm stuck at detecting neighbour cell's properties(its colour) and if condition is matched (neighbour colour is different from mine), the cell shouldn't be filled.
My question are:
1) Is there a better way to check if target square is viable for colour-filling?
2) If there is, how do I handle clicks on new cells correctly?
function checkNeighbourTiles(aX, aY) {
var coords = [
[(aX - 1), (aY - 1)],
[(aX - 1), (aY)],
[(aX - 1), (aY + 1)],
[(aX), (aY - 1)],
[(aX), (aY + 1)],
[(aX + 1), (aY - 1)],
[(aX + 1), (aY - 1)],
[(aX + 1), (aY + 1)]
]
for (i = 0; i < coords.length; i++) {
var x = coords[i][0]
var y = coords[i][1]
var b = cells[x][y]
}
}
My code so far - jsfiddle
It depends on the complexity and performance constraints. As you have done a direct lookup table is about as efficient as can be for a simple grid lookup, though instead of creating the lookup array each time just create an offsets array once.
// an array of offset coordinates in pairs x,y 8 pairs skipping the center
const NEIGHBOURS = [-1, -1, 0, -1, 1, -1, -1, 0, 1, 0, -1, 1, 0, 1, 1, 1];
const GIRD_SIZE = 10; // 10 by ten grid
function checkNeighbourTiles(x,y){
var lx, ly, cellResult;
var i = 0;
while(i < 16){ // check for each offset
lx = x + NEIGHBOURS[i++]; // get the x offset
ly = y + NEIGHBOURS[i++]; // get the y offset
// ensure you are inside the grid
if( ly >= 0 && ly < GRID_SIZE && lx >= 0 && lx < GRID_SIZE ){
cellResult = cell[lx][ly];
// do what is needed with the result;
}
}
}
For the type of 2D array that is about simplest way to do it.
The alternative is a linked array were each cell holds and array of references to the neighbouring cells.
Thus (and with simplicity in mind) just the top left right and bottom. Then each cell would look like
cell = {
top : undefined,
left : undefined,
right : undefined,
bottom : undefined,
... other data
}
Then when you add the cell you set the references to the appropriate cells
// first add all the cells to the array
// then for each cell call this
function AddCell(cell,x,y){
cell.top = cells[x][y-1];
cell.left = cells[x-1][y];
cell.right = cells[x+1][y];
cell.bottom = cells[x][y+1];
// also the cells you just reference should also reference back
// where top refs botton and left refs right and so fourth.
cells.top.bottom = cell;
cells.bottom.top = cell;
cells.left.right = cell;
cells.right.left = cell;
}
Then at any point if you want to find which cell is above
//x and y are the cell
var cellAbove = cell[x][y].top;
This method has many advantages when you start getting complex linking, like dead cells, or skipping cells, or even inserting cells so that you change the topology of the grid.
You can also do complex searches like two left one down
resultCall = cell[x][y].left.left.bottom; // returns the cell two left one down
But it is a pain to maintain the links as there is a lot of extra code involved so for a simple 2D grid your method is the best.
A cleaner way for selecting squares might be using loops:
function (x, y){
var coords = [];
for(i = (x-1); i < (x+2); i++){
for(j = (y-1); j < j (y+2); j++){
coords.push([i, j]);
}
}
//rest of the code
}
If you check the square at [0, 0], this code will search for a square at [-1, -1]. You're gonna need some serious if statements for filtering out the proper squares.
Likewise, if you have a 9x9 grid and you search for [8, 8], the code will look for the [9, 9] square eventually and go out of bounds.
It's a minesweeper game. The objective here is to generate the exact number of mines. In this case I have an 8x8 grid of boxes with 10 mines (see at the bottom). So, the nested for loop generates 64 objects with x and y coordinates (for later drawing the grid) and a state property to indicate whether the field is mined. Then, in generateBombs I generate 10 objects with state:mined with random x and y to overwrite 8 of the 64 objects in the boxes array randomly and thus plant the mines. The problem with my approach here is that there is a possibility of 2 non-unique pairs of x and y objects to be generated, and this way I'll end up with less than the original number of mines, because the same object will be overwritten twice. What is a good approach here?
Also, one of my requirements is for the generator to use a helper function for the mines, but they take the same arguments, the need might be defeated.
var minesweeper = {
boxes: [],
//rows
boxesNum: 0,
bombsNum: 0,
//creates a 8x8 grid
generateMap: function (width, height, bombsNum) {
for (i = 1; i < height; i++) {
this.boxes.push({
x: i,
y: 1,
state: "safe"
});
for (j = 1; j < width; j++) {
this.boxes.push({
x: 1,
y: j,
state: "safe"
});
}
}
this.generateBombs(width, height, bombsNum)
},
//mines random fields from the grid
generateBombs: function (width, height, bombsNum) {
for (k = 0; k < bombsNum; k++) {
this.boxes.push({
x: Math.floor(Math.random() * width + 1),
y: Math.floor(Math.random() * height + 1),
state: "mined"
});
}
}
}
minesweeper.generateMap(8, 8, 10);
You'd be better off working on the array of boxes itself, rather than generating bombs first.
generateBombs: function (width, height, bombsNum) {
var bombCount = 0; // Count how many bombs we planted,
while(bombCount < 10){ // Loop until we have 10 bombs,
var index = parseInt(Math.random() * this.boxes.length + 1); // Get a random box id,
if(this.boxes[index].state === "safe"){ // If the box is safe, plant a bomb.
this.boxes[index].state = "mined";
bombCount++; // Increase bomb count with 1.
}
}
}
This method will guarantee that you have 10 bombs planted at 10 different locations. It could select the same box twice, but if it does so, it just tries again.
In the best case scenario, you have 10 iterations of the loop, compared to other methods that require arrays of coordinates to be checked for every bomb you want to generate.
However, there's one problem with this method of randomly picking a bomb position:
If you increase the bomb count, the method will hit more and more boxes where bombs already have been planted, resulting in an exponential increase of iterations required to plant as many bombs as you want. Basically, the denser the field is, the more likely the function is to randomly select a cell that already has a bomb, so it'd have to try again.
I don't expect this to be noticeable at bomb counts of, say, 50% or lower, though.
Your generateMap function is also broken. Try this instead:
generateMap: function (width, height, bombsNum) {
for (var i = 0; i < width; i++) {
for (var j = 0; j < height; j++) {
this.boxes.push({
x: (i + 1),
y: (j + 1),
state: "safe"
});
}
}
this.generateBombs(width, height, bombsNum)
},
I'd like to do the following;
create a 2 -column array of arbitrary finite length (say, 10 rows)
populate it sequentially from a constant-rate datastream
once its populated, update it from the same datastream ( ie replace element 0, move 1-9 down, discard old 9)
(optimally) output an average for each column
I can probably do 4 myself, but have no idea how to do 1-3.
If it helps, I'm trying to translate this;
http://kindohm.com/2011/03/01/KinectCursorControl.html (see under the dreaded shaking cursor).
This should work ok (nice question, by the way - fun little challenge, since there are tons of ways to do it)
var pointSmoother = (function(){
var pointCount = 10, // number of points to keep
componentCount = 2, // number of components per point (i.e. 2 for x and y)
points = [];
function clear() {
var i, l;
for( i = 0, l = componentCount ; i < l ; i++ ) {
if( typeof points[i] === 'undefined' ) {
points.push([]);
} else {
points[i].splice(0, pointCount);
}
}
}
clear();
function pushPoint( /* point components */ ) {
var i, l;
for( i = 0 ; i < componentCount ; i++ ) {
points[i].unshift(arguments[i]);
points[i] = points[i].slice(0, pointCount);
}
}
function average() {
var i, j, l, sum, averages = [];
l = points[0].length;
for( i = 0 ; i < componentCount ; i++ ) {
sum = 0;
for( j = 0 ; j < l ; j++ ) {
sum += points[i][j];
}
averages.push(sum/l);
}
return averages;
}
function getPoints() {
return points;
}
return {
getPoints: getPoints,
pushPoint: pushPoint,
clear: clear,
average: average
};
}());
What it basically does is it creates an object and assigns it to pointSmoother. The object has 4 methods: pushPoint(), clear(), getPoints() and average(). At the top of the thing you can set how many coordinates a point has, and how many points (maximum) to keep. I used your example of 2 coordinates per point, and 10 points at a time.
Now, I've made the assumption that you get your values in sets of 2 at a time. Let's call those 2 values x and y. When you receive them, add them to the thing by using pointSmoother.pushPoint(x, y);. You can then get the "average point", by calling pointSmoother.average() which will return an array with (in this case) 2 values: average x and average y.
If you want to look at the array yourself, you can call pointSmoother.getPoints() which will return the points array. And lastly, pointSmoother.clear() will empty the array of previous values.
Here's a demo, of sorts: http://jsfiddle.net/tapqs/1/
var nums = [[1,2],[1,3],[2,1]];
alert(nums[0][0]); //1
alert(nums[0][1]); //2
That's a two dimensional array. Loading data works just like with any other array.
To update it sequentially you are looking at queue behavior in javascript. Use unshift() and pop().
Javascript Arrays: http://www.w3schools.com/jsref/jsref_obj_array.asp
Finally for averaging the columns assuming there are 10 positions:
var num1 = 0;
var num2 = 0;
for(int i = 0;i<10;i++)
{
num1 +=array[i][0];
num2 +=array[i][1];
}
num1 = num1/10;
num2 = num2/10;
//num1 is now the average of the first column
//num2 is now the average of the second column